Optimal Vertex Limit for Custom Shapes in Matter.js
This article explores the recommended vertex limits for custom bodies in Matter.js and explains how polygon complexity directly impacts rendering performance and physics calculations. While Matter.js does not enforce an arbitrary hard-coded limit on vertices, maintaining optimal performance requires balancing visual fidelity and computational overhead. Below, you will find direct recommendations for vertex counts, explanations of the underlying collision engine constraints, and methods to optimize custom geometry for physics simulations.
Recommended Vertex Count
For custom rigid bodies in Matter.js, the recommended maximum is
8 to 15 vertices per convex polygon. If you are
creating complex concave shapes using
Matter.Bodies.fromVertices(), the entire shape should
ideally stay below 30 to 50 vertices in total after
decomposition.
Keeping vertex counts within these thresholds ensures your simulation consistently runs at 60 frames per second on standard consumer hardware and mobile devices.
Why Vertex Counts Impact Performance
Matter.js relies on the Separating Axis Theorem (SAT) to detect collisions between convex polygons. The computational cost of SAT scales directly with the number of edges and vertices:
- Collision Check Complexity: The physics engine checks potential separating axes perpendicular to every edge of both colliding bodies. Doubling the vertices on two interacting shapes significantly increases the number of axis projections required per frame.
- Concave Shape Decomposition: Matter.js cannot
calculate physics directly on concave geometry. It relies on a polygon
decomposition library (such as
poly-decomp.js) to break concave paths into multiple convex hulls. An input shape with dozens of vertices can generate numerous internal convex parts, multiplying the number of rigid bodies the physics engine must manage. - Internal Edge Snagging: When a shape is broken down into multiple convex pieces, simulated objects can sometimes catch or snag on internal boundaries during sliding interactions. Minimizing total vertices reduces the number of sub-shapes generated.
Best Practices for Custom Shapes
To maintain smooth physics interactions while using custom shapes, follow these implementation practices:
- Pre-simplify SVG and Vector Paths: Vector assets frequently contain hundreds of unnecessary points along gentle curves. Run paths through a simplification algorithm (like the Ramer-Douglas-Peucker algorithm) to reduce node counts before passing them to Matter.js.
- Decouple Physics from Rendering: Do not use full-resolution visual meshes for physics boundaries. Create a simplified, low-poly physics collision hull (around 6 to 10 vertices) and position the high-resolution visual sprite or mesh directly over it.
- Use Composite Primitive Shapes: If a shape can be
represented by a combination of basic rectangles and circles (such as a
vehicle or character), use
Matter.Body.create({ parts: [...] })with primitive shapes instead of relying on automatic vertex tracing. Circles are computationally efficient because collision detection is based on radius checks rather than multiple edge axes.