Create an Origami Folding Structure in Matter.js

This article explains how to build an origami-style folding mechanism in Matter.js by modeling rigid polygonal plates and connecting them with rotational hinges. By combining Matter.js rigid bodies, custom collision filtering, and distance constraints configured as pivot joints, you can simulate kinetic origami patterns such as Miura-ori folds or accordion hinges within a 2D physics environment.

1. Representing Origami Facets as Rigid Bodies

In origami simulations, the flat polygonal facets act as rigid bodies that do not deform. In Matter.js, these are created using either Matter.Bodies.rectangle for uniform panels or Matter.Bodies.fromVertices for arbitrary polygonal shapes.

When setting up the bodies, adjust their physical properties to allow realistic movement:

const plateOptions = {
    density: 0.001,
    friction: 0.1,
    frictionAir: 0.02,
    restitution: 0.0
};

// Example: Creating two adjacent rectangular plates
const plateA = Matter.Bodies.rectangle(200, 300, 100, 10, plateOptions);
const plateB = Matter.Bodies.rectangle(295, 300, 100, 10, plateOptions);

2. Preventing Self-Collision Between Adjacent Plates

Adjacent plates sharing an edge will continuously overlap at the hinge during rotation. To prevent jitter and unrealistic physics collisions at the joint, configure collision filtering using a shared negative group index or discrete category bitmasks.

const origamiGroup = Matter.Body.nextGroup(true);

plateA.collisionFilter.group = origamiGroup;
plateB.collisionFilter.group = origamiGroup;

Bodies sharing a negative group value will never collide with each other, allowing them to pivot freely around shared edges.

3. Creating Revolute Hinges with Constraints

Matter.js does not have a dedicated "hinge" joint, but a revolute joint is formed by creating a Matter.Constraint with a length of 0 and a stiffness of 1 (or close to 1 to avoid simulation instability). The anchor points (pointA and pointB) must be placed at the respective shared boundary vertices of the two plates.

// Hinge positioned at the right edge of plateA and the left edge of plateB
const hinge = Matter.Constraint.create({
    bodyA: plateA,
    pointA: { x: 50, y: 0 }, // Relative to plateA's center
    bodyB: plateB,
    pointB: { x: -50, y: 0 }, // Relative to plateB's center
    length: 0,
    stiffness: 0.95
});

4. Actuating the Fold

Origami structures require external forces or internal torques to fold and unfold. You can actuate the joints using two primary methods:

// Actuation constraint acting as an elastic muscle across the hinge
const foldSpring = Matter.Constraint.create({
    bodyA: plateA,
    pointA: { x: 0, y: -10 },
    bodyB: plateB,
    pointB: { x: 0, y: -10 },
    stiffness: 0.01,
    length: 20 // Shorter length forces the plates to fold together
});

5. Assembly and Simulation Loop

Add all created plates, hinges, and actuation springs to your simulation world.

const { Engine, Render, Runner, Composite } = Matter;

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

Composite.add(world, [plateA, plateB, hinge, foldSpring]);

const render = Render.create({
    element: document.body,
    engine: engine,
    options: {
        width: 800,
        height: 600,
        wireframes: false
    }
});

Render.run(render);
Runner.run(Runner.create(), engine);

By chaining multiple plates together in alternating mountain and valley orientations, this setup scales into complex, multi-panel origami mechanisms such as deployable solar arrays and tessellations.