### 17. Cloth Physics

By Diederick Huijberts en Rick Companje (Feb 2011)

Springs are structural elements that, when connected between two objects (particles), apply equal and opposite forces to each object.
Simple cloth physics use multiple springs connected to particles in a grid.

#### Vimeo video

The rule related to spring forces is called Hooks law: f = -k * delta L
-k  = spring length: in code just a float strength which often gets a value like 0.1 or 0.001 etc.
delta L = difference between springs "compressed/rest length" and current length.

In simple cloth physics particles are positioned on a grid and then connected by 3 kind of springs:
• structural springs
• shear springs
• bending springs

## testApp.h

```#ifndef _TEST_APP
#define _TEST_APP

#include "ofMain.h"
#include "ofxVectorMath.h"
#include "Particle.h"
#include "Spring.h"

class testApp : public ofBaseApp{
public:
void setup();
void update();
void draw();

vector<Particle> ps;
vector<Spring> sp;
};

#endif```

## Particle.h

```#ifndef PARTICLE_H
#define PARTICLE_H

#include "ofMain.h"

struct Particle {
ofxVec3f pos,vel,forces;
float mass,inverse_mass,drag;

Particle(ofxVec3f pos, float mass, float drag = .96) : pos(pos), mass(mass), drag(drag) {
if (mass==0.0f) inverse_mass = 0;
else if (mass<0.001) mass=0.001;
if (mass!=0.0f) inverse_mass = 1/mass;
}

void update() {
forces *= inverse_mass;
vel += forces;
forces = 0;
vel.limit(15);
pos += vel;
vel *= drag;
}

forces += oForce;
}
};```

## Spring.h

```#ifndef SPRING_H
#define SPRING_H

#include "ofMain.h"
#include "Particle.h"

struct Spring {
Particle *a, *b;
float k;
float rest_length;

Spring(Particle *a, Particle *b, float k = .2) : a(a), b(b), k(k) {
rest_length = (b->pos - a->pos).length();
}

void update() {
ofxVec3f dir = b->pos - a->pos;
float dist = dir.length();
if (dist == 0.0) dist = 0.0001; // prevent division by zero
float f = (rest_length - dist) * k; // linear force spring
dir.normalize();
}
};

#endif```

## testApp.cpp

```#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
ofBackground(0,0,0);
ofSetFrameRate(60);
ofEnableSmoothing();

int rows = 20;
int cols = 20;

//position all particles
for (int i=0; i<rows*cols; i++) {
int x = int(i) % cols * 20;
int y = int(i) / cols * 20;
Particle p(ofxVec3f(x,y,0), y==0 ? 0 : 1, .96);
ps.push_back(p);
}

//create all springs
for (int i=0; i<rows*cols; i++) {
int x = int(i) % cols;
int y = int(i) / cols;

//horizontal structural springs
if (x<cols-1) {
sp.push_back(Spring(&ps[i],&ps[i+1]));
}

//vertical structural springs
if (y<rows-1) {
sp.push_back(Spring(&ps[i],&ps[i+cols]));
}

//shear springs left to right
if (x<cols-1 && y<rows-1) {
sp.push_back(Spring(&ps[i],&ps[i+cols+1]));
}

//shear springs right to left
if (y>0 && x<cols-1 && y<rows) {
sp.push_back(Spring(&ps[i],&ps[i-cols+1]));
}

//bending springs horizontal
if (x<cols-2) {
sp.push_back(Spring(&ps[i],&ps[i+2]));
}

//bending springs vertical
if (y<rows-2) {
sp.push_back(Spring(&ps[i],&ps[i+2*cols]));
}

//bending springs diagonal
if (y<rows-2 && x<cols-2) {
sp.push_back(Spring(&ps[i],&ps[i+2+2*cols]));
}
}

}

//--------------------------------------------------------------
void testApp::update(){

//apply forces
for (int i=0; i<ps.size(); i++) {
}

//update springs
for (int i=0; i<sp.size(); i++) {
sp[i].update();
}

//update particles
for (int i=0; i<ps.size(); i++) {
ps[i].update();
}

}

//--------------------------------------------------------------
void testApp::draw() {

ofTranslate(ofGetWidth()/2-200, 100, -300);

//springs
ofSetColor(255, 255, 255);
glBegin(GL_LINES);
for (int i=0; i<sp.size(); i++) {
glVertex3f(sp[i].a->pos.x, sp[i].a->pos.y, sp[i].a->pos.z);
glVertex3f(sp[i].b->pos.x, sp[i].b->pos.y, sp[i].b->pos.z);
}
glEnd();

//particles
ofSetColor(0, 0, 255);
glPointSize(5);
glBegin(GL_POINTS);
for (int i=0; i<ps.size(); i++) {
glVertex3f(ps[i].pos.x, ps[i].pos.y, ps[i].pos.z);
}
glEnd();
}```
ċ
clothPhysics.zip
(2481k)
Rick Companje,
6 dec. 2011 10:20