three.js through and through
Give it a mesh and it works out the body's mass, inertia and colliders from the geometry. Bodies move their meshes, interpolated between fixed steps, and instanced meshes are bodies too.
Bodies
Bodies built from your meshes, joints with drives and limits, an accurate solver that sleeps what's at rest, and plugins for the sea, sails, cars and triangle meshes.
Faster than cannon-es where real scenes spend their time, and right where cannon-es is wrong.
It gets the physics right. Stacks stand, boxes slide down slopes at the textbook acceleration, balls bounce to the height their restitution says, and a rock's inertia is integrated from its hull, not guessed from its bounding box. It's fast where it counts: real scenes are mostly at rest, and a city full of props costs a thirtieth of cannon-es's; with a crowd of ragdolls all awake and walking it is still the faster of the two. And it's three.js through and through: give it a mesh and it works out the body.
The same scenes in both engines, at 60 steps a second, with the same masses, friction and sleep thresholds; each keeps its own solver defaults. Milliseconds of computing per simulated second on a Ryzen 5 4600H, lower is better.
| Scene | eulerjs | cannon-es | |
|---|---|---|---|
| 125 boxes settled | 5 ms | 204 ms | eulerjs 41× faster |
| 64 rocks (42-corner hulls) | 59 ms | 6093 ms | eulerjs 103× faster |
| Mixed pile: 400 boxes, balls, cylinders and rocks | 447 ms | 8125 ms | eulerjs 18.2× faster |
| Pyramid of 1,015 boxes | 3156 ms | 10864 ms | eulerjs 3.4× faster |
| 125 boxes falling into a pile | 94 ms | 216 ms | eulerjs 2.3× faster |
| 400 spheres, never sleeping | 76 ms | 101 ms | eulerjs 1.3× faster |
| The city at rest | 4 ms | 120 ms | eulerjs 30× faster |
| The city, 25 ragdolls walking | 282 ms | 629 ms | eulerjs 2.2× faster |
| The city, 100 ragdolls walking | 1261 ms | 2670 ms | eulerjs 2.1× faster |
| Accuracy | eulerjs | cannon-es |
|---|---|---|
| 8-box stack kept awake, top's furthest move in 60 s | 2.5 mm | 9.5 m (falls) |
| Box sliding down a slope, acceleration error | 0.0% | −100% (stuck) |
| Ball bounced from 3 m, height error | −1.8% | +21.6% |
| A rock's moment of inertia (9.14 is right) | 9.14 | 66.7 |
| A box resting on the ground, how far it sinks | 0.07 mm | 0.00 mm |
Every number comes from npm run bench in the repository; the performance guide has all of them, and what cannon-es does better.
import { BoxGeometry, Mesh, MeshStandardMaterial } from 'three';
import { World } from '@eulerjs/core';
const world = new World();
// the ground, and a crate dropped on it: mass from the meshes, and boxes fitted round them to collide as
const ground = new Mesh(new BoxGeometry(20, 1, 20), new MeshStandardMaterial());
ground.position.y = -0.5;
world.addBody(ground, { type: 'static', collider: 'box' });
const crate = new Mesh(new BoxGeometry(1, 1, 1), new MeshStandardMaterial({ color: 0xd08770 }));
crate.position.y = 4;
world.addBody(crate, { density: 500, collider: 'box' });
renderer.setAnimationLoop(() => {
// fixed steps for the time gone, then the meshes moved to their bodies
world.update(timer.getDelta());
renderer.render(scene, camera);
});