Browse Source

Merge branch 'master-upstream' into python_bindings

Former-commit-id: 91cc5589430a42eba3f68b7c7d570893b14b9fb6
Sebastian Koch 9 years ago
parent
commit
0c75d16a38
100 changed files with 1702 additions and 462 deletions
  1. 2 2
      README.md
  2. 18 21
      include/igl/AABB.cpp
  3. 19 18
      include/igl/AABB.h
  4. 19 32
      include/igl/ambient_occlusion.cpp
  5. 107 0
      include/igl/cat.cpp
  6. 10 1
      include/igl/copyleft/cgal/half_space_box.cpp
  7. 40 7
      include/igl/copyleft/cgal/intersect_with_half_space.cpp
  8. 28 3
      include/igl/copyleft/cgal/intersect_with_half_space.h
  9. 1 0
      include/igl/copyleft/cgal/propagate_winding_numbers.cpp
  10. 1 1
      include/igl/copyleft/cgal/string_to_mesh_boolean_type.cpp
  11. 49 0
      include/igl/copyleft/swept_volume.cpp
  12. 41 0
      include/igl/copyleft/swept_volume.h
  13. 16 22
      include/igl/doublearea.cpp
  14. 22 21
      include/igl/edge_lengths.cpp
  15. 2 1
      include/igl/fit_rotations.cpp
  16. 81 0
      include/igl/flood_fill.cpp
  17. 23 0
      include/igl/flood_fill.h
  18. 23 0
      include/igl/grid.cpp
  19. 20 0
      include/igl/grid.h
  20. 13 21
      include/igl/internal_angles.cpp
  21. 10 0
      include/igl/list_to_matrix.cpp
  22. 180 0
      include/igl/parallel_for.h
  23. 23 11
      include/igl/per_vertex_normals.cpp
  24. 47 0
      include/igl/png/readPNG.cpp
  25. 39 0
      include/igl/png/readPNG.h
  26. 46 0
      include/igl/png/writePNG.cpp
  27. 41 0
      include/igl/png/writePNG.h
  28. 2 0
      include/igl/project_to_line.cpp
  29. 2 0
      include/igl/project_to_line_segment.cpp
  30. 27 26
      include/igl/repdiag.cpp
  31. 1 1
      include/igl/slice_mask.cpp
  32. 69 82
      include/igl/sort.cpp
  33. 20 0
      include/igl/swept_volume_bounding_box.cpp
  34. 31 0
      include/igl/swept_volume_bounding_box.h
  35. 113 0
      include/igl/swept_volume_signed_distance.cpp
  36. 57 0
      include/igl/swept_volume_signed_distance.h
  37. 27 21
      include/igl/triangle_triangle_adjacency.cpp
  38. 5 3
      include/igl/uniformly_sample_two_manifold.h
  39. 5 0
      include/igl/unique.cpp
  40. 5 0
      include/igl/unique_edge_map.cpp
  41. 6 12
      include/igl/unique_simplices.cpp
  42. 2 0
      include/igl/upsample.cpp
  43. 1 1
      include/igl/viewer/Viewer.cpp
  44. 5 3
      include/igl/viewer/ViewerData.cpp
  45. 4 1
      include/igl/viewer/ViewerData.h
  46. 51 0
      include/igl/voxel_grid.cpp
  47. 28 0
      include/igl/voxel_grid.h
  48. 2 0
      include/igl/writeMESH.cpp
  49. 2 0
      include/igl/writeSTL.cpp
  50. 2 0
      include/igl/writeWRL.cpp
  51. 2 0
      include/igl/write_triangle_mesh.cpp
  52. 2 1
      index.html
  53. 168 100
      shared/cmake/CMakeLists.txt
  54. 4 4
      style-guidelines.html
  55. 1 1
      tutorial/101_FileIO/CMakeLists.txt
  56. 1 1
      tutorial/102_DrawMesh/CMakeLists.txt
  57. 1 1
      tutorial/103_Events/CMakeLists.txt
  58. 1 1
      tutorial/104_Colors/CMakeLists.txt
  59. 1 1
      tutorial/105_Overlays/CMakeLists.txt
  60. 1 1
      tutorial/106_ViewerMenu/CMakeLists.txt
  61. 1 1
      tutorial/201_Normals/CMakeLists.txt
  62. 1 1
      tutorial/202_GaussianCurvature/CMakeLists.txt
  63. 1 1
      tutorial/203_CurvatureDirections/CMakeLists.txt
  64. 1 1
      tutorial/204_Gradient/CMakeLists.txt
  65. 1 1
      tutorial/205_Laplacian/CMakeLists.txt
  66. 1 1
      tutorial/301_Slice/CMakeLists.txt
  67. 1 1
      tutorial/302_Sort/CMakeLists.txt
  68. 1 1
      tutorial/303_LaplaceEquation/CMakeLists.txt
  69. 1 1
      tutorial/304_LinearEqualityConstraints/CMakeLists.txt
  70. 1 1
      tutorial/305_QuadraticProgramming/CMakeLists.txt
  71. 1 1
      tutorial/306_EigenDecomposition/CMakeLists.txt
  72. 1 1
      tutorial/401_BiharmonicDeformation/CMakeLists.txt
  73. 1 1
      tutorial/402_PolyharmonicDeformation/CMakeLists.txt
  74. 4 1
      tutorial/403_BoundedBiharmonicWeights/CMakeLists.txt
  75. 1 1
      tutorial/404_DualQuaternionSkinning/CMakeLists.txt
  76. 1 1
      tutorial/405_AsRigidAsPossible/CMakeLists.txt
  77. 1 1
      tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt
  78. 1 1
      tutorial/407_BiharmonicCoordinates/CMakeLists.txt
  79. 1 1
      tutorial/501_HarmonicParam/CMakeLists.txt
  80. 1 1
      tutorial/502_LSCMParam/CMakeLists.txt
  81. 1 1
      tutorial/503_ARAPParam/CMakeLists.txt
  82. 1 1
      tutorial/504_NRosyDesign/CMakeLists.txt
  83. 1 1
      tutorial/505_MIQ/CMakeLists.txt
  84. 1 1
      tutorial/505_MIQ/main.cpp
  85. 1 1
      tutorial/506_FrameField/CMakeLists.txt
  86. 1 1
      tutorial/507_PolyVectorField/CMakeLists.txt
  87. 1 1
      tutorial/508_ConjugateField/CMakeLists.txt
  88. 1 1
      tutorial/509_Planarization/CMakeLists.txt
  89. 1 1
      tutorial/510_Integrable/CMakeLists.txt
  90. 1 1
      tutorial/601_Serialization/CMakeLists.txt
  91. 1 1
      tutorial/602_Matlab/CMakeLists.txt
  92. 1 1
      tutorial/604_Triangle/CMakeLists.txt
  93. 2 3
      tutorial/605_Tetgen/CMakeLists.txt
  94. 1 1
      tutorial/606_AmbientOcclusion/CMakeLists.txt
  95. 8 0
      tutorial/607_ScreenCapture/CMakeLists.txt
  96. 82 0
      tutorial/607_ScreenCapture/main.cpp
  97. 1 1
      tutorial/608_LIM/CMakeLists.txt
  98. 1 1
      tutorial/609_Boolean/CMakeLists.txt
  99. 1 1
      tutorial/610_CSGTree/CMakeLists.txt
  100. 1 1
      tutorial/701_Statistics/CMakeLists.txt

+ 2 - 2
README.md

@@ -23,8 +23,8 @@ It is **a header-only library**. You do not need to compile anything to use,
 just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
-stored in an n-by-3 matrix of vertex positions V and an m-by-3 matrix of
-triangle indices F.
+stored in an n-by-3 matrix of vertex positions `V` and an m-by-3 matrix of
+triangle indices `F`.
 
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 linked library, for faster compile times with your projects. This only effects

+ 18 - 21
include/igl/AABB.cpp

@@ -28,7 +28,7 @@
 
 template <typename DerivedV, int DIM>
   template <typename Derivedbb_mins, typename Derivedbb_maxs>
-inline void igl::AABB<DerivedV,DIM>::init(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::init(
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::MatrixXi & Ele, 
     const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
@@ -92,7 +92,7 @@ inline void igl::AABB<DerivedV,DIM>::init(
 }
 
   template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::init(
+void igl::AABB<DerivedV,DIM>::init(
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::MatrixXi & Ele)
 {
@@ -102,7 +102,7 @@ inline void igl::AABB<DerivedV,DIM>::init(
 }
 
   template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::init(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::init(
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::MatrixXi & Ele, 
     const Eigen::MatrixXi & SI,
@@ -201,14 +201,14 @@ inline void igl::AABB<DerivedV,DIM>::init(
 }
 
 template <typename DerivedV, int DIM>
-inline bool igl::AABB<DerivedV,DIM>::is_leaf() const
+IGL_INLINE bool igl::AABB<DerivedV,DIM>::is_leaf() const
 {
   return m_primitive != -1;
 }
 
 template <typename DerivedV, int DIM>
 template <typename Derivedq>
-inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
+IGL_INLINE std::vector<int> igl::AABB<DerivedV,DIM>::find(
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::MatrixXi & Ele, 
     const Eigen::PlainObjectBase<Derivedq> & q,
@@ -298,7 +298,7 @@ inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
 }
 
 template <typename DerivedV, int DIM>
-inline int igl::AABB<DerivedV,DIM>::subtree_size() const
+IGL_INLINE int igl::AABB<DerivedV,DIM>::subtree_size() const
 {
   // 1 for self
   int n = 1;
@@ -318,7 +318,7 @@ inline int igl::AABB<DerivedV,DIM>::subtree_size() const
 
 template <typename DerivedV, int DIM>
 template <typename Derivedbb_mins, typename Derivedbb_maxs>
-inline void igl::AABB<DerivedV,DIM>::serialize(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::serialize(
     Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
     Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
     Eigen::VectorXi & elements,
@@ -350,7 +350,7 @@ inline void igl::AABB<DerivedV,DIM>::serialize(
 }
 
 template <typename DerivedV, int DIM>
-inline typename igl::AABB<DerivedV,DIM>::Scalar 
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar 
 igl::AABB<DerivedV,DIM>::squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
@@ -363,7 +363,7 @@ igl::AABB<DerivedV,DIM>::squared_distance(
 
 
 template <typename DerivedV, int DIM>
-inline typename igl::AABB<DerivedV,DIM>::Scalar 
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar 
 igl::AABB<DerivedV,DIM>::squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
@@ -447,7 +447,7 @@ template <
   typename DerivedsqrD, 
   typename DerivedI, 
   typename DerivedC>
-inline void igl::AABB<DerivedV,DIM>::squared_distance(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
   const Eigen::PlainObjectBase<DerivedP> & P,
@@ -475,7 +475,7 @@ template <
   typename DerivedsqrD, 
   typename DerivedI, 
   typename DerivedC>
-inline void igl::AABB<DerivedV,DIM>::squared_distance(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
   const AABB<Derivedother_V,DIM> & other,
@@ -508,7 +508,7 @@ template <
   typename DerivedsqrD, 
   typename DerivedI, 
   typename DerivedC>
-inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
+IGL_INLINE typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
   const AABB<Derivedother_V,DIM> * other,
@@ -733,7 +733,7 @@ inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared
 }
 
 template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
   const RowVectorDIMS & p,
@@ -752,7 +752,7 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
 
 
 template <typename DerivedV, int DIM>
-inline void igl::AABB<DerivedV,DIM>::set_min(
+IGL_INLINE void igl::AABB<DerivedV,DIM>::set_min(
   const RowVectorDIMS & 
 #ifndef NDEBUG
   p
@@ -781,7 +781,7 @@ inline void igl::AABB<DerivedV,DIM>::set_min(
 
 
 template <typename DerivedV, int DIM>
-inline bool 
+IGL_INLINE bool 
 igl::AABB<DerivedV,DIM>::intersect_ray(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
@@ -816,7 +816,7 @@ igl::AABB<DerivedV,DIM>::intersect_ray(
 }
 
 template <typename DerivedV, int DIM>
-inline bool 
+IGL_INLINE bool 
 igl::AABB<DerivedV,DIM>::intersect_ray(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
@@ -871,7 +871,7 @@ igl::AABB<DerivedV,DIM>::intersect_ray(
 }
 
 template <typename DerivedV, int DIM>
-inline bool 
+IGL_INLINE bool 
 igl::AABB<DerivedV,DIM>::intersect_ray(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::MatrixXi & Ele, 
@@ -938,6 +938,7 @@ igl::AABB<DerivedV,DIM>::intersect_ray(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::init(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&);
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
@@ -946,8 +947,4 @@ template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_
 template double igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, 1, 2, 1, 1, 2> const&, int&, Eigen::Matrix<double, 1, 2, 1, 1, 2>&) const;
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 2>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
 template void igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3>::squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&) const;
-
-
 #endif
-
-

+ 19 - 18
include/igl/AABB.h

@@ -9,6 +9,7 @@
 #define IGL_AABB_H
 
 #include "Hit.h"
+#include "igl_inline.h"
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <vector>
@@ -81,7 +82,7 @@ public:
       }
       // Seems like there should have been an elegant solution to this using
       // the copy-swap idiom above:
-      inline void deinit()
+      IGL_INLINE void deinit()
       {
         m_primitive = -1;
         m_box = Eigen::AlignedBox<Scalar,DIM>();
@@ -105,7 +106,7 @@ public:
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   i  recursive call index {0}
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
-        inline void init(
+        IGL_INLINE void init(
             const Eigen::PlainObjectBase<DerivedV> & V,
             const Eigen::MatrixXi & Ele, 
             const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
@@ -113,7 +114,7 @@ public:
             const Eigen::VectorXi & elements,
             const int i = 0);
       // Wrapper for root with empty serialization
-      inline void init(
+      IGL_INLINE void init(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele);
       // Build an Axis-Aligned Bounding Box tree for a given mesh.
@@ -128,13 +129,13 @@ public:
       //   I  #I list of indices into Ele of elements to include (for recursive
       //     calls)
       // 
-      inline void init(
+      IGL_INLINE void init(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele, 
           const Eigen::MatrixXi & SI,
           const Eigen::VectorXi & I);
       // Return whether at leaf node
-      inline bool is_leaf() const;
+      IGL_INLINE bool is_leaf() const;
       // Find the indices of elements containing given point: this makes sense
       // when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
       //
@@ -148,7 +149,7 @@ public:
       // Returns:
       //   list of indices of elements containing q
       template <typename Derivedq>
-      inline std::vector<int> find(
+      IGL_INLINE std::vector<int> find(
           const Eigen::PlainObjectBase<DerivedV> & V,
           const Eigen::MatrixXi & Ele, 
           const Eigen::PlainObjectBase<Derivedq> & q,
@@ -156,7 +157,7 @@ public:
 
       // If number of elements m then total tree size should be 2*h where h is
       // the deepest depth 2^ceil(log(#Ele*2-1))
-      inline int subtree_size() const;
+      IGL_INLINE int subtree_size() const;
 
       // Serialize this class into 3 arrays (so we can pass it pack to matlab)
       //
@@ -166,7 +167,7 @@ public:
       //   elements  max_tree list of element or (not leaf id) indices into Ele
       //   i  recursive call index into these arrays {0}
       template <typename Derivedbb_mins, typename Derivedbb_maxs>
-        inline void serialize(
+        IGL_INLINE void serialize(
             Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
             Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
             Eigen::VectorXi & elements,
@@ -186,14 +187,14 @@ public:
       //
       // Known bugs: currently assumes Elements are triangles regardless of
       // dimension.
-      inline Scalar squared_distance(
+      IGL_INLINE Scalar squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
         int & i,
         RowVectorDIMS & c) const;
 //private:
-      inline Scalar squared_distance(
+      IGL_INLINE Scalar squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
@@ -201,21 +202,21 @@ public:
         int & i,
         RowVectorDIMS & c) const;
       // All hits
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
         const RowVectorDIMS & dir,
         std::vector<igl::Hit> & hits) const;
       // First hit
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
         const RowVectorDIMS & dir,
         igl::Hit & hit) const;
 //private:
-      inline bool intersect_ray(
+      IGL_INLINE bool intersect_ray(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & origin,
@@ -230,7 +231,7 @@ public:
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedC>
-      inline void squared_distance(
+      IGL_INLINE void squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const Eigen::PlainObjectBase<DerivedP> & P,
@@ -243,7 +244,7 @@ public:
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedC>
-      inline void squared_distance(
+      IGL_INLINE void squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const AABB<Derivedother_V,DIM> & other,
@@ -258,7 +259,7 @@ private:
         typename DerivedsqrD, 
         typename DerivedI, 
         typename DerivedC>
-      inline Scalar squared_distance_helper(
+      IGL_INLINE Scalar squared_distance_helper(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const AABB<Derivedother_V,DIM> * other,
@@ -269,14 +270,14 @@ private:
         Eigen::PlainObjectBase<DerivedI> & I,
         Eigen::PlainObjectBase<DerivedC> & C) const;
       // Helper function for leaves: works in-place on sqr_d
-      inline void leaf_squared_distance(
+      IGL_INLINE void leaf_squared_distance(
         const Eigen::PlainObjectBase<DerivedV> & V,
         const Eigen::MatrixXi & Ele, 
         const RowVectorDIMS & p,
         Scalar & sqr_d,
         int & i,
         RowVectorDIMS & c) const;
-      inline void set_min(
+      IGL_INLINE void set_min(
         const RowVectorDIMS & p,
         const Scalar sqr_d_candidate,
         const int i_candidate,

+ 19 - 32
include/igl/ambient_occlusion.cpp

@@ -10,7 +10,7 @@
 #include "ray_mesh_intersect.h"
 #include "EPS.h"
 #include "Hit.h"
-#include <thread>
+#include "parallel_for.h"
 #include <functional>
 #include <vector>
 #include <algorithm>
@@ -38,40 +38,27 @@ IGL_INLINE void igl::ambient_occlusion(
   // Embree seems to be parallel when constructing but not when tracing rays
   const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
 
-  const size_t nthreads = n<1000?1:std::thread::hardware_concurrency();
+  const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
   {
-    std::vector<std::thread> threads(nthreads);
-    for(int t = 0;t<nthreads;t++)
+    const Vector3f origin = P.row(p).template cast<float>();
+    const Vector3f normal = N.row(p).template cast<float>();
+    int num_hits = 0;
+    for(int s = 0;s<num_samples;s++)
     {
-      threads[t] = std::thread(std::bind(
-        [&P,&N,&shoot_ray,&S,&num_samples,&D](const int bi, const int ei, const int t)
-        {
-          // loop over mesh vertices in this chunk
-          for(int p = bi;p<ei;p++)
-          {
-            const Vector3f origin = P.row(p).template cast<float>();
-            const Vector3f normal = N.row(p).template cast<float>();
-            int num_hits = 0;
-            for(int s = 0;s<num_samples;s++)
-            {
-              Vector3f d = D.row(s);
-              if(d.dot(normal) < 0)
-              {
-                // reverse ray
-                d *= -1;
-              }
-              if(shoot_ray(origin,d))
-              {
-                num_hits++;
-              }
-            }
-            S(p) = (double)num_hits/(double)num_samples;
-          }
-        },t*n/nthreads,(t+1)==nthreads?n:(t+1)*n/nthreads,t));
+      Vector3f d = D.row(s);
+      if(d.dot(normal) < 0)
+      {
+        // reverse ray
+        d *= -1;
+      }
+      if(shoot_ray(origin,d))
+      {
+        num_hits++;
+      }
     }
-    std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
-  }
-
+    S(p) = (double)num_hits/(double)num_samples;
+  };
+  parallel_for(n,inner,1000);
 }
 
 template <

+ 107 - 0
include/igl/cat.cpp

@@ -6,12 +6,14 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "cat.h"
+
 #include <cstdio>
 
 // Bug in unsupported/Eigen/SparseExtra needs iostream first
 #include <iostream>
 #include <unsupported/Eigen/SparseExtra>
 
+
 // Sparse matrices need to be handled carefully. Because C++ does not 
 // Template:
 //   Scalar  sparse matrix scalar type, e.g. double
@@ -22,6 +24,7 @@ IGL_INLINE void igl::cat(
     const Eigen::SparseMatrix<Scalar> & B, 
     Eigen::SparseMatrix<Scalar> & C)
 {
+
   assert(dim == 1 || dim == 2);
   using namespace Eigen;
   // Special case if B or A is empty
@@ -36,6 +39,7 @@ IGL_INLINE void igl::cat(
     return;
   }
 
+#if false
   // This **must** be DynamicSparseMatrix, otherwise this implementation is
   // insanely slow
   DynamicSparseMatrix<Scalar, RowMajor> dyn_C;
@@ -77,6 +81,109 @@ IGL_INLINE void igl::cat(
   }
 
   C = SparseMatrix<Scalar>(dyn_C);
+#elif false
+  std::vector<Triplet<Scalar> > CIJV;
+  CIJV.reserve(A.nonZeros() + B.nonZeros());
+  {
+    // Iterate over outside of A
+    for(int k=0; k<A.outerSize(); ++k)
+    {
+      // Iterate over inside
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        CIJV.emplace_back(it.row(),it.col(),it.value());
+      }
+    }
+    // Iterate over outside of B
+    for(int k=0; k<B.outerSize(); ++k)
+    {
+      // Iterate over inside
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        int r = (dim == 1 ? A.rows()+it.row() : it.row());
+        int c = (dim == 2 ? A.cols()+it.col() : it.col());
+        CIJV.emplace_back(r,c,it.value());
+      }
+    }
+
+  }
+
+  C = SparseMatrix<Scalar>( 
+      dim == 1 ? A.rows()+B.rows() : A.rows(),
+      dim == 1 ? A.cols()          : A.cols()+B.cols());
+  C.reserve(A.nonZeros() + B.nonZeros());
+  C.setFromTriplets(CIJV.begin(),CIJV.end());
+#else
+  C = SparseMatrix<Scalar>( 
+      dim == 1 ? A.rows()+B.rows() : A.rows(),
+      dim == 1 ? A.cols()          : A.cols()+B.cols());
+  Eigen::VectorXi per_col = Eigen::VectorXi::Zero(C.cols());
+  if(dim == 1)
+  {
+    assert(A.outerSize() == B.outerSize());
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+    }
+  }else
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        per_col(k)++;
+      }
+    }
+    for(int k = 0;k<B.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        per_col(A.cols() + k)++;
+      }
+    }
+  }
+  C.reserve(per_col);
+  if(dim == 1)
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        C.insert(it.row(),k) = it.value();
+      }
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        C.insert(A.rows()+it.row(),k) = it.value();
+      }
+    }
+  }else
+  {
+    for(int k = 0;k<A.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (A,k); it; ++it)
+      {
+        C.insert(it.row(),k) = it.value();
+      }
+    }
+    for(int k = 0;k<B.outerSize();++k)
+    {
+      for(typename SparseMatrix<Scalar>::InnerIterator it (B,k); it; ++it)
+      {
+        C.insert(it.row(),A.cols()+k) = it.value();
+      }
+    }
+  }
+  C.makeCompressed();
+
+#endif
+
 }
 
 template <typename Derived, class MatC>

+ 10 - 1
include/igl/copyleft/cgal/half_space_box.cpp

@@ -14,7 +14,10 @@ IGL_INLINE void igl::copyleft::cgal::half_space_box(
   typedef CGAL::Point_3<CGAL::Epeck> Point;
   typedef CGAL::Vector_3<CGAL::Epeck> Vector;
   typedef CGAL::Epeck::FT EScalar;
-  Eigen::RowVector3d avg = V.colwise().mean();
+  Eigen::Matrix<typename DerivedV::Scalar,1,3> avg(0,0,0);
+  for(int v = 0;v<V.rows();v++) for(int c = 0;c<V.cols();c++) avg(c) += V(v,c);
+  avg /= V.rows();
+
   Point o3(avg(0),avg(1),avg(2));
   Point o2 = P.projection(o3);
   Vector u;
@@ -109,5 +112,11 @@ IGL_INLINE void igl::copyleft::cgal::half_space_box(
 }
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
+// generated by autoexplicit.sh
+template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
 template void igl::copyleft::cgal::half_space_box<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 8, 3, 0, 8, 3>&, Eigen::Matrix<int, 12, 3, 0, 12, 3>&);
 #endif

+ 40 - 7
include/igl/copyleft/cgal/intersect_with_half_space.cpp

@@ -19,11 +19,11 @@ IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedJ > & J)
 {
-  Eigen::Matrix<CGAL::Epeck::FT,8,3> BV;
-  Eigen::Matrix<int,12,3> BF;
-  half_space_box(p,n,V,BV,BF);
-  // Disturbingly, (BV,BF) must be first argument
-  return mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  typedef CGAL::Plane_3<CGAL::Epeck> Plane;
+  typedef CGAL::Point_3<CGAL::Epeck> Point;
+  typedef CGAL::Vector_3<CGAL::Epeck> Vector;
+  Plane P(Point(p(0),p(1),p(2)),Vector(n(0),n(1),n(2)));
+  return intersect_with_half_space(V,F,P,VC,FC,J);
 }
 
 template <
@@ -40,15 +40,48 @@ IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
   Eigen::PlainObjectBase<DerivedVC > & VC,
   Eigen::PlainObjectBase<DerivedFC > & FC,
   Eigen::PlainObjectBase<DerivedJ > & J)
+{
+  typedef CGAL::Plane_3<CGAL::Epeck> Plane;
+  Plane P(equ(0),equ(1),equ(2),equ(3));
+  return intersect_with_half_space(V,F,P,VC,FC,J);
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVC,
+  typename DerivedFC,
+  typename DerivedJ>
+IGL_INLINE bool igl::copyleft::cgal::intersect_with_half_space(
+  const Eigen::PlainObjectBase<DerivedV > & V,
+  const Eigen::PlainObjectBase<DerivedF > & F,
+  const CGAL::Plane_3<CGAL::Epeck> & P,
+  Eigen::PlainObjectBase<DerivedVC > & VC,
+  Eigen::PlainObjectBase<DerivedFC > & FC,
+  Eigen::PlainObjectBase<DerivedJ > & J)
 {
   Eigen::Matrix<CGAL::Epeck::FT,8,3> BV;
   Eigen::Matrix<int,12,3> BF;
-  half_space_box(equ,V,BV,BF);
+  half_space_box(P,V,BV,BF);
   // Disturbingly, (BV,BF) must be first argument
-  return mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  const bool ret = mesh_boolean(BV,BF,V,F,MESH_BOOLEAN_TYPE_INTERSECT,VC,FC,J);
+  // But now J is wrong...
+  std::for_each(
+    J.data(),
+    J.data()+J.size(),
+    [&BF,&F](typename DerivedJ::Scalar & j)
+      {j = (j<BF.rows()?F.rows()+j:j-BF.rows());}
+    );
+  return ret;
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, 1, 4, 1, 1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::copyleft::cgal::intersect_with_half_space<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 28 - 3
include/igl/copyleft/cgal/intersect_with_half_space.h

@@ -2,6 +2,8 @@
 #define IGL_COPYLEFT_CGAL_INTERSECT_WITH_HALF_SPACE_H
 #include "../../igl_inline.h"
 #include <Eigen/Core>
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Plane_3.h>
 
 namespace igl
 {
@@ -19,7 +21,8 @@ namespace igl
       // Outputs:
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   FC  #FC by 3 list of triangle indices into VC
-      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth" facet
+      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth"
+      //     facet
       template <
         typename DerivedV,
         typename DerivedF,
@@ -36,12 +39,12 @@ namespace igl
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedJ > & J);
-
       // Intersect a PWN mesh with a half-space. Plane equation.
       //
       // Inputs:
       //   V  #V by 3 list of mesh vertex positions
-      //   equ  plane equation: a*x+b*y+c*z + d = 0
+      //   equ  plane equation: P(x,y,z) = a*x+b*y+c*z + d = 0, P(x,y,z) < 0 is
+      //     _inside_.
       // Outputs:
       //   VC  #VC by 3 list of vertex positions of boolean result mesh
       //   FC  #FC by 3 list of triangle indices into VC
@@ -60,6 +63,28 @@ namespace igl
         Eigen::PlainObjectBase<DerivedVC > & VC,
         Eigen::PlainObjectBase<DerivedFC > & FC,
         Eigen::PlainObjectBase<DerivedJ > & J);
+      // Intersect a PWN mesh with a half-space. CGAL Plane.
+      //
+      // Inputs:
+      //   V  #V by 3 list of mesh vertex positions
+      //   P  plane 
+      // Outputs:
+      //   VC  #VC by 3 list of vertex positions of boolean result mesh
+      //   FC  #FC by 3 list of triangle indices into VC
+      //   J  #FC list of indices into [F;F.rows()+[1;2]] revealing "birth" facet
+      template <
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedVC,
+        typename DerivedFC,
+        typename DerivedJ>
+      IGL_INLINE bool intersect_with_half_space(
+        const Eigen::PlainObjectBase<DerivedV > & V,
+        const Eigen::PlainObjectBase<DerivedF > & F,
+        const CGAL::Plane_3<CGAL::Epeck> & P,
+        Eigen::PlainObjectBase<DerivedVC > & VC,
+        Eigen::PlainObjectBase<DerivedFC > & FC,
+        Eigen::PlainObjectBase<DerivedJ > & J);
     }
   }
 }

+ 1 - 0
include/igl/copyleft/cgal/propagate_winding_numbers.cpp

@@ -119,6 +119,7 @@ IGL_INLINE bool igl::copyleft::cgal::propagate_winding_numbers(
   bool valid = true;
   if (!piecewise_constant_winding_number(F, uE, uE2E)) 
   {
+    assert(false && "Input mesh is not orientable");
     std::cerr << "Input mesh is not orientable!" << std::endl;
     valid = false;
   }

+ 1 - 1
include/igl/copyleft/cgal/string_to_mesh_boolean_type.cpp

@@ -1,4 +1,4 @@
-#include "string_to_mesh_boolean_type.h"
+#include "string_to_mesh_boolean_type.h"
 #include <algorithm>
 #include <cassert>
 #include <vector>

+ 49 - 0
include/igl/copyleft/swept_volume.cpp

@@ -0,0 +1,49 @@
+#include "swept_volume.h"
+#include "../swept_volume_bounding_box.h"
+#include "../swept_volume_signed_distance.h"
+#include "../voxel_grid.h"
+#include "marching_cubes.h"
+#include <iostream>
+
+IGL_INLINE void igl::copyleft::swept_volume(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t steps,
+  const size_t grid_res,
+  const size_t isolevel_grid,
+  Eigen::MatrixXd & SV,
+  Eigen::MatrixXi & SF)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  using namespace igl::copyleft;
+
+  const auto & Vtransform = 
+    [&V,&transform](const size_t vi,const double t)->RowVector3d
+  {
+    Vector3d Vvi = V.row(vi).transpose();
+    return (transform(t)*Vvi).transpose();
+  };
+  AlignedBox3d Mbox;
+  swept_volume_bounding_box(V.rows(),Vtransform,steps,Mbox);
+
+  // Amount of padding: pad*h should be >= isolevel
+  const int pad = isolevel_grid+1;
+  // number of vertices on the largest side
+  const int s = grid_res+2*pad;
+  const double h = Mbox.diagonal().maxCoeff()/(double)(s-2.*pad-1.);
+  const double isolevel = isolevel_grid*h;
+
+  // create grid
+  RowVector3i res;
+  MatrixXd GV;
+  voxel_grid(Mbox,s,pad,GV,res);
+
+  // compute values
+  VectorXd S;
+  swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S);
+  S.array()-=isolevel;
+  marching_cubes(S,GV,res(0),res(1),res(2),SV,SF);
+}

+ 41 - 0
include/igl/copyleft/swept_volume.h

@@ -0,0 +1,41 @@
+#ifndef IGL_COPYLEFT_SWEPT_VOLUME_H
+#define IGL_COPYLEFT_SWEPT_VOLUME_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+namespace igl
+{
+  namespace copyleft
+  {
+    // Compute the surface of the swept volume of a solid object with surface
+    // (V,F) mesh under going rigid motion.
+    // 
+    // Inputs:
+    //   V  #V by 3 list of mesh positions in reference pose
+    //   F  #F by 3 list of mesh indices into V
+    //   transform  function handle so that transform(t) returns the rigid
+    //     transformation at time t∈[0,1]
+    //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+    //   grid_res  number of grid cells on the longest side containing the
+    //     motion (isolevel+1 cells will also be added on each side as padding)
+    //   isolevel  distance level to be contoured as swept volume
+    // Outputs:
+    //   SV  #SV by 3 list of mesh positions of the swept surface
+    //   SF  #SF by 3 list of mesh faces into SV
+    IGL_INLINE void swept_volume(
+      const Eigen::MatrixXd & V,
+      const Eigen::MatrixXi & F,
+      const std::function<Eigen::Affine3d(const double t)> & transform,
+      const size_t steps,
+      const size_t grid_res,
+      const size_t isolevel,
+      Eigen::MatrixXd & SV,
+      Eigen::MatrixXi & SF);
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume.cpp"
+#endif
+
+#endif

+ 16 - 22
include/igl/doublearea.cpp

@@ -7,6 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "doublearea.h"
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include "sort.h"
 #include <cassert>
 #include <iostream>
@@ -148,28 +149,21 @@ IGL_INLINE void igl::doublearea(
   assert((Index)s.rows() == m);
   // resize output
   dblA.resize(l.rows(),1);
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(Index i = 0;i<m;i++)
-  {
-    //// Heron's formula for area
-    //const typename Derivedl::Scalar arg =
-    //  s(i)*(s(i)-l(i,0))*(s(i)-l(i,1))*(s(i)-l(i,2));
-    //assert(arg>=0);
-    //dblA(i) = 2.0*sqrt(arg);
-    // Kahan's Heron's formula
-    const typename Derivedl::Scalar arg =
-      (l(i,0)+(l(i,1)+l(i,2)))*
-      (l(i,2)-(l(i,0)-l(i,1)))*
-      (l(i,2)+(l(i,0)-l(i,1)))*
-      (l(i,0)+(l(i,1)-l(i,2)));
-    dblA(i) = 2.0*0.25*sqrt(arg);
-    assert( l(i,2) - (l(i,0)-l(i,1)) && "FAILED KAHAN'S ASSERTION");
-    assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
-  }
+  parallel_for(
+    m,
+    [&l,&dblA](const int i)
+    {
+      // Kahan's Heron's formula
+      const typename Derivedl::Scalar arg =
+        (l(i,0)+(l(i,1)+l(i,2)))*
+        (l(i,2)-(l(i,0)-l(i,1)))*
+        (l(i,2)+(l(i,0)-l(i,1)))*
+        (l(i,0)+(l(i,1)-l(i,2)));
+      dblA(i) = 2.0*0.25*sqrt(arg);
+      assert( l(i,2) - (l(i,0)-l(i,1)) && "FAILED KAHAN'S ASSERTION");
+      assert(dblA(i) == dblA(i) && "DOUBLEAREA() PRODUCED NaN");
+    },
+    1000l);
 }
 
 template <typename DerivedV, typename DerivedF, typename DeriveddblA>

+ 22 - 21
include/igl/edge_lengths.cpp

@@ -6,6 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include <iostream>
 
 template <typename DerivedV, typename DerivedF, typename DerivedL>
@@ -16,10 +17,6 @@ IGL_INLINE void igl::edge_lengths(
 {
   using namespace std;
   const int m = F.rows();
-  // Minimum number of iterms per openmp thread
-#ifndef IGL_OMP_MIN_VALUE
-#  define IGL_OMP_MIN_VALUE 1000
-#endif
   switch(F.cols())
   {
     case 2:
@@ -35,29 +32,33 @@ IGL_INLINE void igl::edge_lengths(
     {
       L.resize(m,3);
       // loop over faces
-      #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-      for(int i = 0;i<m;i++)
-      {
-        L(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
-        L(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
-        L(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
-      }
+      parallel_for(
+        m,
+        [&V,&F,&L](const int i)
+        {
+          L(i,0) = (V.row(F(i,1))-V.row(F(i,2))).norm();
+          L(i,1) = (V.row(F(i,2))-V.row(F(i,0))).norm();
+          L(i,2) = (V.row(F(i,0))-V.row(F(i,1))).norm();
+        },
+        1000);
       break;
     }
     case 4:
     {
       L.resize(m,6);
       // loop over faces
-      #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-      for(int i = 0;i<m;i++)
-      {
-        L(i,0) = (V.row(F(i,3))-V.row(F(i,0))).norm();
-        L(i,1) = (V.row(F(i,3))-V.row(F(i,1))).norm();
-        L(i,2) = (V.row(F(i,3))-V.row(F(i,2))).norm();
-        L(i,3) = (V.row(F(i,1))-V.row(F(i,2))).norm();
-        L(i,4) = (V.row(F(i,2))-V.row(F(i,0))).norm();
-        L(i,5) = (V.row(F(i,0))-V.row(F(i,1))).norm();
-      }
+      parallel_for(
+        m,
+        [&V,&F,&L](const int i)
+        {
+          L(i,0) = (V.row(F(i,3))-V.row(F(i,0))).norm();
+          L(i,1) = (V.row(F(i,3))-V.row(F(i,1))).norm();
+          L(i,2) = (V.row(F(i,3))-V.row(F(i,2))).norm();
+          L(i,3) = (V.row(F(i,1))-V.row(F(i,2))).norm();
+          L(i,4) = (V.row(F(i,2))-V.row(F(i,0))).norm();
+          L(i,5) = (V.row(F(i,0))-V.row(F(i,1))).norm();
+        },
+        1000);
       break;
     }
     default:

+ 2 - 1
include/igl/fit_rotations.cpp

@@ -71,7 +71,7 @@ IGL_INLINE void igl::fit_rotations_planar(
   using namespace std;
   const int dim = S.cols();
   const int nr = S.rows()/dim;
-  assert(dim == 2 && "_planar input should be 2D");
+  //assert(dim == 2 && "_planar input should be 2D");
   assert(nr * dim == S.rows());
 
   // resize output
@@ -105,6 +105,7 @@ IGL_INLINE void igl::fit_rotations_planar(
 #endif  
 
     // Not sure why polar_dec computes transpose...
+    R.block(0,r*dim,dim,dim).setIdentity();
     R.block(0,r*dim,2,2) = ri.transpose();
   }
 }

+ 81 - 0
include/igl/flood_fill.cpp

@@ -0,0 +1,81 @@
+#include "flood_fill.h"
+#include <limits>
+
+IGL_INLINE void igl::flood_fill(
+  const Eigen::RowVector3i & res,
+  Eigen::VectorXd & S)
+{
+  using namespace Eigen;
+  using namespace std;
+  const auto flood = [&res,&S] (
+     const int xi, 
+     const int yi, 
+     const int zi,
+     const int signed_xi, 
+     const int signed_yi, 
+     const int signed_zi,
+     const double s)
+    {
+      // flood fill this value back on this row
+      for(int bxi = xi;signed_xi<--bxi;)
+      {
+        S(bxi+res(0)*(yi + res(1)*zi)) = s;
+      }
+      // flood fill this value back on any previous rows
+      for(int byi = yi;signed_yi<--byi;)
+      {
+        for(int xi = 0;xi<res(0);xi++)
+        {
+          S(xi+res(0)*(byi + res(1)*zi)) = s;
+        }
+      }
+      // flood fill this value back on any previous "sheets"
+      for(int bzi = zi;signed_zi<--bzi;)
+      {
+        for(int yi = 0;yi<res(1);yi++)
+        {
+          for(int xi = 0;xi<res(0);xi++)
+          {
+            S(xi+res(0)*(yi + res(1)*bzi)) = s;
+          }
+        }
+      }
+    };
+  int signed_zi = -1;
+  double s = numeric_limits<double>::quiet_NaN();
+  for(int zi = 0;zi<res(2);zi++)
+  {
+    int signed_yi = -1;
+    if(zi != 0)
+    {
+      s = S(0+res(0)*(0 + res(1)*(zi-1)));
+    }
+    for(int yi = 0;yi<res(1);yi++)
+    {
+      // index of last signed item on this row
+      int signed_xi = -1;
+      if(yi != 0)
+      {
+        s = S(0+res(0)*(yi-1 + res(1)*zi));
+      }
+      for(int xi = 0;xi<res(0);xi++)
+      {
+        int i = xi+res(0)*(yi + res(1)*zi);
+        if(S(i)!=S(i))
+        {
+          if(s == s)
+          {
+            S(i) = s;
+          }
+          continue;
+        }
+        s = S(i);
+        flood(xi,yi,zi,signed_xi,signed_yi,signed_zi,s);
+        // remember this position
+        signed_xi = xi;
+        signed_yi = yi;
+        signed_zi = zi;
+      }
+    }
+  }
+}

+ 23 - 0
include/igl/flood_fill.h

@@ -0,0 +1,23 @@
+#ifndef IGL_FLOOD_FILL_H
+#define IGL_FLOOD_FILL_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Given a 3D array with sparse non-nan (number?) data fill in the NaNs via
+  // flood fill. This should ensure that, e.g., if data near 0 always has a band
+  // (surface) of numbered and signed data, then components of nans will be
+  // correctly signed.
+  //
+  // Inputs:
+  //   res  3-long list of dimensions of grid
+  //   S  res(0)*res(1)*res(2)  list of scalar values (with (many) nans), see
+  //     output
+  // Outputs:
+  //   S  flood fill data in place
+  IGL_INLINE void flood_fill(const Eigen::RowVector3i& res, Eigen::VectorXd& S);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "flood_fill.cpp"
+#endif
+#endif

+ 23 - 0
include/igl/grid.cpp

@@ -0,0 +1,23 @@
+#include "grid.h"
+
+IGL_INLINE void igl::grid(const Eigen::RowVector3i & res, Eigen::MatrixXd & GV)
+{
+  using namespace Eigen;
+  GV.resize(res(0)*res(1)*res(2),3);
+  for(int zi = 0;zi<res(2);zi++)
+  {
+    const auto lerp = 
+      [&](const double di, const int d)->double{return di/(double)(res(d)-1);};
+    const double z = lerp(zi,2);
+    for(int yi = 0;yi<res(1);yi++)
+    {
+      const double y = lerp(yi,1);
+      for(int xi = 0;xi<res(0);xi++)
+      {
+        const double x = lerp(xi,0);
+        GV.row(xi+res(0)*(yi + res(1)*zi)) = RowVector3d(x,y,z);
+      }
+    }
+  }
+}
+

+ 20 - 0
include/igl/grid.h

@@ -0,0 +1,20 @@
+#ifndef IGL_GRID_H
+#define IGL_GRID_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Construct vertices of a regular grid, suitable for input to
+  // `igl::marching_cubes`
+  //
+  // Inputs:
+  //   res  3-long list of number of vertices along the x y and z dimensions
+  // Outputs:
+  //   GV  res(0)*res(1)*res(2) by 3 list of mesh vertex positions.
+  //   
+  IGL_INLINE void grid(const Eigen::RowVector3i & res, Eigen::MatrixXd & GV);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "grid.cpp"
+#endif
+#endif 

+ 13 - 21
include/igl/internal_angles.cpp

@@ -8,6 +8,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "internal_angles.h"
 #include "edge_lengths.h"
+#include "parallel_for.h"
 #include "get_seconds.h"
 
 template <typename DerivedV, typename DerivedF, typename DerivedK>
@@ -70,28 +71,19 @@ IGL_INLINE void igl::internal_angles(
   assert(L.cols() == 3 && "Edge-lengths should come from triangles");
   const Index m = L.rows();
   K.resize(m,3);
-  //for(int d = 0;d<3;d++)
-  //{
-  //  const auto & s1 = L.col(d).array();
-  //  const auto & s2 = L.col((d+1)%3).array();
-  //  const auto & s3 = L.col((d+2)%3).array();
-  //  K.col(d) = ((s3.square() + s2.square() - s1.square())/(2.*s3*s2)).acos();
-  //}
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(Index f = 0;f<m;f++)
-  {
-    for(size_t d = 0;d<3;d++)
+  parallel_for(
+    m,
+    [&L,&K](const Index f)
     {
-      const auto & s1 = L(f,d);
-      const auto & s2 = L(f,(d+1)%3);
-      const auto & s3 = L(f,(d+2)%3);
-      K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
-    }
-  }
+      for(size_t d = 0;d<3;d++)
+      {
+        const auto & s1 = L(f,d);
+        const auto & s2 = L(f,(d+1)%3);
+        const auto & s3 = L(f,(d+2)%3);
+        K(f,d) = acos((s3*s3 + s2*s2 - s1*s1)/(2.*s3*s2));
+      }
+    },
+    1000l);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 10 - 0
include/igl/list_to_matrix.cpp

@@ -118,6 +118,16 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector<T > & V,Eigen::PlainObject
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<int, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 4, 1, 0, 4, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, 2, 1, 0, 2, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 1, 0, 2, 1> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 1, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);

+ 180 - 0
include/igl/parallel_for.h

@@ -0,0 +1,180 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_PARALLEL_FOR_H
+#define IGL_PARALLEL_FOR_H
+#include "igl_inline.h"
+#include <functional>
+
+namespace igl
+{
+  // PARALLEL_FOR Functional implementation of a basic, open-mp style, parallel
+  // for loop. If the inner block of a for-loop can be rewritten/encapsulated in
+  // a single (anonymous/lambda) function call `func` so that the serial code
+  // looks like:
+  // 
+  //     for(int i = 0;i<loop_size;i++)
+  //     {
+  //       func(i);
+  //     }
+  //
+  // then `parallel_for(loop_size,func,min_parallel)` will use as many threads as
+  // available on the current hardware to parallelize this for loop so long as
+  // loop_size<min_parallel, otherwise it will just use a serial for loop.
+  //
+  // Inputs:
+  //   loop_size  number of iterations. I.e. for(int i = 0;i<loop_size;i++) ...
+  //   func  function handle taking iteration index as only arguement to compute
+  //     inner block of for loop I.e. for(int i ...){ func(i); }
+  //   min_parallel  min size of loop_size such that parallel (non-serial)
+  //     thread pooling should be attempted {0}
+  // Returns true iff thread pool was invoked
+  template<typename Index, typename FunctionType >
+  inline bool parallel_for(
+    const Index loop_size, 
+    const FunctionType & func,
+    const size_t min_parallel=0);
+  // PARALLEL_FOR Functional implementation of an open-mp style, parallel for
+  // loop with accumulation. For example, serial code separated into n chunks
+  // (each to be parallelized with a thread) might look like:
+  //     
+  //     Eigen::VectorXd S;
+  //     const auto & prep_func = [&S](int n){ S = Eigen:VectorXd::Zero(n); };
+  //     const auto & func = [&X,&S](int i, int t){ S(t) += X(i); };
+  //     const auto & accum_func = [&S,&sum](int t){ sum += S(t); };
+  //     prep_func(n);
+  //     for(int i = 0;i<loop_size;i++)
+  //     {
+  //       func(i,i%n);
+  //     }
+  //     double sum = 0;
+  //     for(int t = 0;t<n;t++)
+  //     {
+  //       accum_func(t);
+  //     }
+  // 
+  // Inputs:
+  //   loop_size  number of iterations. I.e. for(int i = 0;i<loop_size;i++) ...
+  //   prep_func function handle taking n >= number of threads as only
+  //     argument 
+  //   func  function handle taking iteration index i and thread id t as only
+  //     arguements to compute inner block of for loop I.e. 
+  //     for(int i ...){ func(i,t); }
+  //   accum_func  function handle taking thread index as only argument, to be
+  //     called after all calls of func, e.g., for serial accumulation across
+  //     all n (potential) threads, see n in description of prep_func.
+  //   min_parallel  min size of loop_size such that parallel (non-serial)
+  //     thread pooling should be attempted {0}
+  // Returns true iff thread pool was invoked
+  template<
+    typename Index, 
+    typename PrepFunctionType, 
+    typename FunctionType, 
+    typename AccumFunctionType 
+    >
+  inline bool parallel_for(
+    const Index loop_size, 
+    const PrepFunctionType & prep_func,
+    const FunctionType & func,
+    const AccumFunctionType & accum_func,
+    const size_t min_parallel=0);
+}
+
+// Implementation
+
+#include <cmath>
+#include <cassert>
+#include <thread>
+#include <vector>
+#include <algorithm>
+
+template<typename Index, typename FunctionType >
+inline bool igl::parallel_for(
+  const Index loop_size, 
+  const FunctionType & func,
+  const size_t min_parallel)
+{
+  using namespace std;
+  // no op preparation/accumulation
+  const auto & no_op = [](const size_t /*n/t*/){};
+  // two-parameter wrapper ignoring thread id
+  const auto & wrapper = [&func](Index i,size_t /*t*/){ func(i); };
+  return parallel_for(loop_size,no_op,wrapper,no_op,min_parallel);
+}
+
+template<
+  typename Index, 
+  typename PreFunctionType,
+  typename FunctionType, 
+  typename AccumFunctionType>
+inline bool igl::parallel_for(
+  const Index loop_size, 
+  const PreFunctionType & prep_func,
+  const FunctionType & func,
+  const AccumFunctionType & accum_func,
+  const size_t min_parallel)
+{
+  assert(loop_size>=0);
+  if(loop_size==0) return false;
+  // Estimate number of threads in the pool
+  // http://ideone.com/Z7zldb
+  const static size_t sthc = std::thread::hardware_concurrency();
+  const size_t nthreads = loop_size<min_parallel?0:(sthc==0?8:sthc);
+  if(nthreads==0)
+  {
+    // serial
+    prep_func(1);
+    for(Index i = 0;i<loop_size;i++) func(i,0);
+    accum_func(0);
+    return false;
+  }else
+  {
+    // Size of a slice for the range functions
+    Index slice = 
+      std::max(
+        (Index)std::round((loop_size+1)/static_cast<double>(nthreads)),(Index)1);
+ 
+    // [Helper] Inner loop
+    const auto & range = [&func](const Index k1, const Index k2, const size_t t)
+    {
+      for(Index k = k1; k < k2; k++) func(k,t);
+    };
+    prep_func(nthreads);
+    // Create pool and launch jobs
+    std::vector<std::thread> pool;
+    pool.reserve(nthreads);
+    // Inner range extents
+    Index i1 = 0;
+    Index i2 = std::min(0 + slice, loop_size);
+    {
+      size_t t = 0;
+      for (; t+1 < nthreads && i1 < loop_size; ++t)
+      {
+        pool.emplace_back(range, i1, i2, t);
+        i1 = i2;
+        i2 = std::min(i2 + slice, loop_size);
+      }
+      if (i1 < loop_size)
+      {
+        pool.emplace_back(range, i1, loop_size, t);
+      }
+    }
+    // Wait for jobs to finish
+    for (std::thread &t : pool) if (t.joinable()) t.join();
+    // Accumulate across threads
+    for(size_t t = 0;t<nthreads;t++)
+    {
+      accum_func(t);
+    }
+    return true;
+  }
+}
+ 
+//#ifndef IGL_STATIC_LIBRARY
+//#include "parallel_for.cpp"
+//#endif
+#endif

+ 23 - 11
include/igl/per_vertex_normals.cpp

@@ -10,6 +10,7 @@
 #include "get_seconds.h"
 #include "per_face_normals.h"
 #include "doublearea.h"
+#include "parallel_for.h"
 #include "internal_angles.h"
 
 template <typename DerivedV, typename DerivedF>
@@ -68,23 +69,34 @@ IGL_INLINE void igl::per_vertex_normals(
   }
 
   // loop over faces
-  const int Frows = F.rows();
-//// Minimum number of iterms per openmp thread
-//#ifndef IGL_OMP_MIN_VALUE
-//#  define IGL_OMP_MIN_VALUE 1000
-//#endif
-//#pragma omp parallel for if (Frows>IGL_OMP_MIN_VALUE)
-  for(int i = 0; i < Frows;i++)
+  for(int i = 0;i<F.rows();i++)
   {
     // throw normal at each corner
     for(int j = 0; j < 3;j++)
     {
-      // Q: Does this need to be critical?
-      // A: Yes. Different (i,j)'s could produce the same F(i,j)
-//#pragma omp critical
-      N.row(F(i,j)) += W(i,j)*FN.row(i);
+      N.row(F(i,j)) += W(i,j) * FN.row(i);
     }
   }
+
+  //// loop over faces
+  //std::mutex critical;
+  //std::vector<DerivedN> NN;
+  //parallel_for(
+  //  F.rows(),
+  //  [&NN,&N](const size_t n){ NN.resize(n,DerivedN::Zero(N.rows(),3));},
+  //  [&F,&W,&FN,&NN,&critical](const int i, const size_t t)
+  //  {
+  //    // throw normal at each corner
+  //    for(int j = 0; j < 3;j++)
+  //    {
+  //      // Q: Does this need to be critical?
+  //      // A: Yes. Different (i,j)'s could produce the same F(i,j)
+  //      NN[t].row(F(i,j)) += W(i,j) * FN.row(i);
+  //    }
+  //  },
+  //  [&N,&NN](const size_t t){ N += NN[t]; },
+  //  1000l);
+
   // take average via normalization
   N.rowwise().normalize();
 }

+ 47 - 0
include/igl/png/readPNG.cpp

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "readPNG.h"
+#include <stb_image.h>
+
+IGL_INLINE bool igl::png::readPNG(
+  const std::string png_file,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
+)
+{
+  int cols,rows,n;
+  unsigned char *data = stbi_load(png_file.c_str(), &cols, &rows, &n, 4);
+  if(data == NULL) {
+    return false;
+  }
+
+  R.resize(cols,rows);
+  G.resize(cols,rows);
+  B.resize(cols,rows);
+  A.resize(cols,rows);
+
+  for (unsigned i=0; i<rows; ++i) {
+    for (unsigned j=0; j<cols; ++j) {
+      R(j,rows-1-i) = data[4*(j + cols * i) + 0];
+      G(j,rows-1-i) = data[4*(j + cols * i) + 1];
+      B(j,rows-1-i) = data[4*(j + cols * i) + 2];
+      A(j,rows-1-i) = data[4*(j + cols * i) + 3];
+    }
+  }
+
+  stbi_image_free(data);
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+#endif

+ 39 - 0
include/igl/png/readPNG.h

@@ -0,0 +1,39 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_PNG_READ_PNG_H
+#define IGL_PNG_READ_PNG_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace png
+  {
+    // Read an image from a .png file into 4 memory buffers
+    //
+    // Input:
+    //  png_file  path to .png file
+    // Output:
+    //  R,G,B,A texture channels
+    // Returns true on success, false on failure
+    //
+    IGL_INLINE bool readPNG(const std::string png_file,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A
+    );
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "readPNG.cpp"
+#endif
+
+#endif

+ 46 - 0
include/igl/png/writePNG.cpp

@@ -0,0 +1,46 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "writePNG.h"
+#include <stb_image_write.h>
+#include <vector>
+
+IGL_INLINE bool igl::png::writePNG(
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+  const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
+  const std::string png_file
+)
+{
+  assert((R.rows() == G.rows()) && (G.rows() == B.rows()) && (B.rows() == A.rows()));
+  assert((R.cols() == G.cols()) && (G.cols() == B.cols()) && (B.cols() == A.cols()));
+
+  const int comp = 4;                                  // 4 Channels Red, Green, Blue, Alpha
+  const int stride_in_bytes = R.rows()*comp;           // Lenght of one row in bytes
+  std::vector<unsigned char> data(R.size()*comp,0);     // The image itself;
+
+  for (unsigned i = 0; i<R.rows();++i)
+  {
+    for (unsigned j = 0; j < R.cols(); ++j)
+    {
+        data[(j * R.rows() * comp) + (i * comp) + 0] = R(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 1] = G(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 2] = B(i,R.cols()-1-j);
+        data[(j * R.rows() * comp) + (i * comp) + 3] = A(i,R.cols()-1-j);
+    }
+  }
+
+  stbi_write_png(png_file.c_str(), R.rows(), R.cols(), comp, data.data(), stride_in_bytes);
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+// generated by autoexplicit.sh
+#endif

+ 41 - 0
include/igl/png/writePNG.h

@@ -0,0 +1,41 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Daniele Panozzo <daniele.panozzo@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_PNG_WRITE_PNG_H
+#define IGL_PNG_WRITE_PNG_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+
+namespace igl
+{
+  namespace png
+  {
+    // Writes an image to a png file
+    //
+    // Input:
+    //  R,G,B,A texture channels
+    // Output:
+    //  png_file  path to .png file
+    // Returns true on success, false on failure
+    //
+    IGL_INLINE bool writePNG
+    (
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& R,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B,
+      const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& A,
+      const std::string png_file
+    );
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "writePNG.cpp"
+#endif
+
+#endif

+ 2 - 0
include/igl/project_to_line.cpp

@@ -120,6 +120,8 @@ IGL_INLINE void igl::project_to_line(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::project_to_line<Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
 template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&);
 template void igl::project_to_line<double>(double, double, double, double, double, double, double, double, double, double&, double&,double&,double&, double&);
 template void igl::project_to_line<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);

+ 2 - 0
include/igl/project_to_line_segment.cpp

@@ -43,5 +43,7 @@ IGL_INLINE void igl::project_to_line_segment(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
 template void igl::project_to_line_segment<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 1, 0, 1, 1>, Eigen::Matrix<double, 1, 1, 0, 1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 1, 0, 1, 1> >&);
 #endif

+ 27 - 26
include/igl/repdiag.cpp

@@ -18,7 +18,7 @@ IGL_INLINE void igl::repdiag(
   using namespace Eigen;
   int m = A.rows();
   int n = A.cols();
-
+#if false
   vector<Triplet<T> > IJV;
   IJV.reserve(A.nonZeros()*d);
   // Loop outer level
@@ -35,31 +35,32 @@ IGL_INLINE void igl::repdiag(
   }
   B.resize(m*d,n*d);
   B.setFromTriplets(IJV.begin(),IJV.end());
-  
-
-  // Q: Why is this **Very** slow?
-
-  //int m = A.rows();
-  //int n = A.cols();
-
-  //B.resize(m*d,n*d);
-  //// Reserve enough space for new non zeros
-  //B.reserve(d*A.nonZeros());
-
-  //// loop over reps
-  //for(int i=0;i<d;i++)
-  //{
-  //  // Loop outer level
-  //  for (int k=0; k<A.outerSize(); ++k)
-  //  {
-  //    // loop inner level
-  //    for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
-  //    {
-  //      B.insert(i*m+it.row(),i*n+it.col()) = it.value();
-  //    }
-  //  }
-  //}
-  //B.makeCompressed();
+#else
+  // This will not work for RowMajor
+  B.resize(m*d,n*d);
+  Eigen::VectorXi per_col = Eigen::VectorXi::Zero(n*d);
+  for (int k=0; k<A.outerSize(); ++k)
+  {
+    for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
+    {
+      for(int r = 0;r<d;r++) per_col(n*r + k)++;
+    }
+  }
+  B.reserve(per_col);
+  for(int r = 0;r<d;r++)
+  {
+    const int mr = m*r;
+    const int nr = n*r;
+    for (int k=0; k<A.outerSize(); ++k)
+    {
+      for (typename Eigen::SparseMatrix<T>::InnerIterator it(A,k); it; ++it)
+      {
+        B.insert(it.row()+mr,k+nr) = it.value();
+      }
+    }
+  }
+  B.makeCompressed();
+#endif
 }
 
 template <typename T>

+ 1 - 1
include/igl/slice_mask.cpp

@@ -55,8 +55,8 @@ IGL_INLINE void igl::slice_mask(
     case 1:
     {
       const int ym = R.count();
-      Y.resize(ym,X.cols());
       assert(X.rows() == R.size() && "X.rows() should match R.size()");
+      Y.resize(ym,X.cols());
       {
         int yi = 0;
         for(int i = 0;i<X.rows();i++)

+ 69 - 82
include/igl/sort.cpp

@@ -11,12 +11,11 @@
 #include "reorder.h"
 #include "IndexComparison.h"
 #include "colon.h"
+#include "parallel_for.h"
 
 #include <cassert>
 #include <algorithm>
 #include <iostream>
-#include <thread>
-#include <functional>
 
 template <typename DerivedX, typename DerivedY, typename DerivedIX>
 IGL_INLINE void igl::sort(
@@ -223,98 +222,86 @@ IGL_INLINE void igl::sort3(
     IX.col(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
   }
 
-  const int n = num_outer;
-  const size_t nthreads = n<8000?1:std::thread::hardware_concurrency();
+
+  const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
   {
-    std::vector<std::thread> threads(nthreads);
-    for(int t = 0;t<nthreads;t++)
+    YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
+    YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
+    YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
+    Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
+    Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
+    Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
+    if(ascending)
+    {
+      // 123 132 213 231 312 321
+      if(a > b)
+      {
+        std::swap(a,b);
+        std::swap(ai,bi);
+      }
+      // 123 132 123 231 132 231
+      if(b > c)
+      {
+        std::swap(b,c);
+        std::swap(bi,ci);
+        // 123 123 123 213 123 213
+        if(a > b)
+        {
+          std::swap(a,b);
+          std::swap(ai,bi);
+        }
+        // 123 123 123 123 123 123
+      }
+    }else
     {
-      threads[t] = std::thread(std::bind(
-        [&X,&Y,&IX,&dim,&ascending](const int bi, const int ei, const int t)
+      // 123 132 213 231 312 321
+      if(a < b)
       {
-        // loop over columns (or rows)
-        for(int i = bi;i<ei;i++)
+        std::swap(a,b);
+        std::swap(ai,bi);
+      }
+      // 213 312 213 321 312 321
+      if(b < c)
+      {
+        std::swap(b,c);
+        std::swap(bi,ci);
+        // 231 321 231 321 321 321
+        if(a < b)
         {
-          YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
-          YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
-          YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
-          Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
-          Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
-          Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
-          if(ascending)
-          {
-            // 123 132 213 231 312 321
-            if(a > b)
-            {
-              std::swap(a,b);
-              std::swap(ai,bi);
-            }
-            // 123 132 123 231 132 231
-            if(b > c)
-            {
-              std::swap(b,c);
-              std::swap(bi,ci);
-              // 123 123 123 213 123 213
-              if(a > b)
-              {
-                std::swap(a,b);
-                std::swap(ai,bi);
-              }
-              // 123 123 123 123 123 123
-            }
-          }else
-          {
-            // 123 132 213 231 312 321
-            if(a < b)
-            {
-              std::swap(a,b);
-              std::swap(ai,bi);
-            }
-            // 213 312 213 321 312 321
-            if(b < c)
-            {
-              std::swap(b,c);
-              std::swap(bi,ci);
-              // 231 321 231 321 321 321
-              if(a < b)
-              {
-                std::swap(a,b);
-                std::swap(ai,bi);
-              }
-              // 321 321 321 321 321 321
-            }
-          }
+          std::swap(a,b);
+          std::swap(ai,bi);
         }
-      }, t*n/nthreads, (t+1)==nthreads?n:(t+1)*n/nthreads,t));
+        // 321 321 321 321 321 321
+      }
     }
-    std::for_each(threads.begin(),threads.end(),[](std::thread& x){x.join();});
-  }
+  };
+  parallel_for(num_outer,inner,16000);
 }
 
 template <class T>
 IGL_INLINE void igl::sort(
-  const std::vector<T> & unsorted,
-  const bool ascending,
-  std::vector<T> & sorted,
-  std::vector<size_t> & index_map)
+const std::vector<T> & unsorted,
+const bool ascending,
+std::vector<T> & sorted,
+std::vector<size_t> & index_map)
 {
-  // Original unsorted index map
-  index_map.resize(unsorted.size());
-  for(size_t i=0;i<unsorted.size();i++)
-  {
-    index_map[i] = i;
-  }
-  // Sort the index map, using unsorted for comparison
-  std::sort(
-    index_map.begin(),
-    index_map.end(),
-    igl::IndexLessThan<const std::vector<T>& >(unsorted));
+// Original unsorted index map
+index_map.resize(unsorted.size());
+for(size_t i=0;i<unsorted.size();i++)
+{
+  index_map[i] = i;
+}
+// Sort the index map, using unsorted for comparison
+std::sort(
+  index_map.begin(),
+  index_map.end(),
+  igl::IndexLessThan<const std::vector<T>& >(unsorted));
 
-  // if not ascending then reverse
-  if(!ascending)
-  {
-    std::reverse(index_map.begin(),index_map.end());
-  }
+// if not ascending then reverse
+if(!ascending)
+{
+  std::reverse(index_map.begin(),index_map.end());
+}
   // make space for output without clobbering
   sorted.resize(unsorted.size());
   // reorder unsorted into sorted using index map

+ 20 - 0
include/igl/swept_volume_bounding_box.cpp

@@ -0,0 +1,20 @@
+#include "swept_volume_bounding_box.h"
+
+IGL_INLINE void igl::swept_volume_bounding_box(
+  const size_t & n,
+  const std::function<Eigen::RowVector3d(const size_t vi, const double t)> & V,
+  const size_t & steps,
+  Eigen::AlignedBox3d & box)
+{
+  using namespace Eigen;
+  box.setEmpty();
+  const VectorXd t = VectorXd::LinSpaced(steps,0,1);
+  // Find extent over all time steps
+  for(int ti = 0;ti<t.size();ti++)
+  {
+    for(size_t vi = 0;vi<n;vi++)
+    {
+      box.extend(V(vi,t(ti)).transpose());
+    }
+  }
+}

+ 31 - 0
include/igl/swept_volume_bounding_box.h

@@ -0,0 +1,31 @@
+#ifndef IGL_SWEPT_VOLUME_BOUNDING_BOX_H
+#define IGL_SWEPT_VOLUME_BOUNDING_BOX_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <functional>
+namespace igl
+{
+  // Construct an axis-aligned bounding box containing a shape undergoing a
+  // motion sampled at `steps` discrete momements.
+  //
+  // Inputs:
+  //   n  number of mesh vertices
+  //   V  function handle so that V(i,t) returns the 3d position of vertex
+  //     i at time t, for t∈[0,1]
+  //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+  // Outputs:
+  //   box  box containing mesh under motion
+  IGL_INLINE void swept_volume_bounding_box(
+    const size_t & n,
+    const std::function<
+      Eigen::RowVector3d(const size_t vi, const double t)> & V,
+    const size_t & steps,
+    Eigen::AlignedBox3d & box);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume_bounding_box.cpp"
+#endif
+
+#endif 

+ 113 - 0
include/igl/swept_volume_signed_distance.cpp

@@ -0,0 +1,113 @@
+#include "swept_volume_signed_distance.h"
+#include "flood_fill.h"
+#include "signed_distance.h"
+#include "AABB.h"
+#include "pseudonormal_test.h"
+#include "per_face_normals.h"
+#include "per_vertex_normals.h"
+#include "per_edge_normals.h"
+#include <Eigen/Geometry>
+#include <cmath>
+
+IGL_INLINE void igl::swept_volume_signed_distance(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t & steps,
+  const Eigen::MatrixXd & GV,
+  const Eigen::RowVector3i & res,
+  const double h,
+  const double isolevel,
+  const Eigen::VectorXd & S0,
+  Eigen::VectorXd & S)
+{
+  using namespace std;
+  using namespace igl;
+  using namespace Eigen;
+  S = S0;
+  const VectorXd t = VectorXd::LinSpaced(steps,0,1);
+  const bool finite_iso = isfinite(isolevel);
+  const double extension = (finite_iso ? isolevel : 0) + sqrt(3.0)*h;
+  Eigen::AlignedBox3d box(
+    V.colwise().minCoeff().array()-extension,
+    V.colwise().maxCoeff().array()+extension);
+  // Precomputation
+  Eigen::MatrixXd FN,VN,EN;
+  Eigen::MatrixXi E;
+  Eigen::VectorXi EMAP;
+  per_face_normals(V,F,FN);
+  per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
+  per_edge_normals(
+    V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
+  AABB<MatrixXd,3> tree;
+  tree.init(V,F);
+  for(int ti = 0;ti<t.size();ti++)
+  {
+    const Affine3d At = transform(t(ti));
+    for(int g = 0;g<GV.rows();g++)
+    {
+      // Don't bother finding out how deep inside points are.
+      if(finite_iso && S(g)==S(g) && S(g)<isolevel-sqrt(3.0)*h)
+      {
+        continue;
+      }
+      const RowVector3d gv = 
+        (GV.row(g) - At.translation().transpose())*At.linear();
+      // If outside of extended box, then consider it "far away enough"
+      if(finite_iso && !box.contains(gv.transpose()))
+      {
+        continue;
+      }
+      RowVector3d c,n;
+      int i;
+      double sqrd,s;
+      //signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,gv,s,sqrd,i,c,n);
+      const double min_sqrd = 
+        finite_iso ? 
+        pow(sqrt(3.)*h+isolevel,2) : 
+        numeric_limits<double>::infinity();
+      sqrd = tree.squared_distance(V,F,gv,min_sqrd,i,c);
+      if(sqrd<min_sqrd)
+      {
+        pseudonormal_test(V,F,FN,VN,EN,EMAP,gv,i,c,s,n);
+        if(S(g) == S(g))
+        {
+          S(g) = min(S(g),s*sqrt(sqrd));
+        }else
+        {
+          S(g) = s*sqrt(sqrd);
+        }
+      }
+    }
+  }
+
+  if(finite_iso)
+  {
+    flood_fill(res,S);
+  }else
+  {
+#ifndef NDEBUG
+    // Check for nans
+    for_each(S.data(),S.data()+S.size(),[](const double s){assert(s==s);});
+#endif
+  }
+}
+
+IGL_INLINE void igl::swept_volume_signed_distance(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const std::function<Eigen::Affine3d(const double t)> & transform,
+  const size_t & steps,
+  const Eigen::MatrixXd & GV,
+  const Eigen::RowVector3i & res,
+  const double h,
+  const double isolevel,
+  Eigen::VectorXd & S)
+{
+  using namespace std;
+  using namespace igl;
+  using namespace Eigen;
+  S = VectorXd::Constant(GV.rows(),1,numeric_limits<double>::quiet_NaN());
+  return 
+    swept_volume_signed_distance(V,F,transform,steps,GV,res,h,isolevel,S,S);
+}

+ 57 - 0
include/igl/swept_volume_signed_distance.h

@@ -0,0 +1,57 @@
+#ifndef IGL_SWEPT_VOLUME_SIGNED_DISTANCE_H
+#define IGL_SWEPT_VOLUME_SIGNED_DISTANCE_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+#include <functional>
+namespace igl
+{
+  // Compute the signed distance to a sweep surface of a mesh under-going
+  // an arbitrary motion V(t) discretely sampled at `steps`-many moments in
+  // time at a grid.
+  //
+  // Inputs:
+  //   V  #V by 3 list of mesh positions in reference pose
+  //   F  #F by 3 list of triangle indices [0,n)
+  //   transform  function handle so that transform(t) returns the rigid
+  //     transformation at time t∈[0,1]
+  //   steps  number of time steps: steps=3 --> t∈{0,0.5,1}
+  //   GV  #GV by 3 list of evaluation point grid positions
+  //   res  3-long resolution of GV grid
+  //   h  edge-length of grid
+  //   isolevel  isolevel to "focus" on; grid positions far enough away from
+  //     isolevel (based on h) will get approximate values). Set
+  //     isolevel=infinity to get good values everywhere (slow and
+  //     unnecessary if just trying to extract isolevel-level set).
+  //   S0  #GV initial values (will take minimum with these), can be same
+  //     as S)
+  // Outputs:
+  //   S  #GV list of signed distances
+  IGL_INLINE void swept_volume_signed_distance(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<Eigen::Affine3d(const double t)> & transform,
+    const size_t & steps,
+    const Eigen::MatrixXd & GV,
+    const Eigen::RowVector3i & res,
+    const double h,
+    const double isolevel,
+    const Eigen::VectorXd & S0,
+    Eigen::VectorXd & S);
+  IGL_INLINE void swept_volume_signed_distance(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const std::function<Eigen::Affine3d(const double t)> & transform,
+    const size_t & steps,
+    const Eigen::MatrixXd & GV,
+    const Eigen::RowVector3i & res,
+    const double h,
+    const double isolevel,
+    Eigen::VectorXd & S);
+  }
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "swept_volume_signed_distance.cpp"
+#endif 
+
+#endif

+ 27 - 21
include/igl/triangle_triangle_adjacency.cpp

@@ -9,6 +9,7 @@
 #include "is_edge_manifold.h"
 #include "all_edges.h"
 #include "unique_simplices.h"
+#include "parallel_for.h"
 #include "unique_edge_map.h"
 #include <algorithm>
 #include <iostream>
@@ -172,41 +173,46 @@ template <
   }
 
   // No race conditions because TT*[f][c]'s are in bijection with e's
-  // Minimum number of iterms per openmp thread
+  // Minimum number of items per thread
   //const size_t num_e = E.rows();
-# ifndef IGL_OMP_MIN_VALUE
-#   define IGL_OMP_MIN_VALUE 1000
-# endif
-# pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
   // Slightly better memory access than loop over E
-  for(Index f = 0;f<(Index)m;f++)
-  {
-    for(Index c = 0;c<3;c++)
+  igl::parallel_for(
+    m,
+    [&](const Index & f)
     {
-      const Index e = f + m*c;
-      //const Index c = e/m;
-      const vector<uE2EType> & N = uE2E[EMAP(e)];
-      for(const auto & ne : N)
+      for(Index c = 0;c<3;c++)
       {
-        const Index nf = ne%m;
-        // don't add self
-        if(nf != f)
+        const Index e = f + m*c;
+        //const Index c = e/m;
+        const vector<uE2EType> & N = uE2E[EMAP(e)];
+        for(const auto & ne : N)
         {
-          TT[f][c].push_back(nf);
-          if(construct_TTi)
+          const Index nf = ne%m;
+          // don't add self
+          if(nf != f)
           {
-            const Index nc = ne/m;
-            TTi[f][c].push_back(nc);
+            TT[f][c].push_back(nf);
+            if(construct_TTi)
+            {
+              const Index nc = ne/m;
+              TTi[f][c].push_back(nc);
+            }
           }
         }
       }
-    }
-  }
+    },
+    1000ul);
+
+
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
+template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >, std::allocator<std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > > >&);
+// generated by autoexplicit.sh
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);

+ 5 - 3
include/igl/uniformly_sample_two_manifold.h

@@ -11,8 +11,10 @@
 #include <Eigen/Dense>
 namespace igl
 {
-  // UNIFORMLY_SAMPLE_TWO_MANIFOLD Attempt to sample a mesh uniformly by furthest
-  // point relaxation as described in "Fast Automatic Skinning Transformations"
+  // UNIFORMLY_SAMPLE_TWO_MANIFOLD Attempt to sample a mesh uniformly by
+  // furthest point relaxation as described in "Fast Automatic Skinning
+  // Transformations"
+  //
   // [Jacobson et al. 12] Section 3.3.
   //
   // Inputs:
@@ -37,6 +39,6 @@ namespace igl
     Eigen::VectorXi & S);
 }
 #ifndef IGL_STATIC_LIBRARY
-#  include "uniformly_sample_two_manifold.h"
+#  include "uniformly_sample_two_manifold.cpp"
 #endif
 #endif

+ 5 - 0
include/igl/unique.cpp

@@ -268,4 +268,9 @@ template void igl::unique<double>(std::vector<double, std::allocator<double> > c
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::unique_rows<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+
+#ifdef WIN32
+template void __cdecl igl::unique_rows<class Eigen::Matrix<int, -1, -1, 0, -1, -1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, -1, 0, -1, -1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &);
+#endif
+
 #endif

+ 5 - 0
include/igl/unique_edge_map.cpp

@@ -52,4 +52,9 @@ template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::M
 template void igl::unique_edge_map<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<unsigned long, std::allocator<unsigned long> >, std::allocator<std::vector<unsigned long, std::allocator<unsigned long> > > >&);
+
+#ifdef WIN32
+template void __cdecl igl::unique_edge_map<class Eigen::Matrix<int, -1, 3, 0, -1, 3>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, __int64>(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 3, 0, -1, 3> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class std::vector<class std::vector<__int64, class std::allocator<__int64> >, class std::allocator<class std::vector<__int64, class std::allocator<__int64> > > > &);
+#endif
+
 #endif 

+ 6 - 12
include/igl/unique_simplices.cpp

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
-// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
 // 
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
@@ -8,7 +8,7 @@
 #include "unique_simplices.h"
 #include "sort.h"
 #include "unique.h"
-#include "get_seconds.h"
+#include "parallel_for.h"
 
 template <
   typename DerivedF,
@@ -31,16 +31,7 @@ IGL_INLINE void igl::unique_simplices(
   igl::unique_rows(sortF,C,IA,IC);
   FF.resize(IA.size(),F.cols());
   const size_t mff = FF.rows();
-  // Minimum number of iterms per openmp thread
-  #ifndef IGL_OMP_MIN_VALUE
-  #  define IGL_OMP_MIN_VALUE 1000
-  #endif
-  #pragma omp parallel for if (mff>IGL_OMP_MIN_VALUE)
-  // Copy into output
-  for(size_t i = 0;i<mff;i++)
-  {
-    FF.row(i) = F.row(IA(i));
-  }
+  parallel_for(mff,[&F,&IA,&FF](size_t & i){FF.row(i) = F.row(IA(i));},1000ul);
 }
 
 template <
@@ -64,4 +55,7 @@ template void igl::unique_simplices<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::
 template void igl::unique_simplices<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::unique_simplices<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#ifdef WIN32
+template void __cdecl igl::unique_simplices<class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<int, -1, 2, 0, -1, 2>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > const &, class Eigen::PlainObjectBase<class Eigen::Matrix<int, -1, 2, 0, -1, 2> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &, class Eigen::PlainObjectBase<class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> > &);
+#endif
 #endif

+ 2 - 0
include/igl/upsample.cpp

@@ -105,5 +105,7 @@ IGL_INLINE void igl::upsample(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::upsample<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::upsample<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
 #endif

+ 1 - 1
include/igl/viewer/Viewer.cpp

@@ -353,7 +353,7 @@ namespace viewer
   :       Toggle face labels)"
 #endif
 );
-    std::cout<<usage;
+    std::cout<<usage<<std::endl;
 #endif
   }
 

+ 5 - 3
include/igl/viewer/ViewerData.cpp

@@ -11,6 +11,7 @@
 #include <iostream>
 
 #include <igl/per_face_normals.h>
+#include <igl/material_colors.h>
 #include <igl/per_vertex_normals.h>
 
 #ifdef ENABLE_SERIALIZATION
@@ -104,9 +105,10 @@ IGL_INLINE void igl::viewer::ViewerData::set_mesh(const Eigen::MatrixXd& _V, con
     F = _F;
 
     compute_normals();
-    uniform_colors(Eigen::Vector3d(51.0/255.0,43.0/255.0,33.3/255.0),
-                   Eigen::Vector3d(255.0/255.0,228.0/255.0,58.0/255.0),
-                   Eigen::Vector3d(255.0/255.0,235.0/255.0,80.0/255.0));
+    uniform_colors(
+      Eigen::Vector3d(GOLD_AMBIENT[0], GOLD_AMBIENT[1], GOLD_AMBIENT[2]),
+      Eigen::Vector3d(GOLD_DIFFUSE[0], GOLD_DIFFUSE[1], GOLD_DIFFUSE[2]),
+      Eigen::Vector3d(GOLD_SPECULAR[0], GOLD_SPECULAR[1], GOLD_SPECULAR[2]));
 
     grid_texture();
   }

+ 4 - 1
include/igl/viewer/ViewerData.h

@@ -108,7 +108,10 @@ public:
   IGL_INLINE void compute_normals();
 
   // Assigns uniform colors to all faces/vertices
-  IGL_INLINE void uniform_colors(Eigen::Vector3d ambient, Eigen::Vector3d diffuse, Eigen::Vector3d specular);
+  IGL_INLINE void uniform_colors(
+    Eigen::Vector3d ambient, 
+    Eigen::Vector3d diffuse, 
+    Eigen::Vector3d specular);
 
   // Generates a default grid texture
   IGL_INLINE void grid_texture();

+ 51 - 0
include/igl/voxel_grid.cpp

@@ -0,0 +1,51 @@
+#include "voxel_grid.h"
+#include "grid.h"
+
+IGL_INLINE void igl::voxel_grid(
+  const Eigen::AlignedBox3d & box, 
+  const int in_s,
+  const int pad_count,
+  Eigen::MatrixXd & GV,
+  Eigen::RowVector3i & side)
+{
+  using namespace Eigen;
+  using namespace std;
+  MatrixXd::Index si = -1;
+  box.diagonal().maxCoeff(&si);
+  //MatrixXd::Index si = 0;
+  //assert(si>=0);
+  const double s_len = box.diagonal()(si);
+  assert(in_s>(pad_count*2+1) && "s should be > 2*pad_count+1");
+  const double s = in_s - 2*pad_count;
+  side(si) = s;
+  for(int i = 0;i<3;i++)
+  {
+    if(i!=si)
+    {
+      side(i) = ceil(s * (box.max()(i)-box.min()(i))/s_len);
+    }
+  }
+  side.array() += 2*pad_count;
+  grid(side,GV);
+  // A *    p/s  + B = min
+  // A * (1-p/s) + B = max
+  // B = min - A * p/s
+  // A * (1-p/s) + min - A * p/s = max
+  // A * (1-p/s) - A * p/s = max-min
+  // A * (1-2p/s) = max-min
+  // A  = (max-min)/(1-2p/s)
+  const Array<double,3,1> ps= 
+    (double)(pad_count)/(side.transpose().cast<double>().array()-1.);
+  const Array<double,3,1> A = box.diagonal().array()/(1.0-2.*ps);
+  //// This would result in an "anamorphic", but perfectly fit grid:
+  //const Array<double,3,1> B = box.min().array() - A.array()*ps;
+  //GV.array().rowwise() *= A.transpose();
+  //GV.array().rowwise() += B.transpose();
+  // Instead scale by largest factor and move to match center
+  Array<double,3,1>::Index ai = -1;
+  double a = A.maxCoeff(&ai);
+  const Array<double,1,3> ratio = 
+    a*(side.cast<double>().array()-1.0)/(double)(side(ai)-1.0);
+  GV.array().rowwise() *= ratio;
+  GV.rowwise() += (box.center().transpose()-GV.colwise().mean()).eval();
+}

+ 28 - 0
include/igl/voxel_grid.h

@@ -0,0 +1,28 @@
+#ifndef IGL_VOXEL_GRID_H
+#define IGL_VOXEL_GRID_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+namespace igl
+{
+  // Construct the cell center positions of a regular voxel grid (lattice) made
+  // of perfectly square voxels.
+  // 
+  // Inputs:
+  //   box  bounding box to enclose by grid
+  //   s  number of cell centers on largest side (including 2*pad_count)
+  //   pad_count  number of cells beyond box
+  // Outputs:
+  //   GV  res(0)*res(1)*res(2) by 3 list of cell center positions
+  //   res  3-long list of dimension of voxel grid
+  IGL_INLINE void voxel_grid(
+    const Eigen::AlignedBox3d & box, 
+    const int s,
+    const int pad_count,
+    Eigen::MatrixXd & GV,
+    Eigen::RowVector3i & side);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "voxel_grid.cpp"
+#endif
+#endif

+ 2 - 0
include/igl/writeMESH.cpp

@@ -137,6 +137,8 @@ IGL_INLINE bool igl::writeMESH(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::writeMESH<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+// generated by autoexplicit.sh
 template bool igl::writeMESH<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 //template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 template bool igl::writeMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);

+ 2 - 0
include/igl/writeSTL.cpp

@@ -110,6 +110,8 @@ IGL_INLINE bool igl::writeSTL(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template bool igl::writeSTL<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
 template bool igl::writeSTL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 #endif

+ 2 - 0
include/igl/writeWRL.cpp

@@ -56,6 +56,8 @@ ccw TRUE
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::writeWRL<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&);
+// generated by autoexplicit.sh
 template bool igl::writeWRL<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&);
 template bool igl::writeWRL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
 #endif

+ 2 - 0
include/igl/write_triangle_mesh.cpp

@@ -63,6 +63,8 @@ IGL_INLINE bool igl::write_triangle_mesh(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, bool);
+// generated by autoexplicit.sh
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, const bool);
 template bool igl::write_triangle_mesh<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, bool);
 #endif

+ 2 - 1
index.html

@@ -214,6 +214,7 @@ few labs/companies/institutions using libigl:</p>
 
 <ul>
 <li><a href="http://www.adobe.com/technology/">Adobe Research</a></li>
+<li><a href="http://www.ea.com">Electronic Arts, Inc</a></li>
 <li><a href="http://meshconsultants.ca/">Mesh</a>, consultants, Canada</li>
 <li><a href="http://graphics.pixar.com/research/">Pixar Research</a></li>
 <li><a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
@@ -263,7 +264,7 @@ page</a>.</p>
 <h2 id="copyright">Copyright</h2>
 
 <p>2016 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
-Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+Zhou, Sebastian Koch, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
 Giorgis, Luigi Rocca, Leonardo Sacht, Kevin Walliman, Olga Sorkine-Hornung, and others.</p>
 
 <p>Please see individual files for appropriate copyright notices.</p>

+ 168 - 100
shared/cmake/CMakeLists.txt

@@ -5,9 +5,9 @@ project(libigl)
 option(LIBIGL_USE_STATIC_LIBRARY    "Use libigl as static library" OFF)
 option(LIBIGL_WITH_ANTTWEAKBAR      "Use AntTweakBar"    OFF)
 option(LIBIGL_WITH_BBW              "Use BBW"            OFF)
-option(LIBIGL_WITH_CORK             "Use Cork"           OFF)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           OFF)
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         OFF)
+option(LIBIGL_WITH_CORK             "Use Cork"           OFF)
 option(LIBIGL_WITH_EMBREE           "Use Embree"         OFF)
 option(LIBIGL_WITH_LIM              "Use LIM"            OFF)
 option(LIBIGL_WITH_MATLAB           "Use Matlab"         OFF)
@@ -102,7 +102,51 @@ endif()
 if(LIBIGL_WITH_ANTTWEAKBAR)
   set(ANTTWEAKBAR_DIR "${LIBIGL_EXTERNAL}/anttweakbar")
   set(ANTTWEAKBAR_INCLUDE_DIR "${ANTTWEAKBAR_DIR}/include")
+  set(ANTTWEAKBAR_C_SRC_FILES 
+    "${ANTTWEAKBAR_DIR}/src/TwEventGLFW.c"
+    "${ANTTWEAKBAR_DIR}/src/TwEventGLUT.c"
+    "${ANTTWEAKBAR_DIR}/src/TwEventSDL.c"
+    "${ANTTWEAKBAR_DIR}/src/TwEventSDL12.c"
+    "${ANTTWEAKBAR_DIR}/src/TwEventSDL13.c"
+    )
+  set(ANTTWEAKBAR_CPP_SRC_FILES 
+    "${ANTTWEAKBAR_DIR}/src/LoadOGL.cpp"
+    "${ANTTWEAKBAR_DIR}/src/LoadOGLCore.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwBar.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwColors.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwEventSFML.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwFonts.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwMgr.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwOpenGL.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwOpenGLCore.cpp"
+    "${ANTTWEAKBAR_DIR}/src/TwPrecomp.cpp"
+    )
+    # These are probably needed for windows/Linux, should append if
+    # windows/Linux
+    #"${ANTTWEAKBAR_DIR}/src/TwEventWin.c"
+    #"${ANTTWEAKBAR_DIR}/src/TwEventX11.c"
+    #"${ANTTWEAKBAR_DIR}/src/TwDirect3D10.cpp"
+    #"${ANTTWEAKBAR_DIR}/src/TwDirect3D11.cpp"
+    #"${ANTTWEAKBAR_DIR}/src/TwDirect3D9.cpp"
+  list(
+    APPEND 
+    ANTTWEAKBAR_SRC_FILES 
+    "${ANTTWEAKBAR_C_SRC_FILES}"
+    "${ANTTWEAKBAR_CPP_SRC_FILES}")
+  add_library(AntTweakBar STATIC "${ANTTWEAKBAR_SRC_FILES}")
+  target_include_directories(AntTweakBar PUBLIC "${ANTTWEAKBAR_INCLUDE_DIR}")
+  if(APPLE)
+    set_target_properties(
+      AntTweakBar 
+      PROPERTIES
+      COMPILE_FLAGS
+      "-fPIC -fno-strict-aliasing -x objective-c++")
+    target_compile_definitions(
+      AntTweakBar PUBLIC _MACOSX __PLACEMENT_NEW_INLINE)
+  endif()
   list(APPEND LIBIGL_INCLUDE_DIRS "${ANTTWEAKBAR_INCLUDE_DIR}")
+  set(LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES "AntTweakBar")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES})
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("anttweakbar")
     target_include_directories(iglanttweakbar PRIVATE
@@ -134,8 +178,9 @@ if(LIBIGL_WITH_CGAL) # to be cleaned
   include(${CGAL_USE_FILE})
   list(APPEND LIBIGL_INCLUDE_DIRS ${CGAL_3RD_PARTY_INCLUDE_DIRS})
   list(APPEND LIBIGL_INCLUDE_DIRS ${CGAL_INCLUDE_DIRS})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES ${CGAL_LIBRARIES})
+  list(APPEND LIBIGL_CGAL_EXTRA_LIBRARIES ${CGAL_3RD_PARTY_LIBRARIES})
+  list(APPEND LIBIGL_CGAL_EXTRA_LIBRARIES ${CGAL_LIBRARIES})
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_CGAL_EXTRA_LIBRARIES})
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module_Copyleft("cgal")
     target_include_directories(iglcgal PRIVATE
@@ -144,6 +189,54 @@ if(LIBIGL_WITH_CGAL) # to be cleaned
   endif()
 endif()
 
+#Compile CoMISo
+# NOTE: this cmakefile works only with the
+# comiso available here: https://github.com/libigl/CoMISo
+if(LIBIGL_WITH_COMISO)
+  set(COMISO_DIR "${LIBIGL_EXTERNAL}/CoMISo")
+  set(COMISO_INCLUDE_DIRS
+    "${COMISO_DIR}/ext/gmm-4.2/include"
+    "${COMISO_DIR}/../")
+  list(APPEND LIBIGL_INCLUDE_DIRS ${COMISO_INCLUDE_DIRS})
+  #add_definitions(-DINCLUDE_TEMPLATES) (what need this?)
+  list(APPEND LIBIGL_DEFINITIONS "-DINCLUDE_TEMPLATES")
+  if(APPLE)
+    find_library(accelerate_library Accelerate)
+    list(APPEND LIBIGL_COMISO_EXTRA_LIBRARIES "CoMISo" ${accelerate_library})
+  elseif(UNIX)
+    find_package(BLAS REQUIRED)
+    list(APPEND LIBIGL_COMISO_EXTRA_LIBRARIES "CoMISo" ${BLAS_LIBRARIES})
+  endif(APPLE)
+  if(MSVC)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SCL_SECURE_NO_DEPRECATE")
+    #link_directories("${COMISO_ROOT}/CoMISo/ext/OpenBLAS-v0.2.14-Win64-int64/lib/")
+    list(APPEND LIBIGL_COMISO_EXTRA_LIBRARIES "CoMISo" "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/lib/libopenblas.dll.a.lib")
+  endif()
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_COMISO_EXTRA_LIBRARIES})
+  add_subdirectory("${COMISO_DIR}" "CoMISo")
+  if(MSVC)
+    # Copy the dll
+    add_custom_target(Copy-CoMISo-DLL ALL       # Adds a post-build event to MyTest
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libopenblas.dll"
+        "${CMAKE_CURRENT_BINARY_DIR}/../libopenblas.dll"
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libgcc_s_seh-1.dll"
+        "${CMAKE_CURRENT_BINARY_DIR}/../libgcc_s_seh-1.dll"
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libgfortran-3.dll"
+        "${CMAKE_CURRENT_BINARY_DIR}/../libgfortran-3.dll"
+    COMMAND ${CMAKE_COMMAND} -E copy_if_different
+        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libquadmath-0.dll"
+        "${CMAKE_CURRENT_BINARY_DIR}/../libquadmath-0.dll")
+  endif()
+  if(LIBIGL_USE_STATIC_LIBRARY)
+    CompileIGL_Module_Copyleft("comiso")
+    target_include_directories(iglcomiso PRIVATE ${COMISO_INCLUDE_DIRS})
+    target_compile_definitions(iglcomiso PRIVATE -DINCLUDE_TEMPLATES)
+  endif()
+endif()
+
 ### Compile the cork parts ###
 if(LIBIGL_WITH_CORK)
   set(CORK_DIR "${LIBIGL_EXTERNAL}/cork")
@@ -152,7 +245,8 @@ if(LIBIGL_WITH_CORK)
   # "cork" executable
   add_subdirectory("${CORK_DIR}" "lib-cork")
   list(APPEND LIBIGL_INCLUDE_DIRS "${CORK_INCLUDE_DIR}")
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "cork")
+  list(APPEND LIBIGL_CORK_EXTRA_LIBRARIES "cork")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_CORK_EXTRA_LIBRARIES})
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module_Copyleft("cork")
     target_include_directories(iglcork PRIVATE
@@ -175,7 +269,8 @@ if(LIBIGL_WITH_EMBREE)
 
   add_subdirectory("${EMBREE_DIR}" "embree")
   list(APPEND LIBIGL_INCLUDE_DIRS "${EMBREE_DIR}/include")
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "embree")
+  list(APPEND LIBIGL_EMBREE_EXTRA_LIBRARIES "embree")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_EMBREE_EXTRA_LIBRARIES})
   list(APPEND LIBIGL_DEFINITIONS "-DENABLE_STATIC_LIB")
 
   if(LIBIGL_USE_STATIC_LIBRARY)
@@ -190,7 +285,13 @@ if(LIBIGL_WITH_LIM)
   set(LIM_DIR "${LIBIGL_EXTERNAL}/lim")
   add_subdirectory("${LIM_DIR}" "lim")
   list(APPEND LIBIGL_INCLUDE_DIRS ${LIM_DIR})
-  list(APPEND LIBIGL_LIBRARIES "lim") # it depends on ligigl, so placing it here solve linking problems
+  ## it depends on ligigl, so placing it here solve linking problems
+  #list(APPEND LIBIGL_LIBRARIES "lim") 
+  # ^--- Alec: I don't understand this comment. Does lim need to come before
+  # libigl libraries? Why can't lim be placed where it belongs in
+  # LIBIGL_EXTRA_LIBRARIES?
+  set(LIBIGL_LIM_EXTRA_LIBRARIES "lim")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES "${LIBIGL_LIM_EXTRA_LIBRARIES}")
 
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("lim")
@@ -202,7 +303,8 @@ endif()
 if(LIBIGL_WITH_MATLAB)
   find_package(MATLAB REQUIRED)
   list(APPEND LIBIGL_INCLUDE_DIRS ${MATLAB_INCLUDE_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES ${MATLAB_LIBRARIES})
+  list(APPEND LIBIGL_MATLAB_EXTRA_LIBRARIES ${MATLAB_LIBRARIES})
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_MATLAB_EXTRA_LIBRARIES})
 
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("matlab")
@@ -214,7 +316,8 @@ endif()
 if(LIBIGL_WITH_MOSEK)
   find_package(MOSEK REQUIRED)
   list(APPEND LIBIGL_INCLUDE_DIRS ${MOSEK_INCLUDE_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES ${MOSEK_LIBRARIES})
+  list(APPEND LIBIGL_MOSEK_EXTRA_LIBRARIES ${MOSEK_LIBRARIES})
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_MOSEK_EXTRA_LIBRARIES})
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("mosek")
     target_include_directories(iglmosek PRIVATE ${MOSEK_INCLUDE_DIR})
@@ -223,12 +326,41 @@ else()
   list(APPEND LIBIGL_DEFINITIONS "-DIGL_NO_MOSEK")
 endif()
 
+### Compile the opengl parts ###
+if(LIBIGL_WITH_OPENGL)
+  if(LIBIGL_USE_STATIC_LIBRARY)
+    CompileIGL_Module("opengl")
+    CompileIGL_Module("opengl2")
+    if(NOT APPLE)
+      target_include_directories(iglopengl PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
+      target_include_directories(iglopengl2 PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
+    endif()
+  endif()
+endif()
+
+### Compile the png parts ###
+if(LIBIGL_WITH_PNG)
+  set(STB_IMAGE_DIR "${LIBIGL_EXTERNAL}/stb_image")
+  add_subdirectory("${STB_IMAGE_DIR}" "stb_image")
+  list(APPEND LIBIGL_INCLUDE_DIRS ${STB_IMAGE_DIR})
+  list(APPEND LIBIGL_PNG_EXTRA_LIBRARIES "stb_image")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_PNG_EXTRA_LIBRARIES})
+  if(LIBIGL_USE_STATIC_LIBRARY)
+    CompileIGL_Module("png")
+    target_include_directories(iglpng PRIVATE ${STB_IMAGE_DIR})
+    if(NOT APPLE)
+      target_include_directories(iglpng PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
+    endif()
+  endif()
+endif()
+
 ### Compile the tetgen part ###
 if(LIBIGL_WITH_TETGEN)
   set(TETGEN_DIR "${LIBIGL_EXTERNAL}/tetgen")
   add_subdirectory("${TETGEN_DIR}" "tetgen")
   list(APPEND LIBIGL_INCLUDE_DIRS ${TETGEN_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "tetgen")
+  list(APPEND LIBIGL_TETGEN_EXTRA_LIBRARIES "tetgen")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_TETGEN_EXTRA_LIBRARIES})
 
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module_Copyleft("tetgen")
@@ -241,7 +373,8 @@ if(LIBIGL_WITH_TRIANGLE)
   set(TRIANGLE_DIR "${LIBIGL_EXTERNAL}/triangle")
   add_subdirectory("${TRIANGLE_DIR}" "triangle")
   list(APPEND LIBIGL_INCLUDE_DIRS ${TRIANGLE_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "triangle")
+  list(APPEND LIBIGL_TRIANGLE_EXTRA_LIBRARIES "triangle")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_TRIANGLE_EXTRA_LIBRARIES})
 
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("triangle")
@@ -256,16 +389,16 @@ if(LIBIGL_WITH_VIEWER)
   if(LIBIGL_WITH_NANOGUI)
     list(APPEND LIBIGL_DEFINITIONS "-DIGL_VIEWER_WITH_NANOGUI")
 
