Browse Source

Merge remote-tracking branch 'upstream/master' into viewer

Former-commit-id: 93ac038d96e03109a7bb4ccb3f769eb0b806368e
Jérémie Dumas 7 years ago
parent
commit
e47cf8ae94

+ 17 - 0
CONTRIBUTING.md

@@ -0,0 +1,17 @@
+Before opening an issue on creating a pull request, please check the following:
+
+## Compilation Issues
+
+- If you are on Windows, did you select the **x64** version of the Visual Studio compiler?
+
+- If you have a **CMake issue**, make sure you follow the same approach as the  [libigl-example-project](https://github.com/libigl/libigl-example-project) to build libigl with your project, and make sure that you can compile the example project.
+
+- If you have an issue with a **submodule**, check if your submodules are up to date. If you have a doubt about a submodule, delete its folder and run `git submodule update --init --recursive` in the libigl directory.
+
+- If you have an issue with a missing **template issue**, check if your code compile with the *header-only* option of libigl activated. Turn **`OFF`** the CMake option `LIBIGL_USE_STATIC_LIBRARY`: either modify your `CMakeCache.txt` via CMake GUI or ccmake, or delete your `CMakeCache.txt` and re-run `cmake -DLIBIGL_USE_STATIC_LIBRARY=OFF ..` in your build folder.
+
+- Make sure your read the [**FAQ**](https://github.com/libigl/libigl/wiki/FAQ) before asking a new question, and search [**existing issues**](https://github.com/libigl/libigl/issues?q=is%3Aissue+is%3Aclosed) for a problem similar to yours.
+
+- Make sure you read the informations contained in the libigl [homepage](https://github.com/libigl/libigl) as well as the [tutorials](http://libigl.github.io/libigl/tutorial/tutorial.html).
+
+- If none of these solve your problem, then please report your issue in the bug tracker!

+ 5 - 4
include/igl/grad.cpp

@@ -36,10 +36,11 @@ IGL_INLINE void grad_tet(const Eigen::PlainObjectBase<DerivedV>&V,
     F.row(3*m + i) << T(i,1), T(i,3), T(i,2);
   }
   // compute volume of each tet
-  VectorXd vol; igl::volume(V,T,vol);
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> vol; 
+  igl::volume(V,T,vol);
 
-  VectorXd A(F.rows());
-  MatrixXd N(F.rows(),3);
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> A(F.rows());
+  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> N(F.rows(),3);
   if (!uniform) {
     // compute tetrahedron face normals
     igl::per_face_normals(V,F,N); int norm_rows = N.rows();
@@ -149,7 +150,7 @@ IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
       // get h (by the area of the triangle)
       double h = sqrt( (dblA)/sin(M_PI / 3.0)); // (h^2*sin(60))/2. = Area => h = sqrt(2*Area/sin_60)
 
-      Eigen::Vector3d v1,v2,v3;
+      Eigen::Matrix<typename DerivedV::Scalar, 3, 1> v1,v2,v3;
       v1 << 0,0,0;
       v2 << h,0,0;
       v3 << h/2.,(sqrt(3)/2.)*h,0;

+ 0 - 3
include/igl/matlab/mexErrMsgTxt.cpp

@@ -7,9 +7,6 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "mexErrMsgTxt.h"
 
-// Overload mexErrMsgTxt to check an assertion then print text only if
-// assertion fails
-#include "mex.h"
 IGL_INLINE void igl::matlab::mexErrMsgTxt(bool assertion, const char * text)
 {
   if(!assertion)

+ 3 - 0
include/igl/matlab/mexErrMsgTxt.h

@@ -8,6 +8,9 @@
 #ifndef IGL_MATLAB_MEXERRMSGTXT_H
 #define IGL_MATLAB_MEXERRMSGTXT_H
 #include "../igl_inline.h"
+// Overload mexErrMsgTxt to check an assertion then print text only if
+// assertion fails
+#include "mex.h"
 namespace igl
 {
   namespace matlab

+ 100 - 95
include/igl/opengl/MeshGL.cpp

@@ -165,109 +165,114 @@ IGL_INLINE void igl::opengl::MeshGL::init()
   }
   is_initialized = true;
   std::string mesh_vertex_shader_string =
-  "#version 150\n"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "uniform mat4 normal_matrix;"
-  "in vec3 position;"
-  "in vec3 normal;"
-  "out vec3 position_eye;"
-  "out vec3 normal_eye;"
-  "in vec4 Ka;"
-  "in vec4 Kd;"
-  "in vec4 Ks;"
-  "in vec2 texcoord;"
-  "out vec2 texcoordi;"
-  "out vec4 Kai;"
-  "out vec4 Kdi;"
-  "out vec4 Ksi;"
-
-  "void main()"
-  "{"
-  "  position_eye = vec3 (view * vec4 (position, 1.0));"
-  "  normal_eye = vec3 (normal_matrix * vec4 (normal, 0.0));"
-  "  normal_eye = normalize(normal_eye);"
-  "  gl_Position = proj * vec4 (position_eye, 1.0);" //proj * view * vec4(position, 1.0);"
-  "  Kai = Ka;"
-  "  Kdi = Kd;"
-  "  Ksi = Ks;"
-  "  texcoordi = texcoord;"
-  "}";
+R"(#version 150
+  uniform mat4 view;
+  uniform mat4 proj;
+  uniform mat4 normal_matrix;
+  in vec3 position;
+  in vec3 normal;
+  out vec3 position_eye;
+  out vec3 normal_eye;
+  in vec4 Ka;
+  in vec4 Kd;
+  in vec4 Ks;
+  in vec2 texcoord;
+  out vec2 texcoordi;
+  out vec4 Kai;
+  out vec4 Kdi;
+  out vec4 Ksi;
+
+  void main()
+  {
+    position_eye = vec3 (view * vec4 (position, 1.0));
+    normal_eye = vec3 (normal_matrix * vec4 (normal, 0.0));
+    normal_eye = normalize(normal_eye);
+    gl_Position = proj * vec4 (position_eye, 1.0); //proj * view * vec4(position, 1.0);"
+    Kai = Ka;
+    Kdi = Kd;
+    Ksi = Ks;
+    texcoordi = texcoord;
+  }
+)";
 
   std::string mesh_fragment_shader_string =
-  "#version 150\n"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "uniform vec4 fixed_color;"
-  "in vec3 position_eye;"
-  "in vec3 normal_eye;"
-  "uniform vec3 light_position_eye;"
-  "vec3 Ls = vec3 (1, 1, 1);"
-  "vec3 Ld = vec3 (1, 1, 1);"
-  "vec3 La = vec3 (1, 1, 1);"
-  "in vec4 Ksi;"
-  "in vec4 Kdi;"
-  "in vec4 Kai;"
-  "in vec2 texcoordi;"
-  "uniform sampler2D tex;"
-  "uniform float specular_exponent;"
-  "uniform float lighting_factor;"
-  "uniform float texture_factor;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "vec3 Ia = La * vec3(Kai);"    // ambient intensity
-
-  "vec3 vector_to_light_eye = light_position_eye - position_eye;"
-  "vec3 direction_to_light_eye = normalize (vector_to_light_eye);"
-  "float dot_prod = dot (direction_to_light_eye, normalize(normal_eye));"
-  "float clamped_dot_prod = max (dot_prod, 0.0);"
-  "vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;"    // Diffuse intensity
-
-  "vec3 reflection_eye = reflect (-direction_to_light_eye, normalize(normal_eye));"
-  "vec3 surface_to_viewer_eye = normalize (-position_eye);"
-  "float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);"
-  "dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);"
-  "float specular_factor = pow (dot_prod_specular, specular_exponent);"
-  "vec3 Is = Ls * vec3(Ksi) * specular_factor;"    // specular intensity
-  "vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);"
-  "outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;"
-  "if (fixed_color != vec4(0.0)) outColor = fixed_color;"
-  "}";
+R"(#version 150
+  uniform mat4 view;
+  uniform mat4 proj;
+  uniform vec4 fixed_color;
+  in vec3 position_eye;
+  in vec3 normal_eye;
+  uniform vec3 light_position_eye;
+  vec3 Ls = vec3 (1, 1, 1);
+  vec3 Ld = vec3 (1, 1, 1);
+  vec3 La = vec3 (1, 1, 1);
+  in vec4 Ksi;
+  in vec4 Kdi;
+  in vec4 Kai;
+  in vec2 texcoordi;
+  uniform sampler2D tex;
+  uniform float specular_exponent;
+  uniform float lighting_factor;
+  uniform float texture_factor;
+  out vec4 outColor;
+  void main()
+  {
+  vec3 Ia = La * vec3(Kai);    // ambient intensity
+
+  vec3 vector_to_light_eye = light_position_eye - position_eye;
+  vec3 direction_to_light_eye = normalize (vector_to_light_eye);
+  float dot_prod = dot (direction_to_light_eye, normalize(normal_eye));
+  float clamped_dot_prod = max (dot_prod, 0.0);
+  vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;    // Diffuse intensity
+
+  vec3 reflection_eye = reflect (-direction_to_light_eye, normalize(normal_eye));
+  vec3 surface_to_viewer_eye = normalize (-position_eye);
+  float dot_prod_specular = dot (reflection_eye, surface_to_viewer_eye);
+  dot_prod_specular = float(abs(dot_prod)==dot_prod) * max (dot_prod_specular, 0.0);
+  float specular_factor = pow (dot_prod_specular, specular_exponent);
+  vec3 Is = Ls * vec3(Ksi) * specular_factor;    // specular intensity
+  vec4 color = vec4(lighting_factor * (Is + Id) + Ia + (1.0-lighting_factor) * vec3(Kdi),(Kai.a+Ksi.a+Kdi.a)/3);
+  outColor = mix(vec4(1,1,1,1), texture(tex, texcoordi), texture_factor) * color;
+  if (fixed_color != vec4(0.0)) outColor = fixed_color;
+  }
+)";
 
   std::string overlay_vertex_shader_string =
-  "#version 150\n"
-  "uniform mat4 view;"
-  "uniform mat4 proj;"
-  "in vec3 position;"
-  "in vec3 color;"
-  "out vec3 color_frag;"
-
-  "void main()"
-  "{"
-  "  gl_Position = proj * view * vec4 (position, 1.0);"
-  "  color_frag = color;"
-  "}";
+R"(#version 150
+  uniform mat4 view;
+  uniform mat4 proj;
+  in vec3 position;
+  in vec3 color;
+  out vec3 color_frag;
+
+  void main()
+  {
+    gl_Position = proj * view * vec4 (position, 1.0);
+    color_frag = color;
+  };
+)";
 
   std::string overlay_fragment_shader_string =
-  "#version 150\n"
-  "in vec3 color_frag;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "  outColor = vec4(color_frag, 1.0);"
-  "}";
+R"(#version 150
+  in vec3 color_frag;
+  out vec4 outColor;
+  void main()
+  {
+    outColor = vec4(color_frag, 1.0);
+  }
+)";
 
   std::string overlay_point_fragment_shader_string =
-  "#version 150\n"
-  "in vec3 color_frag;"
-  "out vec4 outColor;"
-  "void main()"
-  "{"
-  "  if (length(gl_PointCoord - vec2(0.5)) > 0.5)"
-  "    discard;"
-  "  outColor = vec4(color_frag, 1.0);"
-  "}";
+R"(#version 150
+  in vec3 color_frag;
+  out vec4 outColor;
+  void main()
+  {
+    if (length(gl_PointCoord - vec2(0.5)) > 0.5)
+      discard;
+    outColor = vec4(color_frag, 1.0);
+  }
+)";
 
   init_buffers();
   create_shader_program(

+ 12 - 11
include/igl/opengl/ViewerData.cpp

@@ -528,7 +528,9 @@ IGL_INLINE void igl::opengl::ViewerData::updateGL(
 
       // Texture coordinates
       if (meshgl.dirty & MeshGL::DIRTY_UV)
+      {
         meshgl.V_uv_vbo = data.V_uv.cast<float>();
+      }
     }
     else
     {
@@ -541,36 +543,35 @@ IGL_INLINE void igl::opengl::ViewerData::updateGL(
 
       if (meshgl.dirty & MeshGL::DIRTY_AMBIENT)
       {
-        meshgl.V_ambient_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_ambient_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_ambient_vbo.col (i*3+j) = data.V_material_ambient.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_ambient_vbo.row(i*3+j) = data.V_material_ambient.row(data.F(i,j)).cast<float>();
       }
       if (meshgl.dirty & MeshGL::DIRTY_DIFFUSE)
       {
-        meshgl.V_diffuse_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_diffuse_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_diffuse_vbo.col (i*3+j) = data.V_material_diffuse.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_diffuse_vbo.row(i*3+j) = data.V_material_diffuse.row(data.F(i,j)).cast<float>();
       }
       if (meshgl.dirty & MeshGL::DIRTY_SPECULAR)
       {
-        meshgl.V_specular_vbo.resize(4,data.F.rows()*3);
+        meshgl.V_specular_vbo.resize(data.F.rows()*3,4);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-            meshgl.V_specular_vbo.col(i*3+j) = data.V_material_specular.row(data.F(i,j)).transpose().cast<float>();
+            meshgl.V_specular_vbo.row(i*3+j) = data.V_material_specular.row(data.F(i,j)).cast<float>();
       }
 
       if (meshgl.dirty & MeshGL::DIRTY_NORMAL)
       {
-        meshgl.V_normals_vbo.resize(3,data.F.rows()*3);
+        meshgl.V_normals_vbo.resize(data.F.rows()*3,3);
         for (unsigned i=0; i<data.F.rows();++i)
           for (unsigned j=0;j<3;++j)
-
-            meshgl.V_normals_vbo.col (i*3+j) =
+            meshgl.V_normals_vbo.row(i*3+j) =
                          per_corner_normals ?
-               data.F_normals.row(i*3+j).transpose().cast<float>() :
-               data.V_normals.row(data.F(i,j)).transpose().cast<float>();
+               data.F_normals.row(i*3+j).cast<float>() :
+               data.V_normals.row(data.F(i,j)).cast<float>();
 
 
         if (invert_normals)

+ 3 - 1
include/igl/opengl/glfw/Viewer.cpp

@@ -172,8 +172,8 @@ namespace glfw
       printf("Failed to load OpenGL and its extensions\n");
       return(-1);
     }
-    printf("OpenGL Version %d.%d loaded\n", GLVersion.major, GLVersion.minor);
     #if defined(DEBUG) || defined(_DEBUG)
+      printf("OpenGL Version %d.%d loaded\n", GLVersion.major, GLVersion.minor);
       int major, minor, rev;
       major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
       minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
@@ -413,6 +413,8 @@ namespace glfw
     data().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));
+
+    // Alec: why?
     if (data().V_uv.rows() == 0)
     {
       data().grid_texture();

+ 2 - 2
include/igl/opengl/glfw/Viewer.h

@@ -142,8 +142,8 @@ namespace glfw
     std::function<bool(Viewer& viewer, float delta_y)> callback_mouse_scroll;
     std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_pressed;
     // THESE SHOULD BE DEPRECATED:
-    std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_down;
-    std::function<bool(Viewer& viewer, unsigned char key, int modifiers)> callback_key_up;
+    std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_down;
+    std::function<bool(Viewer& viewer, unsigned int key, int modifiers)> callback_key_up;
     // Pointers to per-callback data
     void* callback_init_data;
     void* callback_pre_draw_data;

+ 70 - 76
include/igl/principal_curvature.cpp

@@ -105,13 +105,12 @@ public:
     }
 
 
-    IGL_INLINE static Quadric fit(std::vector<Eigen::Vector3d> &VV, bool zeroDetCheck, bool svd)
+    IGL_INLINE static Quadric fit(const std::vector<Eigen::Vector3d> &VV)
     {
-      using namespace std;
       assert(VV.size() >= 5);
       if (VV.size() < 5)
       {
-        cerr << "ASSERT FAILED!" << endl;
+        std::cerr << "ASSERT FAILED! fit function requires at least 5 points: Only " << VV.size() << " were given." << std::endl;
         exit(0);
       }
 
@@ -160,8 +159,6 @@ public:
   bool localMode; /* Use local mode */
   bool projectionPlaneCheck; /* Check collected vertices on tangent plane */
   bool montecarlo;
-  bool svd; /* Use svd calculation instead of pseudoinverse */
-  bool zeroDetCheck; /* Check if the determinant is close to zero */
   unsigned int montecarloN;
 
   searchType st; /* Use either a sphere search or a k-ring search */
@@ -179,23 +176,23 @@ public:
   IGL_INLINE CurvatureCalculator();
   IGL_INLINE void init(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F);
 
-  IGL_INLINE void finalEigenStuff (int, std::vector<Eigen::Vector3d>, Quadric );
-  IGL_INLINE void fitQuadric (Eigen::Vector3d, std::vector<Eigen::Vector3d> ref, const  std::vector<int>& , Quadric *);
-  IGL_INLINE void applyProjOnPlane(Eigen::Vector3d, std::vector<int>, std::vector<int>&);
+  IGL_INLINE void finalEigenStuff(int, const std::vector<Eigen::Vector3d>&, Quadric&);
+  IGL_INLINE void fitQuadric(const Eigen::Vector3d&, const std::vector<Eigen::Vector3d>& ref, const std::vector<int>& , Quadric *);
+  IGL_INLINE void applyProjOnPlane(const Eigen::Vector3d&, const std::vector<int>&, std::vector<int>&);
   IGL_INLINE void getSphere(const int, const double, std::vector<int>&, int min);
   IGL_INLINE void getKRing(const int, const double,std::vector<int>&);
-  IGL_INLINE Eigen::Vector3d project(Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d);
-  IGL_INLINE void computeReferenceFrame(int, Eigen::Vector3d, std::vector<Eigen::Vector3d>&);
-  IGL_INLINE void getAverageNormal(int, std::vector<int>, Eigen::Vector3d&);
-  IGL_INLINE void getProjPlane(int, std::vector<int>, Eigen::Vector3d&);
-  IGL_INLINE void applyMontecarlo(std::vector<int>&,std::vector<int>*);
+  IGL_INLINE Eigen::Vector3d project(const Eigen::Vector3d&, const Eigen::Vector3d&, const Eigen::Vector3d&);
+  IGL_INLINE void computeReferenceFrame(int, const Eigen::Vector3d&, std::vector<Eigen::Vector3d>&);
+  IGL_INLINE void getAverageNormal(int, const std::vector<int>&, Eigen::Vector3d&);
+  IGL_INLINE void getProjPlane(int, const std::vector<int>&, Eigen::Vector3d&);
+  IGL_INLINE void applyMontecarlo(const std::vector<int>&,std::vector<int>*);
   IGL_INLINE void computeCurvature();
-  IGL_INLINE void printCurvature(std::string outpath);
+  IGL_INLINE void printCurvature(const std::string& outpath);
   IGL_INLINE double getAverageEdge();
 
-  IGL_INLINE static int rotateForward (float *v0, float *v1, float *v2)
+  IGL_INLINE static int rotateForward (double *v0, double *v1, double *v2)
   {
-    float t;
+    double t;
 
     if (std::abs(*v2) >= std::abs(*v1) && std::abs(*v2) >= std::abs(*v0))
       return 0;
@@ -208,9 +205,9 @@ public:
     return 1 + rotateForward (v0, v1, v2);
   }
 
-  IGL_INLINE static void rotateBackward (int nr, float *v0, float *v1, float *v2)
+  IGL_INLINE static void rotateBackward (int nr, double *v0, double *v1, double *v2)
   {
-    float t;
+    double t;
 
     if (nr == 0)
       return;
@@ -223,18 +220,18 @@ public:
     rotateBackward (nr - 1, v0, v1, v2);
   }
 
-  IGL_INLINE static Eigen::Vector3d chooseMax (Eigen::Vector3d n, Eigen::Vector3d abc, float ab)
+  IGL_INLINE static Eigen::Vector3d chooseMax (Eigen::Vector3d n, Eigen::Vector3d abc, double ab)
   {
-    int i, max_i;
-    float max_sp;
+    int max_i;
+    double max_sp;
     Eigen::Vector3d nt[8];
 
     n.normalize ();
     abc.normalize ();
 
-    max_sp = - std::numeric_limits<float>::max();
+    max_sp = - std::numeric_limits<double>::max();
 
-    for (i = 0; i < 4; i++)
+    for (int i = 0; i < 4; ++i)
     {
       nt[i] = n;
       if (ab > 0)
@@ -290,7 +287,6 @@ public:
         max_i = i;
       }
     }
-
     return nt[max_i];
   }
 
@@ -315,8 +311,6 @@ IGL_INLINE CurvatureCalculator::CurvatureCalculator()
   this->montecarlo=false;
   this->montecarloN=0;
   this->kRing=3;
-  this->svd=true;
-  this->zeroDetCheck=true;
   this->curvatureComputed=false;
   this->expStep=true;
 }
