update tutorial/tutorial.html to match tutorial/tutorial.md

This commit is contained in:
Daniele Panozzo
2015-02-18 12:37:58 +01:00
parent 5e402daed9
commit 324dc932f2
+193 -100
View File
@@ -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&#8217; 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 &#8211;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&#8217;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 &#8220;differential coordinates&#8221; 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&#8217;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 &quot;igl/serialize.h&quot;
bool b = true;
unsigned int num = 10;
std::vector&lt;float&gt; vec = {0.1,0.002,5.3};
// use overwrite = true for the first serialization to create or overwrite an existing file
igl::serialize(b,&quot;B&quot;,&quot;filename&quot;,true);
// append following serialization to existing file
igl::serialize(num,&quot;Number&quot;,&quot;filename&quot;);
igl::serialize(vec,&quot;VectorName&quot;,&quot;filename&quot;);
// deserialize back to variables
igl::deserialize(b,&quot;B&quot;,&quot;filename&quot;);
igl::deserialize(num,&quot;Number&quot;,&quot;filename&quot;);
igl::deserialize(vec,&quot;VectorName&quot;,&quot;filename&quot;);
</code></pre>
<p>Currently all fundamental data types (bool, int, float, double, &#8230;) 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 &quot;igl/serialize.h&quot;
struct State : public igl::Serializable
{
public:
State() : XMLSerialization(&quot;dummy&quot;) {}
Eigen::MatrixXd V;
Eigen::MatrixXi F;
std::vector&lt;int&gt; ids;
void InitSerialization()
{
xmlSerializer-&gt;Add(V , &quot;V&quot;);
xmlSerializer-&gt;Add(F , &quot;F&quot;);
xmlSerializer-&gt;Add(ids, &quot;ids&quot;);
this-&gt;Add(V , &quot;V&quot;);
this-&gt;Add(F , &quot;F&quot;);
this-&gt;Add(ids, &quot;ids&quot;);
}
};
</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(&quot;601_Serialization&quot;);
serializer_save.Add(state,&quot;State&quot;);
serializer_save.Save(&quot;temp.xml&quot;,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">&lt;:::601_Serialization&gt;
&lt;State&gt;
&lt;V rows=&quot;4&quot; cols=&quot;3&quot; matrix=&quot;
0,0,0,
1,0,0,
1,1,1,
2,1,0&quot;/&gt;
&lt;F rows=&quot;2&quot; cols=&quot;3&quot; matrix=&quot;
0,1,2,
1,3,2&quot;/&gt;
&lt;ids size=&quot;2&quot; vector_int=&quot;
6,7&quot;/&gt;
&lt;/State&gt;
&lt;/:::601_Serialization&gt;
<pre><code class="cpp">namespace igl { namespace serialization {
void serialize(const State&amp; obj,std::vector&lt;char&gt;&amp; buffer){
::igl::serialize(obj.V,std::string(&quot;V&quot;),buffer);
::igl::serialize(obj.F,std::string(&quot;F&quot;),buffer);
::igl::serialize(obj.ids,std::string(&quot;ids&quot;),buffer);
}
void deserialize(State&amp; obj,const std::vector&lt;char&gt;&amp; buffer){
::igl::deserialize(obj.V,std::string(&quot;V&quot;),buffer);
::igl::deserialize(obj.F,std::string(&quot;F&quot;),buffer);
::igl::deserialize(obj.ids,std::string(&quot;ids&quot;),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(&quot;601_Serialization&quot;);
serializer_load.Add(loaded_state,&quot;State&quot;);
serializer_load.Load(&quot;temp.xml&quot;);
<pre><code class="cpp">SERIALIZE_TYPE(State,
SERIALIZE_MEMBER(V)
SERIALIZE_MEMBER(F)
SERIALIZE_MEMBER_NAME(ids,&quot;ids&quot;)
)
</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 &quot;igl/xml/serialize_xml.h&quot;
int number;
// binary = false, overwrite = true
igl::serialize_xml(vec,&quot;VectorXML&quot;,xmlFile,false,true);
// binary = true, overwrite = true
igl::serialize_xml(vec,&quot;VectorBin&quot;,xmlFile,true,true);
igl::deserialize_xml(vec,&quot;VectorXML&quot;,xmlFile);
igl::deserialize_xml(vec,&quot;VectorBin&quot;,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(&amp;engine,&quot;EV&quot;,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 &#8220;resolved&#8221;. 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),
&#8220;resolve&#8221;. Bottom row reveals inner surfaces, darker color indicates
back-facing triangles.</figcaption></figure>
back-facing triangles.</figcaption>
</figure>
<p>The union, symmetric difference and &#8220;resolve&#8221; 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>