Havok physics speed goes x2 if a second engine exists

Hello !

I’m not sure either it’s a known behavior, or a bug :

While playing arround with Havok Physics, I was copy-pasting some stuff from a PG to another, and I came into doubling the speed for apparently no reason. After a closer look, I noticed that I had copied a code which is creating a new engine instead of using the one provided already in a PG context :

engine = new BABYLON.Engine(canvas);
// (scene creation)
engine.runRenderLoop(() => {
    scene.render();
});

Single engine → Speed x1

New engine → Speed x2

New engine, but AFTER a engine.dispose() → Speed x1 again

The last one shows that the previous undisposed engine was somehow doubling the physics speed. I guess it’s because each engine is triggering a physics compute on the same havok instance ?

If it’s the case, I think it should at least be warned (the fact that 2 engines appear to be triggering a compute on the same havok instance, doubling its speed)


Also, what’s surprising is that in the case with 2 engines, the first one is (to my mind) never linked to havok. This line

scene.enablePhysics(new BABYLON.Vector3(0, -55, 0), havokInstance);

Is about scene object, which is itself linked to the second engine only.

But maybe I’m missing something here, I’m new to using Havok with BabylonJS and don’t know the exact internal structure :stuck_out_tongue:

3 Likes

cc @Cedric

IIRC, there should be 2 separated Havok world instance. So, 2 engines should have no impact on speed. I’ll take a closer look asap.

1 Like

Isn’t it simply because 2 engines means 2 render loop and double update?

Hello @Cedric thanks for having a look.

I did some additionnal tests, and results are… Unexpected !


(Reference)
Single engine → Speed x1


Second engine and second render loop → Speed x2


Second engine with NO render loop → Speed x0.2 ( ! )

This last one is the most surprising : I’m just creating an engine

engine = new BABYLON.Engine(canvas);

Without any additional render loop, and physics speed is divided by at least 5 :thinking:


EDIT For the above test, it appears that it’s a matter of reference. If I do :

engine2 = new BABYLON.Engine(canvas);

Then nothing changes on the physics speed.
The fact that engine reference was replaced is triggering something weird

2 Likes

wow! this is wild! Thanks for testing more!
I will take a deeper look asap.

2 Likes

This is a combination of multiple things leading to edge cases and not bugs.
I may have missed subtilities but the core of the explanation should be the same.

Physics tick update is done in render method.
Render is called 2 times: in default PG runRenderLoop call plus in the PG itself.

Removing the 2nd runRenderLoop call leads to way slower tick update. This happens because no renderloop is being use with the engine. its delta time is 0 and this clamp will set it to 1ms instead:

So, to sum up: 2 scene.render calls on the same scene = twice as fast. no renderloop on an engine = update with a delta time of 1ms

There is a 3rd way:

2 engines, 1 render loop. delta time is clamped at 1ms but engine is instanciated with flag to not use delta time but use fixed delta (with a default of 1/60)

This behavior is expected.

1 Like

Hello @Cedric , thanks a lot for your deep investigation into this !

I have to say, I’m quite surprised about this. The fact that the physic update is done on render, why not, but I would expect that whatever the rate of physics update (doubling it for example) the speed would be the same because the delta time would be automatically “global” (for example just saving a timestamp on last physic update, and using it to compute delta time on each new update, whatever its rate)

But maybe the reason is more due to Havok itself than BabylonJS ?

Whatever, at the end it’s not blocking, and still I’m happy that I now understand what’s behind !

Thanks again :slight_smile:
Tricotou

Nop, this is due to choices made (long?) time ago. Delta time is stored in engine and used in scene.render. call it twice and there will be 2 tick updates. if delta time is 0, clamp it to 1ms.
I believe whatever you end up with API/ loop design, you can always break it.

1 Like