Dynamic vs Kinematic Rigid Bodies in Ammo.js
This article explains the technical differences between dynamic and kinematic rigid bodies in the ammo.js physics engine. You will learn how each body type is simulated, how they interact with the physics world, and the specific API calls and flags required to implement them in your JavaScript applications.
Dynamic Rigid Bodies
Dynamic rigid bodies are fully simulated by the ammo.js physics engine. They react to forces, gravity, collisions, and impulses according to the laws of classical mechanics.
Technical Characteristics
- Mass: Must have a mass greater than zero (e.g.,
mass > 0). A non-zero mass tells the physics engine to calculate gravity and inertia for the object. - Inertia: Requires local inertia computation based
on the collision shape. You must call
shape.calculateLocalInertia(mass, localInertia)and pass this value to the construction info. - Movement: The physics engine calculates the velocity, position, and rotation of the body at every simulation step. You do not manually set its coordinates every frame; instead, you apply forces or impulses to influence its movement.
- Motion State Updates: The simulation writes
transform updates out to the body’s
btDefaultMotionState. Your graphics loop reads these transforms from the motion state to update the visual mesh.
Code Implementation
let mass = 1.0;
let localInertia = new Ammo.btVector3(0, 0, 0);
geometryShape.calculateLocalInertia(mass, localInertia);
let startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(new Ammo.btVector3(0, 10, 0));
let motionState = new Ammo.btDefaultMotionState(startTransform);
let rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometryShape, localInertia);
let body = new Ammo.btRigidBody(rbInfo);
physicsWorld.addRigidBody(body);Kinematic Rigid Bodies
Kinematic rigid bodies are hybrid objects that are not affected by physics forces, gravity, or collisions, yet they can collide with and push dynamic bodies. They are typically used for moving platforms, doors, or character controllers.
Technical Characteristics
- Mass: Technically set to zero
(
mass = 0). In the Bullet engine (which ammo.js ports), a mass of zero indicates a static or kinematic object. - Inertia: The local inertia vector is set to zero
(0, 0, 0)because the engine does not calculate physical acceleration for the body. - Movement: Driven entirely by your application code. You manually update the object’s transform in your animation loop.
- Collision Interaction: Dynamic bodies will bounce off kinematic bodies, but kinematic bodies are “unstoppable” and will not deviate from their programmatically defined path during collisions.
- Motion State Updates: Unlike dynamic bodies, the physics engine reads the transform in from the motion state. You write the new coordinates to the motion state, and ammo.js updates the internal physics representation.
Code Implementation
To convert a static body (mass = 0) into a kinematic body in ammo.js, you must explicitly set the kinematic collision flag and disable the sleep state.
let mass = 0; // Must be zero
let localInertia = new Ammo.btVector3(0, 0, 0);
let startTransform = new Ammo.btTransform();
startTransform.setIdentity();
let motionState = new Ammo.btDefaultMotionState(startTransform);
let rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometryShape, localInertia);
let body = new Ammo.btRigidBody(rbInfo);
// Set kinematic flag (CF_KINEMATIC_OBJECT = 2)
body.setCollisionFlags(body.getCollisionFlags() | 2);
// Prevent the body from going to sleep (DISABLE_DEACTIVATION = 4)
body.setActivationState(4);
physicsWorld.addRigidBody(body);To move the kinematic body during your render loop:
let transform = new Ammo.btTransform();
transform.setIdentity();
transform.setOrigin(new Ammo.btVector3(newX, newY, newZ));
// Update the motion state; ammo.js will read this on the next stepSimulation
body.getMotionState().setWorldTransform(transform);Direct Technical Comparison
| Feature | Dynamic Rigid Body | Kinematic Rigid Body |
|---|---|---|
| Mass Value | Greater than zero
(> 0) |
Must be zero (0) |
| Primary Driver | Physics engine (gravity, forces, collisions) | User code (direct transform updates) |
| Affected by Gravity | Yes | No |
| Can Push Dynamic Bodies | Yes | Yes (with infinite simulated mass) |
| Can Be Pushed by Dynamic Bodies | Yes | No |
| Ammo.js Flags Required | Default flags | CF_KINEMATIC_OBJECT &
DISABLE_DEACTIVATION |
| Motion State Pipeline | Physics engine updates the Motion State | User updates the Motion State; Engine reads it |