Mass-Spring Cloth

A cape billowing behind a hero, a flag snapping in the wind, a tablecloth settling over a table's edge — animated cloth looks alive because it is simulated, not keyframed. The workhorse model, introduced by Xavier Provot in 1995, is beautifully simple: pretend the fabric is a grid of tiny point masses stitched together by springs. Each mass feels gravity, wind, and the tug of its springy neighbours; you add up those forces, take a small step forward in time, and repeat. Do that thirty times a second and the grid drapes, folds and flutters like real fabric.

This page builds that model from its three kinds of spring, shows the per-step update loop, and then confronts the one thing that makes cloth genuinely hard: real fabric barely stretches, and forcing a mass-spring grid to barely stretch makes the equations stiff — stiff enough to blow an explicit simulation to infinity in a handful of frames. We meet the classic cures, and drape a little pinned patch under gravity you can play with.

The model: masses joined by three kinds of spring

Lay a regular grid of point masses, one at each fabric vertex — say an n \times m lattice. Every mass i has a position \mathbf{x}_i, a velocity \mathbf{v}_i, and a mass m_i. Now connect them with springs. Provot's insight was that one kind of spring is not enough — a grid of only horizontal-and-vertical springs shears and folds like a floppy trellis. You need three distinct connection patterns, each resisting a different way the cloth can deform.

Each spring stores a rest length L_0 (its length in the flat, undeformed cloth) and a stiffness k. When the spring's current length differs from L_0, it pulls its two ends back toward rest with a Hooke's-law force.

The spring force

Take a single spring between masses i and j. Let \mathbf{d} = \mathbf{x}_j - \mathbf{x}_i be the vector from one to the other, with current length \lVert \mathbf{d} \rVert. Hooke's law says the force on mass i points along the spring, proportional to how far it is stretched past its rest length:

\mathbf{F}_{i} \;=\; k\,\bigl(\lVert \mathbf{d} \rVert - L_0\bigr)\,\frac{\mathbf{d}}{\lVert \mathbf{d} \rVert}.

The bracket (\lVert \mathbf{d} \rVert - L_0) is the strain (positive = stretched, negative = compressed); the unit vector \mathbf{d}/\lVert \mathbf{d} \rVert gives the direction. Mass j feels the equal-and-opposite -\mathbf{F}_i. Real implementations add a damping term proportional to the relative velocity along the spring, so oscillations bleed away instead of ringing forever:

\mathbf{F}^{\text{damp}}_{i} \;=\; c\,\bigl[(\mathbf{v}_j - \mathbf{v}_i)\cdot \hat{\mathbf{d}}\bigr]\,\hat{\mathbf{d}}, \qquad \hat{\mathbf{d}} = \frac{\mathbf{d}}{\lVert \mathbf{d} \rVert}.

The per-step update loop

Simulating the cloth is a loop over small time steps \Delta t. Each step does the same four things:

A cloth of a few thousand masses with three spring types is tens of thousands of springs — but each is a handful of multiplies, so the whole update is cheap. The choice of integrator in step three is where cloth simulation lives or dies, as we are about to see. For the full menu of schemes see numerical integration for animation.

The stretching problem: cloth is stiff

Here is the crux. Take a shirt in both hands and pull: it hardly lengthens at all — maybe a percent or two before it resists hard. To reproduce that "barely stretches" behaviour, the structural springs must be very stiff — a huge k. But a stiff spring produces enormous restoring forces for tiny displacements, and those forces swing back and forth extremely fast. The differential equation becomes what numerical analysts call stiff: it contains oscillations far faster than the motion you care about.

An explicit integrator (plain forward Euler, or even RK4) is only stable if the step \Delta t is small enough to resolve the fastest oscillation. For a spring of stiffness k and mass m, that oscillation has angular frequency \omega = \sqrt{k/m}, and stability roughly demands:

\Delta t \;\lesssim\; \frac{2}{\omega} \;=\; 2\sqrt{\frac{m}{k}}.

Crank k up by 100× to stiffen the cloth and the allowable step shrinks by \sqrt{100} = 10×. Push k high enough for realistic cloth and \Delta t must be so tiny you would need hundreds of substeps per frame; overshoot it by a hair and each step amplifies the error, the springs fling their masses further every step, and the whole sheet explodes to infinity within a few frames. That is the central tension of cloth: realistically inextensible fabric makes the naive method unstable.

Three classic cures

The field solved this three ways, and production systems mix them:

The common thread: don't try to make an explicit spring solver represent near-inextensible cloth by brute force. Either limit the strain, integrate implicitly, or constrain the positions.

Pinning, collision and self-collision

A free grid under gravity just falls. To hang a flag you pin its attached edge: mark those masses as fixed — infinite mass, or simply skip their integration so their positions never change. Everything downstream drapes from the pinned anchors. Pinning two corners of a banner, or the shoulders of a cape, is exactly this.

Cloth must also not pass through the character wearing it. Collision against the body detects masses that have penetrated a collision proxy (spheres, capsules, the mesh) and pushes them back out along the surface normal, killing the inward velocity component. Self-collision — stopping the cloth from passing through itself so folds stack instead of interpenetrating — is far costlier: it needs spatial acceleration structures to test many mass/triangle pairs each frame, and is a classic source of cloth-sim slowness and instability.

Watch it drape

Below is a small mass-spring grid pinned at its two top corners. Drive the gravity / sag slider from 0 (flat, undeformed) up toward 1 (full droop): the interior masses fall, the structural springs along the top row stretch to carry the load, and the sheet settles into the gentle catenary-like curve real hanging fabric takes. The two pinned corners never move — everything hangs from them.

Watch the top row as you increase the sag: those springs stretch the most, because they carry the weight of everything below. That is precisely where strain limiting bites first.

Worked example: a patch pinned at two corners

Take a 3 \times 3 patch, rest spacing L_0 = 1, each mass m = 0.1\,\text{kg}, pinned at the two top corners P_1 and P_2. Release it under gravity.

Which springs stretch? The whole sheet hangs from the two pins, so the top-row structural springs — the ones directly connecting the interior top mass to the pinned corners — carry the entire weight below them and stretch the most. The diagonal shear springs lengthen too as the middle sags into a shallow V, while the bottom-row springs barely change (little hangs beneath them). If the structural springs are soft, the top edge visibly lengthens — the sheet droops far lower than a real cloth of that size would.

How strain limiting caps the sag. Suppose after a step the top-row springs have stretched to length 1.25 — a 25\% strain, well past Provot's 10\% cap. Strain limiting shortens each offending spring back to at most 1.10 by moving its movable end (the pinned end can't move) toward the anchor:

\text{allowed length} = (1 + 0.10)\,L_0 = 1.10, \qquad \text{so the free end is pulled inward until } \lVert \mathbf{d} \rVert \le 1.10.

Applied every step across the sheet, this caps the cumulative stretch: no chain of springs can elongate past roughly 10% of its rest length, so the patch settles at a realistic droop instead of drifting ever lower like taffy — and all with soft, cheap, stable springs.

When a character teleports, or the frame rate hitches so \Delta t suddenly balloons, the stability bound \Delta t \lesssim 2\sqrt{m/k} is momentarily violated. For that one big step the explicit solver over-corrects, springs overshoot, and the cloth wobbles like jelly or shudders before the constraint solver reels it back in. It is the same explosion that would run away forever with stiff springs — just caught and damped after a frame. Engines guard against it by clamping the step size, taking multiple substeps per frame, and leaning on PBD's position projection, which stays stable no matter how large the step.

The tempting fix for a floppy simulation is to reach for the stiffness dial: soft structural springs let the cloth stretch like rubber — a cape that lengthens like chewing gum as the hero runs — so surely just crank k up until it stops? No. With an explicit integrator, a bigger k shrinks the stable step as 1/\sqrt{k}, and past a modest value the simulation explodes — masses fly off to infinity within a few frames. You cannot buy inextensibility by cranking k in an explicit solver. The right tools are strain limiting (clamp the geometry after the step), implicit integration (unconditionally stable, so big k is safe), or position-based constraints (enforce the rest length directly). Keep the springs soft, and make the fabric inextensible some other way.

Xavier Provot's 1995 Graphics Interface paper, "Deformation Constraints in a Mass-Spring Model to Describe Rigid Cloth Behavior," gave us the three-spring grid and the strain-limiting trick in one shot. Three years later Baraff and Witkin's SIGGRAPH 1998 paper "Large Steps in Cloth Simulation" showed that implicit integration let you take frame-sized steps with stiff cloth — the breakthrough that put believable cloth in films. Position-based dynamics (Müller and colleagues, mid-2000s) then made stable cloth fast enough for real-time games. Thirty years on, every one of these ideas is still in the pipeline you see in modern DCC tools.