Skip to content

uingue/geometry-processing-deformation

 
 

Repository files navigation

Geometry Processing – Deformation

To get started: Fork this repository then issue

git clone --recursive http://github.com/[username]/geometry-processing-deformation.git

Installation, Layout, and Compilation

See introduction.

Execution

Once built, you can execute the assignment from inside the build/ by running on a given mesh:

./deformation [path to mesh.obj]

When the mesh is blue, the system is in "place handles" mode. Click on the mesh to select vertex locations for control point handles. After pressing space to switch to deformation mode, drag the handles. Pressing m will switch between different deformation methods.

Background

In this assignment we explore smooth deformation of an existing shape. Shape deformation has many applications in geometry process; we will focus on interactive handle-based deformation. In this setup, the user repositions a sparse set of points and the goal is to propagate the transformation at these "handles" to the rest of the shape. To be interactive we should aim for computing the new deformation of the shape at around 30 frames per second.

Shape deformation is the transformation from its rest shape to a new/current/deformed shape. If the position of a point on some 3D rest shape given by $\hat{\x} ∈ \R³$ then we will write that the unknown position on the deformed shape is given by $\x ∈ \R³$. We can write this point's displacement vector as $\x - \hat{\x} =: \d ∈ \R³$.

The propagation of the handles' deformation can be thought of in two complementary ways:

  1. as a scattered data interpolation problem, where handles provide sparse samples of an unknown displacement field, or
  2. as a shape optimization problem, where we try to define a new shape that retains the details of the old shape but fulfills the handle constraints.

In the following discussion we will take advantage of the ability to switch between thinking of the unknowns as the positions of the deformed shape ($\x$) and displacements ($\d$). These views are equivalent, but often one or the other provides a better intuitive understanding.

Continuity

We will limit ourselves to continuous deformations of shapes. That is, the shape will not tear, crack or change its topological features.