-    option(NANOGUI_BUILD_PYTHON OFF)
-    option(NANOGUI_BUILD_EXAMPLE OFF)
-    option(NANOGUI_BUILD_SHARED  OFF)
+    set(NANOGUI_BUILD_PYTHON OFF CACHE BOOL " " FORCE)
+    set(NANOGUI_BUILD_EXAMPLE OFF CACHE BOOL " " FORCE)
+    set(NANOGUI_BUILD_SHARED  OFF CACHE BOOL " " FORCE)
     add_subdirectory("${NANOGUI_DIR}" "nanogui")
 
     set(VIEWER_INCLUDE_DIRS
       "${NANOGUI_DIR}/include"
       "${NANOGUI_DIR}/ext/nanovg/src"
       "${NANOGUI_DIR}/ext/glfw/include")
-    set(VIEWER_LIBRARIES "nanogui" ${NANOGUI_EXTRA_LIBS})
+    set(LIBIGL_VIEWER_EXTRA_LIBRARIES "nanogui" ${NANOGUI_EXTRA_LIBS})
   else()
     set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL " " FORCE)
     set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE)
@@ -274,7 +407,7 @@ if(LIBIGL_WITH_VIEWER)
     add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
 
     set(VIEWER_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glfw/include")
-    set(VIEWER_LIBRARIES "glfw" ${GLFW_LIBRARIES})
+    set(LIBIGL_VIEWER_EXTRA_LIBRARIES "glfw" ${GLFW_LIBRARIES})
   endif()
 
   ### GLEW for linux and windows
@@ -284,11 +417,11 @@ if(LIBIGL_WITH_VIEWER)
   endif()
   if(NOT APPLE)
     list(APPEND VIEWER_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glew/include")
-    list(APPEND VIEWER_LIBRARIES "glew")
+    list(APPEND LIBIGL_VIEWER_EXTRA_LIBRARIES "glew")
   endif()
 
   list(APPEND LIBIGL_INCLUDE_DIRS ${VIEWER_INCLUDE_DIRS})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES ${VIEWER_LIBRARIES})
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_VIEWER_EXTRA_LIBRARIES})
 
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("viewer")
@@ -299,88 +432,6 @@ if(LIBIGL_WITH_VIEWER)
   endif()
 endif()
 
-### Compile the opengl parts ###
-if(LIBIGL_WITH_OPENGL)
-  if(LIBIGL_USE_STATIC_LIBRARY)
-    CompileIGL_Module("opengl")
-    CompileIGL_Module("opengl2")
-    if(NOT APPLE)
-      target_include_directories(iglopengl PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
-      target_include_directories(iglopengl2 PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
-    endif()
-  endif()
-endif()
-
-### Compile the png parts ###
-if(LIBIGL_WITH_PNG)
-  set(STB_IMAGE_DIR "${LIBIGL_EXTERNAL}/stb_image")
-  add_subdirectory("${STB_IMAGE_DIR}" "stb_image")
-  list(APPEND LIBIGL_INCLUDE_DIRS ${STB_IMAGE_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "stb_image")
-  if(LIBIGL_USE_STATIC_LIBRARY)
-    CompileIGL_Module("png")
-    target_include_directories(iglpng PRIVATE ${STB_IMAGE_DIR})
-    if(NOT APPLE)
-      target_include_directories(iglpng PRIVATE "${LIBIGL_EXTERNAL}/nanogui/ext/glew/include")
-    endif()
-  endif()
-endif()
-
-#Compile CoMISo
-# NOTE: this cmakefile works only with the
-# comiso available here: https://github.com/libigl/CoMISo
-if(LIBIGL_WITH_COMISO)
-  set(COMISO_DIR "${LIBIGL_EXTERNAL}/CoMISo")
-
-  set(COMISO_INCLUDE_DIRS
-    "${COMISO_DIR}/ext/gmm-4.2/include"
-    "${COMISO_DIR}/../")
-
-  list(APPEND LIBIGL_INCLUDE_DIRS ${COMISO_INCLUDE_DIRS})
-
-  #add_definitions(-DINCLUDE_TEMPLATES) (what need this?)
-  list(APPEND LIBIGL_DEFINITIONS "-DINCLUDE_TEMPLATES")
-
-  if(APPLE)
-    find_library(accelerate_library Accelerate)
-    list(APPEND LIBIGL_EXTRA_LIBRARIES "CoMISo" ${accelerate_library})
-  elseif(UNIX)
-    find_package(BLAS REQUIRED)
-    list(APPEND LIBIGL_EXTRA_LIBRARIES "CoMISo" ${BLAS_LIBRARIES})
-  endif(APPLE)
-
-  if(MSVC)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SCL_SECURE_NO_DEPRECATE")
-    #link_directories("${COMISO_ROOT}/CoMISo/ext/OpenBLAS-v0.2.14-Win64-int64/lib/")
-    list(APPEND LIBIGL_EXTRA_LIBRARIES "CoMISo" "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/lib/libopenblas.dll.a.lib")
-  endif()
-
-  add_subdirectory("${COMISO_DIR}" "CoMISo")
-
-  if(MSVC)
-    # Copy the dll
-    add_custom_target(Copy-CoMISo-DLL ALL       # Adds a post-build event to MyTest
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different
-        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libopenblas.dll"
-        "${CMAKE_CURRENT_BINARY_DIR}/../libopenblas.dll"
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different
-        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libgcc_s_seh-1.dll"
-        "${CMAKE_CURRENT_BINARY_DIR}/../libgcc_s_seh-1.dll"
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different
-        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libgfortran-3.dll"
-        "${CMAKE_CURRENT_BINARY_DIR}/../libgfortran-3.dll"
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different
-        "${COMISO_DIR}/ext/OpenBLAS-v0.2.14-Win64-int64/bin/libquadmath-0.dll"
-        "${CMAKE_CURRENT_BINARY_DIR}/../libquadmath-0.dll")
-  endif()
-
-  if(LIBIGL_USE_STATIC_LIBRARY)
-    CompileIGL_Module_Copyleft("comiso")
-    target_include_directories(iglcomiso PRIVATE ${COMISO_INCLUDE_DIRS})
-    target_compile_definitions(iglcomiso PRIVATE -DINCLUDE_TEMPLATES)
-  endif()
-endif()
-
 ### Compile the xml part ###
 if(LIBIGL_WITH_XML)
   set(TINYXML2_DIR "${LIBIGL_EXTERNAL}/tinyxml2")
@@ -390,7 +441,8 @@ if(LIBIGL_WITH_XML)
           VERSION "3.0.0"
           SOVERSION "3")
   list(APPEND LIBIGL_INCLUDE_DIRS ${TINYXML2_DIR})
-  list(APPEND LIBIGL_EXTRA_LIBRARIES "tinyxml2")
+  list(APPEND LIBIGL_XML_EXTRA_LIBRARIES "tinyxml2")
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_XML_EXTRA_LIBRARIES})
   if(LIBIGL_USE_STATIC_LIBRARY)
     CompileIGL_Module("xml")
     target_include_directories(iglxml PRIVATE ${TINYXML2_DIR})
