Physics, Ammo/Cannon: spooky 'down' force in no-force scene

My flight-sim experiment started to behave strange after I added some 2D-UI. I figured out why:

In a scene with gravity (-9.81) and a single counter-force of same strength nothing should move.
In fact there seems to be an additional downforce accelerating impostors downwards.

The effect gets worse if time consuming stuff (like UI updates in my case) is done during onBeforePhysicsObservable up to multiple G.

https://playground.babylonjs.com/#QERG1P

The effect does not show up when starting the physics engine with zero gravity and adding G to each impostor.

Hope for help,

. J

Adding @Cedric a Physx mastermind :slight_smile:

You can fix this issue by adding a subtime step. This will make the physics engine more deterministic with fixed time steps.
https://playground.babylonjs.com/#QERG1P#1
See lines 12-13

Thank you. I played with setSubTimeStep before but found issues. Setting it to 1 extremely accelerates the whole scene: https://playground.babylonjs.com/#QERG1P#2
Looks as if applyForce somehow accumulates or the engine still uses 16.6ms per substep?

Interesting though: setting setSubTimeStep(16.666) cures the issue without generating the phantom force.

yes, time is accumulated. So if your framerate drops to 30fps, physics will still run at 60fps by doing 2 steps instead of 1.

Yes, understood, this explaines very well why setSubTimeStep(16.666) works.

But it does not tell why physics is broken in the described way for setSubTimeStep(1) (beastly accelerated) and setSubTimeStep(0) (the original issue)?

setSubTimeStep parameter is the time step that’s used per frame. If the value is 1, it will decrement with that value the time acculated. So if the time accumulated is 16ms, it will perform 16 iterations. So it will be accelerated as you saw.
setSubTimeStep(0) disables those substeps and takes only the last frame delta time for computation but as you saw as well, the small time difference makes the physics computation per frame unreliable and non deterministic.

Please forgive me being so insisting…

I got that setSubTimeStep(1) will do physics 16x during a common 16ms frame cycle at desirable constant rate. IMHO it should do 16 1ms steps, right?

BUT … IMHO this should not have an effect on forces hence acceleration. G is G, regardless how often it is calculated. Of course the integration result may vary slightly with deltaT (in our case of constant forces). Acceleration of the body MUST not be orders of magnitude higher just because a change of the integration time. Free fall w/o any applyForce MUST be at 9.81m/s²? Regardless of the timestep.

If that would be the case, there would be no means to compute reasonable forces.

yes, you are right.
The issue is in the first frame I think. With physics engine initialization, it might take more than 16.6. Let’s say it take 17ms. The inertia the cube will get can’t be compensated by the force. G is not a force but an acceleration, independant of the mass. So, a tiny delta time in the first frame and the box potential energy can’t be nulled by the applied force.
With a subtimestep, the tiny amount of time more it takes is compensated and flatten.
The force applied only compensate the gravity at t=0. If you start to apply the force anytime later, the potential energy will be bigger and it would fall any way.

Still not sure wether we are discussing the same thing.

Take this sample: https://playground.babylonjs.com/#QERG1P#3

No forces at all, just the global G and setSubTimeStep(1).

The body doesn’t fall with G but much much much faster, it’s down like The Flash.

I see what you mean!
Yep, that’s weird. And I don’t get the same behavior between Ammo and Cannon.
This looks like an issue with fixed timesteps with Cannon. I’m investigating…

1 Like

:slight_smile:

Yep, doesn’t happen with Ammo for me too, but with both Cannon and Oimo.

PR is live Fixed time steps/delta time with sub time step for Oimo and Cannon by CedricGuillemet · Pull Request #7964 · BabylonJS/Babylon.js · GitHub

2 Likes