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\):
- A
stiffnessvalue near1.0attempts to correct nearly all positional drift within the current step, acting like a rigid link but with a higher risk of jitter if iteration counts are low. - A lower
stiffnessvalue (e.g.,0.1to0.5) spreads the correction across multiple simulation ticks, providing a stable, spring-like relaxation that steadily counteracts drift.
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:
engine.positionIterations: Increasing this value allows the engine to run more passes of positional correction per tick, significantly reducing resting drift in complex stacks or tight chains.constraint.stiffness: Controls the rate at which joint drift is recovered. Tuning this parameter prevents joints from visibly stretching under load while avoiding rapid, high-energy snaps.constraint.damping: Works alongside stiffness to suppress oscillatory behaviors caused by the corrective impulses, ensuring that bodies settle into equilibrium quickly.