@@ -337,7 +331,7 @@ IGL_INLINE void CurvatureCalculator::init(const Eigen::MatrixXd& V, const Eigen:
   igl::per_vertex_normals(V, F, face_normals, vertex_normals);
 }
 
-IGL_INLINE void CurvatureCalculator::fitQuadric (Eigen::Vector3d v, std::vector<Eigen::Vector3d> ref, const std::vector<int>& vv, Quadric *q)
+IGL_INLINE void CurvatureCalculator::fitQuadric(const Eigen::Vector3d& v, const std::vector<Eigen::Vector3d>& ref, const std::vector<int>& vv, Quadric *q)
 {
   std::vector<Eigen::Vector3d> points;
   points.reserve (vv.size());
@@ -354,17 +348,25 @@ IGL_INLINE void CurvatureCalculator::fitQuadric (Eigen::Vector3d v, std::vector<
     double z = vTang.dot(ref[2]);
     points.push_back(Eigen::Vector3d (x,y,z));
   }
-  *q = Quadric::fit (points, zeroDetCheck, svd);
+  if (points.size() < 5)
+  {
+    std::cerr << "ASSERT FAILED! fit function requires at least 5 points: Only " << points.size() << " were given." << std::endl;
+    *q = Quadric(0,0,0,0,0);
+  }
+  else
+  {
+    *q = Quadric::fit (points);
+  }
 }
 
-IGL_INLINE void CurvatureCalculator::finalEigenStuff (int i, std::vector<Eigen::Vector3d> ref, Quadric q)
+IGL_INLINE void CurvatureCalculator::finalEigenStuff(int i, const std::vector<Eigen::Vector3d>& ref, Quadric& q)
 {
 
-  double a = q.a();
-  double b = q.b();
-  double c = q.c();
-  double d = q.d();
-  double e = q.e();
+  const double a = q.a();
+  const double b = q.b();
+  const double c = q.c();
+  const double d = q.d();
+  const double e = q.e();
 
 //  if (fabs(a) < 10e-8 || fabs(b) < 10e-8)
 //  {
@@ -457,7 +459,7 @@ IGL_INLINE void CurvatureCalculator::getKRing(const int start, const double r, s
     vv.push_back(toVisit);
     if (distance<(int)r)
     {
-      for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
+      for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); ++i)
       {
         int neighbor=vertex_to_vertices[toVisit][i];
         if (!visited[neighbor])
@@ -488,13 +490,13 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
     int toVisit=queue->front();
     queue->pop_front();
     vv.push_back(toVisit);
-    for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
+    for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); ++i)
     {
       int neighbor=vertex_to_vertices[toVisit][i];
       if (!visited[neighbor])
       {
         Eigen::Vector3d neigh=vertices.row(neighbor);
-        float distance=(me-neigh).norm();
+        double distance=(me-neigh).norm();
         if (distance<r)
           queue->push_back(neighbor);
         else if ((int)vv.size()<min)
@@ -508,13 +510,13 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
     std::pair<int, double> cand=extra_candidates->top();
     extra_candidates->pop();
     vv.push_back(cand.first);
-    for (unsigned int i=0; i<vertex_to_vertices[cand.first].size(); i++)
+    for (unsigned int i=0; i<vertex_to_vertices[cand.first].size(); ++i)
     {
       int neighbor=vertex_to_vertices[cand.first][i];
       if (!visited[neighbor])
       {
         Eigen::Vector3d neigh=vertices.row(neighbor);
-        float distance=(me-neigh).norm();
+        double distance=(me-neigh).norm();
         extra_candidates->push(std::pair<int,double>(neighbor,distance));
         visited[neighbor]=true;
       }
@@ -525,16 +527,15 @@ IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r,
   free(visited);
 }
 
-IGL_INLINE Eigen::Vector3d CurvatureCalculator::project(Eigen::Vector3d v, Eigen::Vector3d  vp, Eigen::Vector3d ppn)
+IGL_INLINE Eigen::Vector3d CurvatureCalculator::project(const Eigen::Vector3d& v, const Eigen::Vector3d& vp, const Eigen::Vector3d& ppn)
 {
   return (vp - (ppn * ((vp - v).dot(ppn))));
 }
 
-IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, Eigen::Vector3d normal, std::vector<Eigen::Vector3d>& ref )
+IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, const Eigen::Vector3d& normal, std::vector<Eigen::Vector3d>& ref )
 {
 
-  Eigen::Vector3d longest_v=Eigen::Vector3d::Zero();
-  longest_v=Eigen::Vector3d(vertices.row(vertex_to_vertices[i][0]));
+  Eigen::Vector3d longest_v=Eigen::Vector3d(vertices.row(vertex_to_vertices[i][0]));
 
   longest_v=(project(vertices.row(i),longest_v,normal)-Eigen::Vector3d(vertices.row(i))).normalized();
 
@@ -546,25 +547,25 @@ IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, Eigen::Vector3
   ref[2]=normal;
 }
 