If we represent our shape discretely as a triangle mesh (e.g., with rest vertices in $\hat{\V} ∈ \R^{n × 3}$ and faces in $F ∈ {1,…,n}^{m × 3}$, then we can trivially ensure a continuous deformation by determining new vertex positions $\V$. The topology (connectivity) of the mesh ($F$) will not change.

Generic Distortion Minimization

A rest surface $\hat{S}$ immersed in $\R³$ can be described as a mapping $\hat{\x}$ from some 2D parametric domain $Ω$. For any parameters $u$ and $v$, $\hat{\x}$ describes the 3D position:

\[ \hat{\x}(u,v) ∈ \R³. \]

Similarly the deformed surface can be represented as a position function $\x: Ω → \R³$. The displacement vector field is thus a function taking the difference: $\d(u,v) = \x(u,v) - \hat{\x}(u,v)$.

For the handle-based deformation problem we would like to find a new surface (defined by $\x$) that:

  1. adds as little distortion as possible to the shape, and
  2. satisfies the users constraints at selected handle positions.

We can cast this as an energy optimization problem. Suppose we have energy functional $E(\x)$ that measures the amount of distortion between the new shape ($\x$) and the rest shape $\hat{x}$, then we could optimize for the best possible shape $\x$ by minimizing $E$:

\[ \min_\x E(\x). \]

To ensure that the user's $k$ handle points are interpolated we add the constraints:

\[ \text{ subject to } \x(u_i, v_i) = \g_i \ ∀ i = {1, … , k}, \] where $\g_i$ is the position of the $i$th control point handle.

While the constraints are straightforward, we have many choices for how to formulate the energy function $E$. A natural choice is to measure distortion in an egalitarian way by integrating a local measure of distortion at all points on the surface:

\[ \min_\x ∫_Ω ‖ e(\x) ‖² \ dA \quad \text{ subject to } \x(u_i, v_i) = \g_i \ ∀ i = {1, … , k}, \]

where $e$ is a vector- or scalar- valued function measuring local (unsquared) distortion. We will now consider different choices for $e$.

Linear Methods

If we assume that the deformation between the rest shape given by $\hat{\x}$ and the new shape given by $\x$ is small then we can measure the distortion of the deformation in terms of the smoothness of the displacement field. This simplest methods will integrate the magnitude of derivatives of the displacement field ($\d$): if the displacement field has large variations or sudden changes then it is inducing a lot of distortion.

Gradient-based energy

Let us first consider minimizing the integral of squared variation of the displacement field:

\[ \min_\d ∫_Ω ‖ ∇\d ‖_F^2 \ dA \quad \text{ subject to } \d_i = \g_i-\hat{\x}_i \ ∀ i = {1, … , k}, \] where $∇\d = \left(\begin{array}{ccc} \frac{∂d^x}{∂u} & \frac{∂d^y}{∂u} & \frac{∂d^z}{∂u} \ \frac{∂d^x}{∂v} & \frac{∂d^y}{∂v} & \frac{∂d^z}{∂v} \end{array}\right)$ the Jacobian matrix of the displacement field $\d$

Deformation Gradient

If $\I ∈ \R^{3 × 3}$ is the identity matrix, then the quantity $\F := \I + ∇\d$ is referred to as the deformation gradient in the mechanics community.

This is simply the familiar Dirichlet energy applied to each coordinate function of the displacement field independently.

We can discretize this over our triangle mesh surface the same way we have in smoothing and parameterization assignments:

\[ \min_{\D} \tr{\D^\transpose \L \D} \quad \text{subject to } \D_\text{handles} = \g_\text{handles} - \hat{\V}\text{handles}, \] where the rows of $\g\text{handles} ∈ \R^{k × 3}$ contains the new positions of the $k$ control point handles.

While easy to implement, this method suffers from a couple immediate problems:

  1. it is not smooth at constraints, and
  2. then influence of handles dies off too quickly.

Two regions of selected points (purple) are constrained. The gradient-based energy produces a continuous displacement but is not smooth at the inner constrained points (sharp crease). The Laplacian-based energy produces a displacement with continuous positions and derivatives.

By minimizing the Dirichlet energy, each coordinate of "displacement field" is a harmonic function. Intuitively (however abstractly) we can think of each function as diffusing the user's constraints as if they were heat values. As such, each function diffuses quickly to an average, slowly varying value over most of the domain. As a displacement field a constant value for each coordinate function would mean a translation: most of the shape is simply translated.

The gradient operator ($∇$) is a linear operator. We can alternatively view our minimization above in terms of the unknown positions $\x$:

\[ \min_\d ∫_Ω ‖ ∇\d ‖F^2 \ dA ⇒ \min\x ∫_Ω ‖ ∇(\x - \hat{\x}) ‖F^2 \ dA ⇒ \min\x ∫_Ω ‖ \underbrace{∇\x}\text{after} - \underbrace{∇\hat{\x}}\text{before} ‖_F^2 \ dA. \] If we think of the gradient of the position function $∇\x$ (with respect to the underlying parameterization $u,v$) as a local geometric feature descriptor then this energy can be re-understood as measuring the difference in this feature before and after the deformation. This is very sensible as we are trying to measure distortion. We would expect that a low-distortion deformation would correspond with a small change to local features.

Unfortunately, the gradient of the position function $\x$ is a poor, first-order local feature.

Laplacian-based energy

If we model distortion as the change in a local feature descriptor, then a natural local and relative descriptor would be one that compared the position of some point on the shape to the average of its local neighborhood. We have studied an operator that computes this in the smoothing assignment. The Laplace(-Beltrami) operator can be derived as taking exactly the difference of a functions value at a point and the average (i.e., centroid) of an infinitesimal region around that point:

\[ ∆ f(\x) = \lim_{|B(\x)| → 0} \frac{1}{|B(\x))|} ∫_{B(\x)} f(\z) ;d\z - f(\x) \]

(see, e.g., "Differential coordinates for local mesh morphing and deformation" [Alexa et al. 2003] and expanded upon in "Laplacian Surface Editing" [Sorkine et al. 2004]).

When applied to the embedding function $\x$ the Laplace operator computes the difference in position between a point and its local neighborhood. This vector points in the normal direction and its magnitude corresponds inversely with how flat the surface is locally.

