Preferred physics engine (cannon.js, ammo.js, DIY...)

Hi All,

Do you have a preferred physics engine? I’m planning to use one for a project I’m starting, but having never used one with Three.js before, I wanted to learn from the masters to hear what they’ve found best.

I’m basically building a very simple platformer-style microgame in which the character can also fly, in case that helps the decision.

Either way, I’d be curious to hear what others think about using a framework like cannon.js or ammo.js vs rolling your own physics. Any tips from experience are very welcome!

Doug

4 Likes

I think it boils down to personal preference in coding style.

I’ve been using cannon for a bit but found that - no matter which engine you use - if you do everything on the main thread (not using workers), it’ll burn your performance quite a bit.

Only consider building your own physics engine if you want really simple stuff (no real physics). Otherwise you’ll go down an endless rabbit hole when you’re writing your solver… Trust me, I’ve been down that road (because I always want to build things myself) and ended up using cannon from a worker (threading) :stuck_out_tongue:

3 Likes

@Harold Do you have an example of “using cannon from a worker”? It’d be super helpful!

2 Likes

Here’s an example using cannonjs in a web worker: https://github.com/schteppe/cannon.js/blob/master/examples/worker.html

The gist is that the worker writes all of the objects’ positions and rotations into a (Float32Array) array and sends array.buffer back to the main thread on each frame. If you have interactive elements (like VR controllers) this becomes a tradeoff, as collisions won’t feel as snappy when physics aren’t synced to VR rendering unless you use some tricks to update earlier. In my opinion the worker only becomes necessary when you have enough objects being simulated that it cuts into your FPS.

I’ve used CannonJS — it’s probably the best documented, which makes it easier to get started with, but isn’t maintained these days. AmmoJS is compiled from the classic Bullet engine, so that’s fully featured and stable, but quite a large library. Oimo.js is also worth a look, although I haven’t tried it.

12 Likes

I happen to be one of the crazy ones that went down the rabbit hole, and to be honest I think I like it here.

I tried out a few other implementations in my FPS, physx and cannon mainly. Cannon worked well for me, it was pretty snappy and looked really realistic, but it’s actually too realistic in that it becomes impossible to easily allow objects to move arbitrarily without constantly changing the physics. The gameplay in my FPS depends on quick fun movements so I had to throw it out.

It took me a good month just to work out the static mesh collision, and it works with moving objects too (I didn’t bother to implement angular momentum though), but it’s solid and quick, and better still I did it almost exclusively with three.js helper functions. Mr. Doob and friends supply almost all of the optimized code.

Was it worth the time it took me to figure out? Absolutely. It feels really good to have a custom engine that does exactly what you need it to do and nothing more, and because I had to understand it intimately to get it running, I have more power to bend it if I have to to be able to do other things, too.

2 Likes

Can you expand on that?

Gonna open source it? :smiley:

Can you expand on that?

Physics engines keep track (and manage) of object position, rotation, etc. If you want to change these manually, it’s usually quite a hassle to update them by hand. You’ll also have to tell whatever engine you’re using to reset things like velocity for the object you want to change the properties of.

2 Likes

I’ve also implemented a sliding-sphere collision, basically this kind of pseudo-physics is used by most games. It’s very fast on big geometries without threads, since it only deals with input velocity per frame, and solves the position with colliding faces.

While i’m mostly familiar with ammo/bullet, it’s seems demanding and the emsripten port using pointer objects doesn’t appear like very memory efficient, it makes it hard to do proper object pooling, but it’s very extensive and more solid/faster than some other engines.

I’ve been looking around for an engine I could use in future projects, and have found a few options that I thought I should share:

Possibly outdated libraries

If anybody has any additional suggestions for a simple box-collision engine, I’d appreciate other options!

21 Likes

Soo lots of comments here.

In general its safe to assume that rudimentary physics use is going to expand over time, the main reason I went with Physijs, it handles all of my needs so far.

Really it’s no issue to make position/rotation etc changes, Physijs allows for movement impulse forces etc, manually changing the actual values simply requires you to set dirty flags, not a real issue to me.

Physijs uses ammo (I think) I got an improved version from err whitehorse/whitestone framework??

Stuffs only outdated when it doesn’t do what you want :slight_smile:

Oimo seems cool, have fun finding user doc. I have looked at it code and its nothing like I write, not judging just different. Without user doc determining from code is an issue for me.

Physijs worker performance is not an issue at the moment. My current setup has multiple animated gltf models, moving with a steering behavior system, shooting balls, with particle explosions, etc. I run at 60 fps render and physics. I limit myself to going no faster at the moment. Some physics lets the system move shapes and some I manually adjust, realtime.

