Custom Shapes in Matter.js Using Matter.Vertices
This guide explains how to define and render custom rigid bodies
using the Matter.Vertices module in Matter.js. You will
learn how to create shapes using coordinate arrays, parse SVG paths into
physics bodies, handle concave geometry with polygon decomposition, and
properly account for the physics engine's automatic center-of-mass
calculations.
1. Defining Vertices Manually
In Matter.js, vertices are represented as an array of 2D vector
objects, where each point has an x and y
property. Points must be defined in clockwise order to form a valid,
closed polygon boundary.
const starCoords = [
{ x: 50, y: 0 },
{ x: 63, y: 38 },
{ x: 100, y: 38 },
{ x: 69, y: 59 },
{ x: 82, y: 100 },
{ x: 50, y: 75 },
{ x: 18, y: 100 },
{ x: 31, y: 59 },
{ x: 0, y: 38 },
{ x: 37, y: 38 }
];2. Creating a Body
with Bodies.fromVertices
Once you have defined your coordinates, pass them to
Matter.Bodies.fromVertices to instantiate a physics
body.
const { Bodies, Composite } = Matter;
const x = 400; // X position in the world
const y = 300; // Y position in the world
const customBody = Bodies.fromVertices(x, y, [starCoords], {
isStatic: false,
render: {
fillStyle: '#e74c3c',
strokeStyle: '#c0392b',
lineWidth: 1
}
});
Composite.add(engine.world, customBody);The third parameter must be an array of vertex sets (an array containing your coordinate array), allowing multiple paths to define compound shapes.
3. Parsing Shapes from SVG Paths
Instead of manually typing coordinates, you can use
Matter.Vertices.fromPath to convert standard SVG path
strings directly into vertices:
const { Vertices, Bodies, Composite } = Matter;
// Standard SVG path definition
const pathData = "M 0 0 L 100 0 L 50 100 Z";
// Parse path into vertex set
const pathVertices = Vertices.fromPath(pathData);
const shape = Bodies.fromVertices(200, 200, [pathVertices], {
restitution: 0.8
});
Composite.add(engine.world, shape);4. Handling Concave
Shapes with poly-decomp
Matter.js collision algorithms require convex polygons. If you pass a
concave shape to Bodies.fromVertices, Matter.js
automatically splits it into multiple convex sub-bodies.
To enable this, you must install and expose the
poly-decomp library to the window or engine context before
creating the body:
<!-- Load poly-decomp before Matter.js -->
<script src="https://cdn.jsdelivr.net/npm/poly-decomp@0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>In modular environments (Node.js/Webpack/Vite):
import Matter from 'matter-js';
import decomp from 'poly-decomp';
// Assign poly-decomp to Matter.Common
Matter.Common.setDecomp(decomp);If poly-decomp is omitted, concave shapes will either
fail to render accurately or will revert to an approximated convex
hull.
5. Utility Methods in
Matter.Vertices
The Matter.Vertices module provides functions to
manipulate coordinate sets before generating bodies:
Vertices.clockwiseSorting(vertices): Sorts points in clockwise order.Vertices.scale(vertices, scaleX, scaleY, point): Rescales vertices around an origin point.Vertices.rotate(vertices, angle, point): Rotates the vertex set by a specified radian angle.Vertices.area(vertices, signed): Calculates the surface area of the polygon.Vertices.centre(vertices): Finds the geometric center (centroid) of the coordinates.
Example of pre-processing vertices:
// Rotate 45 degrees and scale up by 1.5x before creating the body
Matter.Vertices.rotate(starCoords, Math.PI / 4, { x: 50, y: 50 });
Matter.Vertices.scale(starCoords, 1.5, 1.5, { x: 50, y: 50 });6. Center-of-Mass Positioning Caveat
When Bodies.fromVertices builds a shape, it shifts the
origin of the vertices to the polygon's calculated center of mass. This
means the (x, y) arguments supplied to
Bodies.fromVertices dictate where the center of mass will
be placed in the simulation, not the top-left coordinate
(0, 0) of your original vertex data.