Let's replace the gradient feature above with this second-order feature descriptor and massage our optimization problem back in terms of displacements:

\[ \min_\x ∫_Ω ‖ \underbrace{∆\x}\text{after} - \underbrace{∆\hat{\x}}\text{before} ‖^2 \ dA ⇒ \min_\x ∫_Ω ‖ ∆(\x - \hat{\x}) ‖^2 \ dA ⇒ \min_\d ∫_Ω ‖ ∆\d ‖^2 \ dA. \]

Just as we can show that harmonic functions ($∆\d = 0$) minimize the Dirichlet energy, we can use calculus of variations apply Green's identity twice to show that minimizers of the squared-Laplacian energy are _bi-_harmonic functions ($∆∆\d = 0$ or $∆²\d = 0$). Obviously all harmonic functions are also biharmonic functions. This implies that the space of biharmonic functions is strictly larger. In particular, this will allow use to ensure continuity of first derivatives across constrained values at handles.

The fact that each coordinate of the displacement field $\d$ will be a bi-harmonic function is not so elucidating, but by minimizing the squared-Laplacian energy integrated over the domain, we can say that it is as-harmonic-as-possible. Harmonic functions include constant functions (i.e., translations) but also any displacement that bends in one direction by an equal and opposite amount as it bends in the other direction: $∆\d = 0 → ∂\d/∂u

  • ∂\d/∂v = 0 → ∂\d/∂u = -∂\d/∂v$.

To discretize this energy we can make use of our discrete Laplacian operator $\L$. This matrix computes the locally integrated Laplacian of a given function specified by per-vertex values $\f$. Now we would like to integrate the square of the point-wise Laplacian. We can approximate the point-wise Laplacian by the local integral average of the Laplacian $\M^{-1}\L \f$. Integrating this over the mesh we have our complete approximate of the energy:

\[ \begin{align} ∫_Ω ‖∆\d‖² ;dA &≈ \tr{ \D^\transpose \L^\transpose \M^{-\transpose} \M \M^{-1} \L \D}\ &= \tr{ \D^\transpose \underbrace{\L^\transpose \M^{-1} \L}_{\Q} \D }, \end{align} \] where $\M ∈ \R^{n × n}$ is the mass-matrix for the given mesh and $\Q ∈ \R^{n×n}$ can be thought of as the bi-Laplacian matrix.

$k$-harmonic

The logical continuation of harmonic and biharmonic deformation is to consider triharmonic ($∆³\d = 0$) and tetraharmonic ($∆⁴\d = 0$) and so on. It's straightforward to implement these, though there are diminishing returns and increasing costs.

Precomputation

With out loss of generality, assume that the rows of the unknown displacements $\D$ have been sorted so that displacements corresponding to handle vertices are in the bottom part:

\[ \D = \left(\begin{array}{c} \D_\text{u} \ \D_\text{h} \end{array} \right) \]

Since the displacements at handles are known before the optimization, we can separate the knowns and unknowns in the energy:

\[ \min_{\D_\text{u}} \tr{(\D_\text{u}^\transpose \ \D_\text{h}^\transpose) \left(\begin{array}{cc} \Q_\text{u,u} & \Q_\text{u,h} \ \Q_\text{h,u} & \Q_\text{h,h} \end{array}\right) \left(\begin{array}{c} \D_\text{u} \ \D_\text{h} \end{array} \right)} \ \min_{\D_\text{u}} \tr{\D_\text{u}^\transpose \Q_\text{u,u} \D_\text{u} + 2 \D_\text{u}^\transpose \Q_\text{u,h} \D_\text{h} + \underbrace{\D_\text{h}^\transpose \Q_\text{h,h} \D_\text{h}}\text{constant}} \ \min{\D_\text{u}} \tr{ \D_\text{u}^\transpose \Q_\text{u,u} \D_\text{u} + 2 \D_\text{u}^\transpose \Q_\text{u,h} \D_\text{h}} \] where $\Q_\text{u,u} ∈ \R^{(n-k) × (n-k)}$ is the quadratic coefficients matrix corresponding to the unknown displacements.

