[devlog] Bullet SoftBody in JME3.1

Hello monkeys,

I started working on SoftBody so you don’t have to :wink: .

I already have been into this development for about a huge month. Learning how to make a JNI wrapping, learning the Bullet library, building & testing ect …

Since SoftBody features isn’t available in jBullet but only into the native C/C++ Bullet. These features will only be available using the jme3-bullet-native & jme3-bullet libraries.


At this point SoftBodies are getting somewhere (good to know). The very basics bindings are working, but this still a lot of WIP features. You can create a PhysicsSoftBody and add this into a BulletSoftBodyAppState (as adding a PhysicsRigidBody into the BulletAppState). One of the only working (and tested) way to create a SoftBody is to use the constructor with a given Mesh. (Note that only mesh with a triangles faces will work )

You can find the working fork here : GitHub - dokthar/jmonkeyengine: A complete 3D game development suite written purely in Java.

More informations can be found on the wiki page, which is still in early writing stage, so feel free to add your tips.


GETTING STARTED

I do not distribute the dynamics lib (.so / .dll …) so you have to checkout the whole project from GitHub then build the project for your platform.

  1. checkout the project from GitHub.
  2. go into the file gradle.propeties and set the line : buildNativeProjecte = true .
  3. run the command : ./gradlew build
  4. then run the command to build the sdk : ant -f ./sdk/ build-zip
  5. create a new project and make sure you use the following libraries : jme3-bullet-native and jme3-bullet (instead of jme3-jBullet)

EXAMPLE

public void simpleInitApp() {
    softBodyAppState = new BulletSoftBodyAppState();
    getStateManager().attach(softBodyAppState);
    SoftBodyWorldInfo sbwi = softBodyAppState.getPhysicsSoftSpace().getWorldInfo();
    sbwi.setGravity(Vector3f.UNIT_Y.mult(-0.981f));

//start addSoftBunny();
    Material matN = new Material(assetManager, "Common/MatDefs/Misc/ShowNormals.j3md");

    Geometry bunny = new Geometry("b", StandfordBunny.getMesh().deepClone());
    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().setClusterSoftHardness(1);
    soft.config().setClusterSoftImpulseSplitCoef(0);
    soft.config().setClusterKineticHardness(0.1f);
    soft.config().setClusterKineticImpulseSplitCoef(1);*/
    soft.config().setPositionIterations(2);    

    soft.config().setCollisionsFlags(PhysicsSoftBody.Config.CL_SS + PhysicsSoftBody.Config.CL_RS);
    //soft.config().setCollisionsFlags(PhysicsSoftBody.Config.VF_SS+PhysicsSoftBody.Config.Default);

    soft.setPose(false, true);
    soft.setTotalMass(100, true);
    soft.randomizeConstraints();
    softBodyAppState.getPhysicsSoftSpace().add(soft);
// end addSoftBunny();

    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);
}

TODO

You can find the updated todo list on github

28 Likes

Really awesome work. Theres already been a few people who intended to do this but never got there in the end. Kudos to you - also for working your way through it without major hand-holding from our side while still checking back with us on implementation details - this is how contributing to jME works :wink:

2 Likes

gooodiiiies !!
congrats :wink:

Great work… Congrats. :smile:

The basic SoftBodyControl is done : attaching this control to a spatial will search for the first geomtry and create a new SoftBody with the geometry’s mesh. I Also added the update for the update of the vertex normal (based on bullet softbody data ) it’s seem to be done right.


A this point i reached a first milestone : the “proof of concept” passed successfully :smiley:


TODO

  • update the spatial position instead of updating the mesh in the world space, (should be done in native side)
  • destroy the old native object when a new btSoftBody is set.
7 Likes

If you properly correlate java and native objects you should be able to let the garbage collector handle cleanup of native objects in finalize() That is, keep a reference on the java side (e.g. In the control) for the java object that wraps the native object, when that is lost the gc will at some point clean up the native object. This way you get the most java-ish behavior.

For that to work you need a java object wrapping the softbody first though, directly referencing the native object in the control probably isn’t a good idea.

1 Like

Can’t wait to see softbodies on jme :smiley: .
Is everything computed on cpu or there is any gpu acelleration done by bullet for this?

Only RidigBody and maybe basic detection for SoftBody can be done on GPU.

Currently the control extends the PhysicsSoftBody just like the RigidBodyControl.

I was thinking using a private inner class just to store the native reference and the finalize(). But the PhysicsSoftBody use only the objectId (native reference), field from PhysicsCollisionObject his parent.

I can’t use the PhysicsSoftBody just like a wrapping into the SoftBodyControl since it’s is child, breaking this would break the ability to add the control as a softBody into the physicsSpace : /

right now the SoftBodyControl create a new native object when setSpatial is called.

If a softbody can’t be reinitialized and no new shape can be set on it then the Control doesn’t need to have that feature either.

I agree, no need to do extra work, and offer more then bullet can.

(a warning that a shape cannot be set again would be nice tho, if setSpatial is called, and probably will reduce questions on the forums about that.)

Is this a good idea to keep the softBodyControl extending the PhysicsSoftBody (as done with rigidbody), because this lock (or the origin) of the problem of creating a new PhysicsSoftBody bound to a native object.

@RatKod what do you mean? I cannot follow.

Actually nobody should call setSpatial manually, its called when the Control is attached. But then yeah, there should be some kind of warning that the physics SoftBody shape has already been created - if the Geometry is a different one.

Otherwise its exactly as you say, if bullet only allows creating the object once with a new shape then the Control (and base PhysicsSoftBody) doesn’t need to be able to do more - the user simply has to recreate it.

If on the other hand the bullet object allows creating a new shape for the same SoftBody that functionality should be exposed in the core PhysicsSoftBody and be used (I don’t know if thats the case or not).

  1. currently the softBodyControl extends the PhysicsSoftBody like done for rigidbody.
  2. this (see 1.) doesn’t let me simply create a new PhysicsSoftBody when i need it (when setSpatial() is used ).
  3. because of 1. when you create the softBodyControl it is an “empty” native SoftBody.
  4. because of 2. & 3. i create a new native softBody with a given mesh, and use the same softBodyControl (also an PhysicsSoftBody ) when setSpatial() is used
  5. I do like so (see 4.) because i want to be able to do : softAppstate.getSpace().add(softBodyControl)

Is this (5.) a good choice, to want to make something that it can be used just like rigidBody ?
Or should i put the PhysicsSoftBody into a field of the SoftBodyControl this will break 5. but it will allow 2.

Hm break 2 in my opinion, and allow 5. So good solution from my view.

And put a exception in setSpatial that it is not supported to change the spatial the controll is attached to, to prevent un expected behaviour from other users…

This is allowed, it’s just a little “dirty” : it does just like the contructor

You’re recreating the object that is represented by PhysicsSoftBody on the java side which is not good. If the object has to be recreated on the native side just do the same on the java side.

Hm, so you would need to add a destructor call to the native side for this to work.

I see what you mean with somewhat ugly :slight_smile:
Wouldnt adding a bit of code to the Space.add() solve the task of being able to 5 as well?

It’s been quite a while i didn’t put any update, but I m still working on this.
I chose the rebuild the softBody from the control it’s the best way i found, to avoid to call a “contructor” in a methods of the control, softbody had a protected methods to rebuild the soft body. It’s highly inspired by the rigidBody.

I did a lot of JNI binding lately i added the biding to the softBody material struct (i still don’t know how materials are used)
and also to the config struct (with ~ 20 fields) and this struct seem to be important for the “behavior” of the body. (ie how much soft it is)

4 Likes