A custom-built, multithreaded 3D rigid body physics engine written in Rust. This project implements a full physics pipeline from scratch—including broad-phase collision culling, narrow-phase GJK/EPA contact generation, a parallelized sequential impulse solver, a joint constraint system, and a real-time 3D renderer with multiple interactive demos.
- Broad-Phase: Two pluggable implementations selectable per demo:
- AABB Tree: Hierarchical axis-aligned bounding box tree for general-purpose scenes (default).
- Spatial Hashing: 3D grid-based hash for dense, uniform distributions (used by the Molecules demo).
- Narrow-Phase (GJK & EPA): Implements the Gilbert-Johnson-Keerthi (GJK) algorithm for boolean collision queries and the Expanding Polytope Algorithm (EPA) for precise contact manifolds and penetration depths. Supports three collider shapes:
- Sphere
- Box (OBB)
- Convex Hull — arbitrary convex polyhedra defined by a vertex list and triangulated face list. The engine computes the center of mass and inertia tensor analytically from the signed-volume integral over each face.
- Sequential Impulse Solver: Solves velocity constraints iteratively to handle normal forces, restitution, and friction. Warm-starts from cached impulses each frame for fast convergence.
- Parallel Constraint Solving: Uses a
UnionFinddata structure to partition contacts into disjoint collision islands. Each island is solved independently on a separate rayon thread with no data races. - Baumgarte Stabilization: Position-correction bias in the velocity constraint prevents sinking and ensures stable stacking.
- Contact Manifold Cache: Up to 4 contact points per pair are retained and pruned across frames, eliminating popping artifacts and improving warm-start quality.
Three joint types are implemented, all as velocity-level constraints solved in the same sequential-impulse loop:
| Joint | DOF removed | Use case |
|---|---|---|
DistanceJoint |
1 (along connector) | Pendulum strings, Newton's cradle wires |
SpringJoint |
1 (soft, along connector) | Springs, elastic coupling between bodies |
BallAndSocketJoint |
3 (all translational) | Rigid pivots, hinges, anchor points |
Joint anchor points are specified in each body's local frame. The world body (body 0) can serve as a static anchor, enabling pendulums and fixed pivots.
- Compound Rigid Bodies: Bodies can be composed of multiple colliders with independent local offsets and orientations. The engine recomputes the aggregate center of mass and applies the Parallel Axis Theorem to the inertia tensor each time a collider is added.
- Thermostat System: Three velocity-control strategies:
LinearDamping(f)— multiplies all velocities byfeach step (default: 0.999, near-conservative).VelocityRescaling(T)— rescales velocities each step to maintain a target kinetic temperatureT.Langevin(T, γ, kB)— applies friction and stochastic Gaussian forces for Brownian-dynamics-style simulations.
Six interactive demos ship with the engine. Press N to cycle forward, R to reset the current demo, P to pause/resume, and Space to apply random impulses.
| # | Name | Description |
|---|---|---|
| 1 | Cascade | 4×4 grid of boxes + 8 spheres falling under gravity, piling up |
| 2 | Tower | 10-layer box tower struck by a fast-moving sphere |
| 3 | Molecules | ~27 water molecule compounds bouncing under a Langevin thermostat with no gravity |
| 4 | Joints | Pendulum chain (DistanceJoint), rigid tumbling pair (BallAndSocket), oscillating spheres (SpringJoint) |
| 5 | Newton's Cradle | 5 spheres on V-shaped DistanceJoint strings with near-perfect restitution; uses 40 solver iterations |
| 6 | Simple Machine | Convex hull balance arm (octahedron) pivoted via BallAndSocket; spring-coupled pendulum spheres of unequal mass drive a chaotic double-pendulum tetrahedron sub-bob |
Rust and Cargo are required. The engine uses OpenGL via kiss3d for rendering, so a desktop GPU is expected.
# Clone the repository
git clone https://github.com/njweiss/rust_physics.git
cd rust_physics
# Run in release mode (required for real-time performance)
cargo run --releaseDebug builds are too slow for real-time simulation; always use --release.
| File | Role |
|---|---|
world.rs |
Core simulation hub: fixed-timestep pipeline, gravity, thermostat, manifold update, constraint generation and solving, integration |
rigid_body.rs |
RigidBody, Collider (Sphere / Box / ConvexHull), OBB, AABB; support functions, inertia tensor computation |
collision.rs |
Narrow-phase: GJK, EPA, contact manifold generation and pruning |
constraint.rs |
VelocityConstraint math: Jacobian assembly, impulse computation |
joints.rs |
DistanceJoint, SpringJoint, BallAndSocketJoint and the Joint enum dispatcher |
broadphase.rs |
BroadPhase trait; AABBTree and SpatialHashing implementations |
demo.rs |
Demo trait and the six demo structs; all_demos() registry |
main.rs |
kiss3d render loop, scene node sync, joint visualization, HUD |
utils.rs |
UnionFind, safe normalize, random helpers |
The fixed timestep is dt = 1/60 s. World::step() runs the full pipeline each tick.
- Continuous collision detection (CCD) to prevent tunneling at high velocities.
- Sleeping mechanism to freeze inactive bodies and save CPU cycles.
- Rotational friction (rolling / spinning friction).
- Prismatic and revolute joint types.