Skip to content

Commit

Permalink
Fix links to the code.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdumas committed Mar 25, 2018
1 parent ee0c743 commit 27817f4
Show file tree
Hide file tree
Showing 17 changed files with 865 additions and 73 deletions.
2 changes: 1 addition & 1 deletion docs/matlab-to-eigen.html
Expand Up @@ -312,6 +312,6 @@
<a href="http://eigen.tuxfamily.org/dox/AsciiQuickReference.txt">Eigen's
"ASCII Quick Reference" with MATLAB translations</a>
<br>
<a href="./tutorial.html">IGL Lib Tutorial</a>
<a href="./tutorial/chapter-1/">IGL Lib Tutorial</a>
</body>
</html>
26 changes: 13 additions & 13 deletions docs/tutorial/chapter-1.md
Expand Up @@ -152,15 +152,15 @@ Similarly, a mesh can be written in an OBJ file using:
igl::writeOBJ("cube.obj",V,F);
```

[Example 101](101_FileIO/main.cpp) contains a simple mesh
[Example 101]({{ repo_url }}/tutorial/101_FileIO/main.cpp) contains a simple mesh
converter from OFF to OBJ format.

## Visualizing surfaces

Libigl provides an glfw-based OpenGL 3.2 viewer to visualize surfaces, their
properties and additional debugging information.

The following code ([Example 102](102_DrawMesh/main.cpp)) is a basic skeleton
The following code ([Example 102]({{ repo_url }}/tutorial/102_DrawMesh/main.cpp)) is a basic skeleton
for all the examples that will be used in the tutorial.
It is a standalone application that loads a mesh and uses the viewer to
render it.
Expand Down Expand Up @@ -189,9 +189,9 @@ The function `set_mesh` copies the mesh into the viewer.
Additional properties can be plotted on the mesh (as we will see later),
and it is possible to extend the viewer with standard OpenGL code.
Please see the documentation in
[Viewer.h](../include/igl/opengl/glfw/Viewer.h) for more details.
[Viewer.h]({{ repo_url }}/include/igl/opengl/glfw/Viewer.h) for more details.
![([Example 102](102_DrawMesh/main.cpp)) loads and draws a mesh.](images/102_DrawMesh.png)
![([Example 102]({{ repo_url }}/tutorial/102_DrawMesh/main.cpp)) loads and draws a mesh.](images/102_DrawMesh.png)
## Interaction with keyboard and mouse
Expand All @@ -210,7 +210,7 @@ bool (*callback_key_up)(Viewer& viewer, unsigned char key, int modifiers);
```

A keyboard callback can be used to visualize multiple meshes or different
stages of an algorithm, as demonstrated in [Example 103](103_Events/main.cpp), where
stages of an algorithm, as demonstrated in [Example 103]({{ repo_url }}/tutorial/103_Events/main.cpp), where
the keyboard callback changes the visualized mesh depending on the key pressed:

```cpp
Expand Down Expand Up @@ -247,7 +247,7 @@ control the camera directly in your code.

The viewer can be extended using plugins, which are classes that implements all
the viewer's callbacks. See the
[Viewer_plugin](../include/igl/opengl/glfw/ViewerPlugin.h) for more details.
[Viewer_plugin]({{ repo_url }}/include/igl/opengl/glfw/ViewerPlugin.h) for more details.

## Scalar field visualization

Expand All @@ -268,7 +268,7 @@ scalar function is converted to colors using a color transfer function, which
maps a scalar value between 0 and 1 to a color. A simple example of a scalar
field defined on a surface is the z coordinate of each point, which can be
extract from our mesh representation by taking the last column of `V`
([Example 104](104_Colors/main.cpp)). The function `igl::jet` can be used to
([Example 104]({{ repo_url }}/tutorial/104_Colors/main.cpp)). The function `igl::jet` can be used to
convert it to colors:

```cpp
Expand All @@ -279,7 +279,7 @@ igl::jet(Z,true,C);
The first row extracts the third column from `V` (the z coordinate of each
vertex) and the second calls a libigl functions that converts a scalar field to colors. The second parameter of jet normalizes the scalar field to lie between 0 and 1 before applying the transfer function.
![([Example 104](104_Colors/main.cpp)) igl::jet converts a scalar field to a color field.](images/104_Colors.png)
![([Example 104]({{ repo_url }}/tutorial/104_Colors/main.cpp)) igl::jet converts a scalar field to a color field.](images/104_Colors.png)
`igl::jet` 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
Expand Down Expand Up @@ -307,7 +307,7 @@ viewer.data().add_label(p,str);

