In this tutorial I will give an easy and intuitive explanation on how to code a cloth simulator using *Newtons second law*, *Verlet integration*, and *iterative constraint satisfaction*. I do not expect you to know these terms – or physics for that matter. The tutorial is accompanied by easy-to-read source code in object oriented C++. I have opted for a minimal dependency on external libraries (OpenGL and Glut) and kept all source code in a single cpp file.

#### Source Code

Source code including Visual Studio 2005 solution and Makefile

#### Motivation

I wrote my first cloth simulation in 2001 – and it was one of the most gratifying coding experiences I have had. The math involved can be easily understood intuitively, it does not take a long time to code, and the dynamic animation is (to me at least) an impressive emergent property of the very simple rules of particles of mass and interconnecting constraints. Furthermore I have found there to be many interesting applications of related techniques. One such example is the cardiac surgery simulator:

#### A cloth consists of particles and constraints

The simulation of cloth, is really about the simulation of particles with mass and interconnections, called constraints or springs, between these particles – think of them as fibers in the cloth. Particles move around in space due to forces that affect them – e.g. wind, gravity, or springs between particles.

##### Particles: from forces to positions

As a first step we would like to be able to affect particles with forces and calculate how much that shifts their position – within some small amount of time. To do that we need to use two pieces of knowledge.

- Force can be “translated” into acceleration through Newtons second law: acceleration = force/mass
- Acceleration can be “translated” into position by numerical integration – since position twice differentiated is equal to acceleration.

Item 1 is easy, and simply translates into the following method (on Particle class):

1 2 3 4 |
void addForce(Vec3 f) { acceleration += f/mass; } |

If item number 2 does not make intuitively sense to you, then think about a car moving along a road. If you plot a graph of the distance traveled over time, the gradient at a given time is the velocity of the car. If you plot the velocity on a graph and take the curvature at a given time you get the acceleration of your car (the change in velocity/speed). To go from acceleration to position we need to do the “inverse” of differentiation, namely integration. The integration routine we will use is called *verlet integration*. Pure verlet integation looks like this (but notice that we will modify it below to include damping in the source code)

1 2 3 |
Vec3 temp = pos; pos = pos + (pos-old_pos) + acceleration*TIME_STEPSIZE2 old_pos = temp; |

To understand this intuitively I like to think about the problem geometrically. Lets start with a particle that is not moving (pos and old_pos are the same). Lets say that we would like to push the particle by applying some acceleration vector: Intuitively, the particle should move in the direction of the acceleration vector. With that scenario in mind, the above verlet integration formula simply says to offset the current position by the acceleration vector. (The offset is scaled with the time step size to account for the fact that a particle should move a less amount when the piece of time is small, and vice-versa). In our current scenario the consequense is that the current position changes, and the old position stays the same.Now lets assume that we do not affect the particle with acceleration for the next time step. Intuitively, the particle should keep moving in the direction that we pushed it. The is realised through the term (old_pos-pos), a vector from old_pos to pos, in the verlet integration formula – implicitly representing a velocity vector. The next time step would consequently look like this: To get to the final code used in the project we will include some damping (to heuristically account for gradual loss of velocity due to e.g. air resistance). An easy way to do is to simply multiply the velocity vector (old_pos-pos) with an amount between 0 and 1. Closer to zero makes the particle mover slower and slower each time step. An amount closer to one allows the particle to move unrestricted. Since we would like to specify damping, the amount that we will multiply by is (1.0-DAMPING). This writes out like so:

1 |
pos = pos + (pos-old_pos)*(1.0-DAMPING) + acceleration*TIME_STEPSIZE2 |

The final source code for our verlet integration method in the Particle Class is then:

