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:
- 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. - 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:
- Projects the vertices of convex polygon bodies onto perpendicular edge axes.
- Employs dedicated circle-to-circle and circle-to-polygon distance tests for circular bodies.
- Calculates collision response data if an overlap exists on all tested axes, including the minimum translation vector (the collision normal) and penetration depth.
- Identifies specific contact points (support points) where the geometries intersect, which the solver later uses to apply friction and restitution impulses.
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:
- Complex meshes or concave polygons must be decomposed into a composite set of convex parts.
- Matter.js typically accomplishes this using tools like the
poly-decomplibrary, allowing concave objects to be represented as multiple convex rigid bodies rigid-linked together. Each sub-part then undergoes standard narrow-phase evaluation.
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.