Ammo.js Slider Constraint for Linear Movement

This article provides a step-by-step guide on how to implement a slider constraint (btSliderConstraint) in ammo.js to restrict a physics body’s movement to a single linear axis. We will cover initializing the constraint, configuring its linear limits, locking its angular rotation, and adding it to your physics world to achieve controlled, slide-like motion.


Understanding the Slider Constraint

In ammo.js (the WebAssembly/JavaScript port of the Bullet Physics engine), a btSliderConstraint allows a rigid body to slide along a single axis (by default, the local X-axis of the constraint frame) and optionally rotate around that same axis. To restrict the movement to purely linear motion, you must define the translation limits and lock the rotation limits to zero.

Step 1: Initialize the Rigid Body

Before creating the constraint, you need the rigid body that you want to restrict. This body should be dynamic (have non-zero mass).

// Assuming physicsWorld is your Ammo.btDiscreteDynamicsWorld instance
const mass = 1.0;
const startTransform = new Ammo.btTransform();
startTransform.setIdentity();
startTransform.setOrigin(new Ammo.btVector3(0, 5, 0));

const localInertia = new Ammo.btVector3(0, 0, 0);
const shape = new Ammo.btBoxShape(new Ammo.btVector3(1, 1, 1));
shape.calculateLocalInertia(mass, localInertia);

const motionState = new Ammo.btDefaultMotionState(startTransform);
const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
const sliderBody = new Ammo.btRigidBody(rbInfo);

physicsWorld.addRigidBody(sliderBody);

Step 2: Define the Constraint Transform

The slider constraint requires a transform helper (btTransform) to define the axis of translation. By default, the slider moves along the X-axis of this transform. You can rotate this transform if you want the body to slide along a different world axis (e.g., Y or Z).

const localFrame = new Ammo.btTransform();
localFrame.setIdentity(); 

// To slide along the world Z-axis instead of X, rotate the frame:
// const q = new Ammo.btQuaternion();
// q.setEulerZYX(0, Math.PI / 2, 0); // Rotate 90 degrees around Y axis
// localFrame.setRotation(q);

Step 3: Create and Configure the Slider Constraint

Instantiate the btSliderConstraint. You can attach it between two rigid bodies, or attach a single rigid body to a fixed point in the world frame. The example below attaches a single body to the world frame.

// Parameters: rigidBody, frameInBody, useLinearReferenceFrameA
const useLinearReferenceFrameA = true;
const sliderConstraint = new Ammo.btSliderConstraint(sliderBody, localFrame, useLinearReferenceFrameA);

// Define linear movement limits (in meters) along the slider axis
// For example, restrict movement between -3.0 and 3.0 units
sliderConstraint.setLowerLinLimit(-3.0);
sliderConstraint.setUpperLinLimit(3.0);

// Lock angular movement to restrict the body to linear movement only
sliderConstraint.setLowerAngLimit(0.0);
sliderConstraint.setUpperAngLimit(0.0);

Step 4: Add the Constraint to the Physics World

To make the physics engine process the constraint, add it to your dynamics world.

// Parameters: constraint, disableCollisionsBetweenLinkedBodies
const disableCollisions = true;
physicsWorld.addConstraint(sliderConstraint, disableCollisions);

Step 5: Clean Up

When you remove the rigid body or reset your physics scene, remember to remove and destroy the constraint to prevent memory leaks in the WebAssembly heap.

physicsWorld.removeConstraint(sliderConstraint);
Ammo.destroy(sliderConstraint);