1 2 3 4 5 6 7 8 9 10 |
void timeStep() { if(movable) { Vec3 temp = pos; pos = pos + (pos-old_pos)*(1.0-DAMPING) + acceleration*TIME_STEPSIZE2; old_pos = temp; acceleration = Vec3(0,0,0); // acceleration is reset since it HAS been translated into a change in position (and implicitely into velocity) } } |

##### Constraints: move particles back into place !

Moving particles around is fine if you just want a simple particle system with no connections between them – but we want more! We would like to constrain the movement of particles, so that they try to stay in a grid. The more “effective” we are at returning all particles to the same relative position, the more rigid the cloth will behave. Notice that it is not an option to simply “reset” all particles to the original positon, since that contradicts our wish to affect the cloth with other forces such as wind and gravity. We will base our connections on constraints of distances between pairs of particles. Hence, each constraint between two particles has a distance that it would like to return to for the cloth to be at rest – we call that distance *rest_distance*. During the verlet integration, as explained above, particles move around, resulting in particles that are too far away from each other or too near each other. Therefor we introduce *constraint satisfaction* to modify the position of the two particles so that their distance is once again rest_distance. The following illustrations show two particles too far away from each other: Constraint satisfaction works by moving p1 and p2 along the line connecting them, so that they once again have a distance equal to rest_length. To maintain symmetry we will move p1 and p2 by the same amount (either towards each other, or away from each other to satisfy the constraint). As it turns out, if we find the vector (we call it corrrectionVectorHalf) to move p1 by, we can use that same vector in opposite direction to move p2. Consider the vector from p1 to p2. By itself, it is too long an offset vector to be used on p1 (it would bring it all the way to p2). We will find a factor to multiply this vector with, to allow p1 to satisfy (half) of the constraint. That factor is exactly *(1 – rest_distance/current_distance)*0.5*. The 0.5 comes from the fact that we move p1 only half the way to satisfy the constraint (p2 moves the other half). The rest of the factor can be interpreted as finding the percentage of the whole vector p1 to p2 that is beyond rest_length – that is, we take 100%, and subtract rest_distance as a percentage of the whole distance. All in all the satisfyConstraint method on the Constraint class looks like this:

1 2 3 4 5 6 7 8 9 |
void satisfyConstraint() { Vec3 p1_to_p2 = p2->getPos()-p1->getPos(); // vector from p1 to p2 float current_distance = p1_to_p2.length(); Vec3 correctionVector = p1_to_p2*(1 - rest_distance/current_distance); Vec3 correctionVectorHalf = correctionVector*0.5; p1->offsetPos(correctionVectorHalf); p2->offsetPos(-correctionVectorHalf); } |

#### The Cloth Class: Building the cloth

We will connect particles in a certain pattern to make the cloth behave realistically. The cloth should both stay in a grid in the plane of the cloth (structural constraints), resist shearing in the plane of the cloth (shear constraint), and resist bending (bending constraint). Below is illustrated how constraints are constructed for each particle (in red). Notice that the current (red) particle will end up having more constrains than shown since this pattern of constraints is repeated for each particle.In the accompanying source code the build-up of the cloth connections is realized in the Cloth constructor using Particles and Constraints.

#### The Cloth Class: blowing in the wind, gravity and collision with a ball

To make the cloth have an interesting dynamic behavior we will add wind forces and gravity. We will also handle collision with a moving ball. Adding gravity is very easy, we simply add an acceleration vector pointing down to all particles (through the addForce method on the Cloth object). Collision detection and handling is also relatively easy, and I will not go into much detail. The ball is defined by a center and a radius. Detecting collision is done by asking whether the particle is within the radius of the ball, if yes the collision is resolved by moving the particle out of the ball along the vector from center to particle so that the distance is equal to the radius of the ball. Adding wind is a bit more complicated, but results in a very nice effect. We will start by looking at the cloth as a collection of triangles of three particle each, and solve the problem of adding wind one triangle at a time – adding forces to the three particles the triangle consists of. The wind is coming in a certain direction, but forces should only be added in the direction of the normal of the triangle (or negative normal), and the amount of force affecting the triangle should be proportional to the angle (dot product) between the triangle and the wind. This all boils down to a simple formula for a single triangle:

1 2 3 4 5 6 7 8 9 |
void addWindForcesForTriangle(Particle *p1,Particle *p2,Particle *p3, const Vec3 direction) { Vec3 normal = calcTriangleNormal(p1,p2,p3); Vec3 d = normal.normalized(); Vec3 force = normal*(d.dot(direction)); p1->addForce(force); p2->addForce(force); p3->addForce(force); } |

#### Conclusion

I hope that you have enjoyed this tutorial and the source code, and that it helped you in some way. Please leave a comment below or email me (clothTutorial@jespermosegaard.dk) – that would mean a lot to me !

#### Further Reading

I have knowingly skipped a lot of theory, given intuitive explanations instead of complete mathematical proofs, and focused exclusively on a single set of choices for the representation of a cloth simulation. There is a lot more to explore on the subject of physics based animation, and below are a few pointers. My PhD on simulating heart surgery with GPU acceleration spring mass systems Advanced Character Physics by Thomas Jakobsen Cloth Simulation using Mass and Spring System

MNyers

Jun 6, 2009

Really nice tutorial, thx! It would be great to see a sequel about self-collision or cloth tearing.

James George

Jul 29, 2009

hey great little example, very clean.

Just a hint too, if you are on a multicore machine and can use OpenMP, simply multithreading the satisfyConstraints results in massive speed up

#pragma omp parallel for

for(int j=0; j < constraints.size(); j++ )

{

constraints[j].satisfyConstraint();

}

Scoot

Sep 28, 2009

Thx!! It’s really nice!

I ported it to Android, it runs very well.

psb

Nov 14, 2009

Thanks !! You are genius!!

Joshua

Jan 15, 2010

It is a good tutorial. Unfortunately, i can’t open the programming code and try it.

fillo

Apr 1, 2010

Hi! I’ve read this code, it’s really cool. Anyway when i execute it, the animation is really really slow :/ i see about a frame each 2 seconds! do you know how can i improve it and obtain the results that the video show? thank you 🙂

zingy

May 18, 2010

i tried running the code in linux machine but it gave me the following errors:

ClothSim.cpp: In constructor ‘Particle::Particle(Vec3)’:

ClothSim.cpp:137: warning: ‘Particle::acceleration’ will be initialized after

ClothSim.cpp:134: warning: ‘float Particle::mass’

ClothSim.cpp:141: warning: when initialized here

ClothSim.cpp:134: warning: ‘Particle::mass’ will be initialized after

ClothSim.cpp:132: warning: ‘bool Particle::movable’

ClothSim.cpp:141: warning: when initialized here

ClothSim.cpp: In member function ‘void Cloth::drawTriangle(Particle*, Particle*, Particle*, Vec3)’:

ClothSim.cpp:258: warning: taking address of temporary

ClothSim.cpp:261: warning: taking address of temporary

ClothSim.cpp:264: warning: taking address of temporary

ClothSim.cpp: At global scope:

ClothSim.cpp:464: error: ” has incomplete type

ClothSim.cpp:464: error: invalid use of ‘GLvoid’

ClothSim.cpp: In function ‘int main(int, char**)’:

ClothSim.cpp:464: error: too few arguments to function ‘void init()’

ClothSim.cpp:587: error: at this point in file

could u plz suggest me how to make it work?? thanks

王鹏

Jul 8, 2010

Hi, fillo !

You can run in Release mode (not debug mode).

GK

Jul 20, 2010

“If item number 2 does not make intuitively sense to you, then think about a car moving along a road. If you plot a graph of the distance traveled, the curvature at a given time is the velocity of the car.”

A graph of distance with respect to what? Time? Then velocity is the first derivative with respect to time. Curvature is the second derivative with respect to arc length – completely different things.

admin

Oct 12, 2010

GK: you are right. Text corrected. Thanks for pointing it out.

downloader

Oct 4, 2010

this is an awesome tutorial! I’d like to know how to run it as fast as demonstrated in the video 🙁

LG

Oct 20, 2010

Thanks. That really helps.

hazem

Dec 24, 2010

great work … but would you tell me why it is so slow , or could i enhance its speed ..thx 🙂

hazem

Dec 25, 2010

could anyone tell me how i can enhance its speed plz ?

hazem

Dec 27, 2010

I’ve managed to speed it up 🙂

Alireza Sokhandan

Mar 31, 2011

Simple and great

Thanks a lot for this tutorial

safegaard

Apr 5, 2011

Great work. Nice to see another dane on the web, and specialy one like you who are sharing your knowledge like your do.

Tak for det 🙂

waseem

May 4, 2011

hii

thanx about this ,this is very very good

but want to ask you about something

i am studying and in my study make a project online shopping cloth through 3d model

i want to help me by any way i am in level of coding mass spring model to dress the model the cloth how i can start or what i can do

help me plz thanx

Purva Kulkarni

Jun 10, 2019

Hi, It’s been too long. But if you are still interested, I have made a similar project which converts a 2D clothing image into a 3D model using OpenCV and OpenGL. Please check it out->https://www.youtube.com/watch?v=J9FKRR8HsP4&t=20s

Berg

May 18, 2011

Whoa! That’s a cool effect. Thanks for the code. My physics is a bit rusty but I’ll take your word for it on Newton’s law.

herman

May 18, 2011

Hi,

this is a great tutorial but I got a problem here.

How can I simulate a strteching effect such as using two fingers to pull down the cloth?

I tried to add force to it but the results seems not good. Is any tip to simulate this scenario?

Thanks for your help

firebird

May 31, 2011

Thank you very much.

Your article is the best guide about cloth emulation i have ever found.

HRuivo

Jun 9, 2011

Thank you very much, I have been looking for a good tutorial about cloth and yours is definitely the best. Really easy to follow and to understand.

geotavros

Jul 1, 2011

http://www.youtube.com/watch?v=In_WUm1Gsrc

I have successfully ported your algorithm to OpenCL 🙂

NKAID

Sep 8, 2011

Very impressive that tutorial

Anand

Feb 8, 2012

Thanks a lot of this write up.. really helpful

wqs

Mar 19, 2012

hi,

Thanks for you sharing that tutorial,it helps me much.But I have a problem that how to handle cloth self-collision? I hope your can help me,thanks!!!

admin

Apr 19, 2012

The current tutorial does not cover self-collision, and I have not looked into recent results in this area – a brute force method might work for a small enough resolution.

wqs

Mar 19, 2012

hi,

Thanks for you sharing that tutorial,it helps me much.But I have a problem that how to handle cloth self-collision? I hope your can help me,thanks!!!

wqs

jery

Apr 18, 2012

hii,

I’m still studying and doing my project on cloth simulation.

Your tutorial really help me a lot and it’s very impressive. But i would like to know more about the technique your using since i don’t really understand the code and is there any way to speed it up?

can i use other technique like Implicit Midpoint Integration Method and how can i start it or what can i do.

Hope you can help me. Thank you.

admin

Apr 19, 2012

Lot’s of things could speed up the code – if enough people want it, I could do a tutorial on optimization of the cloth code.

ted

Apr 25, 2012

Of course we do 😀

cybercser

Jun 11, 2012

Really intuitive and simple tutorial!! It saves a lot of time for cloth simulation greenhand like me.

ppalasek

Jun 13, 2012

Hello! Thank you for the tutorial!

I just wanted to ask if it is possible that there is an error in your PhD thesis, on page 53, equation (5.6), shouldn’t it be x(t+dt)=(2-lambda)x(t)-(1-lambda)x(t-dt)+x”(t)dt^2 instead of x(t+dt)=x(t-dt)(1-lambda)x(t)lambda

I’m working on a mass spring system and I found your thesis and this website. They are very useful.

Thank you!

Nico

Jul 8, 2012

Very nice tutorial, thank you. It is nice when one is searching for a simple yet effective implementation of something and it appears.

jay

Jul 24, 2012

Thats a very nice tutorial.. Easy to understand,very intuitive ,informative and helpful… Many thanks..!

rsq

Dec 29, 2012

very good i understand it

jiangxu082@gmail.com

Jan 29, 2013

very nice tutorial!

Ian

May 11, 2015

Hi Jesper! This page was very helpful in a course project in which I look into accelerating it with CUDA. You can see my results here:

https://www.andrew.cmu.edu/user/iheath/418/cloth/CUDAClothSimulatorFinalReport.html

Ted

Jun 27, 2015

Great, thank you!

Xincheng Yuan

Apr 29, 2017

Hi, I’m impressed with your nice tutorial. The source code link doesn’t seem to work anymore. Do you still have the source code? I would like to look at it.

Jesper Mosegaard

Jun 8, 2017

Thanks :). The link has been fixed.

Mark

Jul 5, 2017

Thanks a lot!

Have you any suggestion on how to implement collisions with other objects, such as cube, torus, or a cone…? I would appreciate that.

Have a nice day!

Jesper Mosegaard

Aug 3, 2017

You should have a look at literature or introduction to collision handling, those cases are also described

Saman

Jul 28, 2017

Hi, such a great job, thanks Jasper.

Although it is an old source code, I could manage to make it works. It seems that you haven’t written the code based on shaders (to speed up the code using GPU). It would be a good practice for everyone to rewrite the code using the modern OpenGL and its shading language. I really liked the idea of doing everything from the pure code, e.g. adding a texture to the cloth!

Jesper Mosegaard

Aug 3, 2017

Thank you so much. And you are right, the code is before moderne OpenGL. Perhaps one day I should make a WebGL version for easy accessibility 😉 Regards. Jesper

David Escobar Castillejos

Oct 10, 2018

Thanks for the great tutorial Jesper. I would like to know if you could give some advices about how to scalete the concepts and coding you developed but with 3d models. I’m really interested in learning how to apply this tutorial to them (as you did with you surgery simulator). Sincerely, David.

sharun

Aug 8, 2017

really nice turorial

Organism Documentation – Allan's Research Blog

Feb 13, 2018

[…] I’ve completed the code that generates nodes and binds them together via muscles or “constraints”. The code that runs the physics simulation is adapted from a cloth simulation program written in C++ provided by Jesper Mosegaard at https://viscomp.alexandra.dk/?p=147. […]

Victor

Apr 16, 2018

Thanks! I was wondering how to apply forces as vec3

Sotiris Salloumis

Jul 21, 2018

Thanks for sharing, well written tutorial and source code of excellent quality ! Worked fine also on Mac OS. Congrats keep up sharing !

Javier corra

Nov 6, 2018

Thank you for this great article!!, I just found an implementation of this in the ThreeJS library and I thought it would be impossible for me to understand the inner workings but I got it thanks to you!

Marcio Barcellos

Jul 9, 2019

Thank you for sharing!