@@ -411,6 +463,22 @@ if(NOT ${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
 
   set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIRS} PARENT_SCOPE)
   set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} PARENT_SCOPE)
+  set(LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES ${LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES} PARENT_SCOPE)
+  #set(LIBIGL_BBW_EXTRA_LIBRARIES         ${LIBIGL_BBW_EXTRA_LIBRARIES}         PARENT_SCOPE)
+  set(LIBIGL_CGAL_EXTRA_LIBRARIES        ${LIBIGL_CGAL_EXTRA_LIBRARIES}        PARENT_SCOPE)
+  set(LIBIGL_COMISO_EXTRA_LIBRARIES      ${LIBIGL_COMISO_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_CORK_EXTRA_LIBRARIES        ${LIBIGL_CORK_EXTRA_LIBRARIES}        PARENT_SCOPE)
+  set(LIBIGL_EMBREE_EXTRA_LIBRARIES      ${LIBIGL_EMBREE_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_LIM_EXTRA_LIBRARIES         ${LIBIGL_LIM_EXTRA_LIBRARIES}         PARENT_SCOPE)
+  set(LIBIGL_MATLAB_EXTRA_LIBRARIES      ${LIBIGL_MATLAB_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_MOSEK_EXTRA_LIBRARIES       ${LIBIGL_MOSEK_EXTRA_LIBRARIES}       PARENT_SCOPE)
+  set(LIBIGL_NANOGUI_EXTRA_LIBRARIES     ${LIBIGL_NANOGUI_EXTRA_LIBRARIES}     PARENT_SCOPE)
+  #set(LIBIGL_OPENGL_EXTRA_LIBRARIES      ${LIBIGL_OPENGL_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_PNG_EXTRA_LIBRARIES         ${LIBIGL_PNG_EXTRA_LIBRARIES}         PARENT_SCOPE)
+  set(LIBIGL_TETGEN_EXTRA_LIBRARIES      ${LIBIGL_TETGEN_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_TRIANGLE_EXTRA_LIBRARIES    ${LIBIGL_TRIANGLE_EXTRA_LIBRARIES}    PARENT_SCOPE)
+  set(LIBIGL_VIEWER_EXTRA_LIBRARIES      ${LIBIGL_VIEWER_EXTRA_LIBRARIES}      PARENT_SCOPE)
+  set(LIBIGL_XML_EXTRA_LIBRARIES         ${LIBIGL_XML_EXTRA_LIBRARIES}         PARENT_SCOPE)
   set(LIBIGL_EXTRA_LIBRARIES ${LIBIGL_EXTRA_LIBRARIES} PARENT_SCOPE)
   set(LIBIGL_DEFINITIONS ${LIBIGL_DEFINITIONS} PARENT_SCOPE)
 

+ 4 - 4
style-guidelines.html

@@ -185,8 +185,8 @@ Eigen::SparseMatrix&lt;Atype&gt; adjacency_matrix(const ... &amp; F);
 <h2 id="templatingwitheigen">Templating with Eigen</h2>
 
 <p>Functions taking Eigen dense matrices/arrays as inputs and outputs (but <strong>not</strong>
-return arguments), should template on top of <code>Eigen::PlainObjectBase</code>. <strong>Each
-parameter</strong> should be derived using its own template.</p>
+return arguments), should template on top of <code>Eigen::PlainObjectBase</code>. **Each
+parameter** should be derived using its own template.</p>
 
 <p>For example,</p>
 
@@ -264,8 +264,8 @@ unnecessary prefaces. For example, instead of <code>compute_adjacency_matrix</co
 
 <h2 id="variablenamingconventions">Variable naming conventions</h2>
 
-<p>Libigl prefers short (even single character) variable names <em>with heavy
-documentation</em> in the comments in the header file or above the declaration of
+<p>Libigl prefers short (even single character) variable names _with heavy
+documentation_ in the comments in the header file or above the declaration of
 the function. When possible use <code>V</code> to mean a list of vertex positions and <code>F</code>
 to mean a list of faces/triangles.</p>
 

+ 1 - 1
tutorial/101_FileIO/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/102_DrawMesh/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/103_Events/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/104_Colors/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/105_Overlays/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/106_ViewerMenu/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/201_Normals/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/202_GaussianCurvature/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/203_CurvatureDirections/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/204_Gradient/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/205_Laplacian/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/301_Slice/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/302_Sort/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/303_LaplaceEquation/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/304_LinearEqualityConstraints/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/305_QuadraticProgramming/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/306_EigenDecomposition/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/401_BiharmonicDeformation/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/402_PolyharmonicDeformation/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 4 - 1
tutorial/403_BoundedBiharmonicWeights/CMakeLists.txt

@@ -5,4 +5,7 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})
+if(LIBIGL_WITH_MOSEK)
+  target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_MOSEK_EXTRA_LIBRARIES})
+endif()

+ 1 - 1
tutorial/404_DualQuaternionSkinning/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/405_AsRigidAsPossible/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/406_FastAutomaticSkinningTransformations/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/407_BiharmonicCoordinates/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/501_HarmonicParam/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/502_LSCMParam/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/503_ARAPParam/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/504_NRosyDesign/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_COMISO_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/505_MIQ/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_COMISO_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/505_MIQ/main.cpp

@@ -2,7 +2,6 @@
 #include <igl/barycenter.h>
 #include <igl/comb_cross_field.h>
 #include <igl/comb_frame_field.h>
-#include <igl/copyleft/comiso/miq.h>
 #include <igl/compute_frame_field_bisectors.h>
 #include <igl/cross_field_missmatch.h>
 #include <igl/cut_mesh_from_singularities.h>
@@ -10,6 +9,7 @@
 #include <igl/local_basis.h>
 #include <igl/readOFF.h>
 #include <igl/rotate_vectors.h>
+#include <igl/copyleft/comiso/miq.h>
 #include <igl/copyleft/comiso/nrosy.h>
 #include <igl/viewer/Viewer.h>
 #include <sstream>

+ 1 - 1
tutorial/506_FrameField/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_COMISO_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/507_PolyVectorField/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/508_ConjugateField/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/509_Planarization/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/510_Integrable/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/601_Serialization/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_XML_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/602_Matlab/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_MATLAB_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/604_Triangle/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_TRIANGLE_EXTRA_LIBRARIES})