Draws a label containing the string str at the position p, which is a vector of length 3.

These functions are demonstrate in [Example 105](105_Overlays/main.cpp) where
These functions are demonstrate in [Example 105]({{ repo_url }}/tutorial/105_Overlays/main.cpp) where
the bounding box of a mesh is plotted using lines and points.
Using matrices to encode the mesh and its attributes allows to write short and
efficient code for many operations, avoiding to write for loops. For example,
Expand All @@ -318,14 +318,14 @@ Eigen::Vector3d m = V.colwise().minCoeff();
Eigen::Vector3d M = V.colwise().maxCoeff();
```

![([Example 105](105_Overlays/main.cpp)) The bounding box of a mesh is shown using overlays.](images/105_Overlays.png)
![([Example 105]({{ repo_url }}/tutorial/105_Overlays/main.cpp)) The bounding box of a mesh is shown using overlays.](images/105_Overlays.png)

## Viewer Menu

As of latest version, the viewer uses a new menu and completely replaces
[AntTweakBar](http://anttweakbar.sourceforge.net/doc/) and
[nanogui](https://github.com/wjakob/nanogui) with [Dear ImGui](https://github.com/ocornut/imgui). To extend the default menu of the
viewer and to expose more user defined variables you have to implement a custom interface, as in [Example 106](106_ViewerMenu/main.cpp):
viewer and to expose more user defined variables you have to implement a custom interface, as in [Example 106]({{ repo_url }}/tutorial/106_ViewerMenu/main.cpp):
```cpp
// Add content to the default menu window
menu.callback_draw_viewer_menu = [&]()
Expand Down Expand Up @@ -405,7 +405,7 @@ menu.callback_draw_custom_window = [&]()
};
```

![([Example 106](106_ViewerMenu/main.cpp)) The UI of the viewer can be easily customized.](images/106_ViewerMenu.png)
![([Example 106]({{ repo_url }}/tutorial/106_ViewerMenu/main.cpp)) The UI of the viewer can be easily customized.](images/106_ViewerMenu.png)

## Multiple Meshes

Expand All @@ -417,4 +417,4 @@ field. By default it his is set to `0`, so in the typical case of a single mesh
`viewer.data()` returns the `igl::ViewerData` corresponding to the one
and only mesh.

![([Example 107](107_MultipleMeshes/main.cpp)) The `igl::opengl::glfw::Viewer` can render multiple meshes, each with its own attributes like colors.](images/multiple-meshes.png)
![([Example 107]({{ repo_url }}/tutorial/107_MultipleMeshes/main.cpp)) The `igl::opengl::glfw::Viewer` can render multiple meshes, each with its own attributes like colors.](images/multiple-meshes.png)
12 changes: 6 additions & 6 deletions docs/tutorial/chapter-2.md
Expand Up @@ -8,7 +8,7 @@ coloring routines of our viewer.
## Normals
Surface normals are a basic quantity necessary for rendering a surface. There
are a variety of ways to compute and store normals on a triangle mesh. [Example
201](201_Normals/main.cpp) demonstrates how to compute and visualize normals
201]({{ repo_url }}/tutorial/201_Normals/main.cpp) demonstrates how to compute and visualize normals
with libigl.

### Per-face
Expand Down Expand Up @@ -87,7 +87,7 @@ where $N(i)$ are the triangles incident on vertex $i$ and $θ_{ij}$ is the angle
at vertex $i$ in triangle $j$ [^meyer_2003].

Just like the continuous analog, our discrete Gaussian curvature reveals
elliptic, hyperbolic and parabolic vertices on the domain, as demonstrated in [Example 202](202_GaussianCurvature/main.cpp).
elliptic, hyperbolic and parabolic vertices on the domain, as demonstrated in [Example 202]({{ repo_url }}/tutorial/202_GaussianCurvature/main.cpp).

![The `GaussianCurvature` example computes discrete Gaussian curvature and visualizes it in pseudocolor.](images/bumpy-gaussian-curvature.jpg)

Expand Down Expand Up @@ -132,7 +132,7 @@ Alternatively, a robust method for determining principal curvatures is via
quadric fitting [^panozzo_2010]. In the neighborhood around every vertex, a
best-fit quadric is found and principal curvature values and directions are
analytically computed on this quadric ([Example
203](203_curvatureDirections/main.cpp)).
203]({{ repo_url }}/tutorial/203_curvatureDirections/main.cpp)).
![The `CurvatureDirections` example computes principal curvatures via quadric fitting and visualizes mean curvature in pseudocolor and principal directions with a cross field.](images/fertility-principal-curvature.jpg)
Expand Down Expand Up @@ -166,7 +166,7 @@ where $\mathbf{f}$ is $n\times 1$ and $\mathbf{G}$ is an $md\times n$ sparse
matrix. This matrix $\mathbf{G}$ can be derived geometrically, e.g.
ch. 2[^jacobson_thesis_2013].
Libigl's `grad` function computes $\mathbf{G}$ for
triangle and tetrahedral meshes ([Example 204](204_Gradient/main.cpp)):
triangle and tetrahedral meshes ([Example 204]({{ repo_url }}/tutorial/204_Gradient/main.cpp)):
![The `Gradient` example computes gradients of an input function on a mesh and visualizes the vector field.](images/cheburashka-gradient.jpg)
Expand Down Expand Up @@ -239,7 +239,7 @@ book" FEM construction which involves many (small) matrix inversions, cf.
[^sharf_2007].

The operator applied to mesh vertex positions amounts to smoothing by _flowing_
the surface along the mean curvature normal direction ([Example 205](205_Laplacian/main.cpp)). Note that this is equivalent to minimizing surface area.
the surface along the mean curvature normal direction ([Example 205]({{ repo_url }}/tutorial/205_Laplacian/main.cpp)). Note that this is equivalent to minimizing surface area.

![The `Laplacian` example computes conformalized mean curvature flow using the cotangent Laplacian [^kazhdan_2012].](images/cow-curvature-flow.jpg)

Expand Down Expand Up @@ -305,7 +305,7 @@ Eigen::VectorXd d;
igl::exact_geodesic(V,F,VS,FS,VT,FT,d);
```

