Physics : SoftBody
Writing in progress, checkout the forum for additional infos http://hub.jmonkeyengine.org/t/bullet-softbody-in-jme3-1/33110 |
what is a soft body ?
how a soft body is simulated ? ( node, link, face ; spring & damper )
Getting Started
The dynamics libraries for softbody (.so , .dll …) isn’t (yet) prebuild for your platform so you have to checkout the entire project from GitHub then build the project.
How to :
-
checkout the project from GitHub.
-
go into the file gradle.properties and set the line : buildNativeProject = true .
-
run the command : ./gradlew build
-
then build the sdk : ant -f ./sdk/ build-zip (or build the sdk installer)
-
create a new project and make sure you use the following libraries : jme3-bullet-native and jme3-bullet (instead of jme3-jBullet)
Simple Example
public void simpleInitApp() {
softBodyAppState = new BulletSoftBodyAppState();
getStateManager().attach(softBodyAppState);
SoftBodyWorldInfo sbwi = softBodyAppState.getPhysicsSoftSpace().getWorldInfo();
sbwi.setGravity(Vector3f.UNIT_Y.mult(-0.981f));
Geometry bunny = new Geometry("b", StandfordBunny.getMesh().deepClone());
Material matN = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");
bunny.setMaterial(matN);
rootNode.attachChild(bunny);
bunny.addControl(new SoftBodyControl(false));
PhysicsSoftBody soft = bunny.getControl(SoftBodyControl.class);
soft.generateClusters(8);
soft.config().setDynamicFrictionCoef(0.8f);
soft.config().setPoseMatchingCoef(0.2f);
soft.config().setCollisionsFlags(PhysicsSoftBody.Config.CL_SS + PhysicsSoftBody.Config.CL_RS);
soft.setPose(false, true);
soft.setTotalMass(100, true);
soft.randomizeConstraints();
softBodyAppState.getPhysicsSoftSpace().add(soft);
Box floorMesh = new Box(100f, 0.5f, 100f);
Geometry floor = new Geometry("floor", floorMesh);
floor.move(0, -5f, 0);
floor.addControl(new RigidBodyControl(0));
softBodyAppState.getPhysicsSpace().add(floor);
}
Documentation
soft mesh / surface
Cluster ?
(generate) bending constraint ?
config collision flag ?
Ropes
A rope can be created by creating a new SoftBody on a Mesh with Mesh.Mode.Lines. More information on creating custom meshes.
Example
Mesh ropeMesh = new Mesh();
Vector3f[] vertices = {
new Vector3f(0.00f, 0, 0),
new Vector3f(0.50f, 0, 0),
new Vector3f(1.00f, 0, 0),
new Vector3f(1.50f, 0, 0),
new Vector3f(2.00f, 0, 0),
new Vector3f(2.50f, 0, 0),
new Vector3f(3.00f, 0, 0),
new Vector3f(3.50f, 0, 0),
new Vector3f(4.00f, 0, 0)};
int[] indices = {
0, 1,
1, 2,
2, 3,
3, 4,
4, 5,
5, 6,
6, 7,
7, 8};
ropeMesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
ropeMesh.setBuffer(VertexBuffer.Type.Index, 2, BufferUtils.createIntBuffer(indices));
ropeMesh.setMode(Mesh.Mode.Lines);
ropeMesh.updateBound();
Once you have a Line Mesh, you can do as follow :
Geometry t = new Geometry("softRope", ropeMesh);
t.move(0, 5, 0);
t.addControl(new SoftBodyControl(false));
Note
An anchor bind a SoftBody’s node (or Vertex) to a RigidBody, the node will be attached to a RigidBody even if there are space in between.
Anchors are not yet Serialized |
Example
Geometry t = new Geometry("softRope", ropeMesh);
Box box = new Box(1f, 1f, 1f);
Geometry b = new Geometry("rigidBox", box);
t.move(0, 5, 0);
b.move(3f, 5, 0);
t.addControl(new SoftBodyControl(false));
soft = t.getControl(SoftBodyControl.class);
soft.setMass(0, 0); // make the first node static
b.addControl(new RigidBodyControl(1));
rigid = b.getControl(RigidBodyControl.class);
softBodyAppState.getPhysicsSpace().add(rigid);
softBodyAppState.getPhysicsSoftSpace().add(soft);
soft.appendAnchor(8, rigid); //where 8 is the last node of the rope
Anchors can be removed as below. Note that you have to keep the node and RigidBody bind with.
soft.removeAnchor(8,rigid);
LinearJoint
public SoftLinearJoint(Vector3f position, PhysicsSoftBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB);
public SoftLinearJoint(Vector3f position, PhysicsSoftBody nodeA, PhysicsSoftBody nodeB, Vector3f pivotA, Vector3f pivotB);
AngularJoint
public SoftAngularJoint(Vector3f axis, PhysicsSoftBody nodeA, PhysicsRigidBody nodeB, Vector3f pivotA, Vector3f pivotB);
public SoftAngularJoint(Vector3f axis, PhysicsSoftBody nodeA, PhysicsSoftBody nodeB, Vector3f pivotA, Vector3f pivotB);
LinearJoint
Box box = new Box(3f, 1f, 3f);
Geometry b = new Geometry("rigidBox", box);
b.move(0, 5f, 0);
b.addControl(new RigidBodyControl(1));
rigid = b.getControl(RigidBodyControl.class);
Torus torus = new Torus(20, 10, 1f, 1.5f);
Geometry t = new Geometry("softTorus", torus);
t.addControl(new SoftBodyControl(true, false));
soft = t.getControl(SoftBodyControl.class);
soft.generateBendingConstraints(4, soft.material());
soft.generateClusters(4);
softBodyAppState.getPhysicsSpace().add(rigid);
softBodyAppState.getPhysicsSoftSpace().add(soft);
joint = new SoftLinearJoint(Vector3f.UNIT_X, soft, rigid, new Vector3f(0f,2,0f), new Vector3f(0f,-2,0f));
softBodyAppState.getPhysicsSoftSpace().add(joint);
AngularJoint
Box box = new Box(1f, 1f, 1f);
Geometry b = new Geometry("rigidBox", box);
b.move(0, 5f, 0);
b.addControl(new RigidBodyControl(1));
rigid = b.getControl(RigidBodyControl.class);
Torus torus = new Torus(20, 10, 1f, 1.5f);
Geometry t = new Geometry("softTorus", torus);
t.addControl(new SoftBodyControl(true, false));
soft = t.getControl(SoftBodyControl.class);
soft.generateBendingConstraints(4, soft.material());
soft.generateClusters(4);
softBodyAppState.getPhysicsSpace().add(rigid);
softBodyAppState.getPhysicsSoftSpace().add(soft);
joint = new SoftAngularJoint(Vector3f.UNIT_X, soft, rigid, new Vector3f(0,0,2), new Vector3f(0, 0, 2));
softBodyAppState.getPhysicsSoftSpace().add(joint);