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