Matter.js Position Resolver: How solvePosition Works

In Matter.js, the Matter.Resolver.solvePosition function is responsible for resolving geometric overlap between colliding rigid bodies without introducing artificial kinetic energy into the physics simulation. Operating as the positional correction phase of the engine's constraint solver, it directly displaces interpenetrating bodies along their collision normals over a configurable number of iterations. By weighting adjustments according to inverse mass, factoring in positional slop to prevent jitter, and applying a relaxation damping factor, solvePosition ensures stable, non-overlapping body arrangements even in complex scenarios like multi-body stacking.

Collision Detection and Penetration Depth

Before solvePosition executes, the collision detection phase (using the Separating Axis Theorem) identifies colliding pairs and calculates two essential geometric values: the minimum translation vector (the collision normal) and the penetration depth. The penetration depth represents how deeply the shapes overlap along the normal axis. These metrics are stored on the collision pair objects and passed into the resolver.

Mass-Weighted Correction Distribution

When two bodies interpenetrate, solvePosition must decide how much each body should move to clear the overlap. Rather than splitting the separation distance equally, the function weights the displacement using each body's inverse mass:

\[\text{Share}_A = \frac{\text{inverseMass}_A}{\text{inverseMass}_A + \text{inverseMass}_B}\]

\[\text{Share}_B = \frac{\text{inverseMass}_B}{\text{inverseMass}_A + \text{inverseMass}_B}\]

A static body has an inverse mass of zero, meaning its share of the correction is zero, forcing the dynamic body to move the entire distance. If both bodies are dynamic and possess equal mass, each body moves by half the required separation distance.

Positional Slop and Damping

Directly applying the full separation distance in a single step often leads to overshooting, instability, and visual jitter. To counteract this, solvePosition incorporates two stabilization techniques:

Direct Position and Vertex Translation

Unlike impulse solvers that adjust linear and angular velocity, solvePosition performs a direct geometric projection:

  1. The calculated scalar correction is multiplied by the collision normal to produce a translation vector.
  2. The vector is applied directly to the body's coordinates (body.position.x and body.position.y).
  3. The body's vertices, axes, and bounding box are translated alongside the position to keep collision geometry synchronized.

Because this displacement modifies position directly without increasing velocity, bodies do not accumulate velocity-based energy simply from being pushed out of overlapping states.

Iterative Relaxation Loop

A single push can resolve one collision while inadvertently creating or worsening another, particularly in stacks or densely clustered bodies. To achieve equilibrium, Matter.js executes solvePosition repeatedly within an iterative loop controlled by engine.positionIterations.

During each iteration, the solver cycles through all active collisions, recalculates the remaining overlap, and applies incremental positional nudges. Across successive passes, the system converges toward a state where all interpenetrations fall below the slop threshold, successfully stabilizing the simulation.