Now that we have set up the cloth model as a system of masses and springs, we need to integrate the physical equations of motion in order to apply the forces on our cloth's point masses to figure out how they move from one time step to the next.

Take a look at Cloth::simulate in cloth.cpp. This method runs one time step in the simulation of time length delta_t (dtdt in equations below) and applies the accelerations uniformly to all point masses in the cloth. The ClothParameters *cp argument contains the parameters that characterize the cloth and its simulation, such as the spring constant ks and which spring constraints to simulate. collision_objects contains all of the objects in the scene that the cloth needs to check for collisions with at each time step.

In our representation, there are two kinds of forces: external forces (such as gravity) which uniformly affect the cloth and spring correction forces which apply the spring constraints from before to keep the cloth together. The external forces are captured by external_accelerations. On the other hand, the spring correction forces vary between point masses and will be computed based on the state of each spring.

Complete the rest of the Cloth::simulate method:

2.1: Compute total force acting on each point mass

Note: Every point mass has a vector representing the total force vector acting upon it called forces. Use this vector to accumulate the forces acting on each point mass as you compute them. Be sure to clear/reset them at the start of each call to simulate so as to not accumulate extra, nonexistant forces.

First, compute a total external force based on the external_accelerations and the mass (recall that Newton's 2nd Law states that F=maF = ma). Apply this external force to every point mass.

Next, apply the spring correction forces. For each spring, skip over the spring if that spring's constraint type is currently disabled. You can check this using cp, which has boolean values such as enable_structural_constraints. Otherwise, compute the force applied to the two masses on its ends using Hooke's law:

Fs=ks(papbl)F_s = k_s * (|| p_a - p_b || - l)

where ksk_s is the spring constant (ks), pap_a and pbp_b are the positions of the two masses, || indicates magnitude, and ll is the spring's rest length (rest_length). Because the bending constraint should be weaker that structural or shearing constraints, you should multiply your ks by a small constant to achieve this. For example, 0.2 works well.

The force vector is the vector pointing from one point mass to the other with magnitude equal to Fs||F_s||. Apply this force to one point mass and an equal, but opposite force to the other.

2.2: Use Verlet integration to compute new point mass positions

Now that we have computed the force acting on each point mass for this time step, we need to perform numerical integration to compute each point mass's change in position. There are many ways of integrating our equations, which include Euler's method (explicit and implicit), Verlet algorithm, Runge-Kutta method, and more. Here, we will use Verlet integration, an explicit integrator that is fairly accurate and relatively easy to implement.

Verlet integration computes a point mass's new position at time t+dtt + dt, xt+dtx_{t + dt} as follows:

xt+dt=xt+vtdt+atdt2x_{t + dt} = x_t + v_t * dt + a_t * dt^2

where xtx_t is the current position, vtv_t is the current velocity, ata_t is the current total acceleration from all forces, and dtdt is a timestep delta_t.

In Verlet integration, we approximate vtdt=xtxtdtv_t * dt = x_t - x_{t - dt}, where xtdtx_{t - dt} is the position from the last time step.

xt+dt=xt+(xtxtdt)+atdt2x_{t + dt} = x_t + (x_t - x_{t - dt}) + a_t * dt^2

This can be simplified to the following expression:

xt+dt=2xtxtdt+atdt2x_{t + dt} = 2x_t - x_{t - dt} + a_t * dt^2

However, we can add some damping into the simulation to help simulate loss of energy due to friction, heat loss, etc. by slightly scaling down vtv_t:

xt+dt=xt+(1d)(xtxtdt)+atdt2x_{t + dt} = x_t + (1 - d) * (x_t - x_{t - dt}) + a_t * dt^2

where dd is a damping term (usually very small) between 0 and 1. Let dd be the given damping value in cp. Note that the damping value is in units of percentage, so divide by 100 before subtracting from 1. The damping used here is simpler than the one introduced in lecture where only the spring driven motion is dampened.

For each point mass, update the value in position according to the above equations and store the previous time step's position in last_position. Do not do anything if the point mass is pinned!

2.3: Constrain position updates

To help keep springs from being unreasonably deformed during each time step, we will implement an additional feature based on the SIGGRAPH 1995 Provot paper on deformation constraints in mass-spring models (see Section 5 for specific details).

For each spring, apply this constraint by correcting the two point masses' positions such that the spring's length is at most 10% greater than its rest_length at the end of any time step. Maintain the same vector direction between the two point masses and only modify their distance apart from each other. Perform half of the correction to each point mass, unless one of them is pinned, in which case apply the correction entirely to one point mass. Do nothing if both are pinned (they wouldn't satisfy the condition anyways, by construction; can you see why?).

Test your implementation

./clothsim -f ../scene/pinned2.json

You should see your cloth (with 2 corners pinned) fall down fairly realistically to a rest state!

You may need to press P in order to play the simulation.

falldown

falldown_shaded

Part 2 Deliverables

  • Experiment with some the parameters in the simulation. To do so, pause the simulation at the start with P, modify the values of interest, and then resume by pressing P again. You can also restart the simulation at any time from the cloth's starting position by pressing R.
    • Describe the effects of changing the spring constant ks; how does the cloth behave from start to rest with a very low ks? A high ks?
    • What about for density?
    • What about for damping?
    • For each of the above, observe any noticeable differences in the cloth compared to the default parameters and show us some screenshots of those interesting differences and describe when they occur.
  • Show us a screenshot of your shaded cloth from scene/pinned4.json in its final resting state! If you choose to use different parameters than the default ones, please list them.