update tutorial/tutorial.html to match tutorial/tutorial.md
This commit is contained in:
+193
-100
@@ -2,24 +2,32 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>libigl Tutorial</title>
|
||||
<meta name="author" content="Daniele Panozzo and Alec Jacobson"/>
|
||||
<meta name="date" content="07 November 2015"/>
|
||||
<link type="text/css" rel="stylesheet" href="style.css"/>
|
||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<title>libigl</title>
|
||||
<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
|
||||
<link type="text/css" rel="stylesheet" href="../tutorial/style.css"/>
|
||||
<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
|
||||
<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
|
||||
<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>title: libigl Tutorial
|
||||
author: Daniele Panozzo and Alec Jacobson
|
||||
date: 07 November 2015
|
||||
css: style.css
|
||||
html header: <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
|
||||
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script></p>
|
||||
|
||||
<h1 id="libigltutorialnotes">libigl tutorial notes</h1>
|
||||
|
||||
<h4 id="aspresentedbydanielepanozzoandalecjacobsonatsgpgraduateschool2015">as presented by Daniele Panozzo and Alec Jacobson at SGP Graduate School 2015</h4>
|
||||
|
||||
<figure>
|
||||
<img src="images/libigl-logo.jpg" alt="" />
|
||||
<figcaption></figcaption></figure>
|
||||
</figure>
|
||||
|
||||
<p>Libigl is an open source C++ library for geometry processing research and
|
||||
development. Dropping the heavy data structures of tradition geometry
|
||||
@@ -230,7 +238,8 @@ represented as indices pointing to rows of <code>V</code>.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/VF.png" alt="A simple mesh made of 2 triangles and 4 vertices." />
|
||||
<figcaption>A simple mesh made of 2 triangles and 4 vertices.</figcaption></figure>
|
||||
<figcaption>A simple mesh made of 2 triangles and 4 vertices.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Note that the order of the vertex indices in <code>F</code> determines the orientation of
|
||||
the triangles and it should thus be consistent for the entire surface.
|
||||
@@ -300,7 +309,8 @@ Please see the documentation in
|
||||
<img src="images/102_DrawMesh.png" alt="(Example 102) loads and draws a
|
||||
mesh." />
|
||||
<figcaption>(<a href="102_DrawMesh/main.cpp">Example 102</a>) loads and draws a
|
||||
mesh.</figcaption></figure>
|
||||
mesh.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="103">Interaction with keyboard and mouse</h2>
|
||||
|
||||
@@ -387,7 +397,8 @@ vertex) and the second calls a libigl functions that converts a scalar field to
|
||||
<img src="images/104_Colors.png" alt="(Example 104) igl::jet converts a scalar field to a
|
||||
color field." />
|
||||
<figcaption>(<a href="104_Colors/main.cpp">Example 104</a>) igl::jet converts a scalar field to a
|
||||
color field.</figcaption></figure>
|
||||
color field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p><code>igl::jet</code> is an example of a standard function in libigl: it takes simple
|
||||
types and can be easily reused for many different tasks. Not committing to
|
||||
@@ -426,7 +437,8 @@ Eigen::Vector3d M = V.colwise().maxCoeff();
|
||||
<img src="images/105_Overlays.png" alt="(Example 105) The bounding box of a mesh is shown
|
||||
using overlays." />
|
||||
<figcaption>(<a href="105_Overlays/main.cpp">Example 105</a>) The bounding box of a mesh is shown
|
||||
using overlays.</figcaption></figure>
|
||||
using overlays.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h1 id="chapter2:discretegeometricquantitiesandoperators">Chapter 2: Discrete Geometric Quantities and Operators</h1>
|
||||
|
||||
@@ -493,7 +505,8 @@ normals of faces incident on the corresponding vertex which do not deviate by mo
|
||||
<img src="images/fandisk-normals.jpg" alt="The Normals example computes per-face (left), per-vertex (middle) and
|
||||
per-corner (right) normals" />
|
||||
<figcaption>The <code>Normals</code> example computes per-face (left), per-vertex (middle) and
|
||||
per-corner (right) normals</figcaption></figure>
|
||||
per-corner (right) normals</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="gaussiancurvature">Gaussian curvature</h2>
|
||||
|
||||
@@ -525,7 +538,8 @@ elliptic, hyperbolic and parabolic vertices on the domain, as demonstrated in <a
|
||||
<img src="images/bumpy-gaussian-curvature.jpg" alt="The GaussianCurvature example computes discrete Gaussian curvature and
|
||||
visualizes it in pseudocolor." />
|
||||
<figcaption>The <code>GaussianCurvature</code> example computes discrete Gaussian curvature and
|
||||
visualizes it in pseudocolor.</figcaption></figure>
|
||||
visualizes it in pseudocolor.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="curvaturedirections">Curvature directions</h2>
|
||||
|
||||
@@ -576,7 +590,8 @@ fitting and visualizes mean curvature in pseudocolor and principal directions
|
||||
with a cross field." />
|
||||
<figcaption>The <code>CurvatureDirections</code> example computes principal curvatures via quadric
|
||||
fitting and visualizes mean curvature in pseudocolor and principal directions
|
||||
with a cross field.</figcaption></figure>
|
||||
with a cross field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="gradient">Gradient</h2>
|
||||
|
||||
@@ -593,7 +608,8 @@ vertex <span class="math">\(i\)</span> and zero at the other corners.</p>
|
||||
<img src="images/hat-function.jpg" alt="Hat function $\phi_i$ is one at vertex $i$, zero at all other vertices, and
|
||||
linear on incident triangles." />
|
||||
<figcaption>Hat function <span class="math">\(\phi_i\)</span> is one at vertex <span class="math">\(i\)</span>, zero at all other vertices, and
|
||||
linear on incident triangles.</figcaption></figure>
|
||||
linear on incident triangles.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Thus gradients of such piecewise linear functions are simply sums of gradients
|
||||
of the hat functions:</p>
|
||||
@@ -619,7 +635,8 @@ triangle and tetrahedral meshes (<a href="204_Gradient/main.cpp">Example 204</a>
|
||||
<img src="images/cheburashka-gradient.jpg" alt="The Gradient example computes gradients of an input function on a mesh and
|
||||
visualizes the vector field." />
|
||||
<figcaption>The <code>Gradient</code> example computes gradients of an input function on a mesh and
|
||||
visualizes the vector field.</figcaption></figure>
|
||||
visualizes the vector field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="laplacian">Laplacian</h2>
|
||||
|
||||
@@ -694,7 +711,8 @@ the surface along the mean curvature normal direction (<a href="205_Laplacian/ma
|
||||
<img src="images/cow-curvature-flow.jpg" alt="The Laplacian example computes conformalized mean curvature flow using the
|
||||
cotangent Laplacian ." />
|
||||
<figcaption>The <code>Laplacian</code> example computes conformalized mean curvature flow using the
|
||||
cotangent Laplacian <a class="citation" href="#fn:5" title="Jump to citation">[5]<span class="citekey" style="display:none">kazhdan_2012</span></a>.</figcaption></figure>
|
||||
cotangent Laplacian <a class="citation" href="#fn:5" title="Jump to citation">[5]<span class="citekey" style="display:none">kazhdan_2012</span></a>.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h3 id="massmatrix">Mass matrix</h3>
|
||||
|
||||
@@ -785,7 +803,8 @@ functionality is provided in libigl using <code>slice_into</code>:</p>
|
||||
<img src="images/decimated-knight-slice-color.jpg" alt="The example Slice shows how to use igl::slice to change the colors for
|
||||
triangles on a mesh." />
|
||||
<figcaption>The example <code>Slice</code> shows how to use <code>igl::slice</code> to change the colors for
|
||||
triangles on a mesh.</figcaption></figure>
|
||||
triangles on a mesh.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="sort">Sort</h2>
|
||||
|
||||
@@ -824,11 +843,12 @@ X(I(i,j),j);</code>. That is, <code>I</code> reveals how <code>X</code> is sorte
|
||||
|
||||
<figure>
|
||||
<img src="images/decimated-knight-sort-color.jpg" alt="The example Sort shows how to use igl::sortrows to
|
||||
pseudocolor triangles according to their barycenters sorted
|
||||
pseudocolor triangles according to their barycenters' sorted
|
||||
order (Example 302)." />
|
||||
<figcaption>The example <code>Sort</code> shows how to use <code>igl::sortrows</code> to
|
||||
pseudocolor triangles according to their barycenters’ sorted
|
||||
order (<a href="302_Sort/main.cpp">Example 302</a>).</figcaption></figure>
|
||||
order (<a href="302_Sort/main.cpp">Example 302</a>).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h3 id="othermatlab-stylefunctions">Other Matlab-style functions</h3>
|
||||
|
||||
@@ -995,7 +1015,8 @@ rows of <code>Z</code> corresponding to the interior vertices (<a href="303_Lapl
|
||||
<img src="images/camelhead-laplace-equation.jpg" alt="The LaplaceEquation example solves a Laplace equation with Dirichlet
|
||||
boundary conditions." />
|
||||
<figcaption>The <code>LaplaceEquation</code> example solves a Laplace equation with Dirichlet
|
||||
boundary conditions.</figcaption></figure>
|
||||
boundary conditions.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h3 id="quadraticenergyminimization">Quadratic energy minimization</h3>
|
||||
|
||||
@@ -1143,7 +1164,8 @@ hand and foot constrained to be equal)." />
|
||||
<figcaption>The example <code>LinearEqualityConstraints</code> first solves with just fixed value
|
||||
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).</figcaption></figure>
|
||||
hand and foot constrained to be equal).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="quadraticprogramming">Quadratic programming</h2>
|
||||
|
||||
@@ -1192,7 +1214,8 @@ discrete biharmonic kernels at multiple scales
|
||||
." />
|
||||
<figcaption> <a href="305_QuadraticProgramming/main.cpp">Example 305</a> uses an active set solver to optimize
|
||||
discrete biharmonic kernels <a class="citation" href="#fn:6" title="Jump to citation">[6]<span class="citekey" style="display:none">rustamov_2011</span></a> at multiple scales
|
||||
.</figcaption></figure>
|
||||
.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h1 id="chapter4:shapedeformation">Chapter 4: Shape deformation</h1>
|
||||
|
||||
@@ -1292,7 +1315,8 @@ surface (top) and using a biharmonic displacements
|
||||
(bottom)." />
|
||||
<figcaption>The <a href="401_BiharmonicDeformation/main.cpp">BiharmonicDeformation</a> example deforms a statue’s head as a <em>biharmonic
|
||||
surface</em> (top) and using a <em>biharmonic displacements</em>
|
||||
(bottom).</figcaption></figure>
|
||||
(bottom).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h4 id="relationshiptodifferentialcoordinatesandlaplaciansurfaceediting">Relationship to “differential coordinates” and Laplacian surface editing</h4>
|
||||
|
||||
@@ -1336,7 +1360,8 @@ igl::harmonic(V,F,b,bc,k,Z);
|
||||
<img src="images/bump-k-harmonic.jpg" alt="The PolyharmonicDeformation example deforms a flat domain (left) into a bump as a
|
||||
solution to various $k$-harmonic PDEs." />
|
||||
<figcaption>The <a href="402_PolyharmonicDeformation/main.cpp">PolyharmonicDeformation</a> example deforms a flat domain (left) into a bump as a
|
||||
solution to various <span class="math">\(k\)</span>-harmonic PDEs.</figcaption></figure>
|
||||
solution to various <span class="math">\(k\)</span>-harmonic PDEs.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="boundedbiharmonicweights">Bounded biharmonic weights</h2>
|
||||
|
||||
@@ -1404,7 +1429,8 @@ mesh given a skeleton (top) and then animates a linear blend skinning
|
||||
deformation (bottom)." />
|
||||
<figcaption>The example <a href="403_BoundedBiharmonicWeights/main.cpp">BoundedBiharmonicWeights</a> computes weights for a tetrahedral
|
||||
mesh given a skeleton (top) and then animates a linear blend skinning
|
||||
deformation (bottom).</figcaption></figure>
|
||||
deformation (bottom).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="dualquaternionskinning">Dual quaternion skinning</h2>
|
||||
|
||||
@@ -1456,7 +1482,8 @@ quaternion skinning (bottom), highlighting LBSs candy wrapper effect (middle)
|
||||
and joint collapse (right)." />
|
||||
<figcaption>The example <a href="404_DualQuaternionSkinning/main.cpp">DualQuaternionSkinning</a> compares linear blend skinning (top) to dual
|
||||
quaternion skinning (bottom), highlighting LBS’s candy wrapper effect (middle)
|
||||
and joint collapse (right).</figcaption></figure>
|
||||
and joint collapse (right).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="as-rigid-as-possible">As-rigid-as-possible</h2>
|
||||
|
||||
@@ -1560,7 +1587,8 @@ the highly optimized singular value decomposition code from McAdams et al.
|
||||
<img src="images/decimated-knight-arap.jpg" alt="The example AsRigidAsPossible deforms a surface as if it were made of an
|
||||
elastic material" />
|
||||
<figcaption>The example <a href="405_AsRigidAsPossible/main.cpp">AsRigidAsPossible</a> deforms a surface as if it were made of an
|
||||
elastic material</figcaption></figure>
|
||||
elastic material</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The concept of local rigidity will be revisited shortly in the context of
|
||||
surface parameterization.</p>
|
||||
@@ -1673,7 +1701,8 @@ rotation edge sets (right of middle), to the very fast subpsace method
|
||||
<figcaption>The example <a href="406_FastAutomaticSkinningTransformations/main.cpp">FastAutomaticSkinningTransformations</a> 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
|
||||
(right).</figcaption></figure>
|
||||
(right).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h1 id="500">Chapter 5: Parametrization</h1>
|
||||
|
||||
@@ -1743,7 +1772,8 @@ mesh with texture, (right) UV parametrization with
|
||||
texture" />
|
||||
<figcaption>(<a href="501_HarmonicParam/main.cpp">Example 501</a>) Harmonic parametrization. (left)
|
||||
mesh with texture, (right) UV parametrization with
|
||||
texture</figcaption></figure>
|
||||
texture</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="502">Least squares conformal maps</h2>
|
||||
|
||||
@@ -1792,7 +1822,8 @@ vertices to two arbitrary positions. The full source code is provided in <a href
|
||||
<img src="images/502_LSCMParam.png" alt="(Example 502) LSCM parametrization. (left) mesh
|
||||
with texture, (right) UV parametrization" />
|
||||
<figcaption>(<a href="502_LSCMParam/main.cpp">Example 502</a>) LSCM parametrization. (left) mesh
|
||||
with texture, (right) UV parametrization</figcaption></figure>
|
||||
with texture, (right) UV parametrization</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="503">As-rigid-as-possible parametrization</h2>
|
||||
|
||||
@@ -1818,7 +1849,8 @@ the distortion.</p>
|
||||
texture" />
|
||||
<figcaption>(<a href="502_ARAPParam/main.cpp">Example 503</a>) As-Rigid-As-Possible parametrization.
|
||||
(left) mesh with texture, (right) UV parametrization with
|
||||
texture</figcaption></figure>
|
||||
texture</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="504">N-rotationally symmetric tangent fields</h2>
|
||||
|
||||
@@ -1843,7 +1875,8 @@ the triangle mesh (output_field), plus the singularities of the field
|
||||
|
||||
<figure>
|
||||
<img src="images/504_vector_field.png" alt="Design of a unit-length vector field" />
|
||||
<figcaption>Design of a unit-length vector field</figcaption></figure>
|
||||
<figcaption>Design of a unit-length vector field</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The singularities are vertices where the field vanishes (highlighted in red in
|
||||
the figure above). <code>igl::nrosy</code> can also generate N-RoSy fields <a class="citation" href="#fn:20" title="Jump to citation">[20]<span class="citekey" style="display:none">levy_2008</span></a>,
|
||||
@@ -1854,7 +1887,8 @@ N are of different types and they appear in different positions.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/504_nrosy_field.png" alt="Design of a 2-,4- and 9-RoSy field" />
|
||||
<figcaption>Design of a 2-,4- and 9-RoSy field</figcaption></figure>
|
||||
<figcaption>Design of a 2-,4- and 9-RoSy field</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>We demonstrate how to call and plot N-RoSy fields in <a href="504_NRosyDesign/main.cpp">Example
|
||||
504</a>, where the degree of the field can be change
|
||||
@@ -1881,7 +1915,8 @@ from the principal curvature directions. In [<a href="506_FrameField/main.cpp">E
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_1.png" alt="Initial cross field prescribing the edge alignment." />
|
||||
<figcaption>Initial cross field prescribing the edge alignment.</figcaption></figure>
|
||||
<figcaption>Initial cross field prescribing the edge alignment.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h3 id="combingandcutting">Combing and cutting</h3>
|
||||
|
||||
@@ -1896,7 +1931,8 @@ length cross fields.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_2.png" alt="Bisector field." />
|
||||
<figcaption>Bisector field.</figcaption></figure>
|
||||
<figcaption>Bisector field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>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
|
||||
@@ -1904,7 +1940,8 @@ random face.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_3.png" alt="Combed bisector field." />
|
||||
<figcaption>Combed bisector field.</figcaption></figure>
|
||||
<figcaption>Combed bisector field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>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
|
||||
@@ -1914,14 +1951,16 @@ in the combing define the cut graph:</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_4.png" alt="Cut graph." />
|
||||
<figcaption>Cut graph.</figcaption></figure>
|
||||
<figcaption>Cut graph.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Finally, we rotate the combed field by 45 degrees to undo the initial degrees
|
||||
rotation:</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_5.png" alt="Combed cross field." />
|
||||
<figcaption>Combed cross field.</figcaption></figure>
|
||||
<figcaption>Combed cross field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The combed cross field can be seen as the ideal Jacobian of the parametrization
|
||||
that will be computed in the next section.</p>
|
||||
@@ -1941,21 +1980,24 @@ input cross field.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_8.png" alt="Poisson parametrization." />
|
||||
<figcaption>Poisson parametrization.</figcaption></figure>
|
||||
<figcaption>Poisson parametrization.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>We hide the seams by adding integer constraints to the Poisson problem
|
||||
that align the isolines on both sides of each seam <a class="citation" href="#fn:21" title="Jump to citation">[21]<span class="citekey" style="display:none">bommes_2009</span></a>.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_7.png" alt="Seamless Poisson parametrization." />
|
||||
<figcaption>Seamless Poisson parametrization.</figcaption></figure>
|
||||
<figcaption>Seamless Poisson parametrization.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Note that this parametrization can only be used for remeshing purposes, since
|
||||
it contains many overlaps.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/505_MIQ_6.png" alt="Seamless Poisson parametrization (in 2D)." />
|
||||
<figcaption>Seamless Poisson parametrization (in 2D).</figcaption></figure>
|
||||
<figcaption>Seamless Poisson parametrization (in 2D).</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>A quad mesh can be extracted from this parametrization using
|
||||
<a href="https://github.com/hcebke/libQEx">libQEx</a> (not included in libigl).
|
||||
@@ -1982,7 +2024,8 @@ scale. The red faces contains the frame field
|
||||
constraints." />
|
||||
<figcaption>Interpolation of a frame field. Colors on the vectors denote the desired
|
||||
scale. The red faces contains the frame field
|
||||
constraints.</figcaption></figure>
|
||||
constraints.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>After the interpolation, the surface is warped to transform each frame into an
|
||||
orthogonal and unit length cross (i.e. removing the scaling and skewness from
|
||||
@@ -1993,14 +2036,16 @@ surface.</p>
|
||||
<img src="images/506_FrameField_2.png" alt="The surface is deformed to transform the frame field in a cross
|
||||
field." />
|
||||
<figcaption>The surface is deformed to transform the frame field in a cross
|
||||
field.</figcaption></figure>
|
||||
field.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The deformed surface can the be isotropically remeshed using the MIQ algorithm
|
||||
that has been presented in the previous section.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/506_FrameField_3.png" alt="The deformed surface is isotropically remeshed." />
|
||||
<figcaption>The deformed surface is isotropically remeshed.</figcaption></figure>
|
||||
<figcaption>The deformed surface is isotropically remeshed.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The UV coordinates of the deformed surface can then be used to transport the
|
||||
parametrization to the original surface, where the isolines will trace a quad
|
||||
@@ -2011,7 +2056,8 @@ field.</p>
|
||||
<img src="images/506_FrameField_4.png" alt="The global parametrization is lifted to the original surface to create the
|
||||
anisotropic quad meshing." />
|
||||
<figcaption>The global parametrization is lifted to the original surface to create the
|
||||
anisotropic quad meshing.</figcaption></figure>
|
||||
anisotropic quad meshing.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>Our implementation (<a href="506_FrameField/main.cpp">Example 506</a>) uses MIQ to
|
||||
generate the UV parametrization, but other algorithms could be applied: the
|
||||
@@ -2028,7 +2074,8 @@ sparse set of constraints (<a href="507_PolyVectorField/main.cpp">Example 507</a
|
||||
|
||||
<figure>
|
||||
<img src="images/507_PolyVectorField.png" alt="Interpolation of a 6-PolyVector field (right) and a 12-PolyVector field from a sparse set of random constraints." />
|
||||
<figcaption>Interpolation of a 6-PolyVector field (right) and a 12-PolyVector field from a sparse set of random constraints.</figcaption></figure>
|
||||
<figcaption>Interpolation of a 6-PolyVector field (right) and a 12-PolyVector field from a sparse set of random constraints.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The core idea is to represent the vector set as the roots of a complex
|
||||
polynomial: The polynomial coefficients are then harmonically interpolated
|
||||
@@ -2062,7 +2109,8 @@ closest conjugate field (<a href="508_ConjugateField/main.cpp">Example 508</a>).
|
||||
<img src="images/508_ConjugateField.png" alt="A smooth 4-PolyVector field (left) is deformed to become a conjugate field
|
||||
(right)." />
|
||||
<figcaption>A smooth 4-PolyVector field (left) is deformed to become a conjugate field
|
||||
(right).</figcaption></figure>
|
||||
(right).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="509">Planarization</h2>
|
||||
|
||||
@@ -2079,7 +2127,8 @@ igl::palanarize (right). The colors represent the planarity of the
|
||||
quads." />
|
||||
<figcaption>A non-planar quad mesh (left) is planarized using the libigl function
|
||||
igl::palanarize (right). The colors represent the planarity of the
|
||||
quads.</figcaption></figure>
|
||||
quads.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h1 id="600">Chapter 6: External libraries</h1>
|
||||
|
||||
@@ -2098,69 +2147,104 @@ to the extreme difficulty in serializing pointer-based data structured, such as
|
||||
an half-edge data structure (<a href="http://openmesh.org">OpenMesh</a>, <a href="http://www.cgal.org">CGAL</a>), or a pointer based indexed structure (<a href="http://vcg.isti.cnr.it/~cignoni/newvcglib/html/">VCG</a>).</p>
|
||||
|
||||
<p>In libigl, serialization is much simpler, since the majority of the functions use basic types, and pointers are used in very rare cases (usually to interface
|
||||
with external libraries). Libigl bundles a simple and self-contained XML serialization framework, that drastically reduces the overhead required to add
|
||||
with external libraries). Libigl bundles a simple and self-contained binary and XML serialization framework, that drastically reduces the overhead required to add
|
||||
serialization to your applications.</p>
|
||||
|
||||
<p>Assume that the state of your application is a mesh and a set of
|
||||
integer ids:</p>
|
||||
<p>To de-/serialize a set of variables use the following method:</p>
|
||||
|
||||
<pre><code class="cpp">class State : public igl::XMLSerialization
|
||||
<pre><code class="cpp">#include "igl/serialize.h"
|
||||
|
||||
bool b = true;
|
||||
unsigned int num = 10;
|
||||
std::vector<float> vec = {0.1,0.002,5.3};
|
||||
|
||||
// use overwrite = true for the first serialization to create or overwrite an existing file
|
||||
igl::serialize(b,"B","filename",true);
|
||||
// append following serialization to existing file
|
||||
igl::serialize(num,"Number","filename");
|
||||
igl::serialize(vec,"VectorName","filename");
|
||||
|
||||
// deserialize back to variables
|
||||
igl::deserialize(b,"B","filename");
|
||||
igl::deserialize(num,"Number","filename");
|
||||
igl::deserialize(vec,"VectorName","filename");
|
||||
</code></pre>
|
||||
|
||||
<p>Currently all fundamental data types (bool, int, float, double, …) are supported, as well as std::string, basic <code>STL</code> containers, dense and sparse Eigen matrices and nestings of those.
|
||||
Some limitations apply to pointers. Currently, loops or many to one type of link structures are not handled correctly. Each pointer is assumed to point to a different independent object.
|
||||
Uninitialized pointers must be set to <code>nullptr</code> before de-/serialization to avoid memory leaks. Cross-platform issues like little-, big-endianess is currently not supported.
|
||||
To make user defined types serializable, just derive from <code>igl::Serializable</code> and trivially implementing the <code>InitSerialization</code> method.</p>
|
||||
|
||||
<p>Assume that the state of your application is a mesh and a set of integer ids:</p>
|
||||
|
||||
<pre><code class="cpp">#include "igl/serialize.h"
|
||||
|
||||
struct State : public igl::Serializable
|
||||
{
|
||||
public:
|
||||
State() : XMLSerialization("dummy") {}
|
||||
|
||||
Eigen::MatrixXd V;
|
||||
Eigen::MatrixXi F;
|
||||
std::vector<int> ids;
|
||||
|
||||
void InitSerialization()
|
||||
{
|
||||
xmlSerializer->Add(V , "V");
|
||||
xmlSerializer->Add(F , "F");
|
||||
xmlSerializer->Add(ids, "ids");
|
||||
this->Add(V , "V");
|
||||
this->Add(F , "F");
|
||||
this->Add(ids, "ids");
|
||||
}
|
||||
};
|
||||
</code></pre>
|
||||
|
||||
<p>Any class can be made serializable by inheriting from `<code>igl::XMLSerialization</code> and trivially implementing the <code>InitSerialization</code> method. The library can serialize all the basic <code>stl</code> types, all <code>Eigen</code> types and any class inheriting
|
||||
from <code>igl::XMLSerialization</code>.</p>
|
||||
<p>If you need more control over the serialization of your types, you can override the following functions or directly inherit from the interface <code>igl::SerializableBase</code>.</p>
|
||||
|
||||
<p>The state can be saved into an xml file with:</p>
|
||||
|
||||
<pre><code class="cpp">igl::XMLSerializer serializer_save("601_Serialization");
|
||||
serializer_save.Add(state,"State");
|
||||
serializer_save.Save("temp.xml",true);
|
||||
<pre><code class="cpp">bool Serializable::PreSerialization() const;
|
||||
void Serializable::PostSerialization() const;
|
||||
bool Serializable::PreDeserialization();
|
||||
void Serializable::PostDeserialization();
|
||||
</code></pre>
|
||||
|
||||
<p>This code generates the following xml file (assuming <code>V</code> and <code>F</code> contains a simple mesh with two triangles, and <code>ids</code> contains the numbers 6 and 7):</p>
|
||||
<p>Alternatively, if you want a non-intrusive way of serializing your state you can overload the following functions:</p>
|
||||
|
||||
<pre><code class="xml"><:::601_Serialization>
|
||||
<State>
|
||||
<V rows="4" cols="3" matrix="
|
||||
0,0,0,
|
||||
1,0,0,
|
||||
1,1,1,
|
||||
2,1,0"/>
|
||||
<F rows="2" cols="3" matrix="
|
||||
0,1,2,
|
||||
1,3,2"/>
|
||||
<ids size="2" vector_int="
|
||||
6,7"/>
|
||||
</State>
|
||||
</:::601_Serialization>
|
||||
<pre><code class="cpp">namespace igl { namespace serialization {
|
||||
|
||||
void serialize(const State& obj,std::vector<char>& buffer){
|
||||
::igl::serialize(obj.V,std::string("V"),buffer);
|
||||
::igl::serialize(obj.F,std::string("F"),buffer);
|
||||
::igl::serialize(obj.ids,std::string("ids"),buffer);
|
||||
}
|
||||
void deserialize(State& obj,const std::vector<char>& buffer){
|
||||
::igl::deserialize(obj.V,std::string("V"),buffer);
|
||||
::igl::deserialize(obj.F,std::string("F"),buffer);
|
||||
::igl::deserialize(obj.ids,std::string("ids"),buffer);
|
||||
}
|
||||
}}
|
||||
</code></pre>
|
||||
|
||||
<p>The xml file can be loaded in a similar way:</p>
|
||||
<p>Equivalently, you can use the following macros:</p>
|
||||
|
||||
<pre><code class="cpp">State loaded_state;
|
||||
igl::XMLSerializer serializer_load("601_Serialization");
|
||||
serializer_load.Add(loaded_state,"State");
|
||||
serializer_load.Load("temp.xml");
|
||||
<pre><code class="cpp">SERIALIZE_TYPE(State,
|
||||
SERIALIZE_MEMBER(V)
|
||||
SERIALIZE_MEMBER(F)
|
||||
SERIALIZE_MEMBER_NAME(ids,"ids")
|
||||
)
|
||||
</code></pre>
|
||||
|
||||
<p>The serialization framework can also be used as a convenient interface to
|
||||
provide parameters to command line applications, since the xml files can be
|
||||
directly edited with a standard text editor.</p>
|
||||
<p>All the former code is for binary serialization which is especially useful if you have to handle larger data where the loading and saving times become more important.
|
||||
For cases where you want to read and edit the serialized data by hand we provide a serialization to XML files which is based on the library <a href="https://github.com/leethomason/tinyxml2">tinyxml2</a>.
|
||||
There you also have the option to create a partial binary serialization of your data by using the binary parameter, exposed in the function <code>serialize_xml()</code>:</p>
|
||||
|
||||
<pre><code class="cpp">#include "igl/xml/serialize_xml.h"
|
||||
|
||||
int number;
|
||||
|
||||
// binary = false, overwrite = true
|
||||
igl::serialize_xml(vec,"VectorXML",xmlFile,false,true);
|
||||
// binary = true, overwrite = true
|
||||
igl::serialize_xml(vec,"VectorBin",xmlFile,true,true);
|
||||
igl::deserialize_xml(vec,"VectorXML",xmlFile);
|
||||
igl::deserialize_xml(vec,"VectorBin",xmlFile);
|
||||
</code></pre>
|
||||
|
||||
<p>For user defined types derive from <code>XMLSerializable</code>. </p>
|
||||
|
||||
<p>The code snippets above are extracted from <a href="601_Serialization/main.cpp">Example
|
||||
601</a>. We strongly suggest that you make the entire
|
||||
@@ -2208,7 +2292,8 @@ see the sparsity pattern of L using spy:</p>
|
||||
<img src="images/602_Matlab_1.png" alt="The Matlab spy function is called from a libigl-based
|
||||
application." />
|
||||
<figcaption>The Matlab spy function is called from a libigl-based
|
||||
application.</figcaption></figure>
|
||||
application.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The results of Matlab computations can be returned back to the C++ application</p>
|
||||
|
||||
@@ -2222,7 +2307,8 @@ igl::mlgetmatrix(&engine,"EV",EV);
|
||||
<img src="images/602_Matlab_2.png" alt="4 Eigenfunctions of the Laplacian plotted in the libigl
|
||||
viewer." />
|
||||
<figcaption>4 Eigenfunctions of the Laplacian plotted in the libigl
|
||||
viewer.</figcaption></figure>
|
||||
viewer.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h3 id="savingamatlabworkspace">Saving a Matlab workspace</h3>
|
||||
|
||||
@@ -2327,7 +2413,8 @@ in its interior) is triangulated.</p>
|
||||
|
||||
<figure>
|
||||
<img src="images/604_Triangle.png" alt="Triangulation of the interior of a polygon." />
|
||||
<figcaption>Triangulation of the interior of a polygon.</figcaption></figure>
|
||||
<figcaption>Triangulation of the interior of a polygon.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="605">Tetrahedralization of closed surfaces</h2>
|
||||
|
||||
@@ -2340,7 +2427,8 @@ using the function <code>igl::tetrahedralize</code> which wraps the Tetgen libra
|
||||
|
||||
<figure>
|
||||
<img src="images/605_Tetgen.png" alt="Tetrahedralization of the interior of a surface mesh." />
|
||||
<figcaption>Tetrahedralization of the interior of a surface mesh.</figcaption></figure>
|
||||
<figcaption>Tetrahedralization of the interior of a surface mesh.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="606">Baking ambient occlusion</h2>
|
||||
|
||||
@@ -2376,7 +2464,8 @@ single scalar for each sample.</p>
|
||||
<img src="images/606_AmbientOcclusion.png" alt="A mesh rendered without (left) and with (right) ambient
|
||||
occlusion." />
|
||||
<figcaption>A mesh rendered without (left) and with (right) ambient
|
||||
occlusion.</figcaption></figure>
|
||||
occlusion.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="607">Picking</h2>
|
||||
|
||||
@@ -2410,7 +2499,8 @@ by Embree, and <code>fid</code> and <code>vid</code> are the picked face and ver
|
||||
<img src="images/607_Picking.png" alt="(Example 607) Picking via ray casting. The selected
|
||||
vertices are colored in red." />
|
||||
<figcaption>(<a href="607_Picking/main.cpp">Example 607</a>) Picking via ray casting. The selected
|
||||
vertices are colored in red.</figcaption></figure>
|
||||
vertices are colored in red.</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="608">Locally Injective Maps</h2>
|
||||
|
||||
@@ -2427,7 +2517,8 @@ deformation energies. A simple deformation of a 2D grid is computed in <a href="
|
||||
<img src="images/608_LIM.png" alt="A mesh (left) deformed using Laplacian editing (middle) and with Laplacian
|
||||
editing plus the anti-flipping constraints (right)." />
|
||||
<figcaption>A mesh (left) deformed using Laplacian editing (middle) and with Laplacian
|
||||
editing plus the anti-flipping constraints (right).</figcaption></figure>
|
||||
editing plus the anti-flipping constraints (right).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h2 id="609">Boolean operations on meshes</h2>
|
||||
|
||||
@@ -2477,7 +2568,7 @@ intersections have been “resolved”. That is, edges and vertices are
|
||||
exactly at the intersection lines, so the resulting <em>non-manifold</em> mesh <code>(V,F)</code>
|
||||
has no self-intersections.</p>
|
||||
|
||||
<p>Then libigl <em>peals</em> the outer hull <a class="citation" href="#fn:28" title="Jump to citation">[28]<span class="citekey" style="display:none">attene_2014</span></a> off this mesh recursively,
|
||||
<p>Then libigl <em>peels</em> the outer hull <a class="citation" href="#fn:28" title="Jump to citation">[28]<span class="citekey" style="display:none">attene_2014</span></a> off this mesh recursively,
|
||||
keeping track of the iteration parity and orientation flips for each layer.
|
||||
For any boolean operation, these two pieces of information determine for each
|
||||
triangle (1) if it should be included in the output, and (2) if its orientation
|
||||
@@ -2501,7 +2592,8 @@ back-facing triangles." />
|
||||
boolean operations on the <em>Cheburashka</em> (red) and <em>Knight</em> (green). From left
|
||||
to right: union, intersection, set minus, symmetric difference (XOR),
|
||||
“resolve”. Bottom row reveals inner surfaces, darker color indicates
|
||||
back-facing triangles.</figcaption></figure>
|
||||
back-facing triangles.</figcaption>
|
||||
</figure>
|
||||
|
||||
<p>The union, symmetric difference and “resolve” have the same outward
|
||||
appearance, but differ in their treatment of internal structures. The union has
|
||||
@@ -2610,7 +2702,8 @@ generalized winding number function for a tetrahedral mesh inside a cat with
|
||||
holes and self intersections (gold). The silver mesh is surface of the
|
||||
extracted interior tets, and slices show the winding number function on all
|
||||
tets in the convex hull: blue (~0), green (~1), yellow
|
||||
(~2).</figcaption></figure>
|
||||
(~2).</figcaption>
|
||||
</figure>
|
||||
|
||||
<h1 id="future">Outlook for continuing development</h1>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user