Matter.js SAT Performance with High Vertex Counts

Using rigid bodies with high vertex counts in Matter.js significantly degrades physics simulation performance, primarily due to the mathematical overhead of the Separating Axis Theorem (SAT) during collision detection. In Matter.js, SAT serves as the core narrowphase algorithm to determine whether two convex shapes overlap and to calculate collision vectors. When vertex density increases, the calculations required per frame multiply quadratically, causing CPU bottlenecks, garbage collection pressure, and noticeable drops in framerate.

The Mathematical Cost of SAT Projection

The Separating Axis Theorem dictates that two convex bodies do not collide if an axis exists along which their projections do not overlap. To evaluate this:

  1. Axis Generation: The algorithm generates potential separating axes, which correspond to the perpendicular normal vectors of every edge on both polygons. A body with \(N\) vertices produces \(N\) potential axes. For two interacting bodies with \(N\) and \(M\) vertices, the engine must evaluate up to \(N + M\) axes.
  2. Vertex Projection: On each tested axis, every single vertex from both bodies must be projected via vector dot products to find the minimum and maximum extents of the shapes.

Because every axis requires projecting all vertices of both shapes, testing collision between two bodies scales at approximately \(\mathcal{O}((N + M) \times (N + M))\) operations in the worst-case scenario where bodies overlap or are in close proximity. As vertex counts escalate from basic shapes (4–8 vertices) to complex silhouettes (50–100+ vertices), the number of dot products executed in a single frame increases by orders of magnitude.

Narrowphase Bottlenecks in Matter.js

Matter.js uses a broadphase step (bounding box trees or spatial hashing) to quickly discard bodies that are nowhere near each other. However, once bounding boxes intersect, the engine must invoke Matter.SAT.collides.

When high-vertex bodies are closely grouped, stacked, or resting:

Compounding Effects of Non-Convex Decomposition

Matter.js only supports convex polygons for SAT. If a concave body with a high vertex count is imported, it must be decomposed into a set of convex sub-bodies (typically using tools like poly-decomp).

A single complex concave shape can easily split into dozens of convex parts. In this scenario, the total collision cost multiplies exponentially: every sub-part of body A must run SAT against every overlapping sub-part of body B. This turns what appears to be a single collision check into dozens of high-vertex polygon evaluations per frame.

CPU and Memory Pressure

In browser environments, Matter.js runs on a single JavaScript thread. Heavy SAT operations directly contend with application logic and rendering routines. The excessive vector allocations and mathematical operations within the SAT loop create:

Optimization Strategies

To maintain stable 60 FPS simulations while working with complex shapes in Matter.js: