Accuracy and Framerate

I have a problem with physics accuracy and framerate.



I had a physics accuracy of 0.005. It all worked well but 1/60 should be enough and it would perform better on slower machines? So i used the default value of 1/60 but nothing happened. My Object is simply falling down and applying forces in the physicsTick have no effect. Only the gravity is working.

My framerate was set(setFrameRate) at 60fps. But when i set it down on 50 fps it all started to work again. But a higher framerate leads to no force applying. Any idea why this is happening?



I’m using the latest nightly build.

I guess you try to create the value by typing 1/60 instead of 1f/60f

1f/60f is used. I’m aware of the problem ;).

Even when i’m not setting it manually and use the default it behaves the same.

Is the physics system in jme3 framerate independent? For what i can say it’s not.

The more frames i have(fixed physics accuracy) the less force is applied and i need more force to counter it. When i have the same or more framerate than the accuracy no forces are applied and only gravity works.

When i have less frames too much(or too often?) force is applied.

Yes its framerate independent. Apply force works when you call it on the actual physics tick (60fps), I cannot reproduce what you say.

Thanks for looking into it normen. Than the problem must be on my side.

So this is my Testcase.



It’s basically the TestSimplePhysics. I only implemented the PhysicsTickListener. And if you press the X Button a force will be applied to the sphere.

The force is strong enough and the sphere should go up. But it has no effect. On the other hand an applyImpulse works.



[java]

import com.jme3.bullet.BulletAppState;

import com.jme3.app.SimpleApplication;

import com.jme3.bullet.PhysicsSpace;

import com.jme3.bullet.PhysicsTickListener;

import com.jme3.math.Vector3f;

import com.jme3.scene.shape.Sphere;

import com.jme3.bullet.collision.shapes.MeshCollisionShape;

import com.jme3.bullet.collision.shapes.PlaneCollisionShape;

import com.jme3.bullet.collision.shapes.SphereCollisionShape;

import com.jme3.bullet.nodes.PhysicsNode;

import com.jme3.input.KeyInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Plane;

import com.jme3.scene.Geometry;



/**

  • This is a basic Test of jbullet-jme functions

    *
  • @author normenhansen

    /

    public class TestSimplePhysics extends SimpleApplication implements PhysicsTickListener{

    private BulletAppState bulletAppState;

    private PhysicsNode physicsSphere;

    private boolean initial_ready = false;

    Material mat2;

    private static final Sphere bullet;



    static {

    bullet = new Sphere(32, 32, 1f, true, false);

    }



    public static void main(String[] args){

    TestSimplePhysics app = new TestSimplePhysics();

    app.start();

    }



    /
    * Declaring the "Shoot" action and mapping to its triggers. */

    private void initKeys() {

    inputManager.addMapping("start", new KeyTrigger(KeyInput.KEY_X));

    inputManager.addListener(actionListener, "start");

    inputManager.addMapping("stop", new KeyTrigger(KeyInput.KEY_Y));

    inputManager.addListener(actionListener, "stop");

    }



    private ActionListener actionListener = new ActionListener() {



    public void onAction(String name, boolean keyPressed, float tpf) {

    if(name.equals("start") && !keyPressed) {

    initial_ready = true;

    System.out.println("Simulation started…");

    }else if(name.equals("stop") && !keyPressed) {

    //physicsSphere.applyImpulse(new Vector3f(0f, 10f, 0f), Vector3f.ZERO);

    //physicsSphere.applyCentralForce(new Vector3f(0f, 2000f, 0f));

    initial_ready = false;

    System.out.println("Simulation stopped…");

    }

    }

    };



    @Override

    public void simpleInitApp() {

    initKeys();

    bulletAppState = new BulletAppState();

    stateManager.attach(bulletAppState);

    //bulletAppState.getPhysicsSpace().setGravity(new Vector3f(0.0f, 0.0f, 0.0f));

    bulletAppState.getPhysicsSpace().addTickListener(this);



    Material mark_mat4 = new Material(assetManager, "Common/MatDefs/Misc/SolidColor.j3md");

    mark_mat4.setColor("m_Color", ColorRGBA.Cyan);



    // Add a physics sphere to the world

    Geometry bulletg = new Geometry("bullet", bullet);

    bulletg.setMaterial(mark_mat4);

    physicsSphere=new PhysicsNode(new SphereCollisionShape(1),1);

    physicsSphere.setPhysicsLocation(new Vector3f(3,6,0));

    physicsSphere.attachDebugShape(getAssetManager());

    physicsSphere.attachChild(bulletg);

    rootNode.attachChild(physicsSphere);

    getPhysicsSpace().add(physicsSphere);



    // an obstacle mesh, does not move (mass=0)

    Geometry bulletg2 = new Geometry("bullet2", bullet);

    bulletg2.setMaterial(mark_mat4);

    PhysicsNode node2=new PhysicsNode(new MeshCollisionShape(new Sphere(16,16,1f)),0);

    node2.setPhysicsLocation(new Vector3f(2.5f,-4,0f));

    node2.attachDebugShape(getAssetManager());

    node2.attachChild(bulletg2);

    rootNode.attachChild(node2);

    getPhysicsSpace().add(node2);



    // the floor mesh, does not move (mass=0)

    PhysicsNode node3=new PhysicsNode(new PlaneCollisionShape(new Plane(new Vector3f(0,1,0),0)),0);

    node3.setPhysicsLocation(new Vector3f(0f,-6,0f));

    node3.attachDebugShape(getAssetManager());

    rootNode.attachChild(node3);

    getPhysicsSpace().add(node3);

    }



    public void physicsTick(PhysicsSpace space, float tpf) {

    if(initial_ready){

    System.out.println("I TICK!!!");

    physicsSphere.applyCentralForce(new Vector3f(0f, 100f, 0f));

    //physicsSphere.applyImpulse(new Vector3f(0f, 0.5f, 0f), Vector3f.ZERO);

    }

    }



    private PhysicsSpace getPhysicsSpace(){

    return bulletAppState.getPhysicsSpace();

    }

    }

    [/java]

I cant use this testcase atm because I have a bug where the debug meshes dont show up.

I updated the code so you should see some cyan balls.

Ok, it seems like you’re right, the listener gets called on the tick but after the forces have been applied, so it doesn’t apply forces in the tick listener. But using applyImpulse() should work as well, each physics tick the impulses are just combined and applied as applyForce() altogether, so they kind of do what you want by default.

Good to hear that i’m not the only one ;).



And when i set the accuracy to 1f/200f.

[java]bulletAppState.getPhysicsSpace().setAccuracy(1f/200f);[/java]

And limit the framerate to 60(enable vsync on start). Then the force will be applied.

Yes, thats because you make the update happen only once per physics tick this way, its also the reason why it seemingly is dependent on framerate, you apply the force twice per physics tick or only every two ticks when it gets lower.

In order to use applylmpulse i have to scale my force? force/physics_framrate?

Not if you use the tick listener to apply it, no.

The ball has a mass of 1kg. Gravitational acceleration is 9,81. So the down force would be 9,81N. The counter force to lift the ball up should be greater. But when i use 10N as up-force in applyImpulse the ball is too fast(really fast). When i scale it it behaves like expected. And the tick listener is used.

Check the bullet forums, maybe you find more concise info.

I fixed the applying in the tick listener in svn, you can now applyForce in tickListeners prePhysicsTick() method or via the physics queue.

1 Like

I will test it tomorrow when i have time ;).

With the prePhysicsTick it works now. Thanks normen!

Yeah, I found that it has been added to native bullet too, so I guess the idea to do it like this was valid :wink: