diff --git a/README.md b/README.md
index 59798c2..08e22b3 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,3 @@
-[](https://github.com/dilevin/CSC2549-a4-cloth-simulation/actions)
-
## Introduction
This assignment will give you the chance to implement a simple cloth simulation. We will leverage our new found expertise on [finite element methods](www.github.com/dilevin/CSC2549-a3-finite-elements-3d) to build a FEM cloth simulation. This simulation will use triangles, rather than tetrahedron as the finite elements and will use a principal stretch-based model for the cloth material. You will also implement your first contact response model, a simple velocity filter that can be bolted onto standard time integration schemes.
@@ -123,55 +121,37 @@ In the case of cloth, the underformed geometry is of different dimension (2d) t
Just as in the [previous assignment](https://github.com/dilevin/CSC2549-a3-finite-elements-3d), we need to choose basis, or shape functions with which to approximate functions on our, now triangular, mesh. A triangle as 3 nodes our approximations become
-

-
-where
are the [barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) for a 2D triangle and
is the 2d coordinate in the undeformed space.
-
-Our goal is to be able to estimate the 3d world space position of any part of this cloth triangle (for any value of
in the triangle). Using our FEM basis, this becomes
-
-
-
-where
are the 3d, per-vertex positions of the cloth mesh at time
. This gives a mapping from the 2d space of the undeformed cloth to the 3d world space. As usual, we choose the **generalized coordinates** (
) to be the stacked vector of vertex positions, which lets us rewrite the above expression as
-
-
-
-The velocity of the cloth, at any point
is then given by the total time derivative:
+
-
+where
are the [barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) for a 2D triangle and
is the 2d coordinate in the undeformed space.
-which defines the **generalized velocities** as the stacked *9d* vector of per-vertex velocities.
+However, cloth is really a thin volumetric construct, of which our triangle only represents a small part. We might need information lying slightly off the triangle surface. To account for this we will need to modify our FEM model a bit. First, let's assume our triangle is actually embedded in a 3D undeformed space
. Let's try and and build and appropriate mapping from this space to the world space.
-## Deformation Gradient
-
-The final necessary piece of the kinematic puzzle is the measure of deformation. You might be tempted to just compute
but this is going to get you in trouble. The dimensions of this matrix (
) make evaluating material models difficult since such models are *designed* to work for volumetric (re: square) deformation matrices.
-
-There are lots of ways to handle this problem in [literature](https://animation.rwth-aachen.de/media/papers/2013-CAG-AdaptiveCloth.pdf) and in this assignment we will rely on one which is both simple and effective.
+Given any point
in the undeformed space, we can compute the barycentric coordinates of the nearest point on our triangle by solving
-First let's remind ourselves that the functions which define barycentric coordinates require us to solve the linear system
+
,
-
+where
is a matrix of edge vectors. We use the constriaint
to reconstruct
. This equation finds the barycentric coordinates of the nearest point on the triangle to
in a least squares fashion. The error in this least squares solve will be orthogonal to the column space of
, our triangle. For any point
we can work out its offset from the triangle by computing
, where
is the first vertex of our triangle and
is the undeformed surface normal of the triangle. Because our triangle has a constant normal, we don't need to worry about where we compute it, which makes this all very convenient.
-To "square" our deformation gradient, we are going to "lift" the undeformed space of the cloth to 3d. **NOTE:** we are still going to use 2D triangles but now the undeformed vertex positions of those triangles will be given in 3d. Let's call the 3d undeformed vertex positions of our triangle mesh
. So now, given any point in this weird 3d undeformed space, the second and third barycentric coordinates are given by
+Let's assume that our point
maintains a constant offset from the triangle when deformed. This implies we can reconstruct the world space position by offsetting our point the same distance along the world space normal
. This gives us the following mapping from reference space to world space
-
.
+
.
-Ok, we've made everything worse. Now we can't even directly invert the right-hand side. But this is one of those cases wherein things had to get [worse before they get better](https://www.youtube.com/watch?v=uDIgS-Soo9Q). However, we can solve this system in a [least-squares](https://en.wikipedia.org/wiki/Least_squares) sense which gives us
+Now we can choose the **generalized coordinates** (
) to be the stacked vector of vertex positions, which defines the **generalized velocities** as the stacked *9d* vector of per-vertex velocities.
-
-
-which, when coupled with the fact that
gives us everything we need.
+## Deformation Gradient
-This might seem like an esoteric, algebraic solution, but geometrically it is doing something really quite reasonable. Any 3d point
, which is on a triangle yields the same barycentric coordinates as the 2d solution. That's a good feature to have since we always, always, always [only calculate the world space position of the cloth at points on the cloth](https://en.wikipedia.org/wiki/Truism). ~~For 3d points
that are off the cloth, this formulation projects them orthogonally (along the triangle normal) onto the cloth and returns the value for this projected cloth point. Because of this projection, the deformation of the cloth in the normal direction is zero, which makes sense, the discrete cloth has no thickness in this direction and cannot deform. However, because
is now 3d, the derivative
becomes
which means
also becomes a
.~~ This is much easier to deal with down the road.
+There are lots of ways to handle build a cloth deformation gradient in [literature](https://animation.rwth-aachen.de/media/papers/2013-CAG-AdaptiveCloth.pdf). In this assignment we will be able to avoid these more complicated solution due to our particular choice of undeformed to world space mapping which allows us to directly compute a
deformation gradient as
-**This derivation has changed since last year, I will update it soon.**
+
## Kinetic Energy
-Armed with the generalized velocities, the formula for the per-triangle kinetic energy is eerily similar to that of assignment 3. It's an integral of the local kinetic energy over the entire triangle
+Armed with the generalized velocities, the formula for the per-triangle kinetic energy is eerily similar to that of assignment 3. It's an integral of the local kinetic energy over the entire triangle, multiplied by the thickness of the cloth,
. For this assignment you are free to assume the thickness of the cloth is
.
-
+
-and can be compute analytically using a symbolic math package. The per-element mass matrices for the every cloth triangle can then be *assembled* into the mass matrix for the entire mesh.
+and can be compute analytically using a symbolic math package. The per-element mass matrices for every cloth triangle can then be *assembled* into the mass matrix for the entire mesh.
## Potential Energy
@@ -179,59 +159,57 @@ For this assignment we will use a different type of material model to describe t
### Principal Stretches
-Recall that in the previous assignment we used the right Cauchy strain tensor (
) to measure deformation and the rationale for using this was that it measures the squared deformed length of an arbitrary, infinitesimal line of material,
. In other words,
. Because
is symmetric and positive definite, we can perform an [eigendecomposition](https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix) such that
where
is the orthogonal matrix of eigenvectors and
is the diagonal matrix of eigenvalues. This means we can think of this squared length as
where
. In other words, if we transform
just right, its deformation is completely characterized by
.
+Recall that in the previous assignment we used the right Cauchy strain tensor (
) to measure deformation and the rationale for using this was that it measures the squared deformed length of an arbitrary, infinitesimal line of material,
. In other words,
. Because
is symmetric and positive definite, we can perform an [eigendecomposition](https://en.wikipedia.org/wiki/Eigendecomposition_of_a_matrix) such that
where
is the orthogonal matrix of eigenvectors and
is the diagonal matrix of eigenvalues. This means we can think of this squared length as
where
. In other words, if we transform
just right, its deformation is completely characterized by
.
-
are the eigenvalues of
and also the squared [*singular values*](https://en.wikipedia.org/wiki/Singular_value_decomposition) of
. We call these singular values of
the [principal stretches](http://www.femdefo.org). They measure deformation independently of the orientation (or rotation/reflection) of the finite element.
+
are the eigenvalues of
and also the squared [*singular values*](https://en.wikipedia.org/wiki/Singular_value_decomposition) of
. We call these singular values of
the [principal stretches](http://www.femdefo.org). They measure deformation independently of the orientation (or rotation/reflection) of the finite element.
### Linear Elasticity without the Pesky Rotations
-Now we can formulate a linear elastic model using the principal stretches which "filters out" any rotational components. Much like the Neohookean material model, this model will have one energy term which measures deformation and one energy term that tries to preserve volume (well area in the case of cloth). We already know we can measure deformation using the principal stretches. We also know that the determinant of
measures the change in volume of a 3D object. In the volumetric case this determinant is just the product of the principal stretches. But first, we need to understand some specifics about the deformation gradient of cloth.
-
-Recall that our deformation gradient for a cloth triangle is computed using a least squares projection. This is nice because we still have a
matrix on which to perform singular value decomposition on (and later ... (*shudder*) take the derivative of). It's problematic because this deformation gradient has a nullspace normal to the triangle (all points normal to the triangle are mapped to the same barycentric coordinate). This means that, forever and always, **one of the singular values of
will be zero**. Now if we assume that our triangle is not deformed to be inside out or squished to a line or a point, then this zero singular value will always be the last singular value returned by any reasonable SVD code (Eigen is pretty reasonable). Thus rather than use all three principal values in our material model, we will only use the first 2. This gives us the following material model
+Now we can formulate a linear elastic model using the principal stretches which "filters out" any rotational components. Much like the Neohookean material model, this model will have one energy term which measures deformation and one energy term that tries to preserve volume (well area in the case of cloth). We already know we can measure deformation using the principal stretches. We also know that the determinant of
measures the change in volume of a 3D object. In the volumetric case this determinant is just the product of the principal stretches.
-
+
-where
and
are the material properties for the cloth. The first term in this model attempts to keep
and
close to one (limiting deformation) while the second term is attempting to preserve the area of the deformed triangle (it's a linearization of the determinant). This model is called **co-rotational linear elasticity** because it is linear in the principal stretches but rotates *with* each finite element. When we use energy models to measure the in-plane stretching of the cloth (or membrane), we often refer to them as membrane energies.
+where
and
are the material properties for the cloth. The first term in this model attempts to keep
and
close to one (limiting deformation) while the second term is attempting to preserve the volume of the deformed triangle (it's a linearization of the determinant). This model is called **co-rotational linear elasticity** because it is linear in the principal stretches but rotates *with* each finite element. When we use energy models to measure the in-plane stretching of the cloth (or membrane), we often refer to them as membrane energies.
### The Gradient of Principal Stretch Models
The strain energy density for principal stretch models, like the one above, are relatively easy to implement and understand. This is a big reason we like them in graphics. We'll also see that the gradient of this model (needed for force computation) is also pretty easy to compute.
-Really, the derivative we need to understand how to compute is
. Once we have this we can use
to compute the gradient wrt to the generalized coordinates. Conveniently, we have the following for principal stretch models.
+Really, the derivative we need to understand how to compute is
. Once we have this we can use
to compute the gradient wrt to the generalized coordinates. Conveniently, we have the following for principal stretch models.
-
+
-where
is the singular value decomposition.
+where
is the singular value decomposition.
### The Hessian of Principal Stretch Models
-Unfortunately, the gradient of the principal stretch energy is not enough. That's because our favourite implicit integrators require second order information to provide the stability and performance we crave in computer graphics. This is where things get messy. The good news is that, if we can just compute
then we can use
to compute our Hessian wrt to the generalized coordinates (this follows from the linearity of the FEM formulation wrt to the generalized coordinates). This formula is going to get ugly so, in an attempt to make it somewhat clear, we are going to consider derivatives wrt to single entries of
, denoted
. In this context we are trying to compute
+Unfortunately, the gradient of the principal stretch energy is not enough. That's because our favourite implicit integrators require second order information to provide the stability and performance we crave in computer graphics. This is where things get messy. The good news is that, if we can just compute
then we can use
to compute our Hessian wrt to the generalized coordinates (this follows from the linearity of the FEM formulation wrt to the generalized coordinates). This formula is going to get ugly so, in an attempt to make it somewhat clear, we are going to consider derivatives wrt to single entries of
, denoted
. In this context we are trying to compute
-
+
-Here
takes a
vector as input and converts it into a diagonal matrix, with the entries of the matrix on the diagonal. In our case, we define
as
+Here
takes a
vector as input and converts it into a diagonal matrix, with the entries of the matrix on the diagonal. In our case, we define
as
-
+
-The first thing to keep in mind when looking at this formula is **DON'T PANIC**. It's a straight forward application of the chain rule, just a little nastier than usual. The second thing to keep in mind is that all derivatives wrt to
are zero (it never changes, it's always 0). The final thing to keep in mind is that **I am giving you the code to compute SVD derivatives in dsvd.h/dsvd.cpp**.
+The first thing to keep in mind when looking at this formula is **DON'T PANIC**. It's a straight forward application of the chain rule, just a little nastier than usual. The second thing to keep in mind is that all derivatives wrt to
are zero (it never changes, it's always 0). The final thing to keep in mind is that **I am giving you the code to compute SVD derivatives in dsvd.h/dsvd.cpp**.
-If we define the svd of a matrix as
, this code returns
,
and
. Yes this code returns 3 and four dimensional tensors storing this quantities, yes I said never to do this in class, consider this the exception that makes the rule. The latter two indices on each tensor are the
and
indices used in the formula above.
+If we define the svd of a matrix as
, this code returns
,
and
. Yes this code returns 3 and four dimensional tensors storing this quantities, yes I said never to do this in class, consider this the exception that makes the rule. The latter two indices on each tensor are the
and
indices used in the formula above.
-The hardest part of implementing this gradient correctly is handling the SVD terms. These gradients have a different form based on whether your
matrix is square or rectangular. This is one big reason that the
deformation gradient we use in this assignment is desirable. It allows one to use the same singular value decomposition code for volumetric and cloth models.
+The hardest part of implementing this gradient correctly is handling the SVD terms. These gradients have a different form based on whether your
matrix is square or rectangular. This is one big reason that the
deformation gradient we use in this assignment is desirable. It allows one to use the same singular value decomposition code for volumetric and cloth models.
## Collision Detection with Spheres
To make this assignment a little more visually interesting, you will implement simple collision detection and resolution with an analytical sphere. **Collision Detection** is the process of detecting contact between two or more objects in the scene and **Collision Resolution** is the process of modifying the motion of the object in response to these detected collisions.
-For this assignment we will implement per-vertex collision detection with the sphere. This is as simple as detecting if the distance from the center of the sphere to any vertex in your mesh is less than the radius of the sphere. If you detect such a collision, you need to store an **index** to the colliding vertex, along with the outward facing **contact normal**(
). In this case, the outward facing contact normal is the sphere normal at the point of contact.
+For this assignment we will implement per-vertex collision detection with the sphere. This is as simple as detecting if the distance from the center of the sphere to any vertex in your mesh is less than the radius of the sphere. If you detect such a collision, you need to store an **index** to the colliding vertex, along with the outward facing **contact normal**(
). In this case, the outward facing contact normal is the sphere normal at the point of contact.
## Collision Resolution
-The minimal goal of any collision resolution algorithm is to prevent collisions from getting worse locally. To do this we will implement a simple *velocity filter* approach. Velocity filters are so named because the "filter out" components of an objects velocity that will increase the severity of a collision. Given a vertex that is colliding with our sphere, the only way that the collision can get worse locally is if that vertex moves *into* the sphere. One way we can check if this is happening is to compute the projection of the vertex velocity onto the outward facing contact normal (
,
selects the
contacting vertex). If this number is
we are OK, the vertex is moving away from the sphere. If this number is
we better do something.
+The minimal goal of any collision resolution algorithm is to prevent collisions from getting worse locally. To do this we will implement a simple *velocity filter* approach. Velocity filters are so named because the "filter out" components of an objects velocity that will increase the severity of a collision. Given a vertex that is colliding with our sphere, the only way that the collision can get worse locally is if that vertex moves *into* the sphere. One way we can check if this is happening is to compute the projection of the vertex velocity onto the outward facing contact normal (
,
selects the
contacting vertex). If this number is
we are OK, the vertex is moving away from the sphere. If this number is
we better do something.
The thing we will do is project out, or filter out, the component of the velocity moving in the negative, normal direction like so:
-
+
This "fixes" the collision. This approach to collision resolution is fast but for more complicated scenes it is fraught with peril. For instance it doesn't take into account how it is deforming the simulated object which can cause big headaches when objects are stiff or rigid. We'll see a cleaner mathematical approach to content in the final assignment of the course.
@@ -243,7 +221,7 @@ In this assignment you will reuse your linearly implicit integrator to time step
### dphi_cloth_triangle_dX.cpp
-Piecewise constant gradient matrix for linear shape functions. Row
of the returned matrix contains the gradient of the
shape function.
+Piecewise constant gradient matrix for linear shape functions. Row
of the returned matrix contains the gradient of the
shape function.
### T_cloth.cpp
diff --git a/README.tex.md b/README.tex.md
index 43b4c75..a098f69 100644
--- a/README.tex.md
+++ b/README.tex.md
@@ -125,51 +125,36 @@ $$ f\left(\mathbf{Y}\right)=\sum_{i=0}^{2}f_i\phi_i\left(\mathbf{Y}\right) $$
where $\phi_i$ are the [barycentric coordinates](https://en.wikipedia.org/wiki/Barycentric_coordinate_system) for a 2D triangle and $\mathbf{Y} \in \mathcal{R}^2$ is the 2d coordinate in the undeformed space.
-Our goal is to be able to estimate the 3d world space position of any part of this cloth triangle (for any value of $\mathbf{Y}$ in the triangle). Using our FEM basis, this becomes
+However, cloth is really a thin volumetric construct, of which our triangle only represents a small part. We might need information lying slightly off the triangle surface. To account for this we will need to modify our FEM model a bit. First, let's assume our triangle is actually embedded in a 3D undeformed space $\mathbf{X} \in \mathcal{R}^3$. Let's try and and build and appropriate mapping from this space to the world space.
-$$ \mathbf{x}^t\left(\mathbf{Y}\right)=\sum_{i=0}^{2}\mathbf{x}^t_i\phi_i\left(\mathbf{Y}\right) $$
+Given any point $\mathbf{X}$ in the undeformed space, we can compute the barycentric coordinates of the nearest point on our triangle by solving
-where $\mathbf{x}^t_i \in \mathcal{R}^3$ are the 3d, per-vertex positions of the cloth mesh at time $t$. This gives a mapping from the 2d space of the undeformed cloth to the 3d world space. As usual, we choose the **generalized coordinates** ($\mathbf{q} \in \mathcal{R}^9$) to be the stacked vector of vertex positions, which lets us rewrite the above expression as
+$$\begin{bmatrix}\phi_1\left(\mathbf{X}\right)\\\phi_2\left(\mathbf{X}\right)\end{bmatrix} = \left(T^{T}T\right)^{-1}T^T\left(\mathbf{X} - \mathbf{X}_0\right)$$,
-$$\mathbf{x}^t\left(\mathbf{Y}\right) = \underbrace{\begin{bmatrix} \phi_0\left(\mathbf{Y}\right)I & \phi_1\left(\mathbf{Y}\right)I& \phi_2\left(\mathbf{Y}\right)I \end{bmatrix}}_{N} \underbrace{\begin{bmatrix} \mathbf{x}^t_0 \\ \mathbf{x}^t_1 \\ \mathbf{x}^t_2 \end{bmatrix}}_{\mathbf{q}}$$
-
-The velocity of the cloth, at any point $\mathbf{Y}$ is then given by the total time derivative:
+where $T=\begin{bmatrix}\left(\mathbf{X}_1- \mathbf{X}_0\right) & \left(\mathbf{X}_2- \mathbf{X}_0\right)\end{bmatrix}$ is a matrix of edge vectors. We use the constriaint $\phi_0 + \phi_1+\phi_2=1$ to reconstruct $\phi_0$. This equation finds the barycentric coordinates of the nearest point on the triangle to $\mathbf{X}$ in a least squares fashion. The error in this least squares solve will be orthogonal to the column space of $T$, our triangle. For any point $\mathbf{X}$ we can work out its offset from the triangle by computing $(\mathbf{X}-\mathbf{X}_0)^T\mathbf{N}$, where $\mathbf{X}_0$ is the first vertex of our triangle and $\mathbf{N}$ is the undeformed surface normal of the triangle. Because our triangle has a constant normal, we don't need to worry about where we compute it, which makes this all very convenient.
-$$\mathbf{v}^t\left(\mathbf{Y}\right) = \underbrace{\begin{bmatrix} \phi_0\left(\mathbf{Y}\right)I & \phi_1\left(\mathbf{Y}\right)I& \phi_2\left(\mathbf{Y}\right)I \end{bmatrix}}_{N} \underbrace{\begin{bmatrix} \dot{\mathbf{x}}^t_0 \\ \dot{\mathbf{x}}^t_1 \\ \dot{\mathbf{x}}^t_2 \end{bmatrix}}_{\dot{\mathbf{q}}}$$
+Let's assume that our point $\mathbf{X}$ maintains a constant offset from the triangle when deformed. This implies we can reconstruct the world space position by offsetting our point the same distance along the world space normal $\mathbf{n}$. This gives us the following mapping from reference space to world space
-which defines the **generalized velocities** as the stacked *9d* vector of per-vertex velocities.
+$$ x\left(\mathbf{X}\right)=\sum_{i=0}^{2}\mathbf{x}_i\phi_i\left(\mathbf{X}\right)+\left(\mathbf{X}-\mathbf{X}_0\right)^T\mathbf{N}\cdot\mathbf{n}\left(\mathbf{x}_0,\mathbf{x}_1,\mathbf{x}_2\right) $$.
-## Deformation Gradient
-
-The final necessary piece of the kinematic puzzle is the measure of deformation. You might be tempted to just compute $F = \frac{\partial \mathbf{x}^t}{\partial \mathbf{Y}}$ but this is going to get you in trouble. The dimensions of this matrix ($F \in \mathcal{R}^{3\times 2}$) make evaluating material models difficult since such models are *designed* to work for volumetric (re: square) deformation matrices.
-
-There are lots of ways to handle this problem in [literature](https://animation.rwth-aachen.de/media/papers/2013-CAG-AdaptiveCloth.pdf) and in this assignment we will rely on one which is both simple and effective.
-
-First let's remind ourselves that the functions which define barycentric coordinates require us to solve the linear system
-
-$$\begin{bmatrix}\left(\mathbf{Y}_1- \mathbf{Y}_0\right) & \left(\mathbf{Y}_2- \mathbf{Y}_0\right)\end{bmatrix}\begin{bmatrix}\phi_1\left(\mathbf{Y}\right)\\\phi_2\left(\mathbf{Y}\right)\end{bmatrix} = \mathbf{Y} - \mathbf{Y}_0$$
-
-To "square" our deformation gradient, we are going to "lift" the undeformed space of the cloth to 3d. **NOTE:** we are still going to use 2D triangles but now the undeformed vertex positions of those triangles will be given in 3d. Let's call the 3d undeformed vertex positions of our triangle mesh $\mathbf{X}_i$. So now, given any point in this weird 3d undeformed space, the second and third barycentric coordinates are given by
+Now we can choose the **generalized coordinates** ($\mathbf{q} \in \mathcal{R}^9$) to be the stacked vector of vertex positions, which defines the **generalized velocities** as the stacked *9d* vector of per-vertex velocities.
-$$\underbrace{\begin{bmatrix}\left(\mathbf{X}_1- \mathbf{X}_0\right) & \left(\mathbf{X}_2- \mathbf{X}_0\right)\end{bmatrix}}_{T \in \mathcal{R}^{3 \times 2}}\begin{bmatrix}\phi_1\left(\mathbf{X}\right)\\\phi_2\left(\mathbf{X}\right)\end{bmatrix} = \mathbf{X} - \mathbf{X}_0$$.
-
-Ok, we've made everything worse. Now we can't even directly invert the right-hand side. But this is one of those cases wherein things had to get [worse before they get better](https://www.youtube.com/watch?v=uDIgS-Soo9Q). However, we can solve this system in a [least-squares](https://en.wikipedia.org/wiki/Least_squares) sense which gives us
-
-$$\begin{bmatrix}\phi_1\left(\mathbf{X}\right)\\\phi_2\left(\mathbf{X}\right)\end{bmatrix} = \left(T^{T}T\right)^{-1}T^T\left(\mathbf{X} - \mathbf{X}_0\right)$$
-
-which, when coupled with the fact that $\phi_0 = 1-\phi_1-\phi_2$ gives us everything we need.
+## Deformation Gradient
-This might seem like an esoteric, algebraic solution, but geometrically it is doing something really quite reasonable. Any 3d point $\mathbf{X}$, which is on a triangle yields the same barycentric coordinates as the 2d solution. That's a good feature to have since we always, always, always [only calculate the world space position of the cloth at points on the cloth](https://en.wikipedia.org/wiki/Truism). ~~For 3d points $\mathbf{X}$ that are off the cloth, this formulation projects them orthogonally (along the triangle normal) onto the cloth and returns the value for this projected cloth point. Because of this projection, the deformation of the cloth in the normal direction is zero, which makes sense, the discrete cloth has no thickness in this direction and cannot deform. However, because $\mathbf{X}$ is now 3d, the derivative $\frac{\partial \phi_i}{\partial \mathbf{X}}$ becomes $3 \times 3$ which means $F$ also becomes a $3\times 3$. This is much easier to deal with down the road. ~~
+There are lots of ways to handle build a cloth deformation gradient in [literature](https://animation.rwth-aachen.de/media/papers/2013-CAG-AdaptiveCloth.pdf). In this assignment we will be able to avoid these more complicated solution due to our particular choice of undeformed to world space mapping which allows us to directly compute a $3 \times 3$ deformation gradient as
-**This derivation has changed since last year, I will update it soon.**
+$$ \mathrm{F} = \frac{\partial \mathbf{x}}{\partial \mathbf{X}} = \begin{pmatrix} \mathbf{x}_0 & \mathbf{x}_1 & \mathbf{x}_2 & \mathbf{n} \end{pmatrix} \begin{pmatrix} -\mathbf{1}^T\left(\mathrm{T}^T\mathrm{T}\right)^{-1}\mathrm{T}^T\\ \left(\mathrm{T}^T\mathrm{T}\right)^{-1}\mathrm{T}^T\\\mathbf{N}^T\end{pmatrix}$$
## Kinetic Energy
-Armed with the generalized velocities, the formula for the per-triangle kinetic energy is eerily similar to that of assignment 3. It's an integral of the local kinetic energy over the entire triangle
+Armed with the generalized velocities, the formula for the per-triangle kinetic energy is eerily similar to that of assignment 3. It's an integral of the local kinetic energy over the entire triangle, multiplied by the thickness of the cloth, $h$. For this assignment you are free to assume the thickness of the cloth is $1$.
-$$ T_{triangle} = \dot{\mathbf{q}}\underbrace{\left(\int_{\mbox{triangle}}\rho N\left(\mathbf{X}\right)^T N\left(\mathbf{X}\right) dV\right)}_{M_e}\dot{\mathbf{q}} $$
+$$ T_{triangle} = \frac{1}{2}\dot{\mathbf{q}}^T\left(h\int_\Gamma\rho\begin{pmatrix}\phi_0\phi_0\mathrm{I}&\phi_0\phi_1\mathrm{I}&\phi_0\phi_2\mathrm{I}\\
+\phi_1\phi_0\mathrm{I}&\phi_1\phi_1\mathrm{I}&\phi_1\phi_2\mathrm{I}\\
+\phi_2\phi_0\mathrm{I}&\phi_2\phi_1\mathrm{I}&\phi_2\phi_2\mathrm{I}
+\end{pmatrix}d\Gamma\right)\dot{\mathbf{q}} $$
-and can be compute analytically using a symbolic math package. The per-element mass matrices for the every cloth triangle can then be *assembled* into the mass matrix for the entire mesh.
+and can be compute analytically using a symbolic math package. The per-element mass matrices for every cloth triangle can then be *assembled* into the mass matrix for the entire mesh.
## Potential Energy
@@ -183,13 +168,11 @@ $\Lambda$ are the eigenvalues of $F^T F$ and also the squared [*singular values*
### Linear Elasticity without the Pesky Rotations
-Now we can formulate a linear elastic model using the principal stretches which "filters out" any rotational components. Much like the Neohookean material model, this model will have one energy term which measures deformation and one energy term that tries to preserve volume (well area in the case of cloth). We already know we can measure deformation using the principal stretches. We also know that the determinant of $F$ measures the change in volume of a 3D object. In the volumetric case this determinant is just the product of the principal stretches. But first, we need to understand some specifics about the deformation gradient of cloth.
-
-Recall that our deformation gradient for a cloth triangle is computed using a least squares projection. This is nice because we still have a $3 \times 3$ matrix on which to perform singular value decomposition on (and later ... (*shudder*) take the derivative of). It's problematic because this deformation gradient has a nullspace normal to the triangle (all points normal to the triangle are mapped to the same barycentric coordinate). This means that, forever and always, **one of the singular values of $F$ will be zero**. Now if we assume that our triangle is not deformed to be inside out or squished to a line or a point, then this zero singular value will always be the last singular value returned by any reasonable SVD code (Eigen is pretty reasonable). Thus rather than use all three principal values in our material model, we will only use the first 2. This gives us the following material model
+Now we can formulate a linear elastic model using the principal stretches which "filters out" any rotational components. Much like the Neohookean material model, this model will have one energy term which measures deformation and one energy term that tries to preserve volume (well area in the case of cloth). We already know we can measure deformation using the principal stretches. We also know that the determinant of $F$ measures the change in volume of a 3D object. In the volumetric case this determinant is just the product of the principal stretches.
-$$\psi\left(s_0, s_1\right) = \mu\sum_{i=0}^1\left(s_i-1\right)^2 + \frac{\lambda}{2}\left(s_0 + s_1 -2\right)^2 $$
+$$\psi\left(s_0, s_1, s_2\right) = \mu\sum_{i=0}^2\left(s_i-1\right)^2 + \frac{\lambda}{2}\left(s_0 + s_1 +s_2-3\right)^2 $$
-where $\lambda$ and $\mu$ are the material properties for the cloth. The first term in this model attempts to keep $s_0$ and $s_1$ close to one (limiting deformation) while the second term is attempting to preserve the area of the deformed triangle (it's a linearization of the determinant). This model is called **co-rotational linear elasticity** because it is linear in the principal stretches but rotates *with* each finite element. When we use energy models to measure the in-plane stretching of the cloth (or membrane), we often refer to them as membrane energies.
+where $\lambda$ and $\mu$ are the material properties for the cloth. The first term in this model attempts to keep $s_0$ and $s_1$ close to one (limiting deformation) while the second term is attempting to preserve the volume of the deformed triangle (it's a linearization of the determinant). This model is called **co-rotational linear elasticity** because it is linear in the principal stretches but rotates *with* each finite element. When we use energy models to measure the in-plane stretching of the cloth (or membrane), we often refer to them as membrane energies.
### The Gradient of Principal Stretch Models
diff --git a/images/01f349799d08738b3ed7187a8adfa8b7.svg b/images/01f349799d08738b3ed7187a8adfa8b7.svg
new file mode 100644
index 0000000..c301132
--- /dev/null
+++ b/images/01f349799d08738b3ed7187a8adfa8b7.svg
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/034d0a6be0424bffe9a6e7ac9236c0f5.svg b/images/034d0a6be0424bffe9a6e7ac9236c0f5.svg
new file mode 100644
index 0000000..493dd7b
--- /dev/null
+++ b/images/034d0a6be0424bffe9a6e7ac9236c0f5.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/07617f9d8fe48b4a7b3f523d6730eef0.svg b/images/07617f9d8fe48b4a7b3f523d6730eef0.svg
new file mode 100644
index 0000000..6a7d3b5
--- /dev/null
+++ b/images/07617f9d8fe48b4a7b3f523d6730eef0.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/07640d208ac0851eb169c73b736e6bb1.svg b/images/07640d208ac0851eb169c73b736e6bb1.svg
new file mode 100644
index 0000000..3a5c29a
--- /dev/null
+++ b/images/07640d208ac0851eb169c73b736e6bb1.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/0a36368a7b551a7c6aa055de5009bea3.svg b/images/0a36368a7b551a7c6aa055de5009bea3.svg
new file mode 100644
index 0000000..52bcdc1
--- /dev/null
+++ b/images/0a36368a7b551a7c6aa055de5009bea3.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/1757afe2b054e59c6d5c465cf82bd885.svg b/images/1757afe2b054e59c6d5c465cf82bd885.svg
new file mode 100644
index 0000000..bbfe4ee
--- /dev/null
+++ b/images/1757afe2b054e59c6d5c465cf82bd885.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/1767c7f7922c97563d66b8446ba75840.svg b/images/1767c7f7922c97563d66b8446ba75840.svg
new file mode 100644
index 0000000..be8645f
--- /dev/null
+++ b/images/1767c7f7922c97563d66b8446ba75840.svg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/1e910408a8c30e48164f77629c847ebe.svg b/images/1e910408a8c30e48164f77629c847ebe.svg
new file mode 100644
index 0000000..d6495c2
--- /dev/null
+++ b/images/1e910408a8c30e48164f77629c847ebe.svg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/286f7d4815c0996530bda7973b1ec5ea.svg b/images/286f7d4815c0996530bda7973b1ec5ea.svg
new file mode 100644
index 0000000..b62677b
--- /dev/null
+++ b/images/286f7d4815c0996530bda7973b1ec5ea.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/2ad9d098b937e46f9f58968551adac57.svg b/images/2ad9d098b937e46f9f58968551adac57.svg
new file mode 100644
index 0000000..647c6ee
--- /dev/null
+++ b/images/2ad9d098b937e46f9f58968551adac57.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/2f118ee06d05f3c2d98361d9c30e38ce.svg b/images/2f118ee06d05f3c2d98361d9c30e38ce.svg
new file mode 100644
index 0000000..ac5d556
--- /dev/null
+++ b/images/2f118ee06d05f3c2d98361d9c30e38ce.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/357a3518901055dabec2b6272f82e942.svg b/images/357a3518901055dabec2b6272f82e942.svg
new file mode 100644
index 0000000..639ed9d
--- /dev/null
+++ b/images/357a3518901055dabec2b6272f82e942.svg
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/36b5afebdba34564d884d347484ac0c7.svg b/images/36b5afebdba34564d884d347484ac0c7.svg
new file mode 100644
index 0000000..d772fbc
--- /dev/null
+++ b/images/36b5afebdba34564d884d347484ac0c7.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/3b6459009b4b915041dfd6286e7e0c2b.svg b/images/3b6459009b4b915041dfd6286e7e0c2b.svg
new file mode 100644
index 0000000..fec8760
--- /dev/null
+++ b/images/3b6459009b4b915041dfd6286e7e0c2b.svg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/3def24cf259215eefdd43e76525fb473.svg b/images/3def24cf259215eefdd43e76525fb473.svg
new file mode 100644
index 0000000..5c3b3d7
--- /dev/null
+++ b/images/3def24cf259215eefdd43e76525fb473.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/3e365d0313ccf4a7bdc45ac83825ea92.svg b/images/3e365d0313ccf4a7bdc45ac83825ea92.svg
new file mode 100644
index 0000000..5ccbe0d
--- /dev/null
+++ b/images/3e365d0313ccf4a7bdc45ac83825ea92.svg
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/52999a1482045a0142d3cbd60a381afe.svg b/images/52999a1482045a0142d3cbd60a381afe.svg
new file mode 100644
index 0000000..517bdfb
--- /dev/null
+++ b/images/52999a1482045a0142d3cbd60a381afe.svg
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/57354dd3723345bfc2d7b2a89dd465a7.svg b/images/57354dd3723345bfc2d7b2a89dd465a7.svg
new file mode 100644
index 0000000..712e5e4
--- /dev/null
+++ b/images/57354dd3723345bfc2d7b2a89dd465a7.svg
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/57d6ce76b81f64d9de86d723aaf06fcf.svg b/images/57d6ce76b81f64d9de86d723aaf06fcf.svg
new file mode 100644
index 0000000..f08e2fb
--- /dev/null
+++ b/images/57d6ce76b81f64d9de86d723aaf06fcf.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/58c2313bc1ea66cc4d86d27f83c1941d.svg b/images/58c2313bc1ea66cc4d86d27f83c1941d.svg
new file mode 100644
index 0000000..1cf2a00
--- /dev/null
+++ b/images/58c2313bc1ea66cc4d86d27f83c1941d.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/5c09159163d9a8fe55c1a3016a3ad75a.svg b/images/5c09159163d9a8fe55c1a3016a3ad75a.svg
new file mode 100644
index 0000000..6e061e4
--- /dev/null
+++ b/images/5c09159163d9a8fe55c1a3016a3ad75a.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/5cae4b0b649a9b8d2fe83816e5ea8db6.svg b/images/5cae4b0b649a9b8d2fe83816e5ea8db6.svg
new file mode 100644
index 0000000..51778e9
--- /dev/null
+++ b/images/5cae4b0b649a9b8d2fe83816e5ea8db6.svg
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/6018bf12266e0674a19d0a622989ad88.svg b/images/6018bf12266e0674a19d0a622989ad88.svg
new file mode 100644
index 0000000..620bc59
--- /dev/null
+++ b/images/6018bf12266e0674a19d0a622989ad88.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/6f6d7d2d59fa79786810222c5181b7c8.svg b/images/6f6d7d2d59fa79786810222c5181b7c8.svg
new file mode 100644
index 0000000..b1e6383
--- /dev/null
+++ b/images/6f6d7d2d59fa79786810222c5181b7c8.svg
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/77a3b857d53fb44e33b53e4c8b68351a.svg b/images/77a3b857d53fb44e33b53e4c8b68351a.svg
new file mode 100644
index 0000000..d000c3d
--- /dev/null
+++ b/images/77a3b857d53fb44e33b53e4c8b68351a.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/79361f938b80de1c32bb7d7724ce3590.svg b/images/79361f938b80de1c32bb7d7724ce3590.svg
new file mode 100644
index 0000000..6dfb1f0
--- /dev/null
+++ b/images/79361f938b80de1c32bb7d7724ce3590.svg
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/7c7c6fbc6e734e01d65098befa8bd28f.svg b/images/7c7c6fbc6e734e01d65098befa8bd28f.svg
new file mode 100644
index 0000000..2da4445
--- /dev/null
+++ b/images/7c7c6fbc6e734e01d65098befa8bd28f.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/82f2067d05c8a81659bc2b949d23b64a.svg b/images/82f2067d05c8a81659bc2b949d23b64a.svg
new file mode 100644
index 0000000..9c7ec54
--- /dev/null
+++ b/images/82f2067d05c8a81659bc2b949d23b64a.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/84a62034abeb6bfffada277b45a096c7.svg b/images/84a62034abeb6bfffada277b45a096c7.svg
new file mode 100644
index 0000000..e00c750
--- /dev/null
+++ b/images/84a62034abeb6bfffada277b45a096c7.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/870c98e8c4b120f06c7a15af3b02d6e7.svg b/images/870c98e8c4b120f06c7a15af3b02d6e7.svg
new file mode 100644
index 0000000..bb92fd4
--- /dev/null
+++ b/images/870c98e8c4b120f06c7a15af3b02d6e7.svg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/97c7f491f7ac1623c0a86b1fb656029b.svg b/images/97c7f491f7ac1623c0a86b1fb656029b.svg
new file mode 100644
index 0000000..11a2bed
--- /dev/null
+++ b/images/97c7f491f7ac1623c0a86b1fb656029b.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/985383447914a70e21e1b46c8b075b81.svg b/images/985383447914a70e21e1b46c8b075b81.svg
new file mode 100644
index 0000000..d49a22f
--- /dev/null
+++ b/images/985383447914a70e21e1b46c8b075b81.svg
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/9a05c8a8b310cb0d9f34636450b3d442.svg b/images/9a05c8a8b310cb0d9f34636450b3d442.svg
new file mode 100644
index 0000000..522f9ad
--- /dev/null
+++ b/images/9a05c8a8b310cb0d9f34636450b3d442.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/9f2b6b0a7f3d99fd3f396a1515926eb3.svg b/images/9f2b6b0a7f3d99fd3f396a1515926eb3.svg
new file mode 100644
index 0000000..f149035
--- /dev/null
+++ b/images/9f2b6b0a7f3d99fd3f396a1515926eb3.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/a0d1fd43ad34510636923359f83becfa.svg b/images/a0d1fd43ad34510636923359f83becfa.svg
new file mode 100644
index 0000000..a574395
--- /dev/null
+++ b/images/a0d1fd43ad34510636923359f83becfa.svg
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/a8c1f0c39cf12de6d64430cd9bc86046.svg b/images/a8c1f0c39cf12de6d64430cd9bc86046.svg
new file mode 100644
index 0000000..5bf0d82
--- /dev/null
+++ b/images/a8c1f0c39cf12de6d64430cd9bc86046.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/a9a3a4a202d80326bda413b5562d5cd1.svg b/images/a9a3a4a202d80326bda413b5562d5cd1.svg
new file mode 100644
index 0000000..8184e0c
--- /dev/null
+++ b/images/a9a3a4a202d80326bda413b5562d5cd1.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/aba2578ca1be0bea64b5de8519cf7b12.svg b/images/aba2578ca1be0bea64b5de8519cf7b12.svg
new file mode 100644
index 0000000..41dcad2
--- /dev/null
+++ b/images/aba2578ca1be0bea64b5de8519cf7b12.svg
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/ac3148a5746b81298cb0c456b661f197.svg b/images/ac3148a5746b81298cb0c456b661f197.svg
new file mode 100644
index 0000000..725327f
--- /dev/null
+++ b/images/ac3148a5746b81298cb0c456b661f197.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/b23332f99af850a48831f80dbf681ed6.svg b/images/b23332f99af850a48831f80dbf681ed6.svg
new file mode 100644
index 0000000..d17bb47
--- /dev/null
+++ b/images/b23332f99af850a48831f80dbf681ed6.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/b38dda0a0c1ab15d9dae0b9b9e8aa1dc.svg b/images/b38dda0a0c1ab15d9dae0b9b9e8aa1dc.svg
new file mode 100644
index 0000000..d124415
--- /dev/null
+++ b/images/b38dda0a0c1ab15d9dae0b9b9e8aa1dc.svg
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/b56595d2a30a0af329086562ca12d521.svg b/images/b56595d2a30a0af329086562ca12d521.svg
new file mode 100644
index 0000000..d2c9616
--- /dev/null
+++ b/images/b56595d2a30a0af329086562ca12d521.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/b8bc815b5e9d5177af01fd4d3d3c2f10.svg b/images/b8bc815b5e9d5177af01fd4d3d3c2f10.svg
new file mode 100644
index 0000000..96dcde6
--- /dev/null
+++ b/images/b8bc815b5e9d5177af01fd4d3d3c2f10.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/b93e9b71beaf724ff1d0f85841e9ae61.svg b/images/b93e9b71beaf724ff1d0f85841e9ae61.svg
new file mode 100644
index 0000000..e457f33
--- /dev/null
+++ b/images/b93e9b71beaf724ff1d0f85841e9ae61.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/bccab73005d96290c8ef588703533a21.svg b/images/bccab73005d96290c8ef588703533a21.svg
new file mode 100644
index 0000000..fa458f2
--- /dev/null
+++ b/images/bccab73005d96290c8ef588703533a21.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/bfdc1036a225b1cba16ea97fa96d82de.svg b/images/bfdc1036a225b1cba16ea97fa96d82de.svg
new file mode 100644
index 0000000..e4a63ec
--- /dev/null
+++ b/images/bfdc1036a225b1cba16ea97fa96d82de.svg
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/c019432b974b538f20a9d3cb38176a2d.svg b/images/c019432b974b538f20a9d3cb38176a2d.svg
new file mode 100644
index 0000000..1a82058
--- /dev/null
+++ b/images/c019432b974b538f20a9d3cb38176a2d.svg
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/c36ef0ba4721f49285945f33a25e7a45.svg b/images/c36ef0ba4721f49285945f33a25e7a45.svg
new file mode 100644
index 0000000..6268e84
--- /dev/null
+++ b/images/c36ef0ba4721f49285945f33a25e7a45.svg
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/c83e439282bef5aadf55a91521506c1a.svg b/images/c83e439282bef5aadf55a91521506c1a.svg
new file mode 100644
index 0000000..8206b19
--- /dev/null
+++ b/images/c83e439282bef5aadf55a91521506c1a.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/ca2d7f8fc10bcbce38360119af40ad8e.svg b/images/ca2d7f8fc10bcbce38360119af40ad8e.svg
new file mode 100644
index 0000000..a6bab82
--- /dev/null
+++ b/images/ca2d7f8fc10bcbce38360119af40ad8e.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/d05b996d2c08252f77613c25205a0f04.svg b/images/d05b996d2c08252f77613c25205a0f04.svg
new file mode 100644
index 0000000..7c72ee6
--- /dev/null
+++ b/images/d05b996d2c08252f77613c25205a0f04.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/df63751855fcec904c3e28f701952a87.svg b/images/df63751855fcec904c3e28f701952a87.svg
new file mode 100644
index 0000000..b73792f
--- /dev/null
+++ b/images/df63751855fcec904c3e28f701952a87.svg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/e846e5631eca1fe2f735605515f5be61.svg b/images/e846e5631eca1fe2f735605515f5be61.svg
new file mode 100644
index 0000000..05748b9
--- /dev/null
+++ b/images/e846e5631eca1fe2f735605515f5be61.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/e9c52417462e27805f522b91127f71ab.svg b/images/e9c52417462e27805f522b91127f71ab.svg
new file mode 100644
index 0000000..32a280f
--- /dev/null
+++ b/images/e9c52417462e27805f522b91127f71ab.svg
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/ea4bbf715156e61bd05c0ec553601019.svg b/images/ea4bbf715156e61bd05c0ec553601019.svg
new file mode 100644
index 0000000..9dfa065
--- /dev/null
+++ b/images/ea4bbf715156e61bd05c0ec553601019.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/fd8be73b54f5436a5cd2e73ba9b6bfa9.svg b/images/fd8be73b54f5436a5cd2e73ba9b6bfa9.svg
new file mode 100644
index 0000000..6342351
--- /dev/null
+++ b/images/fd8be73b54f5436a5cd2e73ba9b6bfa9.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/fdacaa2009a566aee165e36a976fa9cd.svg b/images/fdacaa2009a566aee165e36a976fa9cd.svg
new file mode 100644
index 0000000..14cb9b4
--- /dev/null
+++ b/images/fdacaa2009a566aee165e36a976fa9cd.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/fe4e62694c7a379a0b31c6aa14046dd0.svg b/images/fe4e62694c7a379a0b31c6aa14046dd0.svg
new file mode 100644
index 0000000..387592a
--- /dev/null
+++ b/images/fe4e62694c7a379a0b31c6aa14046dd0.svg
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/shared/include/EigenTypes.h b/shared/include/EigenTypes.h
index 949caf2..05e633e 100644
--- a/shared/include/EigenTypes.h
+++ b/shared/include/EigenTypes.h
@@ -17,9 +17,11 @@ namespace Eigen {
using Matrix32d = Eigen::Matrix;
using Matrix34d = Eigen::Matrix;
using Matrix36d = Eigen::Matrix;
+ using Matrix39d = Eigen::Matrix;
using Matrix43d = Eigen::Matrix;
using Matrix66d = Eigen::Matrix;
using Matrix99d = Eigen::Matrix;
+ using Matrix93d = Eigen::Matrix;
using Matrix1212d = Eigen::Matrix;
using Matrix44f = Eigen::Matrix;