Matter.js Narrow-Phase Collision Detection

Matter.js fully supports narrow-phase collision detection through a built-in implementation of the Separating Axis Theorem (SAT). While broad-phase collision detection quickly identifies which bodies might be touching by checking their axis-aligned bounding boxes (AABB), the narrow phase performs the precise geometric calculations required to determine exact contact points, penetration depths, and collision normals. This article explains how Matter.js executes narrow-phase detection, its underlying algorithms, its limitations, and how to access narrow-phase collision data in your code.

The Matter.js Collision Pipeline

Matter.js splits its collision pipeline into two distinct phases to maintain high performance in real-time simulations:

  1. Broadphase (Matter.Detector): Scans the simulation space using bounding boxes to group pairs of bodies that are close enough to potentially collide, filtering out impossible collisions early.
  2. Narrowphase (Matter.SAT): Takes the candidate pairs identified by the broadphase and runs accurate geometric tests to confirm whether an actual intersection has occurred.

How Narrow-Phase Detection Works in Matter.js

The core narrow-phase engine in Matter.js relies on the Separating Axis Theorem (SAT), located in the Matter.SAT module. SAT states that two convex shapes do not overlap if there exists an axis onto which the projections of the two shapes do not intersect.

During the narrow phase, Matter.js:

Convex and Concave Geometry Constraints

Because SAT is mathematically limited to convex polygons, Matter.js only supports convex shapes in its native narrow-phase calculations.

To simulate concave shapes:

Accessing Narrow-Phase Results

Developers can query narrow-phase results both automatically via engine events and manually via direct module calls.

Engine Events

When the engine runs, the narrow-phase outputs are encapsulated in collision pairs exposed through collision events (collisionStart, collisionActive, and collisionEnd):

Matter.Events.on(engine, 'collisionStart', (event) => {
    event.pairs.forEach((pair) => {
        const collision = pair.collision;
        console.log('Collision Normal:', collision.normal);
        console.log('Penetration Depth:', collision.depth);
        console.log('Contact Points:', collision.supports);
    });
});

Manual Narrow-Phase Queries

To evaluate narrow-phase collisions between two individual bodies outside of the normal simulation loop, use the Matter.SAT.collides method:

const collision = Matter.SAT.collides(bodyA, bodyB);

if (collision.collided) {
    console.log('Bodies overlap by:', collision.depth);
    console.log('Separation axis normal:', collision.normal);
}

Matter.js provides a complete, performant narrow-phase detection system out of the box, ensuring realistic physical interactions for convex geometries and compound bodies.