Optimizing physics

Hi everyone!

Once again a bit broad question about physics and optimizing. I’ve noticed that, surprise surprise, a large quantity of primitive physics shapes drag down the performance quite a bit. One of the curious things is that the objects are actually just not moving at all. Are there any checks or anything that the physics objects are resting and should not be updated? Like if there is no movement or there is no force that interacts with the object in question?

It is also a bit hard to actually know what is happening in the Ammo engine, since it is pretty obfuscated :smiley:

What is a “large quantity”?
The RigidBodies have a sleep timer and a threshold. When a body’s linear- and angular velocities get below this threshold, the body goes to sleep, and is dormant. If you then apply an impulse, collide with the body or something else that changes the velocities to again get over this threshold, the body wakes up.
When at sleep, the body only needs to check the velocities, as opposed to an active body having to apply forces, integrate velocities, update its position in the broadphase, find potential collisions in the broadphase, create/update/remove itself in the pair cache, check collisions in the narrowphase and then solve velocity-, position- and all other constraints.
Having hundreds of sleeping bodies shouldn’t affect performance, as it essentially just skips most loops of the engine.

2 Likes

For large quantities I was thinking of 100+ physics objects :slight_smile: I’m running the babylon/physics engine on the server side so the client doesn’t have to do anything but render the objects…

Here is a playground with many objects being spawned and the framerate starts to sink a bit: https://playground.babylonjs.com/#S7E00P#143

As you can see, the performance starts to degrade and doesn’t really settle down even if you wait for the objects to “go to sleep” :grin: This is more evident if you check the profiling tools in the chrome tab:

The physics engine seems to take more and more of the frame time if we add more objects (surprise there). Is there any way to debug and see what is taking time? When you go too deep into the rabbit hole and go into the Ammo.js source you kind of have no idea what is happening… :sweat_smile: At least I don’t haha.

And also is there a way to check the sleep thresholds? Or to change them?

If you zoom in, the barrels are clearly not put to sleep.
I tried both setActivationState(1,2,3,4,5) and setSleepingThresholds(l, a) directly on the physicsBody.
Setting the activation state to five, disables the simulation as it rightfully should. There seems to be either a bug or missing feature in AmmoJS itself, as setting the sleeping threshold does nothing. These are simple floats I set directly on the body, so I assume this is an issue with the Bullet port, rather than the BabylonJS plugin implementation. Hmm. I haven’t really played around with AmmoJS for a while, so I can’t really say whether this is an issue with the current transpiled version used in the playground, or if it’s in the original as well.

1 Like

Hmmm, well it is a pretty nasty bug if it resides in the Ammo library… Yikes :sweat_smile: I wonder if the shape is also problematic, or does this happen with boxes as well :thinking:

A bit worried about the physics scene in Babylon, since we are using pretty old and pretty unmaintained repositories… Has anyone looked into integrating something like, for example, Rapier (Getting started | Rapier), which is a Rust based physics engine, that works via webassembly?

1 Like

AmmoJS is certainly a pain, and when I used it, I used a local copy in order to add missing features etc.
There are three physics plugins currently, so if you have time, I don’t think anyone minds you using those as templates to integrate Rapier into BabylonJS :stuck_out_tongue:

1 Like

Would be pretty cool to try to do it, a bit afraid that I have to spend a lot of time understanding what is going under the hood… Might like to consult some pros like you and @Cedric if it is even feasible to do :slight_smile: Would be cool though to have a physics engine that is being maintained properly :laughing:

Currently I am afraid that the current physics engines will not hold up in my multiplayer game if people somehow manage to spawn a lot of physics objects… :grimacing:

1 Like

Wow, I hadn’t seen that engine before. Looks very good indeed :+1:

1 Like

Hi. Main problem with ammo engine its mesh impostor. Try change your impostor type to cylinder Using A Physics Engine | Babylon.js Documentation

1 Like

I could try this, I’ve been planning on testing the creation of primitives in Blender and then just automatically using that in Babylon. For example, I could have a primitive physics collider shape called “collider_box” under the root node of my model, and then have some logic to use that as the box collider. :thinking: Similarly could have like “collider_mesh” to use the mesh impostor for that collider and code to parse out what collider to use if there is one defined. Otherwise it would default to meshImpostor though… :sweat:

But I think the real problem is still the mesh impostor, since I have to use it for some complex shapes… I want to use primitives when I can, but sometimes that is just not enough.

Need a bit of help here with the creation of impostors, trying to see if I can model the colliders in Blender and easily assign them to the primitive colliders in Babylon code… I have this kind of structure for my soda can model now:
image

As you can see, I created two colliders for testing purposes: collider-cube and collider-cylinder. Now, what I want to do is use those as impostors for the main model, which is the Cylinder.

The following playground kind of works, when I search the glb root for children named ‘collider-cube’ for example and the physics objects are kind of created but it doesn’t quite work :smiley:

It kind of seems that the actual model is left out of the party! :frowning: What is the correct workflow for this, without breaking the glb model structure tree, meaning that the structure is the following:
image

Have you iterated through the GLB meshes to create and parent your collider impostor to the root (which should have an impostor type of NoImpostor)?

1 Like

Yeah, this kind of works but it seems the colliders have had too much caffeine :laughing:
Physics yo | Babylon.js Playground (babylonjs.com)
I doubt the cans are resting that much now… I wonder what the problem is though :thinking:

Manual convex decomposition, or creating simplified shapes out of primitives is certainly the most performing way of doing it, but as I said, your dynamic cans are not using a MeshImpostor, but an algorithm to turn the vertices of your mesh into a convex hull shape. You’ll certainly be able to squeeze out more performance by creating these shapes manually and as simple as possible, but this is still not the main issue. The main issue is, that resting bodies without any kind of interaction or external force applied to them, simply do not sleep as they are supposed to:

2 Likes

Decomposing mesh into simpler collision volume is better for CPU and memory. It’s a good idea to use cylinder/box impostors instead of mesh impostor.

I took a look at the Physics yo | Babylon.js Playground (babylonjs.com) and it seems like there is (mostly) always a bit of penetration of cans into the ground mesh. which implies a collision response (with a bit of jittering/shaking). I guess that’s why the bodies never go to sleep.

On my PC, physics simulation with all cans takes 8ms per frame with cans as mesh impostor, 4 with box collider and 3ms when replacing the roomMesh with only a plane impostor.

With a plane impostor, bodies stop moving after some time. Can you replace the room mesh with simpler colliders as well?

When every body will go to sleep, ammojs physics solving will be faster but there will be iterations on bodies. I think 100s or 1000s of sleeping bodies will take some time to solve anyways, every frame.

I don’t know your complete use case but maybe if a body is not meant to move for a very long time, replacing it with a static body (mass = 0) might help. It’s a matter of amortizing the cost of switching Vs cost of resolution each frame.

1 Like

Might have to look into that… My use case is pretty much that I want all the smaller objects in my game to be physics objects. Think of any inventory items you might carry or like the loot in diablo games that drop to the ground. So there is a possibility for large amount of simultaneous objects.

I see I see… I’ve already been thinking of making a workflow using simple shapes in Blender and then using those colliders in Babylon. Of course I don’t want to do this for really complex shapes, since I want only one collider per 3d model. If it is very complex, I would prefer to use a simplified mesh collider I’ve created in Blender.

This is a tricky one… The room mesh in my game is just a one big mesh stitched out of smaller ones as seen in the https://playground.babylonjs.com/#S7E00P#149 example… I could probably use a primitive for the ground, as in have a semi infinite floor for the whole area. But for walls, I’d like to stick to mesh impostor since they can be pretty much any shape.

You are correct sir, the cans do sleep when using the plane impostor :slight_smile: : https://playground.babylonjs.com/#S7E00P#161

1 Like

After several minutes of running, the cans have not come to rest for me?
They don’t move by a lot, but if I zoom in, they very clearly drift. Less noticeable than with a MeshImpostor, but certainly not at sleep.

1 Like

Ugh, you seem to be right :sweat: If I stare the cans intensively really close by, I can see that they seem to drift very slowly… And sometimes they even twitch like the cylinder did in other thread: https://playground.babylonjs.com/#BEFOO#1434

What could be done to fix this? It is a really nasty problem since the physics simulations should hold up a long time in a game environment and be trusted that they do not fall through ground because of twitching… And generally to maintain good performance :thinking:

Should I open a ticket in github or make a separate thread in bugs section?