Even though Physijs does not use buffered geometry, doesn’t threejs convert on its own??

cannon has a maintained version again

6 Likes

enable3d/ammo-on-nodejs does not work on browser with Browserify (I just do not want to install babel and webpack, i use const CANNON = require("cannon");, not import). I wanted to use ammo.js with pure WebGL and for server side. But the idea with enable3d/ammo-on-nodejs was great because I study Bullet with C++ too. For developers of this module: remove Three.js and allow it works on server/client side with Browserify like Cannon.js. People will be able to use it with pure WebGL and with another 3D engines. For now only Cannon.js works fine for me. “cannon-es” does not have the “CDN” like aimo.js. I need CDN to publish on Sandboxes like Plunker.

I try to build “ammo.js” on client side using this command: npm run build

image

  "scripts": {
    "clear": "del /f /q /s .\\public\\js\\*.*",
    "del-bundle": "del /f /q /s .\\src\\bundle.js",
    "bundle-debug": "browserify --debug src/main.js -o public/js/bundle.js",
    "bundle-release": "browserify src/main.js -o src/bundle.js",
    "uglify": "uglifyjs src/bundle.js -o public/js/bundle.min.js",
    "debug": "npm run bundle-debug",
    "release": "npm run clear && npm run bundle-release && npm run uglify && npm run del-bundle"
  },

image

const { Ammo } = require('@enable3d/ammo-on-nodejs');

window.onload = () =>
{
    Ammo().then(start);

    function start() {
        console.log("start");
        setupPhysicsWorld();
    };

    function setupPhysicsWorld() {
        console.log("setupPhysicsWorld");
    }
};

See Ammo is not a function (headless mode v20) · Issue #60 · enable3d/enable3d · GitHub

Not sure what you mean by that:

  • @enable3d/ammo-physics is designed to run in browsers.
  • @enable3d/ammo-on-nodejs extends @enable3d/ammo-physics and is designed to run on node.js.

It only includes three.js because it uses its FBXLoader and GLTFLoader.

btw, version 21 (0.21.0) will become availabe at the end on next week

1 Like

I found a solution how to use Ammo.js with Browserify:

npm install kripken/ammo.js

main.js

const Ammo = require("ammo.js");

let physicsWorld = null;

function main()
{
    Ammo().then(start);

    function start(Ammo)
    {
        console.log("start");
        setupPhysicsWorld(Ammo);
        console.log("gravity =", physicsWorld.getGravity().y());
    }

    function setupPhysicsWorld(Ammo)
    {
        let collisionConfiguration = new Ammo.btDefaultCollisionConfiguration(),
            dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration),
            overlappingPairCache = new Ammo.btDbvtBroadphase(),
            solver = new Ammo.btSequentialImpulseConstraintSolver();

        physicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
        physicsWorld.setGravity(new Ammo.btVector3(0, -10, 0));
    }
}

window.onload = main();

For example you have this project structure:

public/index.html
public/js
src/client/main.js
src/server

Install Browserify and UglifyJS globally:

npm i browserify uglify-js -g

You can add this commands in package.json for release and debug modes:

  "scripts": {
    "clear": "del /f /q /s .\\public\\js\\*.*",
    "del-bundle": "del /f /q /s .\\src\\bundle.js",
    "bundle-debug": "browserify --debug src/client/main.js -o public/js/bundle.js",
    "bundle-release": "browserify src/client/main.js -o src/client/bundle.js",
    "uglify": "uglifyjs src/client/bundle.js -o public/js/bundle.min.js",
    "debug": "npm run bundle-debug",
    "release": "npm run clear && npm run bundle-release && npm run uglify && npm run del-bundle"
  },
npm run debug
npm run release

bundle.js and bundle.min.js will be generated. Comment/Uncomment recently lines in index.html for debug and release:

    <script src="js/bundle.js"></script>
    <!-- <script src="js/bundle.min.js"></script> -->

Usage of Ammo.js with TypeScript (Ammo.js is a port of Bullet Physics Engine)
Usage of Planck.js with TypeScript (Planck.js is a port of Box2D Physics Engine)

1 Like

I know this is a bit less complex than much discussed here, but for quick and clean collision solutions, I’ve been using three.js’s box3.
Low overhead!

1 Like

Rapier physics engine | Rapier looks really interesting - much clearer documentation than most of the alternatives, both 2d and 3d support, WASM support with JavaScript bindings. Relatively new, but has promise.

Unfortunately I can’t seem to get it to actually run, webpack is complaining about the wasm file and I am not sure what’s the right loader I should install for something like this.

And for those hardy souls willing to write their own, there’s always Real-Time Collision Detection (r-5.org)

3 Likes