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°). ![The `Normals` example computes per-face (left), per-vertex (middle) and per-corner (right) normals](images/fandisk-normals.jpg) -## 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. ![The `GaussianCurvature` example computes discrete Gaussian curvature and visualizes it in pseudocolor.](images/bumpy-gaussian-curvature.jpg) -## 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); ![The `PolyharmonicDeformation` example deforms a flat domain (left) into a bump as a solution to various $k$-harmonic PDEs.](images/bump-k-harmonic.jpg) -## 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. + ![The example `FastAutomaticSkinningTransformations` compares a full (slow) -ARAP deformation on a detailed shape (left of middle), to ARAP with grouped rotation edge sets -(right of middle), to the very fast subpsace method +ARAP deformation on a detailed shape (left of middle), to ARAP with grouped +rotation edge sets (right of middle), to the very fast subpsace method (right).](images/armadillo-fast.jpg) # 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). ![([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. ![([Example 503](502_ARAPParam/main.cpp)) 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). -![Design of a unit-lenght vector field](images/504_vector_field.png) +![Design of a unit-length vector field](images/504_vector_field.png) -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. ![Design of a 2-,4- and 9-RoSy field](images/504_nrosy_field.png) 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. ![Initial cross field prescribing the edge alignment.](images/505_MIQ_1.png) ### 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, ![Bisector field.](images/505_MIQ_2.png) 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. ![Combed bisector field.](images/505_MIQ_3.png) 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: ![Cut graph.](images/505_MIQ_4.png) -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: ![Combed cross field.](images/505_MIQ_5.png) -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. ![Interpolation of a frame field. Colors on the vectors denote the desired scale. The red faces contains the frame field constraints.](images/506_FrameField_1.png) 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)). ![Interpolation of a N-PolyVector field from a sparse set of constraints.](images/507_PolyVectorField.png) -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)). ![A smooth 4-PolyVector field (left) is deformed to become a conjugate field (right).](images/508_ConjugateField.png) ## 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)"); ``` -![The matlab spy function is called from a libigl-based +![The Matlab spy function is called from a libigl-based application.](images/602_Matlab_1.png) 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. ![4 Eigenfunctions of the Laplacian plotted in the libigl viewer.](images/602_Matlab_2.png) -## 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 ![A mesh rendered without (left) and with (right) ambient occlusion.](images/606_AmbientOcclusion.png) -## 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