Rigid bodies & the physics world
vgai uses Rapier for physics — directly, with no wrapper. You
reach the world through ctx.rapierWorld and create bodies/colliders with the Rapier API.
The world
Section titled “The world”Physics setup (packages/engine/src/setup/setup-physics.ts) creates a RAPIER.World with a
default gravity of { x: 0, y: -9.81, z: 0 } and a RAPIER.EventQueue(true) for
collision events. A debug LineSegments mesh is created for the collider-wireframe view.
Body types
Section titled “Body types”A physics body is declared on an entity via the physics schema
(packages/engine/src/scene/schema/physics.ts). The bodyType is one of:
| Body type | Behavior |
|---|---|
dynamic | Fully simulated — gravity, forces, collisions move it. |
fixed | Immovable — static geometry (ground, walls). |
kinematic | Script-driven — you set its transform; it pushes dynamic bodies but isn’t pushed. |
mass is optional: if omitted, Rapier computes it from the collider’s density and volume.
The collider field attaches a collider shape.
The per-frame flow
Section titled “The per-frame flow”prePhysics— your code writes forces/velocities onto rigid bodies.physics—rapierWorld.step(eventQueue)advances the simulation.postPhysics— collision events are drained, then the transform writer copies each body’s transform back onto itsObject3D.
The transform writer (packages/engine/src/physics/transform-writer.ts) runs as a single
postPhysics system. Rapier reports world-space transforms; for entities parented under
something other than the scene root, it converts world → parent-local using the inverse
parent matrix. Scale is left untouched (Rapier carries no scale).
The physics registry
Section titled “The physics registry”vgai keeps a bidirectional map between Three.js objects and Rapier handles — the
PhysicsRegistry (packages/engine/src/physics/physics-registry.ts):
add(object3D, body, collider)— register an entity’s physics.get(object3D)— the{ body, collider }for an entity.getByColliderHandle(handle)— the reverse lookup, used to resolve a collision back to its entity.remove(object3D),entries(),clear().
The reverse colliderHandle → Object3D index is what lets
collisions and triggers name the entities involved.
See also
Section titled “See also”- Colliders — shapes, sensors, and collision layers.
- Collisions & triggers — reacting to contact.
- Joints — constraining bodies together.
- The game loop & phases — where each step runs.