Constraints
Per-DOF limits, springs, and motors on a Joint — end-stops, suspension, and powered axes.
Joints lock or free each of their six degrees of freedom. The same Joint also lets each DOF be limited, sprung, or motorised — which is where range-of-motion stops, suspension, and powered hinges come from. Every DOF independently takes one mode (DofMode):
| Mode | Behaviour |
|---|---|
LOCKED | held at the rest value (the rigid joints) |
FREE | unconstrained |
LIMITED | free within [lower, upper], resisted at the stops |
SPRING | a soft spring (stiffness + damping) pulling toward rest |
MOTOR | driven toward a target velocity, bounded by a max force |
You don’t set the mode directly — the helpers below configure the DOF and switch it into the right mode. Axes are 0 = x, 1 = y, 2 = z of the joint’s frame.
Limits — end-stops and range of motion
// A hinge that only opens 0°–90°:
const door = new Joint().asHinge(/* free axis */ 1);
door.setAngularLimit(1, 0, Math.PI / 2);
// A slider with 0–2 m of travel:
const lift = new Joint().asPrismatic(0);
lift.setLinearLimit(0, 0, 2);
setLinearLimit(axis, lower, upper) is metres; setAngularLimit(axis, lower, upper) is radians. The angular limit uses a small-angle measure that’s accurate for modest ranges; for wide cones (ragdoll shoulders) reach for asConeTwist, which measures swing and twist as exact angles.
Springs — suspension and soft returns
// A wheel on a vertical suspension spring:
const suspension = new Joint().asPrismatic(1);
suspension.setLinearSpring(1, /* stiffness N/m */ 4000, /* damping N·s/m */ 300);
// A lever that springs back to centre:
hinge.setAngularSpring(0, /* N·m/rad */ 20, /* N·m·s/rad */ 2);
A spring DOF yields under load and drives back toward its rest pose (place the anchors so the relaxed position is the zero) instead of holding rigid. Stiffness 0 makes it a pure damper.
Motors — powered axes
// A powered wheel spinning at 10 rad/s, up to 50 N·m:
wheel.setAngularMotor(0, /* target rad/s */ 10, /* max torque N·m */ 50);
// A conveyor / piston pushing at 1 m/s:
piston.setLinearMotor(0, /* target m/s */ 1, /* max force N */ 200);
A motor is a force-limited velocity servo: it pulls the relative velocity toward the target as hard as the force budget allows (Infinity for an ideal drive, 0 to switch it off).
Determinism
Constraints solve in the same fixed-step solver loop as contacts and locked joints, so everything you build with them inherits the engine’s determinism — limits, springs, and motors all reproduce bit-for-bit across V8 runtimes.
Where to go next
- Joints — the joint types these modes build on.
- Determinism — why a sprung, motorised rig still replays exactly.