From 035364f1e5465ddb743ab2160453e2fdbe4ee752 Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:03:47 -0500 Subject: [PATCH 1/8] update readme --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 465159a..a1e2161 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,11 @@ For that, you'll want to consider higher-order optimization algorithms or [local The objective we aim to minimize is the sum of internal elastic energy potentials plus a quadratic penalty of linear momentum: -,
-, +$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$ +$`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, for vertex locations *x*, time step (sec) *h*, diagonal mass matrix *M*, velocities *v*, and external forces (gravity, wind, etc...) -. The term is the *explicit predictor* +$`f_{ext}`$. The term $`\bar{x}`$ is the *explicit predictor* that is computed at the beginning of the time step. Computing a frame of animation amounts to iteratively minimizing the above objective until some convergence criteria is met (e.g., the norm of the gradient is below some threshold). @@ -56,20 +56,20 @@ To compile, execute the following commands: ### Energies -Whenever I write a new simulator, I start with the most basic elastic energy as the deformable primitives: a Hookean spring with stiffness *k* and rest length . The potential energy of a spring is . +Whenever I write a new simulator, I start with the most basic elastic energy as the deformable primitives: a Hookean spring with stiffness *k* and rest length $`\ell`$. The potential energy of a spring is $`(k/2)(\|x_a-x_b\|-\ell)^2`$. These springs are created from the unique edges of tCe triangle mesh, with bending springs created between adjacent triangles. The [ClothMesh class](src/ClothMesh.hpp) generates this data given vertex and face buffers. We can also evaluate temporary springs to deal with collisions. One end point is the vertex, and the other is the projection onto the surface it's penetrating. ### Optimization -[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. *x* at each iteration: . We use *i* to denote the iteration and *p* as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! +[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. *x* at each iteration: $`p = -\nabla g(x^i)`$. We use *i* to denote the iteration and *p* as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar *s* using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: -,
-,
-. +$`p = -\nabla g(x^i)`$,
+$`s = linesearch(x^i, p)`$,
+$`x^{i + 1} = x^i + s * p`$. Both energy and gradient use similar calculations so you can save resources (and implementation efforts) by computing them both at same time. I like to use one function for both and skip gradient calculation with a conditional during line search. You can see the evaluation of the objective and gradient in the [Objective class](src/Objective.hpp), with gradient descent in [Solver](src/Solver.hpp). From 6f7bcc276399d3b468870a1a377d5862a3e3bda8 Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:07:28 -0500 Subject: [PATCH 2/8] italics to math --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a1e2161..a9fbd1b 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,11 @@ For that, you'll want to consider higher-order optimization algorithms or [local The objective we aim to minimize is the sum of internal elastic energy potentials plus a quadratic penalty of linear momentum: -$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$ +$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$, + $`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, -for vertex locations *x*, time step (sec) *h*, diagonal mass matrix *M*, velocities *v*, and external forces (gravity, wind, etc...) +for vertex locations $x$, time step (sec) $h$, diagonal mass matrix $M$, velocities $v$, and external forces (gravity, wind, etc...) $`f_{ext}`$. The term $`\bar{x}`$ is the *explicit predictor* that is computed at the beginning of the time step. Computing a frame of animation amounts to iteratively minimizing the above objective until some convergence criteria is met (e.g., the norm of the gradient is below some threshold). @@ -56,16 +57,16 @@ To compile, execute the following commands: ### Energies -Whenever I write a new simulator, I start with the most basic elastic energy as the deformable primitives: a Hookean spring with stiffness *k* and rest length $`\ell`$. The potential energy of a spring is $`(k/2)(\|x_a-x_b\|-\ell)^2`$. +Whenever I write a new simulator, I start with the most basic elastic energy as the deformable primitives: a Hookean spring with stiffness $k$ and rest length $`\ell`$. The potential energy of a spring is $`(k/2)(\|x_a-x_b\|-\ell)^2`$. These springs are created from the unique edges of tCe triangle mesh, with bending springs created between adjacent triangles. The [ClothMesh class](src/ClothMesh.hpp) generates this data given vertex and face buffers. We can also evaluate temporary springs to deal with collisions. One end point is the vertex, and the other is the projection onto the surface it's penetrating. ### Optimization -[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. *x* at each iteration: $`p = -\nabla g(x^i)`$. We use *i* to denote the iteration and *p* as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! +[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. $x$ at each iteration: $`p = -\nabla g(x^i)`$. We use $i$ to denote the iteration and $p$ as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! -Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar *s* using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: +Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar $s$ using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: $`p = -\nabla g(x^i)`$,
$`s = linesearch(x^i, p)`$,
From f747aefa9a1c3ad9fe4249e4d098095cf63a736a Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:09:17 -0500 Subject: [PATCH 3/8] sub i for iter --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a9fbd1b..cc997af 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,13 @@ We can also evaluate temporary springs to deal with collisions. One end point is ### Optimization -[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. $x$ at each iteration: $`p = -\nabla g(x^i)`$. We use $i$ to denote the iteration and $p$ as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! +[Gradient descent](https://en.wikipedia.org/wiki/Gradient_descent) is a simple first-order method that steps along the negative gradient w.r.t. $x$ at each iteration: $`p = -\nabla g(x_i)`$. We use $i$ to denote the iteration and $p$ as the descent direction. By all accounts, gradient descent is a poor choice due to its low rate of convergence. You can certainly improve performance with other higher-order optimizers. However, I personally advocate starting with gradient descent when writing new optimization code. The optimizer is so simple it's hard to make a mistake - if there are bugs, they are surely in your energy or gradient calculations. This can be a helpful debugging strategy! Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar $s$ using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: -$`p = -\nabla g(x^i)`$,
-$`s = linesearch(x^i, p)`$,
-$`x^{i + 1} = x^i + s * p`$. +$`p = -\nabla g(x_i)`$,
+$`s = linesearch(x_i, p)`$,
+$`x_{i + 1} = x_i + s * p`$. Both energy and gradient use similar calculations so you can save resources (and implementation efforts) by computing them both at same time. I like to use one function for both and skip gradient calculation with a conditional during line search. You can see the evaluation of the objective and gradient in the [Objective class](src/Objective.hpp), with gradient descent in [Solver](src/Solver.hpp). From 95a2bc3a69b999709f6b97eec6ccfe23e43f3ba2 Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:13:47 -0500 Subject: [PATCH 4/8] center eqs --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cc997af..e57d067 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,11 @@ For that, you'll want to consider higher-order optimization algorithms or [local The objective we aim to minimize is the sum of internal elastic energy potentials plus a quadratic penalty of linear momentum: +

$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$, $`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, +

for vertex locations $x$, time step (sec) $h$, diagonal mass matrix $M$, velocities $v$, and external forces (gravity, wind, etc...) $`f_{ext}`$. The term $`\bar{x}`$ is the *explicit predictor* @@ -68,9 +70,13 @@ We can also evaluate temporary springs to deal with collisions. One end point is Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar $s$ using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: -$`p = -\nabla g(x_i)`$,
-$`s = linesearch(x_i, p)`$,
+

+$`p = -\nabla g(x_i)`$, + +$`s = linesearch(x_i, p)`$, + $`x_{i + 1} = x_i + s * p`$. +

Both energy and gradient use similar calculations so you can save resources (and implementation efforts) by computing them both at same time. I like to use one function for both and skip gradient calculation with a conditional during line search. You can see the evaluation of the objective and gradient in the [Objective class](src/Objective.hpp), with gradient descent in [Solver](src/Solver.hpp). From b45bb8d4341c20ee5a46920bca6f5ef965b66766 Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:14:43 -0500 Subject: [PATCH 5/8] center eqs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e57d067..4d1b9e6 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The objective we aim to minimize is the sum of internal elastic energy potential $`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$, $`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, -

+

for vertex locations $x$, time step (sec) $h$, diagonal mass matrix $M$, velocities $v$, and external forces (gravity, wind, etc...) $`f_{ext}`$. The term $`\bar{x}`$ is the *explicit predictor* @@ -76,7 +76,7 @@ $`p = -\nabla g(x_i)`$, $`s = linesearch(x_i, p)`$, $`x_{i + 1} = x_i + s * p`$. -

+

Both energy and gradient use similar calculations so you can save resources (and implementation efforts) by computing them both at same time. I like to use one function for both and skip gradient calculation with a conditional during line search. You can see the evaluation of the objective and gradient in the [Objective class](src/Objective.hpp), with gradient descent in [Solver](src/Solver.hpp). From 35aca88aec354b0445cb965c379c599869e9dd8e Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:19:01 -0500 Subject: [PATCH 6/8] center eqs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4d1b9e6..2b9522e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ For that, you'll want to consider higher-order optimization algorithms or [local The objective we aim to minimize is the sum of internal elastic energy potentials plus a quadratic penalty of linear momentum: -

+

$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$, $`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, @@ -70,7 +70,7 @@ We can also evaluate temporary springs to deal with collisions. One end point is Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar $s$ using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: -

+

$`p = -\nabla g(x_i)`$, $`s = linesearch(x_i, p)`$, From 8078eca4343a44a77704603d2358d3267c040eeb Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:19:29 -0500 Subject: [PATCH 7/8] give up --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 2b9522e..7ffc8ba 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,9 @@ For that, you'll want to consider higher-order optimization algorithms or [local The objective we aim to minimize is the sum of internal elastic energy potentials plus a quadratic penalty of linear momentum: -

$`\bar{x} = x + hv + h^2 M^{-1} f_{ext}`$, $`g(x) = \frac{1}{2h^2}\|M^{1/2}(x-\bar{x})\|^2 + \sum E(x)`$, -

for vertex locations $x$, time step (sec) $h$, diagonal mass matrix $M$, velocities $v$, and external forces (gravity, wind, etc...) $`f_{ext}`$. The term $`\bar{x}`$ is the *explicit predictor* @@ -70,13 +68,11 @@ We can also evaluate temporary springs to deal with collisions. One end point is Each iteration, we have to make sure we aren't overshooting the objective and increase the energy. This is accomplished by scaling the descent direction with a scalar $s$ using [line search](https://en.wikipedia.org/wiki/Line_search). All together, an iteration of gradient descent involves: -

$`p = -\nabla g(x_i)`$, $`s = linesearch(x_i, p)`$, $`x_{i + 1} = x_i + s * p`$. -

Both energy and gradient use similar calculations so you can save resources (and implementation efforts) by computing them both at same time. I like to use one function for both and skip gradient calculation with a conditional during line search. You can see the evaluation of the objective and gradient in the [Objective class](src/Objective.hpp), with gradient descent in [Solver](src/Solver.hpp). From 336f3a6601b93db3e425f73fdcc9c564b3c8f2ba Mon Sep 17 00:00:00 2001 From: mattoverby Date: Thu, 21 Aug 2025 13:20:38 -0500 Subject: [PATCH 8/8] spelling --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ffc8ba..3151655 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ To compile, execute the following commands: ### Energies Whenever I write a new simulator, I start with the most basic elastic energy as the deformable primitives: a Hookean spring with stiffness $k$ and rest length $`\ell`$. The potential energy of a spring is $`(k/2)(\|x_a-x_b\|-\ell)^2`$. -These springs are created from the unique edges of tCe triangle mesh, with bending springs created between adjacent triangles. +These springs are created from the unique edges of the triangle mesh, with bending springs created between adjacent triangles. The [ClothMesh class](src/ClothMesh.hpp) generates this data given vertex and face buffers. We can also evaluate temporary springs to deal with collisions. One end point is the vertex, and the other is the projection onto the surface it's penetrating.