![[Example 206](206_GeodesicDistance/main.cpp) allows to interactively pick the source vertex and displays the distance using a periodic color pattern.](images/geodesicdistance.jpg)
![[Example 206]({{ repo_url }}/tutorial/206_GeodesicDistance/main.cpp) allows to interactively pick the source vertex and displays the distance using a periodic color pattern.](images/geodesicdistance.jpg)

## References

Expand Down
14 changes: 7 additions & 7 deletions docs/tutorial/chapter-3.md
Expand Up @@ -17,7 +17,7 @@ If `A` is a $m \times n$ matrix and `R` is a $j$-long list of row-indices
(between 1 and $m$) and `C` is a $k$-long list of column-indices, then as a
result `B` will be a $j \times k$ matrix drawing elements from `A` according to
`R` and `C`. In libigl, the same functionality is provided by the `slice`
function ([Example 301](301_Slice/main.cpp)):
function ([Example 301]({{ repo_url }}/tutorial/301_Slice/main.cpp)):

```cpp
VectorXi R,C;
Expand Down Expand Up @@ -82,7 +82,7 @@ where again `I` reveals the index of sort so that it can be reproduced with
Analogous functions are available in libigl for: `max`, `min`, and `unique`.
![The example `Sort` shows how to use `igl::sortrows` to pseudocolor triangles according to their barycenters' sorted order ([Example 302](302_Sort/main.cpp)).](images/decimated-knight-sort-color.jpg)
![The example `Sort` shows how to use `igl::sortrows` to pseudocolor triangles according to their barycenters' sorted order ([Example 302]({{ repo_url }}/tutorial/302_Sort/main.cpp)).](images/decimated-knight-sort-color.jpg)
### Other Matlab-style functions
Expand Down Expand Up @@ -202,7 +202,7 @@ this solution is not very general.
With array slicing no explicit sort is needed. Instead we can _slice-out_
submatrix blocks ($\mathbf{L}_{in,in}$, $\mathbf{L}_{in,b}$, etc.) and follow
the linear algebra above directly. Then we can slice the solution _into_ the
rows of `Z` corresponding to the interior vertices ([Example 303](303_LaplaceEquation/main.cpp)).
rows of `Z` corresponding to the interior vertices ([Example 303]({{ repo_url }}/tutorial/303_LaplaceEquation/main.cpp)).
![The `LaplaceEquation` example solves a Laplace equation with Dirichlet boundary conditions.](images/camelhead-laplace-equation.jpg)
Expand Down Expand Up @@ -351,7 +351,7 @@ difference from the straight quadratic _minimization_ system, is that this
saddle problem system will not be positive definite. Thus, we must use a
different factorization technique (LDLT rather than LLT): libigl's
`min_quad_with_fixed_precompute` automatically chooses the correct solver in
the presence of linear equality constraints ([Example 304](304_LinearEqualityConstraints/main.cpp)).
the presence of linear equality constraints ([Example 304]({{ repo_url }}/tutorial/304_LinearEqualityConstraints/main.cpp)).
![The example `LinearEqualityConstraints` 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).](images/cheburashka-biharmonic-leq.jpg)
Expand Down Expand Up @@ -397,7 +397,7 @@ igl::active_set_params as;
igl::active_set(Q,B,b,bc,Aeq,Beq,Aieq,Bieq,lx,ux,as,Z);
```

