How to obtain stable results of collision detection?

Hey~All, recently I started using ammojs. I met a strange thing.
Our Dancer can’t always stand on the hexagonal floor.
I mean, sometimes it goes straight through the floor or falls into the floor.
This phenomenon is not always repeated, so you need to press Run several times to observe it.
pg: https://playground.babylonjs.com/#QANVC6#2158

Hi musk,

I think what’s going on here is that your cube impostor is so small that it’s completely passing through the floor collider within a single fixed timestep.

(Warning: I’m not an expert on Ammo.js, so please take the following explanation as sort of a general conceptual overview, as Bullet’s implementation might be different. :slightly_smiling_face:) To explain this a little more, a common way of simulating physics is to examine collision states at discrete points in time – for example, for a 60 FPS app, at frame times such as 0ms and 16ms. You simply look at the state of the physics simulation at such discrete time points, check whether any two things intersect that should collide, and deal with the collision if they do. This works very well in most situations; however, it has a flaw if your scene includes things that move fast relative to their size. For example, if I have imposters in my scene that can move 10 meters per second (roughly fall speed after 1 second of falling), then those imposters can travel up to 16cm in a single simulation frame. If an imposter is larger than 16cm, this is no problem. If the imposter is smaller than 16cm, however, then it’s possible for the imposter to for neither of the positions to actually intersect a given plane the imposter’s supposed to be colliding with. For example, if falling to a plane at y=0, the object’s centroid (from which it protrudes 5cm on either side) could be at 6cm on frame 0, its bottom edge a comfortable 1cm above the floor, and then at -10cm on frame 1, with its top edge already 4cm below the floor. The simulation will note that neither of these frames contain any overlap, so it will conclude that no collision took place and the falling imposter will simply appear to pass through the floor imposter. This, I think, is almost exactly what’s happening in your Playground.

I know of two ways to directly observe this and overcome it, depending on what you need. The easiest way to address this is to just make the falling collider larger (or slower). If you change the cube’s size or falling height so that the ratio of velocity to scale is smaller, you should see the simulation become much more consistent.

If you really need something this small to move this fast, however, you can adjust the way Ammo.js is simulating the physics like this:

Cylinder Mesh | Babylon.js Playground (babylonjs.com)

The lines I’ve added here (4 and 5) change the “fixed time step” at which Ammo simulates the physics. Circling back to the above example, most physics engines that simulate discrete time steps don’t actually use render frames because rendering framerate can be unpredictable and isn’t easily tweaked. Instead, physics engines will have their own “fixed time step” interval at which they will evaluate the physics simulation which allows them to evaluate “intermediate frames” in order to detect collisions between smaller physics objects. The smaller this “fixed time step” interval is, the more work the physics engine has to do, but the more precisely it will be able to detect collisions between small imposters. Generally speaking, I don’t recommend messing with this value if you can avoid it – it doesn’t actually solve the problem and allow you to go arbitrarily fast, just “raises the speed limit” on how fast things can go relative to their size – but if you have a very specific scenario where your objects have to be small and have to move fast, this is a way to make that scenario simulate more reliably.

Hope this helps, and best of luck!

3 Likes

Thank you for explaining the principle behind this. It’s very helpful. I solved it with the first solution :kissing_heart: