Create Soft Body Cloth with Matter.js Constraints
This article explains how to simulate a realistic soft body cloth in Matter.js by linking a grid of rigid point-mass bodies using distance constraints. You will learn the mechanics behind mass-spring cloth systems, how to assemble the particle grid, how to anchor fixed points, and how to adjust constraint parameters like stiffness and damping to control the fabric's behavior.
Core Concepts of Matter.js Cloth Simulation
Matter.js is inherently a rigid-body 2D physics engine, meaning it does not possess dedicated deformable body primitives out of the box. To achieve a soft body cloth effect, you must construct a point-mass lattice. In this system:
- Particles: Small, circular bodies with mass that serve as the vertices of the fabric mesh.
- Structural Constraints: Elastic connections between neighboring vertical and horizontal particles that resist stretching and compression.
- Shear Constraints (Optional): Diagonal connections that prevent the cloth from collapsing or shearing uncontrollably.
- Anchors: Fixed particles
(
isStatic: true) that suspend the cloth in mid-air.
Implementing Cloth with Built-In Composites
Matter.js includes a built-in helper method,
Matter.Composites.softBody, which generates a grid of
circular bodies interconnected by constraints.
const { Engine, Render, Runner, Composites, Common, World, Bodies } = Matter;
// Create engine and world
const engine = Engine.create();
const world = engine.world;
// Create renderer
const render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
wireframes: false
}
});
Render.run(render);
Runner.run(Runner.create(), engine);
// Cloth configuration
const startX = 200;
const startY = 100;
const columns = 20;
const rows = 12;
const columnGap = 20;
const rowGap = 20;
const particleRadius = 4;
// Generate cloth using Composites.softBody
const cloth = Composites.softBody(
startX, startY,
columns, rows,
columnGap, rowGap,
false,
particleRadius,
{
collisionFilter: { group: Matter.Body.nextGroup(true) }, // Prevent self-collision artifacts
frictionAir: 0.05,
render: { visible: true, fillStyle: '#4a90e2' }
},
{
stiffness: 0.9,
damping: 0.1,
render: { strokeStyle: '#ffffff', lineWidth: 1 }
}
);
// Pin the top row of particles
for (let i = 0; i < columns; i++) {
cloth.bodies[i].isStatic = true;
}
World.add(world, cloth);Creating a Custom Cloth Grid with Manual Constraints
For finer control over structural integrity, tearing, and diagonal
bracing, you can build the cloth manually using
Matter.Constraint.create and a two-dimensional array of
bodies.
const { World, Bodies, Constraint } = Matter;
const cols = 15;
const rows = 10;
const spacing = 25;
const originX = 220;
const originY = 80;
const grid = [];
const group = Matter.Body.nextGroup(true);
// 1. Create Particles
for (let y = 0; y < rows; y++) {
grid[y] = [];
for (let x = 0; x < cols; x++) {
const isPinned = y === 0 && (x === 0 || x === cols - 1 || x === Math.floor(cols / 2));
const particle = Bodies.circle(
originX + x * spacing,
originY + y * spacing,
5,
{
isStatic: isPinned,
collisionFilter: { group: group },
frictionAir: 0.02
}
);
grid[y][x] = particle;
World.add(world, particle);
}
}
// 2. Link Particles with Constraints
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
// Horizontal link
if (x < cols - 1) {
World.add(world, Constraint.create({
bodyA: grid[y][x],
bodyB: grid[y][x + 1],
stiffness: 0.8,
render: { strokeStyle: '#888' }
}));
}
// Vertical link
if (y < rows - 1) {
World.add(world, Constraint.create({
bodyA: grid[y][x],
bodyB: grid[y + 1][x],
stiffness: 0.8,
render: { strokeStyle: '#888' }
}));
}
// Diagonal link (Shear resistance)
if (x < cols - 1 && y < rows - 1) {
World.add(world, Constraint.create({
bodyA: grid[y][x],
bodyB: grid[y + 1][x + 1],
stiffness: 0.4,
render: { visible: false } // Keep diagonal supports hidden
}));
}
}
}Tuning Cloth Parameters
stiffness: Ranges from0to1. A value near1.0yields stiff fabric (e.g., heavy denim or canvas), while values around0.1to0.4produce stretchy, rubber-like materials.damping: Adds resistance to constraint contraction and expansion, reducing excessive bouncing and vibrations.frictionAir: Adding small air friction (around0.02to0.05) to particles simulates atmospheric drag, helping the fabric settle naturally.- Constraint Iterations: High-tension cloths can sag
or stretch unnaturally if the physics engine solves constraints too few
times per frame. Increase
engine.constraintIterations(default is2) to6or10to maintain rigid links under heavy loads.