![ [Example 305](305_QuadraticProgramming/main.cpp) uses an active set solver to optimize discrete biharmonic kernels [^rustamov_2011] at multiple scales .](images/cheburashka-multiscale-biharmonic-kernels.jpg)
![ [Example 305]({{ repo_url }}/tutorial/305_QuadraticProgramming/main.cpp) uses an active set solver to optimize discrete biharmonic kernels [^rustamov_2011] at multiple scales .](images/cheburashka-multiscale-biharmonic-kernels.jpg)

## Eigen Decomposition

Expand Down Expand Up @@ -440,7 +440,7 @@ slowly changing functions over the mesh (e.g. [^hildebrandt_2011]). Modal
analysis and model subspaces have been used frequently in real-time deformation
(e.g. [^barbic_2005]).

In [Example 306](306_EigenDecomposition/main.cpp)), the first 5 eigen vectors
In [Example 306]({{ repo_url }}/tutorial/306_EigenDecomposition/main.cpp)), the first 5 eigen vectors
of the discrete Laplace-Beltrami operator are computed and displayed in
pseudo-color atop the beetle. Eigen vectors are computed using `igl::eigs`
(mirroring MATLAB's `eigs`). The 5 eigen vectors are placed into the columns
Expand All @@ -455,7 +455,7 @@ Eigen::VectorXd S;
igl::eigs(L,M,5,igl::EIGS_TYPE_SM,U,S);
```
![([Example 306](306_EigenDecomposition/main.cpp)) Low frequency eigen vectors of the discrete Laplace-Beltrami operator vary smoothly and slowly over the _Beetle_.](images/beetle-eigen-decomposition.gif)
![([Example 306]({{ repo_url }}/tutorial/306_EigenDecomposition/main.cpp)) Low frequency eigen vectors of the discrete Laplace-Beltrami operator vary smoothly and slowly over the _Beetle_.](images/beetle-eigen-decomposition.gif)
## References
Expand Down
14 changes: 7 additions & 7 deletions docs/tutorial/chapter-4.md
Expand Up @@ -91,7 +91,7 @@ igl::harmonic(V,F,b,D_bc,2,D);
U = V+D;
```

![The [BiharmonicDeformation](401_BiharmonicDeformation/main.cpp) example deforms a statue's head as a _biharmonic surface_ (top) and using a _biharmonic displacements_ (bottom).](images/max-biharmonic.jpg)
![The [BiharmonicDeformation]({{ repo_url }}/tutorial/401_BiharmonicDeformation/main.cpp) example deforms a statue's head as a _biharmonic surface_ (top) and using a _biharmonic displacements_ (bottom).](images/max-biharmonic.jpg)

#### Relationship to "differential coordinates" and Laplacian surface editing
Biharmonic functions (whether positions or displacements) are solutions to the
Expand Down Expand Up @@ -130,7 +130,7 @@ int k = 2;// or 1,3,4,...
igl::harmonic(V,F,b,bc,k,Z);
```
![The [PolyharmonicDeformation](402_PolyharmonicDeformation/main.cpp) example deforms a flat domain (left) into a bump as a solution to various $k$-harmonic PDEs.](images/bump-k-harmonic.jpg)
![The [PolyharmonicDeformation]({{ repo_url }}/tutorial/402_PolyharmonicDeformation/main.cpp) 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
In computer animation, shape deformation is often referred to as "skinning".
Expand Down Expand Up @@ -191,7 +191,7 @@ parition of unity and encourage sparsity:
This is a quadratic programming problem and libigl solves it using its active
set solver or by calling out to [Mosek](http://www.mosek.com).
![The example [BoundedBiharmonicWeights](403_BoundedBiharmonicWeights/main.cpp) computes weights for a tetrahedral mesh given a skeleton (top) and then animates a linear blend skinning deformation (bottom).](images/hand-bbw.jpg)
![The example [BoundedBiharmonicWeights]({{ repo_url }}/tutorial/403_BoundedBiharmonicWeights/main.cpp) computes weights for a tetrahedral mesh given a skeleton (top) and then animates a linear blend skinning deformation (bottom).](images/hand-bbw.jpg)
## Dual quaternion skinning
Even with high quality weights, linear blend skinning is limited. In
Expand Down Expand Up @@ -237,7 +237,7 @@ internally converts to the dual quaternion representation before blending:
igl::dqs(V,W,vQ,vT,U);
```

![The example [DualQuaternionSkinning](404_DualQuaternionSkinning/main.cpp) compares linear blend skinning (top) to dual quaternion skinning (bottom), highlighting LBS's candy wrapper effect (middle) and joint collapse (right).](images/arm-dqs.jpg)
![The example [DualQuaternionSkinning]({{ repo_url }}/tutorial/404_DualQuaternionSkinning/main.cpp) compares linear blend skinning (top) to dual quaternion skinning (bottom), highlighting LBS's candy wrapper effect (middle) and joint collapse (right).](images/arm-dqs.jpg)

## As-rigid-as-possible

Expand Down Expand Up @@ -340,7 +340,7 @@ Libigl's implementation of as-rigid-as-possible deformation takes advantage of
the highly optimized singular value decomposition code from McAdams et al.
[^mcadams_2011] which leverages SSE intrinsics.

![The example [AsRigidAsPossible](405_AsRigidAsPossible/main.cpp) deforms a surface as if it were made of an elastic material](images/decimated-knight-arap.jpg)
![The example [AsRigidAsPossible]({{ repo_url }}/tutorial/405_AsRigidAsPossible/main.cpp) deforms a surface as if it were made of an elastic material](images/decimated-knight-arap.jpg)

The concept of local rigidity will be revisited shortly in the context of
surface parameterization.
Expand Down Expand Up @@ -447,7 +447,7 @@ biharmonic distance embedding.
In this light, we can think of the "spokes+rims" style surface ARAP as a (slight and
redundant) clustering of the per-triangle edge-sets.

![The example [FastAutomaticSkinningTransformations](406_FastAutomaticSkinningTransformations/main.cpp) 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).](images/armadillo-fast.jpg)
![The example [FastAutomaticSkinningTransformations]({{ repo_url }}/tutorial/406_FastAutomaticSkinningTransformations/main.cpp) 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).](images/armadillo-fast.jpg)

## Biharmonic Coordinates

Expand Down Expand Up @@ -528,7 +528,7 @@ handles):
igl::biharmonic_coordinates(V,F,S,W);
```
![([Example 407](407_BiharmonicCoordinates/main.cpp)) shows a physics simulation on a coarse orange mesh. The vertices of this mesh become control points for a biharmonic coordinates deformation of the blue high-resolution mesh.](images/octopus-biharmonic-coordinates-physics.gif)
![([Example 407]({{ repo_url }}/tutorial/407_BiharmonicCoordinates/main.cpp)) shows a physics simulation on a coarse orange mesh. The vertices of this mesh become control points for a biharmonic coordinates deformation of the blue high-resolution mesh.](images/octopus-biharmonic-coordinates-physics.gif)
## References
Expand Down

0 comments on commit 27817f4

Please sign in to comment.