diff --git a/tutorial/tutorial.md b/tutorial/tutorial.md
index 055670481..2f6111c27 100644
--- a/tutorial/tutorial.md
+++ b/tutorial/tutorial.md
@@ -1,5 +1,5 @@
title: libigl Tutorial
-author: Daniele Panozzo, Alec Jacobson and others
+author: Daniele Panozzo and Alec Jacobson
date: 20 June 2014
css: style.css
html header:
@@ -7,7 +7,12 @@ html header:
-# libigl Tutorial notes
+> Warning: This tutorial has been prepared for the static material accompanying
+> SGP Grad School 2014. Please find our up-to-date tutorial notes at
+> https://github.com/libigl/libigl/tutorial/tutorial.md
+
+
+# libigl tutorial notes
Libigl is an open source C++ library for geometry processing research and
development. Dropping the heavy data structures of tradition geometry
libraries, libigl is a simple header-only library of encapsulated functions.
@@ -19,7 +24,7 @@ computation of differential quantities and operators, real-time deformation,
global parametrization, numerical optimization and mesh repair. Each section
of these lecture notes links to a cross-platform example application.
-# Table of Contents
+# Table of contents
* [Chapter 1: Introduction to libigl][100]
* [101 Mesh representation][101]
@@ -45,7 +50,7 @@ of these lecture notes links to a cross-platform example application.
* [Chapter 3: Matrices and Linear Algebra](#chapter3:matricesandlinearalgebra)
* [301 Slice](#slice)
* [302 Sort](#sort)
- * [Other Matlab-style functions](#othermatlab-stylefunctions)
+ * [Other Matlab-style functions](#otherMatlab-stylefunctions)
* [303 Laplace Equation](#laplaceequation)
* [Quadratic energy minimization](#quadraticenergyminimization)
* [304 Linear Equality Constraints](#linearequalityconstraints)
@@ -58,6 +63,7 @@ of these lecture notes links to a cross-platform example application.
* [405 As-rigid-as-possible](#as-rigid-as-possible)
* [406 Fast automatic skinning
transformations](#fastautomaticskinningtransformations)
+ * [ARAP with grouped edge-sets]
* [Chapter 5: Parametrization][500]
* [501 Harmonic parametrization][501]
@@ -72,8 +78,8 @@ of these lecture notes links to a cross-platform example application.
* [Chapter 6: External libraries][600]
* [601 State serialization][601]
- * [602 Mixing matlab code][602]
- * [603 Calling igl functions from matlab][603]
+ * [602 Mixing Matlab code][602]
+ * [603 Calling libigl functions from Matlab][603]
* [604 Triangulation of closed polygons][604]
* [605 Tetrahedralization of closed surfaces][605]
* [606 Baking ambient occlusion][606]
@@ -391,7 +397,7 @@ libigl:
compilation speed, it is also possible to build the library as a [static
library](../build/))
-# Chapter 2: Discrete Geometric Quantities and Operators
+# Chapter 2: Discrete geometric quantities and operators
This chapter illustrates a few discrete quantities that libigl can compute on a
mesh. This also provides an introduction to basic drawing and coloring routines
in our example viewer. Finally, we construct popular discrete differential
@@ -460,7 +466,7 @@ specified dihedral angle (e.g. 20°).

-## Gaussian Curvature
+## Gaussian curvature
Gaussian curvature on a continuous surface is defined as the product of the
principal curvatures:
@@ -488,7 +494,7 @@ elliptic, hyperbolic and parabolic vertices on the domain.

-## Curvature Directions
+## Curvature directions
The two principal curvatures $(k_1,k_2)$ at a point on a surface measure how
much the surface bends in different directions. The directions of maximum and
minimum (signed) bending are call principal directions and are always
@@ -703,7 +709,7 @@ since the Laplacian is the divergence of gradient. Naturally, $\mathbf{G}^T$ is
$n \times md$ sparse matrix which takes vector values stored at triangle faces
to scalar divergence values at vertices.
-# Chapter 3: Matrices and Linear Algebra
+# Chapter 3: Matrices and linear algebra
Libigl relies heavily on the Eigen library for dense and sparse linear algebra
routines. Besides geometry processing routines, libigl has a few linear algebra
routines which bootstrap Eigen and make Eigen feel even more like a high-level
@@ -712,9 +718,9 @@ algebra library like Matlab.
## Slice
A very familiar and powerful routine in Matlab is array slicing. This allows
reading from or writing to a possibly non-contiguous sub-matrix. Let's consider
-the matlab code:
+the Matlab code:
-```matlab
+```Matlab
B = A(R,C);
```
@@ -733,9 +739,9 @@ igl::slice(A,R,C,B);
`A` and `B` could also be sparse matrices.
-Similarly, consider the matlab code:
+Similarly, consider the Matlab code:
-```matlab
+```Matlab
A(R,C) = B;
```
@@ -755,7 +761,7 @@ triangles on a mesh.](images/decimated-knight-slice-color.jpg)
Matlab and other higher-level languages make it very easy to extract indices of
sorting and comparison routines. For example in Matlab, one can write:
-```matlab
+```Matlab
[Y,I] = sort(X,1,'ascend');
```
@@ -770,9 +776,9 @@ This same functionality is supported in libigl:
igl::sort(X,1,true,Y,I);
```
-Similarly, sorting entire rows can be accomplished in matlab using:
+Similarly, sorting entire rows can be accomplished in Matlab using:
-```matlab
+```Matlab
[Y,I] = sortrows(X,'ascend');
```
@@ -795,7 +801,7 @@ order.](images/decimated-knight-sort-color.jpg)
### Other Matlab-style functions
Libigl implements a variety of other routines with the same api and
-functionality as common matlab functions.
+functionality as common Matlab functions.
- `igl::any_of` Whether any elements are non-zero (true)
- `igl::cat` Concatenate two matrices (especially useful for dealing with Eigen
@@ -818,7 +824,7 @@ functionality as common matlab functions.
- `igl::setdiff` Set difference of matrix elements
- `igl::speye` Identity as sparse matrix
-## Laplace Equation
+## Laplace equation
A common linear system in geometry processing is the Laplace equation:
$∆z = 0$
@@ -949,7 +955,7 @@ igl::min_quad_with_fixed_solve(mqwf,B,bc,Beq,Z);
The output `Z` is a $n \times 1$ vector of solutions with fixed values
correctly placed to match the mesh vertices `V`.
-## Linear Equality Constraints
+## Linear equality constraints
We saw above that `min_quad_with_fixed_*` in libigl provides a compact way to
solve general quadratic programs. Let's consider another example, this time
with active linear equality constraints. Specifically let's solve the
@@ -1025,7 +1031,7 @@ constraints (left: 1 and -1 on the left hand and foot respectively), then
solves with an additional linear equality constraint (right: points on right
hand and foot constrained to be equal).](images/cheburashka-biharmonic-leq.jpg)
-## Quadratic Programming
+## Quadratic programming
We can generalize the quadratic optimization in the previous section even more
by allowing inequality constraints. Specifically box constraints (lower and
@@ -1071,7 +1077,7 @@ igl::active_set(Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,as,Z);
discrete biharmonic kernels at multiple scales
[#rustamov_2011][].](images/cheburashka-multiscale-biharmonic-kernels.jpg)
-# Chapter 4: Shape Deformation
+# Chapter 4: Shape deformation
Modern mesh-based shape deformation methods satisfy user deformation
constraints at handles (selected vertices or regions on the mesh) and propagate
these handle deformations to the rest of shape _smoothly_ and _without removing
@@ -1080,7 +1086,7 @@ state-of-the-art deformation techniques, ranging from quadratic mesh-based
energy minimizers, to skinning methods, to non-linear elasticity-inspired
techniques.
-## Biharmonic Deformation
+## Biharmonic deformation
The period of research between 2000 and 2010 produced a collection of
techniques that cast the problem of handle-based shape deformation as a
quadratic energy minimization problem or equivalently the solution to a linear
@@ -1202,7 +1208,7 @@ igl::harmonic(V,F,b,bc,k,Z);

-## Bounded Biharmonic Weights
+## Bounded biharmonic weights
In computer animation, shape deformation is often referred to as "skinning".
Constraints are posed as relative rotations of internal rigid "bones" inside a
character. The deformation method, or skinning method, determines how the
@@ -1265,7 +1271,7 @@ set solver or by calling out to Mosek.
mesh given a skeleton (top) and then animates a linear blend skinning
deformation (bottom).](images/hand-bbw.jpg)
-## Dual Quaternion Skinning
+## Dual quaternion skinning
Even with high quality weights, linear blend skinning is limited. In
particular, it suffers from known artifacts stemming from blending rotations as
as matrices: a weight combination of rotation matrices is not necessarily a
@@ -1420,30 +1426,118 @@ elastic material](images/decimated-knight-arap.jpg)
This concept of local rigidity will be revisited shortly in the context of
surface parameterization.
-## Fast Automatic Skinning Transformations
+## Fast automatic skinning transformations
-- Can be seen as fast, subspace optimization for ARAP,
+Non-linear optimization is, unsurprisingly, slower than its linear cousins. In
+the case of the as-rigid-as-possible optimization, the bottleneck is typically
+the large number of polar decompositions necessary to recover best fit
+rotations for each edge-set (i.e. for each triangle, tetrahedron, or vertex
+cell). Even if this code is optimized, the number of primary degrees of freedom
+is tied to the discretization level, despite the deformations' low frequency
+behavior.
-- Or as a automatic method to find the best skinning transformation degrees of freedom
+This invites two routes toward fast non-linear optimization. First, is it
+necessary (or even advantageous) to find so many best-fit rotations? Second,
+can we reduce the degrees of freedom to better reflect the frequency of the
+desired deformations.
-Optimization in two steps:
+Taken in turn, these optimizations culminate in a method which optimizes over
+the space of linear blend skinning deformations spanned by high-quality weights
+(i.e. manually painted ones or bounded biharmonic weights). This space is a
+low-dimensional subspace of all possible mesh deformations, captured by writing
+linear blend skinning in matrix form:
-- subspace
+ $\mathbf{X}' = \mathbf{M}\mathbf{T}$
-- grouping
+where the mesh vertex positions in the $n \times 3$ matrix $\mathbf{X}'$ are
+replaced by a linear combination of a small number of degrees of freedom in the
+$(3+1)m \times 3$ stack of transposed "handle" transformations. Swapping in
+$\mathbf{M}\mathbf{T}$ for $\mathbf{X}'$ in the ARAP energies above immediately
+sees performance gains during the global solve step as $m << n$.
+
+The complexity of the local step---fitting rotations---is still bound
+to the original mesh discretization. However, if the skinning is well behaved,
+we can make the assumption that places on the shape with similar skinning
+weights will deform similarly and thus imply similar best-fit rotations.
+Therefor, we cluster edge-sets according to their representation in
+_weight-space_: where a vertex $\mathbf{x}$ takes the coordinates
+$[w_1(\mathbf{x}),w_2(\mathbf{x}),\dots,w_m(\mathbf{x})]$. The number of
+clustered edge-sets show diminishing returns on the deformation quality so we
+may choose a small number of clusters, proportional to the number of skinning
+weight functions (rather than the number of discrete mesh vertices).
+
+This proposed deformation model [#jacobson_2012][], can simultaneously be seen as a
+fast, subspace optimization for ARAP and as an automatic method for finding
+_the best_ skinning transformation degrees of freedom.
+
+A variety of user interfaces are supported via linear equality constraints on
+the skinning transformations associated with handles. To fix a transformation
+entirely we simply add the constraint:
+
+ $\left(\begin{array}{cccc}
+ 1 & 0 & 0 & 0\\
+ 0 & 1 & 0 & 0\\
+ 0 & 0 & 1 & 0\\
+ 0 & 0 & 0 & 1\end{array}\right)
+ \mathbf{T}_i^T = \hat{\mathbf{T}}_i^T,$
+
+where $\hat{\mathbf{T}}_i^T$ is the $(3+1) \times 3$ transposed fixed
+transformation for handle $i$.
+
+To fix only the origin of a handle, we add a constraint requiring the
+transformation to interpolate a point in space (typically the centroid of all
+points with $w_i = 1$:
+
+ $\mathbf{c}'^T\mathbf{T}_i^T = \mathbf{c}^T,$
+
+where $\mathbf{c}^T$ is the $1 \times (3+1)$ position of the point at rest in
+transposed homogeneous coordinates, and $\mathbf{c}'^T$ the point given by the
+user.
+
+We can similarly fix just the linear part of the transformation at a handle,
+freeing the translation component (producing a "chickenhead" effect):
+
+ $\left(\begin{array}{cccc}
+ 1&0&0&0\\
+ 0&1&0&0\\
+ 0&0&1&0\end{array}\right)
+ \mathbf{T}_i^T = \hat{\mathbf{L}}_i^T,$
+
+where $\hat{\mathbf{L}}_i^T$ is the fixed $3 \times 3$ linear part of the
+transformation at handle $i$.
+
+And lastly we can allow the user to entirely _free_ the transformation's
+degrees of freedom, delegating the optimization to find the best possible
+values for all elements. To do this, we simply abstain from adding a
+corresponding constraint.
### ARAP with grouped edge-sets
+Being a subspace method, an immediate disadvantage is the reduced degrees of
+freedom. This brings performance, but in some situations limits behavior too
+much. In such cases one can use the skinning subspace to build an effective
+clustering of rotation edge-sets for a traditional ARAP optimization: forgoing
+the subspace substitution. This has an two-fold effect. The cost of the
+rotation fitting, local step drastically reduces, and the deformations are
+"regularized" according the clusters. At a vague, high level, if the clusters
+are derived from skinning weights, then they will discourage bending,
+especially along isolines of the weight functions.
+
+In this light, we can few the "spokes+rims" style surface ARAP as a (slight and
+redundant) clustering of the per-triangle edge-sets.
+

# Chapter 5: Parametrization [500]
In computer graphics, we denote as surface parametrization a map from the
surface to \\(\mathbf{R}^2\\). It is usually encoded by a new set of 2D
-coordinates for each vertex of the mesh (and possibly also by a new set of faces in one to one correspondence with the faces of the original surface). Note that
+coordinates for each vertex of the mesh (and possibly also by a new set of
+faces in one to one correspondence with the faces of the original surface).
+Note that
this definition is the *inverse* of the classical differential geometry
definition.
@@ -1503,9 +1597,11 @@ mesh ([Example 501](501_HarmonicParam/main.cpp)).
mesh with texture, (right) UV parametrization with
texture](images/501_HarmonicParam.png)
-## Least-Square Conformal Maps [502]
+## Least squares conformal maps [502]
-Least-square conformal maps parametrization [#levy_2002][] minimizes the conformal (angular) distortion of the parametrization. Differently from harmonic parametrization, it does not need to have a fixed boundary.
+Least squares conformal maps parametrization [#levy_2002][] minimizes the
+conformal (angular) distortion of the parametrization. Differently from
+harmonic parametrization, it does not need to have a fixed boundary.
LSCM minimizes the following energy:
@@ -1544,36 +1640,43 @@ igl::vector_area_matrix(F,A);
```
The final energy matrix is the sum of these two matrices. Note that in this
-case we do not need to fix the boundary. To remove the null space of the energy and make the minimum unique, it is sufficinet to fix two arbitrary
-vertices to two arbitrary positions. The full source code is provided in [Example 502](502_LSCMParam/main.cpp).
+case we do not need to fix the boundary. To remove the null space of the energy
+and make the minimum unique, it is sufficinet to fix two arbitrary vertices to
+two arbitrary positions. The full source code is provided in [Example
+502](502_LSCMParam/main.cpp).
) LSCM parametrization. (left) mesh
with texture, (right) UV parametrization](images/502_LSCMParam.png)
-## As-Rigid-As-Possible parametrization [503]
+## As-rigid-as-possible parametrization [503]
-As-Rigid-As-Possible parametrization [#liu_2008][] is a powerful single-patch, non-linear
-algorithm to compute a parametrization that strives to preserve distances (and
-thus angles). The idea is very similar to ARAP surface deformation: each
-triangle is mapped to the plane trying to preserve its original shape, up to a
-rigid rotation.
+As-rigid-as-possible parametrization [#liu_2008][] is a powerful single-patch,
+non-linear algorithm to compute a parametrization that strives to preserve
+distances (and thus angles). The idea is very similar to ARAP surface
+deformation: each triangle is mapped to the plane trying to preserve its
+original shape, up to a rigid rotation.
The algorithm can be implemented reusing the functions discussed in the
-deformation chapter: `igl::arap_precomputation` and `igl::arap_solve`. The only difference is that the optimization has to be done in 2D instead of 3D and that we need to compute a starting point. While for 3D deformation
-the optimization is bootstrapped with the original mesh, this is not the case for ARAP parametrization since the starting point must be a 2D mesh. In [Example
-503](503_ARAPParam/main.cpp), we initialize the optimization with harmonic parametrization. Similarly to LSCM, the boundary is free to deform to minimize the distortion.
+deformation chapter: `igl::arap_precomputation` and `igl::arap_solve`. The only
+difference is that the optimization has to be done in 2D instead of 3D and that
+we need to compute a starting point. While for 3D deformation the optimization
+is bootstrapped with the original mesh, this is not the case for ARAP
+parametrization since the starting point must be a 2D mesh. In [Example
+503](503_ARAPParam/main.cpp), we initialize the optimization with harmonic
+parametrization. Similarly to LSCM, the boundary is free to deform to minimize
+the distortion.
) As-Rigid-As-Possible parametrization.
(left) mesh with texture, (right) UV parametrization with
texture](images/503_ARAPParam.png)
-## N-Rotationally symmetric tangent fields [504]
+## N-rotationally symmetric tangent fields [504]
The design of tangent fields is a basic tool used to design guidance fields for
-uniform quadrilateral and hexaedral remeshing. libigl contains an
-implementation of all the state-of-the-art algorithms to design N-RoSy
-fields and their generalizations.
+uniform quadrilateral and hexahedral remeshing. libigl contains an
+implementation of all the state-of-the-art algorithms to design N-RoSy fields
+and their generalizations.
In libigl, tangent unit-length vector fields are piece-wise constant on the
faces of a triangle mesh, and they are described by one or more vectors per-face. The function
@@ -1583,70 +1686,90 @@ igl::nrosy(V,F,b,bc,b_soft,b_soft_weight,bc_soft,N,0.5,
output_field,output_singularities);
```
-creates a smooth unit-length vector field (N=1) starting from a sparse set of constrained faces, whose indices are listed in b and their constrained value is specified in bc. The functions supports soft_constraints (b_soft, b_soft_weight, bc_soft), and returns the interpolated field for each face of the triangle mesh (output_field), plus the singularities of the field (output_singularities).
+creates a smooth unit-length vector field (N=1) starting from a sparse set of
+constrained faces, whose indices are listed in b and their constrained value is
+specified in bc. The functions supports soft_constraints (b_soft,
+b_soft_weight, bc_soft), and returns the interpolated field for each face of
+the triangle mesh (output_field), plus the singularities of the field
+(output_singularities).
-
+
-The singularities are vertices where the field vanishes (highlighted in red in the figure above). `igl::nrosy` can also generate N-RoSy fields [#levy_2008][], which are a generalization of vector fields where in every face the vector is defined up to a constant rotation of \\( 2\pi / N \\). As can be observed in the
-following figure, the singularities of the fields generated with different N are of different types and they appear in different positions.
+The singularities are vertices where the field vanishes (highlighted in red in
+the figure above). `igl::nrosy` can also generate N-RoSy fields [#levy_2008][],
+which are a generalization of vector fields where in every face the vector is
+defined up to a constant rotation of \\( 2\pi / N \\). As can be observed in
+the following figure, the singularities of the fields generated with different
+N are of different types and they appear in different positions.

We demonstrate how to call and plot N-RoSy fields in [Example
-504](504_NRosyDesign/main.cpp), where the degree of the field can be change pressing the number keys. `igl::nrosy` implements the algorithm proposed in
-[#bommes_2009][]. N-RoSy fields can also be interpolated with the algorithm proposed in [#knoppel_2013][], see Section [507] for more details ([igl::n_polyvector](../include/igl/n_polyvector.h)).
+504](504_NRosyDesign/main.cpp), where the degree of the field can be change
+pressing the number keys. `igl::nrosy` implements the algorithm proposed in
+[#bommes_2009][]. N-RoSy fields can also be interpolated with the algorithm
+proposed in [#knoppel_2013][], see Section [507] for more details
+([igl::n_polyvector](../include/igl/n_polyvector.h)).
### Global, seamless integer-grid parametrization [505]
-The previous parametrization methods were focusing on creating
-parametrizations of surface patches aimed at texture mapping or baking
-of other surface properties such as normals and high-frequency details. Global,
-seamless parametrization aims at parametrizing complex shapes with a
-parametrization that is aligned with a given set of directions for the purpose
-of surface remeshing. In libigl, we provide a reference implementation of
-the pipeline proposed in the mixed integer quadrangulation paper [#bommes_2009][].
+The previous parametrization methods were focusing on creating parametrizations
+of surface patches aimed at texture mapping or baking of other surface
+properties such as normals and high-frequency details. Global, seamless
+parametrization aims at parametrizing complex shapes with a parametrization
+that is aligned with a given set of directions for the purpose of surface
+remeshing. In libigl, we provide a reference implementation of the pipeline
+proposed in the mixed integer quadrangulation paper [#bommes_2009][].
The first step involves the design of a 4-RoSy field (sometimes called *cross*
-field) that describes the alignment of the edges of the desired quadrilateral remeshing. The field constraints are usually manually specified or extracted from the principal curvature directions. In [[Example 506](506_FrameField/main.cpp)], we simply fix one face in a random direction.
+field) that describes the alignment of the edges of the desired quadrilateral
+remeshing. The field constraints are usually manually specified or extracted
+from the principal curvature directions. In [[Example
+506](506_FrameField/main.cpp)], we simply fix one face in a random direction.

### Combing and cutting
Given the cross field, we now want to cut the surface so that it becomes
-homeorphic to a disk. While this could be done directly on the cross-field, we
-opt to perform this operation on its bisector field (a copy of the field rotated
-by 45 degrees) since it is more stable and generic. Working on the bisectors allow us to take as input generalized, non-orthogonal and non-unit lenght cross fields.
+homeomorphic to a disk. While this could be done directly on the cross-field, we
+opt to perform this operation on its bisector field (a copy of the field
+rotated by 45 degrees) since it is more stable and generic. Working on the
+bisectors allow us to take as input generalized, non-orthogonal and non-unit
+length cross fields.
We thus rotate the field,

and we remove the rotation ambiguity by assigning to each face a u and a v
-direction. The assignment is done with a breadth-first search starting from a random face.
+direction. The assignment is done with a breadth-first search starting from a
+random face.

You can imagine this process as combing an hairy surface: you will be able to
comb part of it, but at some point you will not be able to consistently comb
the entire surface ([Hairy ball
-theorem](http://en.wikipedia.org/wiki/Hairy_ball_theorem)). The discontinuites
+theorem](http://en.wikipedia.org/wiki/Hairy_ball_theorem)). The discontinuities
in the combing define the cut graph:

-Finally, we rotate the combed field by 45 degrees to undo the initial
-degrees rotation:
+Finally, we rotate the combed field by 45 degrees to undo the initial degrees
+rotation:

-The combed cross field can be seen as the ideal Jacobian of the parametrization that will be computed in the next section.
+The combed cross field can be seen as the ideal Jacobian of the parametrization
+that will be computed in the next section.
### Poisson parametrization
-The mesh is cut along the seams and a parametrization is computed
-trying to find two scalar functions whose gradient matches the combed cross
-field directions. This is a classical Poisson problem, that is solved minimizing the following quadratic energy:
+The mesh is cut along the seams and a parametrization is computed trying to
+find two scalar functions whose gradient matches the combed cross field
+directions. This is a classical Poisson problem, that is solved minimizing the
+following quadratic energy:
\\[ E(\mathbf{u},\mathbf{v}) = |\nabla \mathbf{u} - X_u|^2 + |\nabla \mathbf{v} - X_v|^2 \\]
@@ -1672,23 +1795,25 @@ The full pipeline is implemented in [Example 505](505_MIQ/main.cpp).
## Anisotropic remeshing [506]
-Anisotropic and non-uniform quad remeshing is important to concentrate the elements in the regions with more details. It is possible to extend the MIQ
+Anisotropic and non-uniform quad remeshing is important to concentrate the
+elements in the regions with more details. It is possible to extend the MIQ
quad meshing framework to generate anisotropic quad meshes using a mesh
deformation approach [#panozzo_2014][].
-The input of the anisotropic remeshing algorithm is a sparse set of constraints that define the shape and scale of the desired quads. This can be encoded
-as a frame field, which is a pair of non-orthogonal and non-unit lenght
-vectors. The frame field can be interpolated by decomposing it in a 4-RoSy
-field and a unique affine transformation. The two parts can then be
-interpolated separately, using `igl::nrosy` for the cross field, and an harmonic
-interpolant for the affine part.
+The input of the anisotropic remeshing algorithm is a sparse set of constraints
+that define the shape and scale of the desired quads. This can be encoded as a
+frame field, which is a pair of non-orthogonal and non-unit length vectors. The
+frame field can be interpolated by decomposing it in a 4-RoSy field and a
+unique affine transformation. The two parts can then be interpolated
+separately, using `igl::nrosy` for the cross field, and an harmonic interpolant
+for the affine part.

After the interpolation, the surface is warped to transform each frame into an
-orthogonal and unit lenght cross (i.e. removing the scaling and skewness from
+orthogonal and unit length cross (i.e. removing the scaling and skewness from
the frame). This deformation defines a new embedding (and a new metric) for the
surface.
@@ -1716,17 +1841,22 @@ possible.
## N-PolyVector fields [507]
N-RoSy vector fields can be further generalized to represent arbitrary
-vector-sets, with arbitrary angles between them and with arbitrary lenghts [#diamanti_2014][].
-This generalization is called N-PolyVector field, and libigl provides the
-function `igl::n_polyvector` to design them starting from a sparse set of
-constraints ([Example 507](507_PolyVectorField/main.cpp)).
+vector-sets, with arbitrary angles between them and with arbitrary lengths
+[#diamanti_2014][]. This generalization is called N-PolyVector field, and
+libigl provides the function `igl::n_polyvector` to design them starting from a
+sparse set of constraints ([Example 507](507_PolyVectorField/main.cpp)).

-The core idea is to represent the vector set as the roots of a complex polynomial: The polynomial coefficients are then harmonically interpolated leading to polynomials whose roots smoothly vary over the surface.
+The core idea is to represent the vector set as the roots of a complex
+polynomial: The polynomial coefficients are then harmonically interpolated
+leading to polynomials whose roots smoothly vary over the surface.
-Globally optimal direction fields [#knoppel_2013][] are a special case of Poly-Vector fields. If the constraints are taken from an N-RoSy field, `igl::n_polyvector` generates a field that is equivalent, after normalization, to a globally optimal direction field.
+Globally optimal direction fields [#knoppel_2013][] are a special case of
+Poly-Vector fields. If the constraints are taken from an N-RoSy field,
+`igl::n_polyvector` generates a field that is equivalent, after normalization,
+to a globally optimal direction field.
## Conjugate vector fields [508]
@@ -1734,25 +1864,27 @@ Two tangent vectors lying on a face of a triangle mesh are conjugate if
\\[ k_1 (u^T d_1)(v^T d_1) + k_2(u^T d_2)(v^T d_2) = 0. \\]
-This condition is very important in architectural geometry: The faces of
-an infinitely dense quad mesh whose edges are aligned with a conjugate field
-are planar. Thus, a quad mesh whose edges follow a conjugate field are easier to planarize [#liu_2011].
+This condition is very important in architectural geometry: The faces of an
+infinitely dense quad mesh whose edges are aligned with a conjugate field are
+planar. Thus, a quad mesh whose edges follow a conjugate field are easier to
+planarize [#liu_2011].
Finding a conjugate vector field that satisfies given directional constraints
is a standard problem in architectural geometry, which can be tackled by
deforming a Poly-Vector field to the closest conjugate field.
-This algorithm [#diamanti_2014] alternates a global step, which enforces smoothness, with a local step, that projects the field on every face to the closest conjugate field
-([Example 508](508_ConjugateField/main.cpp)).
+This algorithm [#diamanti_2014] alternates a global step, which enforces
+smoothness, with a local step, that projects the field on every face to the
+closest conjugate field ([Example 508](508_ConjugateField/main.cpp)).

## Planarization [509]
-A quad mesh can be transformed in a planar quad mesh with Shape-Up [#bouaziz_2012], a
-local/global approach that uses the global step to enforce surface continuity
-and the local step to enforce planarity.
+A quad mesh can be transformed in a planar quad mesh with Shape-Up
+[#bouaziz_2012], a local/global approach that uses the global step to enforce
+surface continuity and the local step to enforce planarity.
[Example 509](509_Planarization/main.cpp) planarizes a quad mesh until it
satisfies a user-given planarity threshold.
@@ -1793,7 +1925,7 @@ Assume that the state of your application is composed of a mesh and set of
integer ids:
``` cpp
-class State : public ::igl::XMLSerialization
+class State : public igl::XMLSerialization
{
public:
State() : XMLSerialization("dummy") {}
@@ -1811,15 +1943,15 @@ public:
};
```
-A class can be made serializable by inheriting from ::igl::XMLSerialization and
+A class can be made serializable by inheriting from `igl::XMLSerialization` and
trivially implementing the InitSerialization method. Note that you don't have
to care the types, Add is able to serialize all basic stl types, all Eigen
-types and any class inheriting from ::igl::XMLSerialization.
+types and any class inheriting from `igl::XMLSerialization`.
It is then possible to save the state to an xml file:
``` cpp
-::igl::XMLSerializer serializer_save("601_Serialization");
+igl::XMLSerializer serializer_save("601_Serialization");
serializer_save.Add(state,"State");
serializer_save.Save("temp.xml",true);
```
@@ -1848,7 +1980,7 @@ The xml file can then be loaded in a similar way:
``` cpp
State loaded_state;
-::igl::XMLSerializer serializer_load("601_Serialization");
+igl::XMLSerializer serializer_load("601_Serialization");
serializer_load.Add(loaded_state,"State");
serializer_load.Load("temp.xml");
```
@@ -1865,21 +1997,21 @@ common to have to do small changes to figures during the production of a paper,
and being able to serialize the entire state just before you take screenshots
will save you many painful hours before a submission deadline.
-## Mixing matlab code [602]
+## Mixing Matlab code [602]
-libigl can be interfaced matlab, to offload some of the numerically heavy
-computation to a matlab script. This has the major advantage of allowing to
+libigl can be interfaced Matlab, to offload some of the numerically heavy
+computation to a Matlab script. This has the major advantage of allowing to
develop efficient and complex UI in C++, while keeping the advantage of fast
-protototyping of matlab. In particular, using an external matlab script in a
-libigl application allows to change the algorithm in the matlab script without
+protototyping of Matlab. In particular, using an external Matlab script in a
+libigl application allows to change the algorithm in the Matlab script without
having to recompile the C++ part.
-We demonstrate how to integrate matlab in a libigl application in [Example
-602](602_Matlab/main.cpp). The example uses matlab to compute the
+We demonstrate how to integrate Matlab in a libigl application in [Example
+602](602_Matlab/main.cpp). The example uses Matlab to compute the
Eigenfunctions of the discrete Laplacian operator, relying on libigl for mesh
IO, visualization and for computing the Laplacian operator.
-libigl can connect to an existing instance of matlab (or launching a new one on
+libigl can connect to an existing instance of Matlab (or launching a new one on
Linux/MacOSX) using:
``` cpp
@@ -1887,21 +2019,21 @@ igl::mlinit(&engine);
```
The cotangent laplacian is computed using igl::cotmatrix and uploaded to the
-matlab workspace:
+Matlab workspace:
``` cpp
igl::cotmatrix(V,F,L);
igl::mlsetmatrix(&engine,"L",L);
```
-It is now possible to use any matlab function on the data. For example, we can
+It is now possible to use any Matlab function on the data. For example, we can
see the sparsity pattern of L using spy:
``` cpp
igl::mleval(&engine,"spy(L)");
```
-
You can also do some computation and then return it back to the C++ application
@@ -1916,11 +2048,11 @@ and then use libigl functions to plot the eigenfunctions.

-## Calling igl functions from matlab [603]
+## Calling libigl functions from Matlab [603]
-It is also possible to call libigl functions from matlab, compiling them as MEX
+It is also possible to call libigl functions from Matlab, compiling them as MEX
functions. This can be very useful to offload to C++ code the computationally
-intensive parts of a matlab application.
+intensive parts of a Matlab application.
We provide a wrapper for igl::readOBJ in [Example 603](603_MEX/compileMEX.m).
We plan to provide wrappers for all our functions in the future, if you are
@@ -1931,9 +2063,9 @@ us know.
The generation of high-quality triangle and tetrahedral meshes is a very common
task in geometry processing. We provide wrappers in libigl to triangle and
-tetegen.
+Tetgen.
-A triangle mesh canb e cerated starting from a set of boundary edges using
+A triangle mesh can be created starting from a set of boundary edges using
igl::triangulate.
``` cpp
@@ -1996,14 +2128,14 @@ Ambient occlusion can be used to darken the surface colors, as shown in

-## Locally Injective Maps [607]
+## Locally injective maps [607]
Extreme deformations or parametrizations with high-distortion might flip
elements. This is undesirable in many applications, and it is possible to
avoid it by introducing a non-linear contraints that guarantees that the area
of every element remain positive.
-libigl can be used to compute Locally Injective Maps using a variety of
+libigl can be used to compute locally injective maps using a variety of
deformation energies. A simple deformation of a 2D grid is computed in [Example
607](607_LIM/main.cpp).
@@ -2028,7 +2160,7 @@ in the next months:
only remeshing functions available are only able to create quadrilateral
remeshings
-* Generate matlab and python wrappers for all libigl functions
+* Generate Matlab and python wrappers for all libigl functions
* Implement a mixed-integer solver which only uses Eigen to remove the
dependency on CoMiSo
@@ -2051,6 +2183,8 @@ Real-Time Freeform Modeling," 2004.
[#jacobson_thesis_2013]: Alec Jacobson,
_Algorithms and Interfaces for Real-Time Deformation of 2D and 3D Shapes_,
2013.
+[#jacobson_2012]: Alec Jacobson, Ilya Baran, Ladislav Kavan, Jovan Popović, and
+Olga Sorkine. "Fast Automatic Skinning Transformations," 2012.
[#jacobson_2011]: Alec Jacobson, Ilya Baran, Jovan Popović, and Olga Sorkine.
["Bounded Biharmonic Weights for Real-Time Deformation,"](https://www.google.com/search?q=Bounded+biharmonic+weights+for+real-time+deformation) 2011.
[#jacobson_mixed_2010]: Alec Jacobson, Elif Tosun, Olga Sorkine, and Denis