Cloth simulation

FULL SCREEN

Particles and forces

The simulation of cloth is about the simulation of particles with mass and interconnections, called constraints between these particles.

To be able to affect particles with forces and calculate how much that shifts their position we need two things:

  • Newton second law, to translate force into acceleration:

{\displaystyle {\vec {a}}={\frac {1}{m}}\sum _{i}{{\vec {\mathrm {F} }}_{i}}}

  • Verlet integration, to translate acceleration into position:

{\displaystyle {\vec {x}}(t+\Delta t)=2{\vec {x}}(t)-{\vec {x}}(t-\Delta t)+{\vec {a}}(t)\Delta t^{2}+O(\Delta t^{4}).\,}

Particle Class in Javascript :

function Particle( x, y, z, mass ) {

  this.position = clothFunction( x, y ); // position
  this.previous = clothFunction( x, y ); // previous
  this.original = clothFunction( x, y );
  this.a = new THREE.Vector3( 0, 0, 0 ); // acceleration
  this.mass = mass;
  this.invMass = 1 / mass;
  this.tmp = new THREE.Vector3();
  this.tmp2 = new THREE.Vector3();

}

Method add Force:

// Force -> Acceleration

Particle.prototype.addForce = function( force ) {

  this.a.add(
    this.tmp2.copy( force ).multiplyScalar( this.invMass )
  );

};

Method to compute Verlet intgration, here lithgly modified for adding damping (DRAG = 1-DAMPING ):

  // Performs Verlet integration
Particle.prototype.integrate = function( timesq ) {

  var newPos = this.tmp.subVectors( this.position, this.previous );
  newPos.multiplyScalar( DRAG ).add( this.position );
  newPos.add( this.a.multiplyScalar( timesq ) );

  this.tmp = this.previous;
  this.previous = this.position;
  this.position = newPos;

  this.a.set( 0, 0, 0 );

};

So far we have what it takes to move particles in space, now we need the constraints that will make this set of particles behave like a cloth. We will add connections to constrain the particles to form a grid.

Position constraints

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 ( restDistance ). Therefor we introduce constraint satisfaction to modify the position of the two particles so that their distance is once again restDistance.
Here P1 and P2 are too far to each other:

To satisfy the constraints we move P1 and P2 the same amount ( correctionHalf ) .

var diff = new THREE.Vector3();

function satisfyConstraints( p1, p2, distance ) {

  diff.subVectors( p2.position, p1.position );
  var currentDist = diff.length();
  if ( currentDist === 0 ) return; // prevents division by 0
  var correction = diff.multiplyScalar( 1 - distance / currentDist );
  var correctionHalf = correction.multiplyScalar( 0.5 );
  p1.position.add( correctionHalf );
  p2.position.sub( correctionHalf );

}

Classe Cloth

The Cloth Class is very simpe, we need just a constructor wich instanciate a collection of particles with their constraints associated.

The 2 two kind of constraints used here: