Create Grid Soft Bodies with Matter.Composites.mesh

This guide explains how to create a flexible, grid-based soft body simulation in Matter.js using Matter.Composites.mesh. You will learn how to generate an array of physical bodies using Matter.Composites.stack, bind them together into an elastic lattice using Matter.Composites.mesh, and adjust constraint stiffness and bracing to control deformation and bounce.

Understanding How Matter.Composites.mesh Works

In Matter.js, Matter.Composites.mesh does not generate rigid bodies on its own. Instead, it takes an existing composite containing bodies arranged in rows and columns and automatically generates horizontal, vertical, and optional diagonal distance constraints between neighboring bodies.

The method accepts five arguments:

Matter.Composites.mesh(composite, columns, rows, crossBrace, options);

Step-by-Step Implementation

1. Set Up the Engine and Renderer

Begin by aliasing Matter.js modules and initializing the engine, world, and canvas renderer.

const { Engine, Render, Runner, Bodies, Composite, Composites, Mouse, MouseConstraint } = Matter;

const engine = Engine.create();
const world = engine.world;

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. Create the Particle Grid with Composites.stack

Before calling mesh, create a regular grid of particle bodies using Composites.stack. Small circular bodies with reduced friction work best for soft body nodes.

const columns = 6;
const rows = 6;
const particleRadius = 15;
const startX = 300;
const startY = 100;
const gap = 10;

// Create a composite grid of circular bodies
const particleGrid = Composites.stack(
  startX, 
  startY, 
  columns, 
  rows, 
  gap, 
  gap, 
  (x, y) => {
    return Bodies.circle(x, y, particleRadius, {
      friction: 0.05,
      restitution: 0.1,
      density: 0.002,
      render: {
        fillStyle: '#3498db'
      }
    });
  }
);

3. Connect the Nodes with Composites.mesh

Pass the created particleGrid into Composites.mesh. Define constraint properties inside the options parameter to control flexibility.

const softBody = Composites.mesh(
  particleGrid,
  columns,
  rows,
  true, // Enables diagonal cross-bracing to prevent collapsing
  {
    stiffness: 0.4,       // Lower values (e.g., 0.1) make it gelatinous; higher values (e.g., 0.9) make it stiff
    damping: 0.05,        // Absorbs oscillation energy over time
    render: {
      visible: true,
      lineWidth: 2,
      strokeStyle: '#2980b9'
    }
  }
);

// Add the soft body to the world
Composite.add(world, softBody);

4. Add Boundaries and Interactivity

Add static boundaries and a mouse constraint so you can grab, pull, and observe the soft body deformation.

// Add a static floor and walls
const ground = Bodies.rectangle(400, 580, 810, 40, { isStatic: true });
const leftWall = Bodies.rectangle(10, 300, 20, 600, { isStatic: true });
const rightWall = Bodies.rectangle(790, 300, 20, 600, { isStatic: true });
Composite.add(world, [ground, leftWall, rightWall]);

// Add mouse interaction
const mouse = Mouse.create(render.canvas);
const mouseConstraint = MouseConstraint.create(engine, {
  mouse: mouse,
  constraint: {
    stiffness: 0.9,
    render: { visible: false }
  }
});
Composite.add(world, mouseConstraint);
render.mouse = mouse;

Key Configuration Tips