This quadratic optimization problem may solved by setting all partial derivatives with respect to degrees of freedom in $\D_\text{u}$ to zero:

\[ 2 \Q_\text{u,u} \D_\text{u} + 2 \Q_\text{u,h} \D_\text{h} = 0 → \D_\text{u} = \Q_\text{u,u}^{-1} \Q_\text{u,h} \D_\text{h} \]

If we don't change which vertices are handles, but only change the positions of the selected handles, then only $\D_\text{h}$ changes above. In particular, the matrix $\Q_\text{u,u}$ is unchanged. Therefore, we can prefactorize it so that applying its inverse is fast (igl::min_quad_with_fixed does this for you).

Actually the entire term $\Q_\text{u,u}^{-1} \Q_\text{u,h} =: \W ∈ \R^{(n-k) × k}$ does not change. The columns of $\W$ reveal how unknown displacements respond to each handle point's displacement (see also "An intuitive framework for real-time freeform modeling" [Botsch & Kobbelt 2004]). This provides a gateway to the relationship with linear blend skinning and automatic (biharmonic) weighting functions (see "Bounded Biharmonic Weights for Real-Time Deformation" [Jacobson et al. 2011]).

Trouble in paradise

Biharmonic displacements work well for small deformations and deformations that do not imply a large rotation. However, the Laplacian of the position function $∆\x$ as a feature descriptor is not rotation invariant. This problem is true for all linear differential features including the gradient of the embedding function $∇\x$ considered above (see "On linear variational surface deformation methods" [Botsch & Sorkine 2008]).

This means that if the user transforms all of the handle locations by a rigid transformation $\T$ these energies will not measure zero for a displacement equivalent to applying the rigid transformation $\T$ to the entire shape. We would like global rotation invariance, but we would also like this property to apply locally so that parts of the shape can easily rotate.

As-rigid-as-possible

In the scenario where each handle $i$ are perfectly transformed by a rigid transformation $\x_i = \Rot \hat{\x}_i + \t$, where $\Rot ∈ SO(3) ⊂ \R^{3×3}$ is a rotation matrix and $\t∈\R^3$ is a translation vector. If an oracle could only tell us this particular rigid transformation then we could repair the gradient-based energy above by pre-rotating the rest shape by this transformation:

\[ \begin{align} ∫_Ω ‖ ∇ \x - ∇(\Rot \hat{\x} + \t) ‖² ;dA &= ∫_Ω ‖ ∇ \x - ∇(\Rot \hat{\x}) - ∇\t‖² ;dA \ &= ∫_Ω ‖ ∇ \x - \Rot ∇\hat{\x} ‖² ;dA, \end{align} \]

where the translation vector $\t$ falls out because a translation has constant gradient.

We do not know the rotation $\Rot$ ahead of time, but we could be as generous as possible and use the "best" rotation $\Rot ← \argmin_\Rot ∫_Ω ‖ ∇\x - \Rot ∇\hat{\x} ‖² ;dA$:

\[ ∫_Ω \left|∇\x - \left( \argmin_\Rot ∫_Ω ‖ ∇\x - \Rot ∇\hat{\x} ‖² ;dA \right)∇\hat{\x}\right|² ;dA. \]

If we treat $\Rot$ as a degree of freedom along with the unknown positions $\x$, we can unify this into an optimization over $\x$ and $\Rot$:

\[ \min_{\x,\Rot∈SO(3)} ∫_Ω \left|∇\x - \Rot ∇\hat{\x}\right|² ;dA. \]

Optimizing this energy will ensure global rotation invariance. To ensure local rotation invariance, we can replace $\Rot ∈ SO(3)$ with a spatially varying function $\Rot : Ω → SO(3)$ that outputs a "best" rotation for any point on the shape (see "A simple geometric model for elastic deformations" [Chao et al. 2010]). In this way, the optimal rotation will be locally rigid everywhere, or as-rigid-as-possible (ARAP).

For embedded solid shapes, we can take the rest shape given by $\hat{\x}$ as the parameterization $Ω$, so that $∇\hat{\x} = \I$. This allows us to rewrite the as-rigid-as-possible energy as the square of the difference between the deformation gradient and the closest rotation:

\[ ∫_Ω \left|∇\x - \Rot ∇\hat{\x}\right|² ;dA \ ∫_Ω \left|(∇\x + \I - \I) - \Rot \I \right|² ;dA \ ∫_Ω \left|(\I + ∇\x - ∇\hat{x}) - \Rot \right|² ;dA \ ∫_Ω \left|(\I + ∇\d) - \Rot \right|² ;dA \ ∫_Ω \left|\F - \Rot \right|² ;dA \ \]

This form provides a bridge between the as-rigid-as-possible energy common in geometry processing to corotated linear elasticity used in mechanics/physically-based simulation (made explicit in "A simple geometric model for elastic deformations" [Chao et al. 2010]). See Section 3.4 of "FEM Simulation of 3D Deformable Solids" [Sifakis 2012] for a graphics-mechanics perspective.

Discrete as-rigid-as-possible energy

For a triangle mesh with displacing vertices, the gradient of the embedding function is constant inside each triangle. In this way we can write the raw gradient energy above as a double sum over all half-edges $ij$ of all faces $f$ in the mesh:

\[ ½ ∫_Ω ‖ ∇ \x - ∇\hat{\x}‖² ;dA = ½ ∑\limits_{f ∈ F} ∑\limits_{ ij ∈ f} c_{ij} ‖ (\v_i-\v_j) - (\hat{\v}_i-\hat{\v}j)‖², \] where $c{ij}$ is cotangent of the angle opposite half-edge $ij$.

To inject localized best fit rotations, we will assign an unknown rotation matrix $\Rot_k$ to each vertex $k$ of the mesh and accounts for a third of the energy integrated over incident triangles: \[ ½ ∫_Ω ‖ ∇ \x - \Rot ∇\hat{\x}‖² ;dA = ⅙ ∑\limits_{k=1}^n ∑\limits_{ ij ∈ F(k)} c_{ij} ‖ (\v_i-\v_j) - \Rot_k (\hat{\v}_i-\hat{\v}_j)‖², \] where $F(k)$ is the set of all faces incident on the $k$-th vertex.

Where do rotations live?

We have assigned a rotation for each vertex: there are $n$ rotation matrices as auxiliary degrees of freedom. This is in contrast to assigning rotations per face (as in "A Local/Global Approach to Mesh Parameterization" [Liu et al. 2008]). Per-face--or more generally per-element--rotations work well for codimension zero objects (triangle meshes in $\R²$ or tetrahedral meshes in $\R³$). But for triangle mesh surfaces in $\R³$ (i.e., codimension 1), per-face rotations would lead to "crumpling") because bending along edges would not be measured.

Optimization

The simplest method for optimizing the ARAP energy is by alternating between

  1. finding the optimal rotations $\Rot_k$ assuming the vertex positions $\V$ are fixed, and
  2. finding the optimal vertex positions $\V$ assuming all rotations $\Rot_k$ are fixed.

Each rotation $\Rot_k$ only affects the local energy and doesn't interact with the other rotations. So each can be optimized locally. In contrast, the mesh vertex positions $\V$ depend on each other requiring a global solve. In the geometry processing literature, this is known as a local-global optimization (see "As-rigid-as-possible surface modeling" [Sorkine & Alexa 2007]). It is also known as "alternating block coordinate descent" because we have separated the variables into disjoint sets ($\V,\Rot_1,…,\Rot_n$) and taking the optimal descent direction for each independently.

Observing the discrete energy above we can see that the energy is quadratic in $\V$ and quadratic in each $\Rot_k$. Let's start by separating the terms that are quadratic and linear in $\V$:

\[ ⅙ \underbrace{∑\limits_{k=1}^n ∑\limits_{ ij ∈ F(k)} c_{ij} (\v_i-\v_j)^\transpose(\v_i-\v_j)}\text{quadratic} + ⅙ \underbrace{∑\limits{k=1}^n ∑\limits_{ ij ∈ F(k)} c_{ij} (\v_i-\v_j)^\transpose \Rot_k (\hat{\v}_i-\hat{\v}j)}\text{linear} \]

if we stack the rotation matrices $\Rot_k$ into large matrix $\Rot ∈ \R^{3n × 3}$ then we can write this energy in matrix form as:

\[ \tr{ \V^\transpose \L \V } + \tr{ \V^\transpose \K \Rot }, \] where $\L ∈ \R^{n × n}$ is the familiar cotangent discrete Laplacian matrix and $\K ∈ \R^{n × 3n}$ sparse matrix containing cotangents multiplied against differences across edges in the rest mesh (e.g., $\hat{\v}_i - \hat{\v}_j$).

I'm so confused. What's in the $\K$ matrix?

Let's take it slow. The $\K$ matrix is represents the bilinear form that combines unknown vertex positions and unknown rotations. We have identified above that we can write this in summation or matrix form: \[ ⅙ ∑\limits_{k=1}^n ∑\limits_{ ij ∈ F(k)} c_{ij} (\v_i-\v_j)^\transpose \Rot_k (\hat{\v}_i-\hat{\v}_j) = \tr{ \V^\transpose \K \Rot }, \] but how did we get here?

Let's start with the summation form. The constants of this formula are the $c_{ij}$ terms and the $(\hat{\v}_i-\hat{\v}j)$ terms. Since these always appear together, let us merge them into weighted edge difference vectors $c{ij} (\hat{\v}_i-\hat{\v}j) =: \hat{\e}{ij} ∈ \R³$:

\[ ⅙ ∑\limits_{k=1}^n ∑\limits_{ ij ∈ F(k)} \underbrace{(\v_i-\v_j)^\transpose \Rot_k \hat{\e}{ij}}{∈\R}, \] the inner term in the summation is an inner product; that is, a scalar. Let's expose this by expanding the matrix-vector products of the inner-product: \[ ⅙ ∑\limits_{k=1}^n ∑\limits_{ ij ∈ F(k)} ∑\limits_{α=1}^3 ∑\limits_{β=1}^3 (v_i^α - v_j^α)R_k^{αβ}\hat{e}_{ij}^β. \]

If our mesh is stored as a vertex list and face list, it's not easy/efficient to loop over per-vertex rotations (outer sum) and then over all half-edges of incident faces (second sum). Instead, let's rearrange these sums to loop over all faces first, then the half-edges of that face, and then over all per-vertex rotations that involve this half-edge: \[ ⅙ ∑\limits_{f=1}^m ∑\limits_{ ij ∈ E(f)} \quad ∑\limits_{k | ij ∈F(k)} \quad ∑\limits_{α=1}^3 ∑\limits_{β=1}^3 (v_i^α - v_j^α)R_k^{αβ}\hat{e}_{ij}^β, \] where the third sum is over all rotations $k$ such that the half-edge $ij$ belongs to the half-edges of the faces incident on the $k$-th vertex: $k | ij ∈F(k)$. Well, this means $k$ can either be $i$ or $j$ or the third vertex of the $f$-th face.

Now let's turn our attention back to the summand. The terms indexed by $α$ never mix. That is, we never add/multiply $v_i^α$, $v_j^γ$, and $R_k^{δβ}$ unless $α=γ=δ$. This implies that we can write this summation in matrix form as: \[ \V₁^\transpose \K₁ \Rot₁ +
\V₂^\transpose \K₂ \Rot₂ +
\V₃^\transpose \K₃ \Rot₃, \] where $\V_α ∈ \R^n$ is $α$-th column of $\V$, $\Rot_α ∈ \R^{3n}$ is the $α$-th column of $\Rot$ and $\K₁,\K₂,\K₃ ∈ \R^{n × 3n}$ are sparse matrices.

Further, the constant term $\hat{e}^β_{ij}$ in the summation acts the same on $(v_i^α - v_j^α)R_k^{αβ}$ for any $α$ value. This implies that $\K₁=\K₂=\K₃$, so we can reduce the matrix form to: \[ \tr{\V \K \Rot}. \]

Finally, we can answer what is in each entry $K_{vw}$, where $v$ chooses the row and $w=3k+β$ chooses the column of $\K$. Treating our nested summation as nested for-loops, we can increment entries in $\K$ \[ \begin{align} K_{i\ 3k+β} & \mathrel{+}= \hat{e}{ij}^β, \ K{j\ 3k+β} & \mathrel{+}= -\hat{e}_{ij}^β, \ \end{align} \] for each half-edge encountered.

Local step

Minimizing this energy with respect $\Rot$ corresponds to minimizing:

\[ \tr{ \underbrace{\V^\transpose \K}_{\C^\transpose} \Rot }, \] where $\C ∈ \R^{3n × 3}$ stacks weighted covariance matrices $\C_k ∈ \R^{3 × 3}$ for each region covered by the corresponding rotation $\Rot_k$. We have seen this problem before in the registration assignment. For each $\C_k$, $\Rot_k$ will be the closest rotation matrix solved via singular value decomposition.

Global step

Minimizing the energy above with respect to $\V$ corresponds to solving a Dirichlet energy-like minimization problem:

\[ \min_\V \tr{ \V^\transpose \L \V } + \tr{ \V^\transpose \B } \]

where $\K \Rot =: \B ∈ \R^{n × 3}$ is a matrix of rotated vertex gradients. Adding the handle constraints to the corresponding rows of $\V$ this is easily minimized by setting all partial derivatives with respect to the unknowns in $\V$ equal to zero (as in the linear methods above).

Implementation

In order to facilitate interactive deformation we would like our local and global iterations to be computed as quickly as possible. Since the quadratic form in the global step is the same regardless of the current rotations or current handle positions, we can prefactorize it (again, as above). The matrix $\K$ also does not depend on the rotations, current positions or handle positions, so we can pre-build this matrix. This way computing $\C$ and $\B$ is a simple matrix-matrix multiplication.

Note: When constructing $\K$ it's easiest to iterate over all half-edges in the mesh (by iterating over all faces and then each of the three edges). Each half-edge $ij$ contributes terms tying $\v_i,\v_j$ to each of the (three) rotations $\Rot_k$ that apply against their difference (see "Fast Automatic Skinning Transformations" [Jacobson et al. 2012]).

Still trouble in paradise

The as-rigid-as-possible deformation method for surfaces described above has a number of remaining problems:

  1. like its gradient-based energy ancestor the deformation is not smooth at constraints;
  2. the energy punishes bending of the surface--which is good--but does so in a way that diminishes as the mesh becomes higher and higher resolution, in otherwords, the discrete energy is mesh-resolution dependent; and
  3. the energy is biased by the original combinatorics of the mesh (even in flat regions).

Tasks

Blacklist

  • igl::arap
  • igl::arap_linear_block
  • igl::covariance_scatter_matrix
  • igl::harmonic

Whitelist

  • igl::polar_svd3x3 (or your previous assignment's closest_rotation)
  • igl::min_quad_with_fixed
  • igl::cotmatrix_entries
  • igl::cotmatrix (or your previous implementation)
  • igl::massmatrix (or your previous implementation)

src/biharmonic_precompute.cpp

Precompute data needed to efficiently solve for a biharmonic deformation given a mesh with vertices V and faces F and a list of selected vertices as indices b into V. The output should be a prefacorized system using the data struct employed by igl::min_quad_with_fixed.

src/biharmonic_solve.cpp

Given precomputation data and a list of handle displacements determine displacements for all vertices in the mesh.

src/arap_precompute.cpp

Precompute data needed to efficiently conduct local-global iterations for an arap deformation. This includes the data struct employed by igl::min_quad_with_fixed to solve the global step" and constructing the bilinear form K that mixes rotation degrees of freedom with unknown positions for preparing the covariance matrices of the local step and the linear term of the global step.

src/arap_single_iteration.cpp

Given precomputed data (data and K), handle positions bc and current positions of all vertices U, conduct a single iteration of the local-global solver for minimizing the as-rigid-as-possible energy. Output the positions of all vertices of the mesh (by overwriting U).

About

Deformation assignment for Geometry Processing course

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • CSS 50.3%
  • C++ 43.0%
  • CMake 6.7%