-IGL_INLINE void CurvatureCalculator::getAverageNormal(int j, std::vector<int> vv, Eigen::Vector3d& normal)
+IGL_INLINE void CurvatureCalculator::getAverageNormal(int j, const std::vector<int>& vv, Eigen::Vector3d& normal)
 {
   normal=(vertex_normals.row(j)).normalized();
   if (localMode)
     return;
 
-  for (unsigned int i=0; i<vv.size(); i++)
+  for (unsigned int i=0; i<vv.size(); ++i)
   {
     normal+=vertex_normals.row(vv[i]).normalized();
   }
   normal.normalize();
 }
 
-IGL_INLINE void CurvatureCalculator::getProjPlane(int j, std::vector<int> vv, Eigen::Vector3d& ppn)
+IGL_INLINE void CurvatureCalculator::getProjPlane(int j, const std::vector<int>& vv, Eigen::Vector3d& ppn)
 {
   int nr;
-  float a, b, c;
-  float nx, ny, nz;
-  float abcq;
+  double a, b, c;
+  double nx, ny, nz;
+  double abcq;
 
   a = b = c = 0;
 
@@ -605,9 +606,9 @@ IGL_INLINE double CurvatureCalculator::getAverageEdge()
   double sum = 0;
   int count = 0;
 
-  for (int i = 0; i<faces.rows(); i++)
+  for (int i = 0; i<faces.rows(); ++i)
   {
-    for (short unsigned j=0; j<3; j++)
+    for (short unsigned j=0; j<3; ++j)
     {
       Eigen::Vector3d p1=vertices.row(faces.row(i)[j]);
       Eigen::Vector3d p2=vertices.row(faces.row(i)[(j+1)%3]);
@@ -623,14 +624,14 @@ IGL_INLINE double CurvatureCalculator::getAverageEdge()
 }
 
 
-IGL_INLINE void CurvatureCalculator::applyProjOnPlane(Eigen::Vector3d ppn, std::vector<int> vin, std::vector<int> &vout)
+IGL_INLINE void CurvatureCalculator::applyProjOnPlane(const Eigen::Vector3d& ppn, const std::vector<int>& vin, std::vector<int> &vout)
 {
-  for (std::vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
-    if (vertex_normals.row(*vpi) * ppn > 0.0f)
-      vout.push_back (*vpi);
+  for (std::vector<int>::const_iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
+    if (vertex_normals.row(*vpi) * ppn > 0.0)
+      vout.push_back(*vpi);
 }
 
-IGL_INLINE void CurvatureCalculator::applyMontecarlo(std::vector<int>& vin, std::vector<int> *vout)
+IGL_INLINE void CurvatureCalculator::applyMontecarlo(const std::vector<int>& vin, std::vector<int> *vout)
 {
   if (montecarloN >= vin.size ())
   {
@@ -639,24 +640,22 @@ IGL_INLINE void CurvatureCalculator::applyMontecarlo(std::vector<int>& vin, std:
   }
 
   float p = ((float) montecarloN) / (float) vin.size();
-  for (std::vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
+  for (std::vector<int>::const_iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
   {
     float r;
     if ((r = ((float)rand () / RAND_MAX)) < p)
     {
-      vout->push_back (*vpi);
+      vout->push_back(*vpi);
     }
   }
 }
 
 IGL_INLINE void CurvatureCalculator::computeCurvature()
 {
-  using namespace std;
-
   //CHECK che esista la mesh
-  size_t vertices_count=vertices.rows() ;
+  const size_t vertices_count=vertices.rows();
 
-  if (vertices_count <=0)
+  if (vertices_count ==0)
     return;
 
   curvDir=std::vector< std::vector<Eigen::Vector3d> >(vertices_count);
@@ -691,10 +690,9 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
         return;
     }
 
-    std::vector<Eigen::Vector3d> ref(3);
     if (vv.size()<6)
     {
-      std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
+      std::cerr << "Could not compute curvature of radius " << scaledRadius << std::endl;
       return;
     }
 
@@ -704,8 +702,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
       vvtmp.reserve (vv.size ());
       applyProjOnPlane (vertex_normals.row(i), vv, vvtmp);
       if (vvtmp.size() >= 6 && vvtmp.size()<vv.size())
-	  vv = vvtmp;
-
+        vv = vvtmp;
     }
 
 
@@ -723,7 +720,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
     }
     if (vv.size()<6)
     {
-      std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
+      std::cerr << "Could not compute curvature of radius " << scaledRadius << std::endl;
       return;
     }
     if (montecarlo)
@@ -737,6 +734,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
 
     if (vv.size()<6)
       return;
+    std::vector<Eigen::Vector3d> ref(3);
     computeReferenceFrame(i,normal,ref);
 
     Quadric q;
@@ -748,7 +746,7 @@ IGL_INLINE void CurvatureCalculator::computeCurvature()
   curvatureComputed=true;
 }
 
-IGL_INLINE void CurvatureCalculator::printCurvature(std::string outpath)
+IGL_INLINE void CurvatureCalculator::printCurvature(const std::string& outpath)
 {
   using namespace std;
   if (!curvatureComputed)
@@ -765,7 +763,7 @@ IGL_INLINE void CurvatureCalculator::printCurvature(std::string outpath)
 
   int vertices_count=vertices.rows();
   of << vertices_count << endl;
-  for (int i=0; i<vertices_count; i++)
+  for (int i=0; i<vertices_count; ++i)
   {
     of << curv[i][0] << " " << curv[i][1] << " " << curvDir[i][0][0] << " " << curvDir[i][0][1] << " " << curvDir[i][0][2] << " " <<
     curvDir[i][1][0] << " " << curvDir[i][1][1] << " " << curvDir[i][1][2] << endl;
@@ -792,12 +790,10 @@ IGL_INLINE void igl::principal_curvature(
   unsigned radius,
   bool useKring)
 {
-  using namespace std;
-
   if (radius < 2)
   {
     radius = 2;
-    cout << "WARNING: igl::principal_curvature needs a radius >= 2, fixing it to 2." << endl;
+    std::cout << "WARNING: igl::principal_curvature needs a radius >= 2, fixing it to 2." << std::endl;
   }
 
   // Preallocate memory
@@ -823,10 +819,8 @@ IGL_INLINE void igl::principal_curvature(
   cc.computeCurvature();
 
   // Copy it back
-  for (unsigned i=0; i<V.rows(); i++)
+  for (unsigned i=0; i<V.rows(); ++i)
   {
-    Eigen::Vector3d d1;
-    Eigen::Vector3d d2;
     PD1.row(i) << cc.curvDir[i][0][0], cc.curvDir[i][0][1], cc.curvDir[i][0][2];
     PD2.row(i) << cc.curvDir[i][1][0], cc.curvDir[i][1][1], cc.curvDir[i][1][2];
     PD1.row(i).normalize();
@@ -843,7 +837,7 @@ IGL_INLINE void igl::principal_curvature(
 
     if (PD1.row(i) * PD2.row(i).transpose() > 10e-6)
     {
-      cerr << "PRINCIPAL_CURVATURE: Something is wrong with vertex: i" << endl;
+      std::cerr << "PRINCIPAL_CURVATURE: Something is wrong with vertex: " << i << std::endl;
       PD1.row(i) *= 0;
       PD2.row(i) *= 0;
     }

+ 5 - 3
include/igl/slice_cached.h

@@ -14,9 +14,11 @@
 namespace igl
 {  
 
-  // Act like the matlab X(row_indices,col_indices) operator, where
-  // row_indices, col_indices are non-negative integer indices. This is a fast version
-  // of igl::slice that can analyze and store the sparsity structure. It is slower at the // first evaluation (slice_cached_precompute), but faster on the subsequent ones.
+  // Act like the matlab X(row_indices,col_indices) operator, where row_indices,
+  // col_indices are non-negative integer indices. This is a fast version of
+  // igl::slice that can analyze and store the sparsity structure. It is slower
+  // at the irst evaluation (slice_cached_precompute), but faster on the
+  // subsequent ones.
   // 
   // Inputs:
   //   X  m by n matrix

+ 41 - 43
shared/cmake/libigl.cmake

@@ -1,24 +1,42 @@
 cmake_minimum_required(VERSION 3.1)
 
+### Find packages to populate default options ###
+#
+# COMPONENTS should match subsequent calls
+find_package(CGAL COMPONENTS Core) # --> CGAL_FOUND
+find_package(Boost 1.48 COMPONENTS thread system) # --> BOOST_FOUND
+if(CGAL_FOUND AND BOOST_FOUND)
+  set(CGAL_AND_BOOST_FOUND TRUE)
+endif()
+find_package(Matlab COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY) # --> Matlab_FOUND
+find_package(MOSEK) # --> MOSEK_FOUND
+find_package(OpenGL) # --> OPENGL_FOUND
+
 ### Available options ###
 option(LIBIGL_USE_STATIC_LIBRARY     "Use libigl as static library" OFF)
 option(LIBIGL_WITH_ANTTWEAKBAR       "Use AntTweakBar"    OFF)
-option(LIBIGL_WITH_CGAL              "Use CGAL"           ON)
+option(LIBIGL_WITH_CGAL              "Use CGAL"           "${CGAL_AND_BOOST_FOUND}")
 option(LIBIGL_WITH_COMISO            "Use CoMiso"         ON)
 option(LIBIGL_WITH_CORK              "Use Cork"           OFF)
 option(LIBIGL_WITH_EMBREE            "Use Embree"         OFF)
 option(LIBIGL_WITH_LIM               "Use LIM"            ON)
-option(LIBIGL_WITH_MATLAB            "Use Matlab"         ON)
-option(LIBIGL_WITH_MOSEK             "Use MOSEK"          ON)
-option(LIBIGL_WITH_OPENGL            "Use OpenGL"         ON)
-option(LIBIGL_WITH_OPENGL_GLFW       "Use GLFW"           ON)
-option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use ImGui"          ON)
+option(LIBIGL_WITH_MATLAB            "Use Matlab"         "${Matlab_FOUND}")
+option(LIBIGL_WITH_MOSEK             "Use MOSEK"          "${MOSEK_FOUND}")
+option(LIBIGL_WITH_NANOGUI           "Use Nanogui menu"   OFF)
+option(LIBIGL_WITH_OPENGL            "Use OpenGL"         "${OPENGL_FOUND}")
+option(LIBIGL_WITH_OPENGL_GLFW       "Use GLFW"           "${OPENGL_FOUND}")
+option(LIBIGL_WITH_OPENGL_GLFW_IMGUI "Use IMGUI"          OFF)
 option(LIBIGL_WITH_PNG               "Use PNG"            ON)
 option(LIBIGL_WITH_TETGEN            "Use Tetgen"         ON)
 option(LIBIGL_WITH_TRIANGLE          "Use Triangle"       ON)
+option(LIBIGL_WITH_VIEWER            "Use OpenGL viewer"  "${OPENGL_FOUND}")
 option(LIBIGL_WITH_XML               "Use XML"            ON)
 option(LIBIGL_WITH_PYTHON            "Use Python"         OFF)
 
+if(LIBIGL_WITH_VIEWER AND (NOT LIBIGL_WITH_OPENGL_GLFW OR NOT LIBIGL_WITH_OPENGL) )
+  message(FATAL_ERROR "LIBIGL_WITH_VIEWER=ON requires LIBIGL_WITH_OPENGL_GLFW=ON and LIBIGL_WITH_OPENGL=ON")
+endif()
+
 ################################################################################
 
 ### Configuration
@@ -128,19 +146,15 @@ endif()
 if(LIBIGL_WITH_CGAL)
   # CGAL Core is needed for
   # `Exact_predicates_exact_constructions_kernel_with_sqrt`
-  find_package(CGAL COMPONENTS Core)
-  if(CGAL_FOUND)
-    compile_igl_module("cgal")
-    if(WIN32)
-      set(Boost_USE_STATIC_LIBS ON) # Favor static Boost libs on Windows
-    endif()
-    target_include_directories(igl_cgal ${IGL_SCOPE} "${GMP_INCLUDE_DIR}" "${MPFR_INCLUDE_DIR}")
-    find_package(Boost 1.48 REQUIRED thread system)
-    target_include_directories(igl_cgal ${IGL_SCOPE} ${CGAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
-    target_link_libraries(igl_cgal ${IGL_SCOPE} CGAL::CGAL CGAL::CGAL_Core ${Boost_LIBRARIES})
-  else()
-    set(LIBIGL_WITH_CGAL OFF CACHE BOOL "" FORCE)
+  find_package(CGAL REQUIRED COMPONENTS Core)
+  compile_igl_module("cgal")
+  if(WIN32)
+    set(Boost_USE_STATIC_LIBS ON) # Favor static Boost libs on Windows
   endif()
+  target_include_directories(igl_cgal ${IGL_SCOPE} "${GMP_INCLUDE_DIR}" "${MPFR_INCLUDE_DIR}")
+  find_package(Boost 1.48 REQUIRED thread system)
+  target_include_directories(igl_cgal ${IGL_SCOPE} ${CGAL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
+  target_link_libraries(igl_cgal ${IGL_SCOPE} CGAL::CGAL CGAL::CGAL_Core ${Boost_LIBRARIES})
 endif()
 
 # Helper function for `igl_copy_cgal_dll()`
@@ -241,28 +255,20 @@ endif()
 ################################################################################
 ### Compile the matlab part ###
 if(LIBIGL_WITH_MATLAB)
-  find_package(Matlab)
-  if(MATLAB_FOUND)
-    compile_igl_module("matlab")
-    target_link_libraries(igl_matlab ${IGL_SCOPE} ${MATLAB_LIBRARIES})
-    target_include_directories(igl_matlab ${IGL_SCOPE} ${MATLAB_INCLUDE_DIR})
-  else()
-    set(LIBIGL_WITH_MATLAB OFF CACHE BOOL "" FORCE)
-  endif()
+  find_package(Matlab REQUIRED COMPONENTS MEX_COMPILER MX_LIBRARY ENG_LIBRARY)
+  compile_igl_module("matlab")
+  target_link_libraries(igl_matlab ${IGL_SCOPE} ${Matlab_LIBRARIES})
+  target_include_directories(igl_matlab ${IGL_SCOPE} ${Matlab_INCLUDE_DIRS})
 endif()
 
 ################################################################################
 ### Compile the mosek part ###
 if(LIBIGL_WITH_MOSEK)
-  find_package(MOSEK)
-  if(MOSEK_FOUND)
-    compile_igl_module("mosek")
-    target_link_libraries(igl_mosek ${IGL_SCOPE} ${MOSEK_LIBRARIES})
-    target_include_directories(igl_mosek ${IGL_SCOPE} ${MOSEK_INCLUDE_DIRS})
-    target_compile_definitions(igl_mosek ${IGL_SCOPE} -DLIBIGL_WITH_MOSEK)
-  else()
-    set(LIBIGL_WITH_MOSEK OFF CACHE BOOL "" FORCE)
-  endif()
+  find_package(MOSEK REQUIRED)
+  compile_igl_module("mosek")
+  target_link_libraries(igl_mosek ${IGL_SCOPE} ${MOSEK_LIBRARIES})
+  target_include_directories(igl_mosek ${IGL_SCOPE} ${MOSEK_INCLUDE_DIRS})
+  target_compile_definitions(igl_mosek ${IGL_SCOPE} -DLIBIGL_WITH_MOSEK)
 endif()
 
 ################################################################################
@@ -297,9 +303,6 @@ if(LIBIGL_WITH_OPENGL_GLFW)
       add_subdirectory(${LIBIGL_EXTERNAL}/glfw glfw)
     endif()
     target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw)
-  else()
-    message(WARNING "GLFW module could not be compiled")
-    set(LIBIGL_WITH_OPENGL_GLFW OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 
@@ -314,9 +317,6 @@ if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
       add_subdirectory(${LIBIGL_EXTERNAL}/imgui imgui)
     endif()
     target_link_libraries(igl_opengl_glfw_imgui ${IGL_SCOPE} igl_opengl_glfw imgui)
-  else()
-    message(WARNING "ImGui module could not be compiled")
-    set(LIBIGL_WITH_OPENGL_GLFW_IMGUI OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 
@@ -332,8 +332,6 @@ if(LIBIGL_WITH_PNG)
     endif()
     compile_igl_module("png" "")
     target_link_libraries(igl_png ${IGL_SCOPE} igl_stb_image igl_opengl)
-  else()
-    set(LIBIGL_WITH_PNG OFF CACHE BOOL "" FORCE)
   endif()
 endif()
 

+ 1 - 1
tutorial/107_MultipleMeshes/CMakeLists.txt

@@ -2,4 +2,4 @@ cmake_minimum_required(VERSION 2.8.12)
 project(107_MultipleMeshes)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw igl::opengl_glfw_imgui tutorials)
+target_link_libraries(${PROJECT_NAME}_bin igl::core igl::opengl igl::opengl_glfw tutorials)

+ 15 - 48
tutorial/107_MultipleMeshes/main.cpp

@@ -1,68 +1,35 @@
 #include "tutorial_shared_path.h"
 #include <igl/opengl/glfw/Viewer.h>
-#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
-#include <igl/opengl/glfw/imgui/ImGuiHelpers.h>
+#include <GLFW/glfw3.h>
 #include <string>
-#include <map>
 #include <iostream>
 
-// Add custom data to a viewer mesh
-struct MeshData
-{
-  std::string name;
-  Eigen::RowVector3d color;
-};
-int last_colored_index = -1;
-
-// Set colors of each mesh
-void update_colors(igl::opengl::glfw::Viewer &viewer)
-{
-  for (auto &data : viewer.data_list)
-  {
-    data.set_colors(data.attr<MeshData>().color);
-  }
-  viewer.data_list[viewer.selected_data_index].set_colors(Eigen::RowVector3d(0.9,0.1,0.1));
-  last_colored_index = viewer.selected_data_index;
-}
-
 int main(int argc, char * argv[])
 {
   igl::opengl::glfw::Viewer viewer;
-  auto names = {"cube.obj","sphere.obj","xcylinder.obj","ycylinder.obj","zcylinder.obj"};
+  const auto names = 
+    {"cube.obj","sphere.obj","xcylinder.obj","ycylinder.obj","zcylinder.obj"};
   for(const auto & name : names)
   {
     viewer.load_mesh_from_file(std::string(TUTORIAL_SHARED_PATH) + "/" + name);
-    viewer.data().attr<MeshData>().name = name;
-    viewer.data().attr<MeshData>().color = Eigen::RowVector3d::Random();
   }
 
-  // Attach a custom menu
-  igl::opengl::glfw::imgui::ImGuiMenu menu;
-  viewer.plugins.push_back(&menu);
-
-  // Customize default menu
-  menu.draw_viewer_menu_func = [&]()
-  {
-    if (ImGui::Combo("Selected Mesh", (int *) &viewer.selected_data_index,
-          [&](int i) { return viewer.data_list[i].attr<MeshData>().name.c_str(); },
-          viewer.data_list.size())
-      || last_colored_index != viewer.selected_data_index)
-    {
-      update_colors(viewer);
-    }
-  };
-
-  // Color each mesh differently
-  update_colors(viewer);
-
-  viewer.callback_key_down =
+  // Set colors of each mesh by selecting its index first
+  viewer.selected_data_index = 0;
+  viewer.data().set_colors(Eigen::RowVector3d(0.8,0.47,0.22));
+  viewer.selected_data_index = 1;
+  viewer.data().set_colors(Eigen::RowVector3d(0.6,0.01,0.11));
+  viewer.selected_data_index = 2;
+  viewer.data().set_colors(Eigen::RowVector3d(0.37,0.06,0.25));
+  viewer.selected_data_index = 3;
+  viewer.data().set_colors(Eigen::RowVector3d(1,1,1));
+
+  viewer.callback_key_down = 
     [&](igl::opengl::glfw::Viewer &, unsigned int key, int mod)
   {
-    // Delete
-    if(key == '3')
+    if(key == GLFW_KEY_BACKSPACE)
     {
       viewer.erase_mesh(viewer.selected_data_index);
-      update_colors(viewer);
       return true;
     }
     return false;

+ 47 - 46
tutorial/206_GeodesicDistance/main.cpp

@@ -3,71 +3,72 @@
 #include <igl/exact_geodesic.h>
 #include <igl/colormap.h>
 #include <igl/unproject_onto_mesh.h>
-
 #include <iostream>
 #include "tutorial_shared_path.h"
 
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
 
-void plotMeshDistance(igl::opengl::glfw::Viewer& viewer, const Eigen::MatrixXd& V, const Eigen::MatrixXi& F, const Eigen::VectorXd& d, const double strip_size )
+int main(int argc, char *argv[])
 {
-    // Rescale the function depending on the strip size
-    Eigen::VectorXd f = (d/strip_size);
+  using namespace Eigen;
+  using namespace std;
+  Eigen::MatrixXd V;
+  Eigen::MatrixXi F;
+  igl::opengl::glfw::Viewer viewer;
+  // Load a mesh in OFF format
+  igl::readOBJ(TUTORIAL_SHARED_PATH "/armadillo.obj", V, F);
 
+  const auto update_distance = [&](const int vid)
+  {
+    Eigen::VectorXi VS,FS,VT,FT;
+    // The selected vertex is the source
+    VS.resize(1);
+    VS << vid;
+    // All vertices are the targets
+    VT.setLinSpaced(V.rows(),0,V.rows()-1);
+    Eigen::VectorXd d;
+    std::cout<<"Computing geodesic distance to vertex "<<vid<<"..."<<std::endl;
+    igl::exact_geodesic(V,F,VS,FS,VT,FT,d);
+    const double strip_size = 0.05;
     // The function should be 1 on each integer coordinate
-    f = (f*M_PI).array().sin().abs();
-
+    d = (d/strip_size*M_PI).array().sin().abs().eval();
     // Compute per-vertex colors
     Eigen::MatrixXd C;
-    igl::colormap(igl::COLOR_MAP_TYPE_INFERNO,f,false,C);
-
+    igl::colormap(igl::COLOR_MAP_TYPE_INFERNO,d,false,C);
     // Plot the mesh
     viewer.data().set_mesh(V, F);
     viewer.data().set_colors(C);
-}
-
-int main(int argc, char *argv[])
-{
-  using namespace Eigen;
-  using namespace std;
-
-  // Load a mesh in OFF format
-  igl::readOBJ(TUTORIAL_SHARED_PATH "/armadillo.obj", V, F);
-
+  };
 
-  igl::opengl::glfw::Viewer viewer;
   // Plot a distance when a vertex is picked
   viewer.callback_mouse_down =
   [&](igl::opengl::glfw::Viewer& viewer, int, int)->bool
   {
-      int fid;
-      Eigen::Vector3f bc;
-      // Cast a ray in the view direction starting from the mouse position
-      double x = viewer.current_mouse_x;
-      double y = viewer.core.viewport(3) - viewer.current_mouse_y;
-      if(igl::unproject_onto_mesh(Eigen::Vector2f(x,y), viewer.core.view,
-                                  viewer.core.proj, viewer.core.viewport, V, F, fid, bc))
-      {
-          int max;
-          bc.maxCoeff(&max);
-          int vid = F(fid,max);
-          Eigen::VectorXi VS,FS,VT,FT;
-          // The selected vertex is the source
-          VS.resize(1);
-          VS << vid;
-          // All vertices are the targets
-          VT.setLinSpaced(V.rows(),0,V.rows()-1);
-          Eigen::VectorXd d;
-          igl::exact_geodesic(V,F,VS,FS,VT,FT,d);
-
-          plotMeshDistance(viewer,V,F,d,0.05);
-      }
-      return false;
+    int fid;
+    Eigen::Vector3f bc;
+    // Cast a ray in the view direction starting from the mouse position
+    double x = viewer.current_mouse_x;
+    double y = viewer.core.viewport(3) - viewer.current_mouse_y;
+    if(igl::unproject_onto_mesh(
+      Eigen::Vector2f(x,y),
+      viewer.core.view,
+      viewer.core.proj,
+      viewer.core.viewport,
+      V,
+      F,
+      fid,
+      bc))
+    {
+      int max;
+      bc.maxCoeff(&max);
+      int vid = F(fid,max);
+      update_distance(vid);
+      return true;
+    }
+    return false;
   };
   viewer.data().set_mesh(V,F);
 
-  cout << "Press [space] to smooth." << endl;;
-  cout << "Press [r] to reset." << endl;;
+  cout << "Click on mesh to define new source.\n" << std::endl;
+  update_distance(0);
   return viewer.launch();
 }

+ 5 - 0
tutorial/306_EigenDecomposition/main.cpp

@@ -36,6 +36,7 @@ int main(int argc, char * argv[])
   {
     cout<<"failed."<<endl;
   }
+  // Normalize
   U = ((U.array()-U.minCoeff())/(U.maxCoeff()-U.minCoeff())).eval();
 
   igl::opengl::glfw::Viewer viewer;
@@ -67,5 +68,9 @@ int main(int argc, char * argv[])
   };
   viewer.callback_key_down(viewer,' ',0);
   viewer.data().show_lines = false;
+  std::cout<<
+R"(
+  [space] Cycle through eigen modes
+)";
   viewer.launch();
 }

+ 3 - 1
tutorial/CMakeLists.txt

@@ -53,7 +53,9 @@ if(TUTORIALS_CHAPTER1)
   add_subdirectory("103_Events")
   add_subdirectory("104_Colors")
   add_subdirectory("105_Overlays")
-  add_subdirectory("106_ViewerMenu")
+  if(LIBIGL_WITH_OPENGL_GLFW_IMGUI)
+    add_subdirectory("106_ViewerMenu")
+  endif()
   add_subdirectory("107_MultipleMeshes")
 endif()