<- back
hw10 (100 pts) upload hw.cpp to glow codebase
// NOTE Your code will run really slow in debug mode (and also fairly slow in release mode) -- on Thursday I will explain why & hopefully release a patch that makes it fast. let's start by getting acquainted with the data draw the mesh exactly as indicated by the TODO's in void simulation_draw(...); ⚠ TYPO in hw.cpp: the pins should be in _yellow_, not dark blue int num_nodes; int num_springs; int num_pins; vec2 *X; is the rest position of the mesh. vec2 *x; is the current position of the mesh. int2 *springs; int *pins; e.g., node k has rest position X[k] e.g., the k-th spring is attached to nodes springs[k].i and springs[k].j e.g., the k-th pin is attached to node pins[k]
✨ read this explanation of void compute_and_add_to(...); U is the "energy" $U$ U_x is the gradient $\frac{dU}{d\mathbf{x}},$ which is a long row vector U_xx is the Hessian $\frac{d^2U}{d\mathbf{x}^2},$ which is a big square matrix (in code we are storing it as a sparse matrix; will discuss Thursday) we are given a pointer to the energy; don't forget to dereference. (*U) += d; adds double $d$ to the energy. instead of adding energy terms to the gradient & Hessian one entry at a time... ...it can be very convenient to add "segments" (vec2's) to the gradient and blocks (mat2's) to the Hessian. add(U_x, i, s); adds vec2 $\mathbf{s}$ to $\frac{dU}{d\mathbf{x}_i}$ // NOTE $\frac{dU}{d\mathbf{x}_i}$ is the $i$-th "2-segment" of the gradient. here are the equivalent entry-wise operations: U_x[2 * i + 0] += s.x; U_x[2 * i + 1] += s.y; add(U_xx, i, j, M); adds mat2 $\mathbf{M}$ to $\frac{d^2U}{d\mathbf{x}_id\mathbf{x}_j}$ // NOTE $\frac{d^2U}{d\mathbf{x}_id\mathbf{x}_j}$ is the $(i, j)$-th 2x2 block of the Hessian. here are the equivalent entry-wise operations (don't do this): sbuff_push_back(&U_xx, { 2 * i + 0, 2 * j + 0, M(0, 0) }); sbuff_push_back(&U_xx, { 2 * i + 1, 2 * j + 0, M(1, 0) }); sbuff_push_back(&U_xx, { 2 * i + 1, 2 * j + 1, M(1, 1) }); sbuff_push_back(&U_xx, { 2 * i + 0, 2 * j + 1, M(0, 1) }); 🚨 important! you must guard all modifications to U, U_x, and U_xx (the usage of compute_and_add_to(...) allows for U, U_x, U_xx to be NULL) e.g. if (U) { (*U) += ...; } e.g. if (U_x) { add(U_x, ...); } e.g. if (U_xx) { add(U_xx, ...); }
// NOTE to check if your derivatives are correct, play the simulation with check_derivatives turned on -- i.e. press 'a' // NOTE (though it should be pretty obvious just from dragging nodes around etc.) implement gravity where indicated by the TODO in of compute_and_add_to(...) consider node $i$ it has current position $\mathbf{x}_i=(x_i^x, x_i^y)$ its gravity energy contribution is $E^{\text{gravity}}_i = mgx_i^y$ its gravity gradient contribution is $\frac{dE^{\text{gravity}}_i}{d\mathbf{x}_i} = (0, mg)^T$
✨ SPOILERif (U_x) { add(U_x, i, V2(0, m * g)); }
it makes no gravity Hessian contribution (since its gravity gradient contribution is constant) implement pins where indicated by the TODO in compute_and_add_to(...) say node $i$ is pinned it has current position $\mathbf{x}_i$ and rest position $\mathbf{X}_i$ its deformation is $\Delta_i = \mathbf{x}_i - \mathbf{X}_i$ its pin energy contribution is $E^{\text{pin}}_i = k^\text{pin} |\Delta_i|^2 / 2$ // NOTE use squaredNorm its pin gradient contribution is $\frac{dE^{\text{pin}}_i}{d\mathbf{x}_i} = k^\text{pin} \Delta_i$ its pin Hessian contribution is $\frac{d^2E^{\text{pin}}_i}{d\mathbf{x}_i^2} = k^\text{pin} \mathbf{I}$ // NOTE $\mathbf{I}$ is the 2x2 identity extend your gravity implementation to support gravity pointing in any direction the angle of the gravity vector (from the positive $x$-axis) is tweaks.theta_gravity // NOTE i draw a yellow arrow to visualize $\theta_{\text{gravity}}.$
✨ HINTconsider a constant external force $\mathbf{f}$ acting on node $i$ its energy contribution is $E^{\text{force}}_i = -(\mathbf{f} \cdot \mathbf{x}_i)$ its gradient contribution is $\frac{dE^{\text{force}}_i}{d\mathbf{x}_i} = -\mathbf{f}$

(optional) implement another energy (as well as its gradient and Hessian) e.g., force that pulls every node towards your mouse e.g., very simple buoyancy model (draw some nice transparent water, remove the pins, and watch the bar float) (very optional) delete my implementation of the springs energy, gradient, and Hessian and implement it yourself (will explain math to anyone who is interested 🙂👍)
🐄