Optimizing physics

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.

2 Likes

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?

Hmm. Here’s a recreation of my simple box example, using native AmmoJS calls:

The box goes to sleep after the (I believe) default 3 second sleep timer

1 Like

I found a pg prepared that shows the problem, i think.

(settings related to this comment)
scene.getPhysicsEngine().setSubTimeStep(5);
scene.getPhysicsEngine().setGravity(new Babylon.Vector(0,-1,0);

For this first example, it seems like it could be considered a bug in babylon, it’s just a bad default value though. It could be that setting the default value to 1 would cause buggy behavior elsewhere. In the second example with the cylinder on the ground.

see line 15:

scene.getPhysicsEngine().setSubTimeStep(8);

Now, try commenting it out out and change the values around.
(note) commenting it out is the default babylon behavior (perhaps should be changed).

try each of these and replay:

//scene.getPhysicsEngine().setSubTimeStep(8);
scene.getPhysicsEngine().setSubTimeStep(1);
scene.getPhysicsEngine().setSubTimeStep(0.1);

The behavior when you comment out line 15 is buggy and inconsistent. It seems setting this value to some value but greater than 0 by default could fix some issues for falling objects. It doesn’t help for rolling objects though (see ex below)

@Panuchka

I made the same changes to your pg, using 5 as a default value seems pretty good. But, thats mainly because it doesn’t fall over.

i added a timeout to modify setting the settings after 5 seconds to show the difference here. It still doesnt settle though. It starts to behave nicely, but then it’s like there is some constant acceleration and vibration that leads to catastrophic resonance. is there some damping setting? maybe that could stop it going apeshit after like 30 seconds.

setting the timestamp to 1 in the settimeout callback in this example caused a halo-like super jump. I googled about that, and it said its caused by the player (cylinder here) falling through the level and the engine applying a a very strong impulse to counter-act it. maybe something similar is happening?

related:

1 Like

Things are looking a bit grim it seems… No good to have an engine with some bugs that can’t be fixed :frowning: Also it seems that Ammo.js has been a bit abandoned so… Time to invest creating that RapierPlugin for Babylon? :smiley:

3 Likes

As far as I’ve seen Rapier could be the best alternative.

2 Likes

@Cedric and @RaananW, I guess we should dig into this ? this is so sad Physix engines gets abandoned like this :frowning:

cc @Deltakosh

5 Likes

A Rapier plugin could be a very nice addition, I agree

3 Likes

GitHub - jeremy-coleman/babylon-rapier-plugin . lul

4 Likes

From your comment:
“ these 4 methods were in the 10 mandatory methods stated in the docs but not present in the IPhysicsEnginePlugin interface”

I recall following the docs when I made a Babylon physics plugin a few months ago and it was failing at run time when I used the scene inspector. The docs seem to apply from a while ago, but I suppose few venture into that area. I meant to update the docs and didn’t. All the notes were on my old computer that I wiped! Anyway, if you get further along make sure to turn physics debug on in scene explorer!!

4 Likes

Before going further with rust, I would really like some opinions on something like this glsl implementation from u guys with bigger brains than mine, especially @Cedric @Evgeni_Popov

It works and the demos work, with seemingly minimal three related code, unless there is three specific uniforms in the glsl code, idk, i am still a cg padewon and dont know what is built in to glsl or not. I also dont know how to properly assess performance, the latency and number of calls between gpu vs cpu clone vs cpu atomics, what can and cant feasibly run in parallel under the bjs engine, etc.

2 Likes

I have no strong opinion as I’ve never worked on GPU physics but some highlights/questions:

  • Does it work on mobile? (readme says only desktop pc)
  • It needs another impl for webgpu (with compute shaders?)
  • it looks like it supports only ‘simple’ primitives: cube, capsule. How do you handle triangle meshes?
  • does it support joints?
  • does is support soft bodies?

I think GPU physics engine are possible for simple (and massive) things. like 10000s of box collision is doable but a single ragdoll falling on a mesh might be way more difficult.
Moreover, the devil is in the details. Physics engine like Bullet Physics, Cannon,… takes years of work to make it behave properly. Starting something like this means years of work for optimization and consistent results.

6 Likes

Those are all very good questions. BTW it’s written by the author of cannon. For desktop pc only, I’m not sure if that’s actually true. I think that’s really a question of how well angle / dawn translates glsl to integrated graphics / cpu. I make the same assumptions for gpu physics, good for lots of objects that don’t change shape, otherwise cpu will run faster. (why falling box examples are dumb - they just tell you which impl is using gpu physics aka unity). I think some compilers can automatically split things between a cpu and gpu impl. BJS could maybe do something similar at runtime since its javascript. I was hoping mr popov would have some insights on if compute shaders could further improve stuff. I know its a stretch goal, but at the same time, maintaining shaders seems like a lot less hassle than ammo etc.

emscripten is so janky, and rust’s wasm ecosystem is pretty bad too. you can’t use wasm bindgen to interop with c code. You can use emscripten backend with rust, but emscripten is the nightmare id really like avoid. With rust, you can also use a wasi backend, but that whole ecosystem is full of people trying to appropriate wasi to edge computing. I’ve tried zig, dlang, and tinygo too. Dlang has a good llvm backend now, it’s pretty nice to use, and has a package manger. I’d say it’s been the best experience so far. Zig is nice, but the last 3 releases i’ve seen decreased stability. The devs are also hipsters and do stuff like refuse to account for windows style newlines. With zig, I’ve had to use the zig compiler to just create object files then use llvm manually to output wasm… not ideal lol. Zig has a good feature though that you can define arbitrarily sized integers (like a u3 or something). It’s also pretty readable for most people. dlang is really nice in that you can basically do an iife callback to link javascript code. like you basically do function(window){ … can reference window here and it just works }. Sadly, zig is trying to self host the compiler instead of sticking to llvm, which is a tragic mistake i think. The main point is that maintaing wasm code sucks, and if we can do it in shaders instead , that might be a godsend.

I agree about not throwing away the years of work of libs like Bullet or physx in lieu of something relatively new like rapier. I kind of realized, the issue isnt with bullet (ammo), its with the build system. Rust solves this , but so does zig/dlang because they can cross compile. I think it’s also an important point that developing with bullet or physx , you get to use apis that are ubiquitous and used from a bouncing ball on the web through billion dollar AAA games. Thats good for newcomers like me and its good for experienced experts contributing back knowledge to bjs, which seems like all you guys on the bjs team and some members on this forum.

For building, one thought i had, was to possibly use the dotnet build tools instead of docker or the emscripten cli to use emscripten. Docker is the only way i can run emscripten and it just doesn’t seem like the best fit for an open source javascript library. Here is a link to a c# script that defines an emscripten task, i just have no experience with c#, or dotnet. runtime/EmccCompile.cs at main · dotnet/runtime · GitHub
you can also do “dotnet workload install wasm-tools”, which installs correctly, but then what?
How can I to compile an add.c to wasm using the dotnet emscripten task instead of the emscripten cli?

Sorry for overly long ramble, i guess the TLDR is that i think it’s better to
explore gpu physics and fix the bullet build first. If that fails, try physx. Finally, move forward with rapier.

[one other thing]
perhaps collision / gravity on gpu and joints/softbodies on cpu (or some other mix)?. Would it be possible to take the cannon plugin and incrementally overwrite methods on the prototype with gpu implementations? Also, how difficult is this stuff for you guys with years of cg experience?

Also, physx seems to be a thing for the web now.
Amazon uses it sumerian host and its also in lumberyard , nvidia is still doing stuff with it, they have omniverse apps etc. I actually would personally prefer to use physx over bullet for my own self development, but that doesnt and shouldnt matter unless many others feel that way too

here is a demo using physx on the web with ragdolls
https://fabmax.github.io/kool/kool-js/?demo=phys-ragdoll

3 Likes

Physx is IMHO the best physics engine available. I’d rather on it port and maintenance. In the long term, it has to be maintain by a team. I’ve only seen individuals doing it so far.

5 Likes

apparently amazon has a PR on the physx repo to add some emscripten wrappers. They have some marketing material for physx in sumerian host. Im guessing Amazon probably has a lot of people familiar with physx, judging by how integrated it is into o3de. Idk if u guys have a working relationship with them or not.

this is the PR:

it seems to be just this one file for bindings. .PhysX/PxWebBindings.cpp at emscripten · prestomation/PhysX · GitHub

and adding an emscripten target in the python cmake script
.PhysX/cmake_generate_projects.py at a9dd37cb331cfd2967954b3fc7041112af96e501 · prestomation/PhysX · GitHub

also cocos seems to be maintaing something

Maybe we could get a web version of havok? satya pls :pray:

emscripten/clang notes:
emscripten isn’t strictly required. emscripten basically shims system libraries and then prepends an underscore to function names, then throws in a mile of javascript to rename all the functions back. not ideal. A lot of the purported functionality of emscripten is actually just llvm. Emscripten does have a plugin system though, which like 3 people on the planet know how to use, but still its there.

here is an example of a clang only wasm setup , it was the first result when i searched for wasm clang. it works great. git clone to a triangle in my browser in less than 10 seconds. That might require some code changes instead of cmake changes though. Again, zig and dlang can be nice to use here because they both have llvm backends. I mean using them as compilers, not the language btw.

if you notice the clang script has ‘-Wl,–export-all’ , which allows you to basically avoid all the javascript glue code - thats the part that ensures all the functions are on the export object. You can just import a .wasm file like you’re supposed to, and the function names will be available on the import object. easy peasy. I could imagine that limits some llvm optimizations. I was trying to improve auto vectorization with little success.

here were my commands:
clang++ --target=wasm32 -std=c++17 -nostdlib -fno-math-errno -fsave-optimization-record -fno-exceptions -ffreestanding -msimd128 -matomics -mbulk-memory ‘-Wl,–no-entry’ ‘-Wl,–export-all’ ‘-Wl,–allow-undefined’ -O3 -ffast-math

-fsave-optimization-record will print a yaml file of the llvm autovec results, which does 2 passes. 1 for loops and 1 for arrays. I can barely console log anything in cpp, so i just use a vscode addon that converts .wasm to .wat and i look for wasm simd-specific intrinsics in addition to the yaml files.

sidenote:
Yesterday , I discovered the webpack plugin for building rust has a pretty significant bug that makes it unusable with multiple crates / cargo workspaces. Not really a huge deal , because its not really needed in the first place tbh, but, worth putting down in words for others to see

3 Likes