JavaScript Physics Engines Comparison 2026 — Cannon-es, Rapier, Ammo.js, OimoPhysics
Choosing a physics engine for a Three.js project involves trade-offs between bundle size, simulation quality, WASM startup latency, API ergonomics, and constraint support. This reference covers the four most-used options plus emerging alternatives, with code snippets showing the minimal integration for each.
1. Feature Comparison Table
| Feature | Cannon-es | Rapier.jsWASM | Ammo.jsWASM | OimoPhysics |
|---|---|---|---|---|
| Language | TypeScript | Rust → WASM | C++ Bullet → WASM | JavaScript |
| Bundle size (gzip) | ~55 KB | ~180 KB | ~750 KB | ~45 KB |
| Rigid bodies | ✓ | ✓ | ✓ | ✓ |
| Convex shapes | ✓ | ✓ | ✓ | △ limited |
| Concave (trimesh) | △ static only | ✓ | ✓ | ✗ |
| Joints/Constraints | ✓ basic | ✓ full | ✓ full (Bullet) | △ basic |
| Soft bodies / cloth | ✗ | ✗ | ✓ (Bullet) | ✗ |
| CCD (tunneling prevent) | △ threshold | ✓ | ✓ | ✗ |
| Deterministic replay | ✗ | ✓ (Rust) | △ | ✗ |
| TypeScript types | ✓ native | ✓ generated | △ community | △ |
| Three.js helper lib | cannon-es | @dimforge/rapier3d | three/examples/jsm | — |
| Performance (10k bodies) | ~45 fps | ~58 fps | ~50 fps | ~52 fps |
| Recommendation | Beginner | Production | Soft bodies | Legacy |
Performance figures are approximate at 1000 dynamic boxes, desktop Chrome, M2 MacBook. △ = partial support.
2. Cannon-es
cannon-es is a community-maintained fork of the original cannon.js, rewritten in TypeScript. It is the most beginner-friendly option and used throughout this site's simulations.
- Pure JS/TS — no WASM, no build step required, works with CDN import
- Excellent documentation and many Three.js examples online
- Limitations: no concave trimesh dynamics, basic joint selection, no determinism
// CDN import (ES Module)
import * as CANNON from 'https://cdn.jsdelivr.net/npm/cannon-es@0.20.0/dist/cannon-es.js';
const world = new CANNON.World({ gravity: new CANNON.Vec3(0, -9.82, 0) });
const body = new CANNON.Body({
mass: 1,
shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
position: new CANNON.Vec3(0, 5, 0),
});
world.addBody(body);
// Sync Three.js mesh per frame
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
3. Rapier.js (WASM)
Rapier is written in Rust, compiled to WebAssembly, and designed from the ground up for correctness, performance, and determinism. It is the best choice for production games and simulations that require accurate CCD and complex constraints.
- ~3–4× faster than Cannon-es for large scenes (benefits from SIMD WASM)
- Full CCD, all joint types (revolute, prismatic, fixed, spherical), heightfield
- Deterministic across platforms — same floating-point sequence every run
- Requires async WASM initialization (await RAPIER.init())
import RAPIER from 'https://cdn.skypack.dev/@dimforge/rapier3d-compat';
await RAPIER.init();
const gravity = { x: 0, y: -9.81, z: 0 };
const world = new RAPIER.World(gravity);
const bodyDesc = RAPIER.RigidBodyDesc.dynamic().setTranslation(0, 5, 0);
const rigidBody = world.createRigidBody(bodyDesc);
const colliderDesc = RAPIER.ColliderDesc.cuboid(.5, .5, .5);
world.createCollider(colliderDesc, rigidBody);
// Step the world
world.step();
const pos = rigidBody.translation(); // { x, y, z }
@pmndrs/cannon and
@react-three/rapier packages provide declarative React
Three Fiber bindings. For vanilla Three.js, sync is manual (same as
Cannon-es pattern above).
4. Ammo.js (Bullet Physics)
Ammo.js is an Emscripten compilation of the Bullet Physics C++ library — the same engine used in Blender, Maya, and many AAA games. It provides the widest feature set, including soft bodies, cloth simulation, and vehicle dynamics.
- Full Bullet API available in JS (though with C-style bindings)
- Largest bundle (~750 KB gzip) and slowest startup (WASM + large heap)
- Soft body and cloth simulation not available in any other web option
-
Three.js Examples include
examples/jsm/physics/AmmoPhysics.jshelper
Ammo.destroy()
required for heap objects). This makes it significantly more verbose
than Cannon-es or Rapier. Use it when you specifically need soft
bodies or vehicle physics.
5. OimoPhysics
OimoPhysics is a pure-JavaScript port of the Java Oimo Physics engine. Smallest bundle, decent performance for simple scenes, but limited features and no active development since 2016.
- Good for legacy code and very small bundle budgets
- Lacks trimesh, CCD, and advanced constraints
- Not recommended for new projects
6. How to Choose
- First project / learning: Cannon-es — best docs, most examples, no WASM complexity
- Production game / simulation: Rapier.js — fastest, deterministic, full constraint support
- Cloth or soft bodies: Ammo.js — only option with Bullet soft body solver
-
React Three Fiber stack:
@react-three/rapieror@react-three/cannon - Particle-based fluids / granular: Custom SPH or MPM — no production-ready JS lib exists yet
jolt-physics npm
package). Early benchmarks show 2× Rapier speed for large scenes.
Watch for 2026 maturity.