Havok and BabylonJS are out of sync

Hello everyone!
I’m experimenting with floating origin and havok (keeping an object at the center of the scene at all times).

It seems like havok is updating the physics body faster than what babylonjs renders on the screen: https://playground.babylonjs.com/#Z8HTUN#650

I also found that changing scene.registerBeforeRender to scene.registerAfterRender fixed the synchronization issue. However with a floating origin the object that stays in the center must be already in the center before any rendering happens.

Is there some kind of scene.registerBeforeRenderButAfterHavokStuff in the new physics engine? I couldn’t find anything up until now.

1 Like

Hey there! I don’t think you need to leverage anything new, but you may want to look at registering your update logic in the pre- or post- physics update step observable.

If your using deterministic lockstep, you can also use the similar onBeforeStep or onAfterStep Observables

HTH!

2 Likes

Thanks for the quick answer! I changed my playground and it is definitely better: https://playground.babylonjs.com/#Z8HTUN#653

But there is still some strange vibrations going on when falling from a height (like 15 here) or when at rest against the ground. I guess the disablePreStep = false is to blame but I can’t see how to do floating origin without it.

I just realized that in the new playground the sphere wasn’t actually at the origin, to put it back at the origin, the translation must occur after every physic movement, which gives this: https://playground.babylonjs.com/#Z8HTUN#654

The problem is that the desync occurs again even though it is translated back after the physics update.

Use the onAfterRenderObservable to translate the coordinates, like this: Babylon.js Playground

Indeed that corrects the desync, but the issue is that the sphere is not at the center of the scene when the rendering occurs as we move it back to the center afterward. This is not an issue when the speed of the sphere is small, but if it goes very fast, we would loose the appeal of floating origin because the sphere would be far from the origin when rendering.

I think the solution will be to use some havok function to move manually the physics body back to the origin after the physics calculation and before the render.

One trick that kinda works is by executing an empty havok step after repositionning the sphere to the origin https://playground.babylonjs.com/#Z8HTUN#658

Executing the empty step forces havok to sync with the current babylonjs step thanks to disablePreStep = false

This is not perfect but it works, still I have no idea why there is such jittering going on. Does the executeStep method calls the observables as well?

It doesn’t, the observables are called by the Scene class. As for the jittering, I tested lowering the gravity and it becomes way less jittery: PhysicsUpdateProblem | Babylon.js Playground (babylonjs.com), possibly because the bodies are being updated by a smaller distance during each step? :thinking: I don’t think that’s the solution, @eoin probably has a better one :sweat_smile:

2 Likes

Interesting, I tried dropping the ball from higher and it does confirm that the jitter comes from the speed of the objects https://playground.babylonjs.com/#Z8HTUN#660

It jitters the most when colliding with the ground and then it settles when it reaches maximum height (and thus its speed reaches 0) before falling again.

It is almost like the executeStep while syncing the physics body to the babylon mesh also tries to apply the current velocity to the body. This is weird because the deltatime is 0 and we should expect the body to stay still as the translation is probably something like position += velocity * deltatime.

Babylon uses a variable framerate by default, which is what causes the apparent jitter. Enabling deterministic lockstep will remove the jitter.

However, in your onAfterPhysicsObservable, you’re teleporting every body every step; this will cause problems for both performance and behaviour, in any physics engine, not just Havok. I strongly recommend you do not do this to the physics - simulate physics with a fixed coordinate system and transform the coordinates wherever your application needs to present them.

3 Likes

Thanks for the answer!
Does setTimestep switches havok to deterministic timestep because this is still jittering with a timestep of 0.016: https://playground.babylonjs.com/#Z8HTUN#661 ?

Transforming the scene only at render time makes perfect sense, I made this for now https://playground.babylonjs.com/#Z8HTUN#663 which does not work yet but I will go back at it tomorrow

1 Like

Okay so I worked some more on moving everything to the origin only for rendering but I get this strange result: https://playground.babylonjs.com/#Z8HTUN#664

The physics is working as expected but for reasons I don’t understand the babylon mesh stays still…

When I change spherePosition = sphereAggregate.transformNode.getAbsolutePosition() to spherePosition = sphereAggregate.body.getObjectCenterWorld() I get a different result: https://playground.babylonjs.com/#Z8HTUN#665. Shouldn’t they be the same thing?

In that scene, you’re teleporting the objects twice, so you’re going to have exactly the same performance and behaviour problems with the original. I’d recommend either using a physics-only scene and transforming the objects or managing the physics objects directly via the IPhysicsEngine (have not tried this, so might be tricky)

3 Likes

If I understand correctly, teleporting an object then rendering the scene then translating it back in its original position leads to performance issues because Havok performs continuous collision detection.
I know this might sound a little ugly, but is there a way to make havok forget about the 2 last translations of the object as they perfectly cancel each other? It would remove the performance issue while keeping the rendered object at the origin.

I am not sure about what you mean by “transforming” the objects. My understanding was that by teleporting back the object in their original position I would achieve “physics-only and transforming the objects”.