Page 2: Cloth Simulation
In this page, we’re going to learn how to create a simple cloth simulator using THREE.js and the CS559 framework. We’ll start from the basics and build things up step by step.
Here’s what we’ll cover:
- Modeling cloth with a mass–spring system: how to represent cloth as particles and springs (spatial discretization).
- Simulating motion over time: how to update the cloth step by step so it moves naturally (temporal discretization).
- Numerical issues: what can go wrong (like instability or stretching) and how to address these problems.
- Making it realistic: adding details so the cloth looks and behaves more like the real thing.
By the end, you’ll have your very own cloth simulation running in the browser — and a better understanding of how physics-based simulation works in computer graphics.
(If you need a bit of convincing about why cloth simulation matters, check out this Virtual Runway demo. It shows how realistic cloth movement can bring graphics and animation to life.)
Modeling Cloth with a Mass–Spring System
When building a cloth simulation, the first question you might ask is:
“How can we represent cloth in a computer so that it makes sense to the program?”
The key difference between cloth and the rigid objects we’ve dealt with so far is that cloth cannot be represented by a single transformation matrix. For rigid objects, the relative positions of vertices never change, so storing one matrix for translation, rotation, and scaling is sufficient.
Cloth, however, behaves differently. The relative positions between its particles change over time because it deforms. That means we need to track the position of every vertex individually and compute the forces acting on each one.
One of the simplest and most intuitive ways to model this behavior is with a mass–spring system, as shown below:
In this tutorial, we’ll represent cloth as a mass–spring model, where each mass point is connected to its neighbors by springs. These springs follow Hooke’s law, which states that the force of a spring is proportional to how much it is stretched or compressed:
- : spring stiffness constant
- : amount of stretch or compression (current length – rest length)
- : unit vector pointing from one mass point to the other
For more details on the physics, see Hooke’s law.
Time Integration
In the previous section, we learned how to model cloth with a data structure that the computer can understand — a process called spatial discretization. Now, we need to think about time discretization: how to update the system step by step over time.
In other words:
“If we know the current positions and velocities of the mass points, how can we determine their positions in the next moment?”
Explicit Euler Integration
One of the simplest approaches is the Explicit Euler method. The idea is straightforward:
-
Compute acceleration using Newton’s second law:
-
Update velocity:
-
Update position:
Now, we have all the core components needed to build a basic cloth simulation!
Simple Mass–Spring Simulation
Let’s start with a simple mass–spring simulation. Please read
10-02-01.js
, which implements a single mass–spring system.
In this code, the stepWorld function performs time integration: it calculates spring forces using Hooke’s law, computes acceleration, updates velocity, and finally determines the next position of the mass point. The code is short, so you should be able to follow it easily.
Try increasing the timestep or the spring constant. You’ll notice the simulation becomes inaccurate and eventually blows up (values go to NaN).
Is this a bug in our code? Fortunately (or unfortunately), it isn’t. The instability comes from numerical errors in the time integration method. Since Explicit Euler updates positions and velocities using only the current state, errors accumulate over time, leading to increasingly large spring forces and eventual instability.
Things get worse in more complex systems:
In
10-02-02.js
, which implements four connected mass–spring points, try running the same settings with timestep = 0.03 in both
10-02-01.js
(single spring) and
10-02-02.js
(four springs). You’ll see that while the single spring might remain stable, the four-spring system blows up. This shows that larger systems with more springs are much more susceptible to instability.
Simulation code can be tricky — when something goes wrong, it’s often hard to tell whether it’s a bug or numerical instability. To handle this, always start with simple scenarios and mild settings (small timestep, low spring stiffness), and include code that checks for NaN values (NaN means “Not a Number”). You can find NaN detection code inside the stepWorld function.
In the next example, you can experiment with higher-resolution cloth and observe how instability increases with more mass points, stiffer springs, or stronger gravity:
The UI also includes a “damping” slider. Damping helps reduce instability by scaling down velocity each timestep:
mass.velocity.multiplyScalar(damping);
You’ll notice that higher damping (smaller damping factor) makes the simulation more stable. However, this damping is not physically realistic — it doesn’t follow any real-world physics. If the damping is too strong, the motion freezes; if it’s too weak, the system becomes unstable.
In the next section, you will learn how to make the simulation more stable in a physically accurate way.
Toward More Stable and Realistic Simulation
Our simulator ( 10-02-03.js ) works, but it’s far from realistic. It’s either unstable or static due to excessive damping. In this section, we’ll add new features to improve both realism and stability.
1. Realistic Damping
Previously, we used a non-physical damping term. In reality, drag force is proportional to the square of velocity:
Here, is the drag coefficient. This force slows particles down in a way that resembles air resistance. The total acceleration becomes:
Unlike artificial damping, this model is physically realistic. Because it scales with velocity, it applies stronger damping only when particles move faster — keeping motion lively and natural.
2. More Stable Integration
Previously, our Explicit Euler integration updated blindly using only the current values:
What if we try updating with future values instead?
Here, depends on the unknown future state.
To compute this, we need to solve a nonlinear equation, for example:
By substituting the second equation into the first, we end up with a root-finding problem in terms of .
This is the Implicit Euler integration scheme.
The benefit is that it’s extremely stable — instead of letting errors grow, it tends to damp them out over time.
The downside is that each timestep requires solving a nonlinear equation, which is computationally expensive.
Still, implicit schemes are the industry standard — as you saw in the Virtual Runway video, most state-of-the-art cloth simulation systems and commercial software rely on them.
Since solving nonlinear equations is a deeper topic (if you’re interested, check out a Numerical Analysis course at UW–Madison), we won’t go into it here.
Instead, we’ll look at an integration scheme that lies between explicit and implicit methods.
It’s called the Symplectic Euler (Semi-Implicit Euler) scheme.
It uses the current acceleration to update velocity, and then uses the updated velocity to compute the next position:
This small change makes the simulation much more stable than the explicit Euler scheme, while still keeping the implementation simple.
(Other integration schemes, such as Verlet integration, are also simple to implement and help improve stability.)
3. Additional Spring Types
So far, we have only used structural springs, which makes the simulation look more like a net than actual cloth. To improve realism, we can add other types of springs, as shown below:
- Shear springs: connect diagonal neighbors to prevent the cloth from collapsing into parallelogram shapes.
- Bending springs: connect vertices two steps apart, adding resistance to folding and floppiness.
Implementing these springs results in much more natural-looking motion.
4. Meshing the Cloth
Up to this point, our cloth ( 10-02-03.js ) has existed only as a grid of particles connected by springs. To visualize it as real cloth, we need to convert this grid into a triangular mesh that can be rendered. Each particle becomes a vertex, and every small square of four neighboring points is divided into two triangles. By connecting all the points this way, we form a smooth rectangular surface — the standard representation used by rendering engines like THREE.js.
If you complete meshing the cloth, you can also try adding texture. For texturing, you have to manually map each mass point to texture coordinates (UVs).
Now, let’s create your own cloth simulator!
Implement the concepts discussed so far in
10-02-04.js
.
If you successfully complete this step, your cloth should appear both stable and realistic. You are also encouraged to add your own improvements to make the simulation more dynamic and visually appealing.
Below are the requirements for this exercise.
Basic Items
10-02-04
- The default simulation settings should be numerically stable.
- Include UI controls for interactivity (e.g., moving or adjusting cloth corners through the interface).
- Implement a more stable integration method such as Symplectic Euler or Verlet integration.
- Implement a drag (air resistance) force, with parameters adjustable through the UI.
- Convert the cloth into a triangular mesh for rendering.
Advanced Items
10-02-04
- The simulation should show dynamic motion (e.g., fluttering in the wind). Be creative with your scenario!
- Implement shear and bending springs, and add a wireframe view option in the UI to visually show different spring connections.
- Add texture mapping to the cloth surface.
- Implement collision with an object (e.g., a sphere).
- Introduce technically challenging and visually noticeable features, such as:
- self-collision (collision between cloth particles and springs)
- collision with complex objects or meshes
- tearing effects
- or other creative extensions
Advanced References
If you’d like to learn more about physics-based simulation, check out these resources:
- Physics-Based Simulation: A comprehensive and up-to-date tutorial series on physics-based simulation.
- Large Steps in Cloth Simulation: The first stable cloth simulation paper (implicit integration). This paper explains how to solve nonlinear equations arising from implicit integration.
- Physics-Based Animation Blog by Christopher Batty: Modern research and tutorials on simulation in graphics.
- Real-Time Collision Detection: A classic textbook on efficient collision detection.