+ 2 - 3
tutorial/605_Tetgen/CMakeLists.txt

@@ -1,8 +1,7 @@
 cmake_minimum_required(VERSION 2.8.12)
 project(605_Tetgen)
 
-add_executable(${PROJECT_NAME}_bin
-  main.cpp)
+add_executable(${PROJECT_NAME}_bin main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_TETGEN_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/606_AmbientOcclusion/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_EMBREE_EXTRA_LIBRARIES})

+ 8 - 0
tutorial/607_ScreenCapture/CMakeLists.txt

@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(607_ScreenCapture)
+
+add_executable(${PROJECT_NAME}_bin
+  main.cpp)
+target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
+target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_PNG_EXTRA_LIBRARIES})

+ 82 - 0
tutorial/607_ScreenCapture/main.cpp

@@ -0,0 +1,82 @@
+#include <igl/readOFF.h>
+#include <igl/viewer/Viewer.h>
+#include <iostream>
+#include "tutorial_shared_path.h"
+#include <igl/png/writePNG.h>
+#include <igl/png/readPNG.h>
+
+// This function is called every time a keyboard button is pressed
+bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
+{
+  if (key == '1')
+  {
+    // Allocate temporary buffers
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R(1280,800);
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> G(1280,800);
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> B(1280,800);
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> A(1280,800);
+
+    // Draw the scene in the buffers
+    viewer.core.draw_buffer(viewer.data,viewer.opengl,false,R,G,B,A);
+
+    // Save it to a PNG
+    igl::png::writePNG(R,G,B,A,"out.png");
+  }
+
+  if (key == '2')
+  {
+    // Allocate temporary buffers
+    Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> R,G,B,A;
+
+    // Read the PNG
+    igl::png::readPNG("out.png",R,G,B,A);
+
+    // Replace the mesh with a triangulated square
+    Eigen::MatrixXd V(4,3);
+    V <<
+      -0.5,-0.5,0,
+       0.5,-0.5,0,
+       0.5, 0.5,0,
+      -0.5, 0.5,0;
+    Eigen::MatrixXi F(2,3);
+    F <<
+      0,1,2,
+      2,3,0;
+    Eigen::MatrixXd UV(4,2);
+    UV <<
+      0,0,
+      1,0,
+      1,1,
+      0,1;
+
+    viewer.data.clear();
+    viewer.data.set_mesh(V,F);
+    viewer.data.set_uv(UV);
+    viewer.core.align_camera_center(V);
+    viewer.core.show_texture = true;
+
+    // Use the image as a texture
+    viewer.data.set_texture(R,G,B);
+
+  }
+
+
+  return false;
+}
+
+int main(int argc, char *argv[])
+{
+  // Load a mesh in OFF format
+  Eigen::MatrixXd V;
+  Eigen::MatrixXi F;
+  igl::readOFF(TUTORIAL_SHARED_PATH "/bunny.off", V, F);
+
+  std::cerr << "Press 1 to render the scene and save it in a png." << std::endl;
+  std::cerr << "Press 2 to load the saved png and use it as a texture." << std::endl;
+
+  // Plot the mesh and register the callback
+  igl::viewer::Viewer viewer;
+  viewer.callback_key_down = &key_down;
+  viewer.data.set_mesh(V, F);
+  viewer.launch();
+}

+ 1 - 1
tutorial/608_LIM/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_LIM_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/609_Boolean/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_CGAL_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/610_CSGTree/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES} ${LIBIGL_CGAL_EXTRA_LIBRARIES})

+ 1 - 1
tutorial/701_Statistics/CMakeLists.txt

@@ -5,4 +5,4 @@ add_executable(${PROJECT_NAME}_bin
   main.cpp)
 target_include_directories(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_INCLUDE_DIRS})
 target_compile_definitions(${PROJECT_NAME}_bin PRIVATE ${LIBIGL_DEFINITIONS})
-target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_EXTRA_LIBRARIES})
+target_link_libraries(${PROJECT_NAME}_bin ${LIBIGL_LIBRARIES} ${LIBIGL_VIEWER_EXTRA_LIBRARIES})

Some files were not shown because too many files changed in this diff