Hello to everybody,
I was performing a feasibility test using Minie and starting from an example, letting “splash” a soft body on the ground.
I’m facing some pass-trough effect that not happened if I use the box.
Can you help me understand which is the proper way to configure SoftBodyConfig, the terrain and the body to avoid that the body pass through the ground?
import com.jme3.anim.AnimComposer;
import com.jme3.anim.util.AnimMigrationUtils;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.PhysicsSoftSpace;
import com.jme3.bullet.SoftPhysicsAppState;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.HeightfieldCollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.control.SoftBodyControl;
import com.jme3.bullet.objects.PhysicsBody;
import com.jme3.bullet.objects.PhysicsSoftBody;
import com.jme3.bullet.objects.infos.Sbcp;
import com.jme3.bullet.objects.infos.SoftBodyConfig;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Spatial;
import com.jme3.scene.debug.custom.ArmatureDebugAppState;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.scene.shape.Sphere.TextureMode;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
import com.jme3.texture.Texture;
import java.util.LinkedList;
/**
* A simple example of a soft body.
*
* @author Stephen Gold sgold@sonic.net
*/
public class HelloSoftBody extends SimpleApplication {
private PhysicsSoftSpace physicsSpace;
private ArmatureDebugAppState debugAppState;
private AnimComposer composer;
final private LinkedList<String> anims = new LinkedList<>();
private TerrainQuad terrain;
private Material mat_terrain;
private RigidBodyControl ball_phy;
private static Sphere sphere;
private Material stone_mat;
public static void main(String[] ignored) {
HelloSoftBody application = new HelloSoftBody();
application.start();
}
/**
* Initialize this application.
*/
@Override
public void simpleInitApp() {
flyCam.setMoveSpeed(100);
// Set up Bullet physics.
SoftPhysicsAppState bulletAppState = new SoftPhysicsAppState();
stateManager.attach(bulletAppState);
bulletAppState.setDebugEnabled(true);
physicsSpace = bulletAppState.getPhysicsSoftSpace();
// Add a light to the scene.
Vector3f direction = new Vector3f(1f, -2f, -4f).normalizeLocal();
DirectionalLight sun = new DirectionalLight(direction);
rootNode.addLight(sun);
// Add a model to the scene.
Spatial cgModel = assetManager.loadModel("Models/Jaime/Jaime.j3o");
AnimMigrationUtils.migrate(cgModel);
//cgModel.scale(0.3f);
rootNode.attachChild(cgModel);
// Add a soft-body control to the model.
SoftBodyControl sbc = new SoftBodyControl();
cgModel.addControl(sbc);
// Translate and rotate the model's physics body. Since the control
// is "dynamic", the model will follow its body.
PhysicsSoftBody body = sbc.getBody();
//body.applyRotation(new Quaternion().fromAngles(0.4f, 0f, 1f));
body.applyTranslation(new Vector3f(10f, 50f, 10f));
// Relocate the camera.
cam.setLocation(new Vector3f(-40f, 1f, -40f));
cam.lookAtDirection(new Vector3f(body.getPhysicsLocation().getX(), 3, body.getPhysicsLocation().getZ()), Vector3f.UNIT_Y);
// Set the body's default frame pose: if deformed,
// it will tend to return to its current shape.
boolean setVolumePose = true;
boolean setFramePose = false;
body.setPose(setVolumePose, setFramePose);
// Make the body bouncy by enabling pose matching.
SoftBodyConfig config = body.getSoftConfig();
config.set(Sbcp.PoseMatching, 0.5f);
sbc.setPhysicsSpace(physicsSpace);
// Check with a rigid body
addBall();
// This work
//addBox();
// This not work perfectly
initTerrain();
// Test RBC with HeightfieldCollisionShape
HeightfieldCollisionShape hcs = new HeightfieldCollisionShape(terrain, new Vector3f(2, 1, 2));
RigidBodyControl plane_phy = new RigidBodyControl(hcs,PhysicsBody.massForStatic);
terrain.addControl(plane_phy);
plane_phy.setPhysicsSpace(physicsSpace);
// Test RBC without HeightfieldCollisionShape
//RigidBodyControl rbc = new RigidBodyControl(PhysicsBody.massForStatic);
//terrain.addControl(rbc);
//bulletAppState.getPhysicsSpace().add(rbc);
}
/**
* Add a large static cube to serve as a platform.
*/
private void addBox() {
float halfExtent = 4f; // mesh units
Mesh mesh = new Box(halfExtent, halfExtent, halfExtent);
Geometry geometry = new Geometry("cube platform", mesh);
rootNode.attachChild(geometry);
geometry.move(10f, -halfExtent - 12f, 10f);
ColorRGBA color = new ColorRGBA(0.1f, 0.4f, 0.1f, 1f);
Material material = new Material(assetManager,
"Common/MatDefs/Light/Lighting.j3md");
material.setBoolean("UseMaterialColors", true);
material.setColor("Diffuse", color);
geometry.setMaterial(material);
geometry.setShadowMode(RenderQueue.ShadowMode.Receive);
BoxCollisionShape shape = new BoxCollisionShape(halfExtent);
RigidBodyControl boxBody
= new RigidBodyControl(shape, PhysicsBody.massForStatic);
geometry.addControl(boxBody);
boxBody.setPhysicsSpace(physicsSpace);
}
private void addBall() {
stone_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG");
key2.setGenerateMips(true);
Texture tex2 = assetManager.loadTexture(key2);
stone_mat.setTexture("ColorMap", tex2);
sphere = new Sphere(32, 32, 0.4f, true, false);
sphere.setTextureMode(TextureMode.Projected);
Geometry ball_geo = new Geometry("ball", sphere);
ball_geo.setMaterial(stone_mat);
rootNode.attachChild(ball_geo);
ball_geo.setLocalTranslation(new Vector3f(11f, 50f, 11f));
ball_phy = new RigidBodyControl(1f);
ball_geo.addControl(ball_phy);
ball_phy.setPhysicsSpace(physicsSpace);
}
private void initTerrain() {
mat_terrain = new Material(assetManager,
"Common/MatDefs/Terrain/Terrain.j3md");
mat_terrain.setTexture("Alpha", assetManager.loadTexture(
"Textures/Terrain/splat/alphamap.png"));
Texture grass = assetManager.loadTexture(
"Textures/Terrain/splat/grass.jpg");
grass.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex1", grass);
mat_terrain.setFloat("Tex1Scale", 64f);
Texture dirt = assetManager.loadTexture(
"Textures/Terrain/splat/dirt.jpg");
dirt.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex2", dirt);
mat_terrain.setFloat("Tex2Scale", 32f);
Texture rock = assetManager.loadTexture(
"Textures/Terrain/splat/road.jpg");
rock.setWrap(Texture.WrapMode.Repeat);
mat_terrain.setTexture("Tex3", rock);
mat_terrain.setFloat("Tex3Scale", 128f);
Texture heightMapImage = assetManager.loadTexture(
"Textures/Terrain/splat/mountains512.png");
AbstractHeightMap heightmap = new ImageBasedHeightMap(heightMapImage.getImage());
heightmap.load();
terrain = new TerrainQuad("my terrain", 65, 513, heightmap.getHeightMap());
terrain.setMaterial(mat_terrain);
terrain.setLocalTranslation(0, -100, 0);
terrain.setLocalScale(2f, 1f, 2f);
rootNode.attachChild(terrain);
}
}
Here is a video of the code running
SoftMonkey