Physics engines allow you to simulate physical phenomena like gravity, collisions, and forces within your 3D capabilities. In a typical three.js scene, objects are moved by directly modifying their position or rotation. When using a physics engine, however, you create a parallel physics world where bodies react to forces and collisions. You then synchronize the three.js meshes with these physics bodies on every frame, creating the illusion of a physically simulated environment.
It should be noted that the physics engine does not necessarily have to be updated every frame. Usually, to keep experiences consistent, physics are updated at fixed time steps. For instance, it could be that we are running the game loop at 60fps but the physics engine at 30fps (that is 1/30=3.33ms) while updating the three.js meshes' transforms (e.g., positions and rotations) with the most recent state from the physics engine.
Physics simulations are particularly useful for games, interactive visualizations, and any application requiring realistic object behavior, such as objects falling, bouncing, or sliding.
There are three main ways to integrate a physics engine into a three.js project:
Three.js provides wrapper classes for several popular physics engines in the examples/jsm/physics directory. These addons simplify the setup process by handling the initialization of the physics world and the synchronization of meshes.
Available addons include:
These addons effectively hide much of the complexity of the underlying engines. For standard use cases, they offer a very quick way to get started.
Many physics engines are written directly in JavaScript or TypeScript and are designed to work easily with the web ecosystem. Libraries like cannon-es are popular choices because they are lightweight and easy to integrate specifically with three.js.
When using these libraries, you instantiate the physics world and bodies yourself, then manually copy the position and quaternion from the physics body to the three.js mesh in your animation loop.
It should also be noted that there are a couple of 3D physics engines that are seemingly written in JS/TS but are in reality calling other standalone 3D physics engines. For example:
For maximum performance, stability, and precision, especially with complex simulations, you can use physics engines written in C++ or Rust (or any other language that supports WASM) that have been compiled to WebAssembly (WASM). Engines like Ammo.js (a port of Bullet Physics) and Rapier fall into this category.
While this approach offers the most features and best performance, it often requires more setup code to handle the WASM memory management and interaction with the physics API directly.
Some of these multi-platform 3D physics engines have a ready-to-use WASM port, including: