How to Use Matter.Vertices.hull in Matter.js
This guide explains how to generate a convex hull from an arbitrary
set of 2D coordinates using the Matter.Vertices.hull method
in Matter.js. You will learn the purpose of a convex hull in 2D physics
simulations, how to format your input data, how to execute the function,
and how to convert the resulting vertices into an active rigid body.
What is a Convex Hull in Matter.js?
A convex hull is the smallest convex polygon that completely encloses a given set of points, resembling the shape formed by wrapping a rubber band around the points.
Matter.js relies heavily on convex shapes for its default collision detection routines (SAT - Separating Axis Theorem). When you have scattered point clouds, dynamic particle traces, or complex point collections, calculating a convex hull ensures that the resulting shape is convex, computationally efficient, and safe to use directly in the physics engine.
1. Preparing the Point Collection
Matter.Vertices.hull expects an array of vector-like
objects. Each point must contain numeric x and
y properties:
const points = [
{ x: 10, y: 10 },
{ x: 50, y: 100 },
{ x: 80, y: 30 },
{ x: 20, y: 60 },
{ x: 90, y: 90 },
{ x: 40, y: 40 } // Interior point
];Interior points will automatically be discarded by the hull algorithm, leaving only the exterior boundary points.
2. Generating the Hull
To compute the hull, pass your array of points directly to
Matter.Vertices.hull():
const hullVertices = Matter.Vertices.hull(points);The returned hullVertices is an array of point objects
ordered sequentially around the perimeter of the hull. Any colinear or
internal points are removed.
3. Creating a Physics Body from the Hull
Once the hull vertices are generated, you can construct a rigid body
using Matter.Bodies.fromVertices.
Because Matter.Vertices.hull produces a strictly convex
set of vertices, Matter.Bodies.fromVertices can easily form
a single rigid body without needing complex polygon decomposition:
// World coordinates where the body should be placed
const spawnX = 400;
const spawnY = 300;
// Bodies.fromVertices expects an array of vertex sets
const hullBody = Matter.Bodies.fromVertices(
spawnX,
spawnY,
[hullVertices],
{
isStatic: false,
restitution: 0.5,
friction: 0.1
}
);
// Add the body to the Matter.js world
Matter.Composite.add(engine.world, hullBody);Complete Implementation Example
const { Engine, Render, Runner, Bodies, Composite, Vertices } = Matter;
// 1. Initialize Matter.js environment
const engine = Engine.create();
const render = Render.create({
element: document.body,
engine: engine,
options: { width: 800, height: 600, wireframes: false }
});
Render.run(render);
Runner.run(Runner.create(), engine);
// 2. Define arbitrary points
const randomPoints = [
{ x: 0, y: 0 },
{ x: 100, y: 50 },
{ x: 80, y: 120 },
{ x: 20, y: 110 },
{ x: 50, y: 50 } // Interior point
];
// 3. Compute the convex boundary
const convexVertices = Vertices.hull(randomPoints);
// 4. Create and add the body
const body = Bodies.fromVertices(400, 200, [convexVertices], {
render: {
fillStyle: '#2ecc71',
strokeStyle: '#27ae60',
lineWidth: 2
}
});
const ground = Bodies.rectangle(400, 580, 810, 40, { isStatic: true });
Composite.add(engine.world, [body, ground]);Key Points to Keep in Mind
- Winding Order:
Matter.Vertices.hullnormalizes the winding order of the vertices, preparing them for collision detection. - Minimum Point Count: You need at least three non-colinear points to form a valid 2D polygon body.
- Centering Offset:
Matter.Bodies.fromVerticescomputes the center of mass automatically and offsets the provided vertices so the body's position matches the center of mass.