This video was captured on an i9-13900K
try it your self: bullet-wasm (bullet-rust-wasm.netlify.app)
The number of rigidbodies will vary depending on CPU performance.
Introduction
Physics simulation is one of the biggest performance bottlenecks in web 3D applications.
Generally, physics engines running in modern browsers are all compiled to WebAssembly, and the WebAssembly modules are used from the JavaScript side.
I’ve analyzed this approach and considered which areas could be improved to eliminate performance bottlenecks:
1. Frequent calls to wasm functions from JavaScript
The number of wasm function calls can be drastically reduced by directly accessing specific parts of the WebAssembly instance memory from JavaScript,
ammo.js needs to read the transform values of btDefaultMotionState
after each simulation step. If there are 100 rigidbodies in the simulation, this means that the wasm function must be called at least 100 times from JavaScript.
By accessing WebAssembly.Memory
and reading it with a TypedArray, it would be possible to run the simulation with ideally only one wasm function call per frame.
2. Threading in wasm could enable larger simulations
The threading approach here refers to simultaneously simulating multiple independent physics worlds.
Some games/applications don’t require perfect collision handling for all objects.
In such cases, parallel processing of multiple physics worlds is very useful.
Using WebAssembly, we can write traditional thread-based programs more easily than using JavaScript workers and SharedArrayBuffer directly.
The demo above shows 24 physics worlds being processed in parallel using rayon-rs’s thread pool.
So, what does this project do?
This project compiles Bullet Physics to WebAssembly.
However, unlike ammo.js, it statically links Bullet Physics into a Rust project using wasm-bindgen.
By using Rust, we can easily handle multithreading with rayon-rs.
I simplified the Bullet Physics API as much as possible in Rust and exported it, allowing the physics engine to be used in JavaScript with minimal wasm function calls.
Unfortunately, I don’t have the time to develop this demo into library, and I’m not sure how many people actually want something like this. However, I hope that sharing this idea with the Babylon.js community will be meaningful.
Here is all the source code: