Matter.js Baumgarte Stabilization Explained

Matter.js counteracts positional drift and prevents overlapping bodies by integrating a variation of Baumgarte stabilization directly into its iterative constraint and collision resolver. Due to discrete numerical integration, rigid bodies in physical simulations naturally experience penetration errors and joint separation over time. Matter.js resolves this positional drift by converting a controlled fraction of the spatial error into corrective impulse biases across multiple solver iterations, smoothing out constraints without injecting artificial energy into the system.

The Nature of Positional Drift

In a discrete time-step physics engine, velocity updates do not always maintain exact boundary constraints. When two bodies collide or are tethered by a joint, standard velocity projections enforce that their relative approach speed becomes zero or reverses. However, truncation errors, numerical approximations, and high external forces cause objects to slightly penetrate one another or cause constraint links to stretch. Without direct position correction, these small spatial errors accumulate each frame, leading to sinking bodies, drifting joints, and physical instability.

Baumgarte Stabilization in Concept

Baumgarte stabilization resolves drift by modifying the velocity constraint equation to include a feedback term based on the current position error. Rather than resolving position errors instantly—which can cause violent velocity spikes and explosive instability—the solver introduces a bias velocity:

\[v_{bias} = \frac{\beta}{\Delta t} C(x)\]

Here, \(C(x)\) represents the constraint error (such as penetration depth or distance beyond a joint's resting length), \(\Delta t\) is the simulation time-step, and \(\beta\) is a stabilization parameter typically between 0.1 and 0.3. This bias term forces the velocity solver to gradually consume the positional error over several frames.

How Matter.js Implements the Technique

Matter.js adapts this stabilization concept within its impulse-based relaxation solver, primarily divided between collision resolution (Resolver.js) and constraint handling (Constraint.js).

1. Collision Penetration Correction

During collision resolution, Matter.js calculates the exact penetration depth and contact normal via the Separating Axis Theorem (SAT). Instead of shifting the objects entirely in a single frame, the solver applies a damping factor to the penetration error.

The engine scales the penetration resolution through an internal bias factor. By applying only a percentage of the total positional overlap during each iteration, Matter.js prevents overshooting—a phenomenon where bodies aggressively bounce away from resting contacts.

2. Constraint and Joint Stabilization

For distance constraints and pin joints, Matter.js evaluates the difference between the current distance and the target resting length. The corrective impulse applied to both bodies uses the stiffness property as an analog to the Baumgarte parameter \(\beta\):

3. Iterative Relaxation (Position Iterations)

Matter.js relies on iterative projection (similar to Sequential Impulses and Position Based Dynamics). The engine runs a configurable number of position iterations (engine.positionIterations) and velocity iterations (engine.velocityIterations).

During each position iteration, the Baumgarte-style position correction is distributed proportionally according to the inverse masses and moments of inertia of the interacting bodies. Splitting the correction across multiple passes ensures that resting stacks of objects remain stable without sinking into floors or lower bodies.

Tuning Drift Correction in Matter.js

Developers can manage positional drift and engine stability by adjusting several core engine properties: