pass on tutorial, arap notes
This commit is contained in:
+256
-122
@@ -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: <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
@@ -7,7 +7,12 @@ html header: <script type="text/javascript" src="http://cdn.mathjax.org/mathja
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user