[Solved] Remaining physics determinism while using kinematic bodys (updating SceneGraph from another thread)

Hi,
I just love the scenegraph-mechanics and the way relative positions are defined in jME3. My game makes extensive use of this with kinematic rigidbodycontrols, which positions are updated somewhere in the main update-loop. They are interacting with kinetic rigidbodys. Bullet might run with a much higher framerate, than my update-loop.
I want to maintain absolute determinism in my game. The same initial situation shall always lead to the exact same results, if the player doesn’t interact with the game. My first approach was framerate dependent. Now I’d like to update the position of my kinematic bodys from the physicsThread through physicsTickListeners.

I wrote a simple testCase for that:

package kinematics;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.PhysicsTickListener;
import com.jme3.bullet.collision.shapes.CollisionShape;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.bullet.util.CollisionShapeFactory;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;


import com.jme3.scene.shape.Box;

public class Main extends SimpleApplication implements PhysicsTickListener {

    private BulletAppState bulletAppState;
    private PhysicsSpace physicsSpace;
    private float time = 0;
    private Geometry boxGeo;
    private RigidBodyControl boxPhy;

    public static void main(String[] args) {
        Main app = new Main();
        app.setPauseOnLostFocus(false);
        app.start();
    }

    @Override
    public void simpleInitApp() {
        bulletAppState = new BulletAppState();
        bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL); //Doesn't work with Sequential either
      
        
        stateManager.attach(bulletAppState);
        physicsSpace = bulletAppState.getPhysicsSpace();
        physicsSpace.addTickListener(this);

        Box box = new Box(1, 1, 1);
        boxGeo = new Geometry("blue cube", box);
        CollisionShape sceneShape = CollisionShapeFactory.createBoxShape(boxGeo);

        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        boxGeo.setMaterial(mat);
        rootNode.attachChild(boxGeo);


        boxPhy = new RigidBodyControl(sceneShape, 1);
        boxPhy.setKinematic(true);
        boxGeo.addControl(boxPhy);
        physicsSpace.add(boxPhy);
        //physicsSpace.setAccuracy(1 / 60f);
        bulletAppState.setDebugEnabled(true);
    }

    @Override
    public void simpleUpdate(float tps) {
    }

    public void prePhysicsTick(PhysicsSpace space, float tpf) {
        // throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void physicsTick(PhysicsSpace space, float tpf) {
        time += physicsSpace.getAccuracy();
        boxGeo.setLocalTranslation(0, time * 0.2f, 0);
        System.out.println(time);
    }
}

Of course this leads to some synchronisation probems. I’m getting a IllegalStateException after a few ticks, because the SceneGraph was modified after rootNode.updateGeometricState() was called.

So I need to solve this problem. I’d try to delay the physics-thread for a while when the SceneGraph is rendering and apply my changes afterwards. Is there any build-in method, or listener that tells me when it is save to update the Scenegraph? Or is there another solution to maintain determinism?

Simply only update physics objects on the physics tick (not the spatial its attached to).

As I said, I’m making extensive use of the jME3 Scenegraph concept with Nodes and relative motions.
Imagine a solar system. The sun-spatial is stationary. There are Planets orbiting the sun and moons orbiting the planets, space stations orbiting the moons… //just a constructed example (and not a good one)^^
My Game has many systems like this.

I defined the translation of every spatial relative to their parentNode as a function of time.
If I would update just the physicsObject I would have to do all the Math involved to get the absolute position of the spatial on my own. I could implement my own scenegraph-mechanics. That should do the trick, but is a little bit overkill.

Is there a more elegant solution?

I hope that you know the physics engine is an diferent engine then the game engine itself, and its called bullet, it runs in a diferent thread and its syncronized using the physics tick methods.
If you try to change game objects on the physics tick you will have bad results, you shold make changes on game object on update only.
If you want to move objects on the physics engine ( physicstick ), use diferent methods like apply forces or setphysical location for that.
If you need bether tick for your game ( bullet runs at 60 ticks max ), you will need to implement an custom collision or to build another physical engine…

Thank you very much. I know the basic concepts of jME3 and Bullet. The very essence of my problem is, that I need to update the positions of all kinematic bodys from the physics-thread and still want to use the tree structure of the scenegraph.

And how you will handle the collisions if you just move the objects ?
I mean, you can use the set physical location for this, but you will not have natural collisions.
If you dont need the natural collisions, and want to move the objects on the game thread, there is an kinematic physics option for that, maybe its what you need ?

Haa, sorry, I just notice you are using kinematics…
You should not have this problem with kinematics if you put the move code on the update.
You can control the determinism with the fps, so I didnt understand your problem…

One way would be to remove the normal multi step approach bullet uses if fps drops to low,

You can force it to only do one tick, and also to run on the render thread.
This has quite a few downsides to it, but if your use case is special enough it might be worth it.

I thought about that as well, but due to my ‘function of time-approach’ (incremented by physicsTickListeners) everything would run in slow motion, when the framerate drops. This would make my game way less enjoyable.

Are you using real models for the bullets ? Did you try to use points rigid bodys or even rays intersections on the bullets to improve performance ? I am assuming your performance problem is because of the bullets determinism right ?

You could run fixed steps of the physics separate from the render and just use clever data structures to interpolate in the render. Physics might lag… but then physics would have lagged anyway. Not much you can do about it.

Simply keep the positioning in another realm and apply it to the physics and scenegraph, there won’t be any way around that with your requirements.

@normen is it possible to use setPhysicsLocation() on a kinematic object or does it synchronize the location from the parent spatial? Just wanted to confirm the behavior …

Both is possible. Spatial to kinematic and kinematic to spatial.

Thank you alll for your help.
I just want to let you know, how I solved this problem. I extended Node and RigidBodyControl.

Basically every time a child (A), with a kinematic RigidBodyControl attached to it, is added to a node (B) the tree to this node is checked recursively for the next node with a RigidBodyControl attached to it ©.

In this process a reference of (A) is passed up the hierarchy and added to a field ArrayList ‘kinematicChildren’ of every node it passed. When © is found, a reference of this ‘physicsParent’ is passed back to (A) and saved in a field variable. Then the ‘linear and angular offset’ of (B) relative to © is calculated and stored in the extended RigidBodyControl.

I added a method ‘updatePhysics()’ to my RigidBodyControl class. This method will update the physics-world-transformation of the kinematic body, using the reference to its ‘physicsParent’, the offset values and the given function of time. Then the updatePhysics() method of every kinematicChildren is called. So the kinematics are updated recursively. The first updatePhysics() method is called by a physicsTickListener.

If a node is transformed between (A) and © the offset-values are recalculated.

This solution works for my specific useCase, but I don’t think it is applicable in most games. Plus it would create dependencies between the core library and the bullet-libraries. So I see no point in contributing it.

If someone is in the same situation, as I was, and has a need to see the code, let me know. :wink:

Just for future reference, this is what you get when you abuse the functionality of a library instead of using it for what its meant for and doing everything else in your own code :slight_smile:

1 Like

http://rs1img.memecdn.com/if-it-looks-stupid-but-works-it-ain-t-stupid_o_2793315.jpg

btw, I’m a mechanical engineer :wink: