Optimizing physics

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:

2 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

4 Likes

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

3 Likes

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

3 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

2 Likes

Some notes on rust:
wasm bindgen is similar to emscripten in that its not required, and imo should be avoided if possible. Wasm bindgen renames functions similar to emscripten, except that it changes snake case rust to something else. You can avoid using the #[wasm-bindgen] macro by using #[no_mangle] instead. Note, #[wasm-bindgen] could be useful to rename functions for use in a babylon physics plugin if certain functions already matched the methods parameters. The syntax is something like #[wasm-bindgen(“FunctionNameHere”)] .

To use the cargo cli directly (as opposed to the wasm-pack cli) similar to clang/zig/dlang , you can do so via the cli with “cargo build --release --target=wasm32-unknown-unknown” . You can also use wasm32-wasi or wasm32-unknown-emscripten as targets, but that is rare to see.

wasm-opt is a wasm postprocessor used by wasm-pack and binaryian. wasm-opt prioritizes code size instead of performance, which doesnt make sense to me, considering wasm parsing time is so f’ing fast. It also will error if you enable simd, which in my mind, makes it useless. There is some useful tree shaking that wasm-opt does but i havnt looked at how to enable that while disabling perf deopt. getting autovec to work is the number 1 priority imo. the wasm-pack cli uses wasm-opt by default, and figuring out how to disable it is not clear at all, so let me save you an hour of googling. add this to your cargo.toml .

[package.metadata.wasm-pack.profile.release]
wasm-opt = false

[package.metadata.wasm-pack.profile.dev]
wasm-opt = false