This post will be my notes on PDB study and will only include points I feel note-worthy. It is by no means a well-rounded tutorial. Btw I learned the principals from this online course: https://www.youtube.com/watch?v=fH3VW9SaQ_c (kudos)
Along with the note I’ll implement the distance constraint to illustrate how it works.
Reminders
- PBD does not even try to simulate actual physics. It only looks good. All physics ‘references’ (for example, so-called momentum conservation) are attempts to make the scene look real.
- PDB algorithm is a constraint solver. The algorithm introduced in the course is one-constraint-a-time, Gauss-Seidel method.
Math Review
- Gauss-Seidel updates proposed values during iteration
- Jacobi updates values only after each iteration (symmetrical?)
PBD Loop
before mainloop, all vertices should be assigned an initial position x_i, velocity v_i and invert-mass w_i (1/m_i).
- for each vert i, update proposed velocity v_i = v_i + t * w_i * external_force_i
- damp velocities. a simple way is times 0.99
- for each vert i, update proposed position p_i = x_i + t * v_i
- for each vert i, detect collection and generate collision constraints x_i -> p_i
- solve constraints – it’s numerical solver, so here will be an inner loop
- for each vert i, finalize velocity v_i to be actual velocity (p_i – x_i) / t
- for each vert i, finalize position x_i to be p_i
Cheatsheet
Distance constraint C(p_i, p_j) = |p_i, p_j| - d (look carefully you will notice it is not Hooke's law) For constraint C(p1, p2), with invert mass of w1, w2 respectively, Gradient of p1: (p1-p2)/|p1-p2| Gradient of p2: (p2-p1)/|p2-p1| Update of p1: -w1/(w1+w2)*(|p1-p2|-d)*(p1-p2)/|p1-p2| Update of p2: +w2/(w1+w2)*(|p1-p2|-d)*(p1-p2)/|p1-p2|
Code
GitHub Gist: https://gist.github.com/stormouse/90a8d22582ad4e9bc6c91c4a5f80e842