Visual Computing/Position-Based Dynamics
2 / 67

03/2022Visual Computing

Position-Based Dynamics

A C++ simulator built on position-based dynamics: rather than mass-spring forces, it projects predicted positions directly onto geometric constraints.

╌╌╌╌

A C++ body simulator built on position-based dynamics (PBD), following Müller et al. Instead of accumulating spring forces and integrating them into velocities, PBD works directly on positions: it predicts where particles will move, then projects those positions onto a set of constraints. The scheme is stabler than mass-spring at large timesteps, generalizes to many constraint types, and costs less per step.

Each step first moves every particle by its external forces alone, producing a predicted position . The predictions ignore internal interactions and generally violate the constraints (a stretched edge, an overlapping pair), so the solver corrects them. Each constraint is enforced by a position correction along its gradient,

where is the inverse mass, so heavier particles move less. The scaling lands the correction exactly on the constraint for a linearized , and weighting by inverse mass conserves linear and angular momentum.

A predicted particle sits off the constraint (the curve ). The solver moves it along the constraint gradient onto the nearest point that satisfies ; the arrow is that projection.

Geometrically, points normal to the constraint surface, so the correction moves each particle along that normal; the factor sets how far, chosen so a single step reaches when the constraint is locally linear and is re-solved when it is not.

Constraints are projected one after another in a Gauss-Seidel sweep, each seeing the corrections of the ones before it, and the whole set is swept a few times per step, with more iterations stiffening the material toward rigid. Once the projections settle, velocities are read back from how far each particle actually moved:

Algorithm:Step(h)\textsc{Step}(h) — one position-based dynamics update
  1. 1
    input: timestep hh, positions xi\mathbf x_i, velocities vi\mathbf v_i, constraints {C}\{C\}, solver iterations nn
  2. 2
    for each particle ii do
  3. 3
    vivi+hwifiext\mathbf v_i \gets \mathbf v_i + h\,w_i\,\mathbf f_i^{\text{ext}}
  4. 4
    pixi+hvi\mathbf p_i \gets \mathbf x_i + h\,\mathbf v_i
  5. 5
    for k1k \gets 1 to nn do
  6. 6
    for each constraint CC do
  7. 7
    project p\mathbf p so that C(p)=0C(\mathbf p) = 0
  8. 8
    for each particle ii do
  9. 9
    vi(pixi)/h\mathbf v_i \gets (\mathbf p_i - \mathbf x_i) / h
  10. 10
    xipi\mathbf x_i \gets \mathbf p_i
A hanging chain under position-based dynamics. Each frame predicts positions from gravity, then projects the pairwise distance constraints the selected number of times; links tint orange as they stretch past rest length. One iteration leaves the chain visibly elastic under a whip, twelve pull it taut — changing the count re-kicks the swing so the difference shows immediately.
Position-based chain

Because a correction is a position projection rather than a force, there is no stiff spring constant to overshoot and blow up the integrator. A force-based solver picks a stiffness and then must keep , so a rigid material demands a tiny timestep; PBD instead moves the particle straight onto the constraint, and stiffness becomes the number of solver iterations — a quantity that can only converge, never diverge. That is why PBD holds together at the large, fixed timestep a game loop runs on, and why the same solver handles distance, volume, and collision constraints without retuning: each is just another to project onto.

The same solver in 2-D: a cloth patch hung from a rail of pins across its whole top edge — distance constraints along warp and weft (drawn), plus compression-only diagonal floors across each quad — the weave shears and the sheet swings freely, while a fold that crushes a diagonal gets pushed back out — under gravity, an ambient breeze, and a gust on demand. Links tint orange as the weave stretches — with one iteration a gust billows the cloth into visible sag, with twelve it recovers a stiff drape.
Position-based cloth

References

  1. Project repository
  2. Reference notes: Linear Algebra

╌╌ END ╌╌