How to Create a Rotary Damper in Matter.js
This article explains how to construct a rotary damper joint in Matter.js to resist rapid angular rotation. While Matter.js includes standard linear spring-damper constraints, it lacks a native rotational viscous damper. You can achieve this effect by pairing a standard pin constraint with an event hook that dynamically applies a counteracting torque proportional to the relative angular velocity between two bodies.
Understanding the Physics
A rotary damper (or torsional dashpot) exerts a torque that opposes the direction of angular movement. The magnitude of this torque is directly proportional to the angular velocity:
\[\tau = -c \cdot \Delta\omega\]
Where:
- \(\tau\) is the applied resistive torque.
- \(c\) is the damping coefficient (resistance intensity).
- \(\Delta\omega\) is the difference in angular velocity between the two connected bodies (or relative to the world if one body is fixed).
Step 1: Create the Pin Constraint
First, establish a standard revolute joint using a
Constraint that binds Body A to Body B at a shared pivot
point without restricting rotation:
const { Bodies, Constraint, Composite } = Matter;
const bodyA = Bodies.rectangle(400, 300, 200, 20, { isStatic: true });
const bodyB = Bodies.rectangle(400, 300, 150, 20);
// Pin constraint serving as the axle
const pinJoint = Constraint.create({
bodyA: bodyA,
pointA: { x: 0, y: 0 },
bodyB: bodyB,
pointB: { x: -60, y: 0 },
length: 0,
stiffness: 1
});
Composite.add(world, [bodyA, bodyB, pinJoint]);Step 2: Implement Dynamic Angular Damping
To resist rapid turns, hook into the beforeUpdate event
of the physics engine. In this callback, calculate the relative angular
velocity between the bodies and apply an opposing torque directly to the
rotating body's torque property before each physics
step.
const { Events } = Matter;
// Higher values resist faster rotations more aggressively
const rotaryDamping = 0.05;
Events.on(engine, 'beforeUpdate', () => {
// Determine relative angular speed
const angularVelocityA = bodyA.isStatic ? 0 : bodyA.angularVelocity;
const angularVelocityB = bodyB.isStatic ? 0 : bodyB.angularVelocity;
const relativeAngularVelocity = bodyB.angularVelocity - angularVelocityA;
// Calculate opposing torque
const dampingTorque = -rotaryDamping * relativeAngularVelocity;
// Apply opposing torque to both bodies (Newton's third law)
if (!bodyB.isStatic) {
bodyB.torque += dampingTorque;
}
if (!bodyA.isStatic) {
bodyA.torque -= dampingTorque;
}
});Step 3: Tuning Stability
Because the damping torque accumulates linearly with speed, very high damping values combined with low body inertia can cause numerical instability or oscillation.
To fine-tune performance:
- Prevent Over-Correction: Clamp the maximum damping
torque to ensure it never exceeds the value required to stop the
rotation within a single frame:
const maxTorque = Math.abs((relativeAngularVelocity * bodyB.inertia) / engine.timing.lastDelta); const clampedTorque = Math.sign(dampingTorque) * Math.min(Math.abs(dampingTorque), maxTorque); bodyB.torque += clampedTorque; - Use Friction Air as a Baseline: If you only need a
single body rotating around a static anchor to resist high speeds
globally, increasing
bodyB.frictionAirprovides a quick approximation, though applying manual torque viabeforeUpdateremains necessary for precise two-body damping interactions.