Преглед изворни кода

Merge branch 'dev' into fast-winding-number-soups

Jérémie Dumas пре 6 година
родитељ
комит
4dd39445ce
38 измењених фајлова са 256 додато и 119 уклоњено
  1. 14 1
      cmake/libigl.cmake
  2. 2 2
      include/igl/EPS.h
  3. 1 1
      include/igl/bounding_box.cpp
  4. 2 2
      include/igl/copyleft/quadprog.cpp
  5. 42 16
      include/igl/file_dialog_open.cpp
  6. 38 11
      include/igl/file_dialog_save.cpp
  7. 1 0
      include/igl/internal_angles.cpp
  8. 1 1
      include/igl/jet.cpp
  9. 1 0
      include/igl/launch_medit.cpp
  10. 6 6
      include/igl/opengl/glfw/imgui/ImGuiTraits.h
  11. 7 3
      include/igl/path_to_executable.cpp
  12. 1 1
      include/igl/signed_distance.cpp
  13. 15 10
      include/igl/sort_triangles.cpp
  14. 4 4
      include/igl/sort_triangles.h
  15. 2 1
      python/modules/py_igl_opengl_glfw.cpp
  16. 2 2
      python/tutorial/103_Events.py
  17. 1 1
      python/tutorial/205_Laplacian.py
  18. 5 5
      python/tutorial/401_BiharmonicDeformation.py
  19. 6 6
      python/tutorial/402_PolyharmonicDeformation.py
  20. 5 5
      python/tutorial/403_BoundedBiharmonicWeights.py
  21. 9 9
      python/tutorial/404_DualQuaternionSkinning.py
  22. 4 4
      python/tutorial/405_AsRigidAsPossible.py
  23. 2 2
      python/tutorial/501_HarmonicParam.py
  24. 2 2
      python/tutorial/502_LSCMParam.py
  25. 2 2
      python/tutorial/503_ARAPParam.py
  26. 1 1
      python/tutorial/505_MIQ.py
  27. 4 4
      python/tutorial/606_AmbientOcclusion.py
  28. 2 2
      python/tutorial/607_ScreenCapture.py
  29. 3 3
      python/tutorial/609_Boolean.py
  30. 1 1
      python/tutorial/704_SignedDistance.py
  31. 2 2
      python/tutorial/707_SweptVolume.py
  32. 3 3
      python/tutorial/708_Picking.py
  33. 5 5
      python/tutorial/709_VectorFieldVisualizer.py
  34. 10 0
      tests/CMakeLists.txt
  35. 15 0
      tests/include/igl/path_to_executable.cpp
  36. 1 1
      tests/include/igl/qslim.cpp
  37. 23 0
      tutorial/407_BiharmonicCoordinates/main.cpp
  38. 11 0
      tutorial/604_Triangle/main.cpp

+ 14 - 1
cmake/libigl.cmake

@@ -148,7 +148,20 @@ function(compile_igl_module module_dir)
     endif()
     add_library(${module_libname} STATIC ${SOURCES_IGL_${module_name}} ${ARGN})
     if(MSVC)
-      target_compile_options(${module_libname} PRIVATE /w) # disable all warnings (not ideal but...)
+      # Silencing some compile warnings
+      target_compile_options(${module_libname} PRIVATE 
+        # Type conversion warnings. These can be fixed with some effort and possibly more verbose code.
+        /wd4267 # conversion from 'size_t' to 'type', possible loss of data
+        /wd4244 # conversion from 'type1' to 'type2', possible loss of data
+        /wd4018 # signed/unsigned mismatch
+        /wd4305 # truncation from 'double' to 'float'
+        # This one is from template instantiations generated by autoexplicit.sh:
+        /wd4667 # no function template defined that matches forced instantiation ()
+        # This one is easy to fix, just need to switch to safe version of C functions
+        /wd4996 # this function or variable may be unsafe
+        # This one is when using bools in adjacency matrices
+        /wd4804 #'+=': unsafe use of type 'bool' in operation
+      )
     else()
       #target_compile_options(${module_libname} PRIVATE -w) # disable all warnings (not ideal but...)
     endif()

+ 2 - 2
include/igl/EPS.h

@@ -13,8 +13,8 @@ namespace igl
   // Define a standard value for double epsilon
   const double DOUBLE_EPS    = 1.0e-14;
   const double DOUBLE_EPS_SQ = 1.0e-28;
-  const float FLOAT_EPS    = 1.0e-7;
-  const float FLOAT_EPS_SQ = 1.0e-14;
+  const float FLOAT_EPS    = 1.0e-7f;
+  const float FLOAT_EPS_SQ = 1.0e-14f;
   // Function returning EPS for corresponding type
   template <typename S_type> IGL_INLINE S_type EPS();
   template <typename S_type> IGL_INLINE S_type EPS_SQ();

+ 1 - 1
include/igl/bounding_box.cpp

@@ -30,7 +30,7 @@ IGL_INLINE void igl::bounding_box(
   const auto & minV = V.colwise().minCoeff().array()-pad;
   const auto & maxV = V.colwise().maxCoeff().array()+pad;
   // 2^n vertices
-  BV.resize((1<<dim),dim);
+  BV.resize((1ull<<dim),dim);
 
   // Recursive lambda to generate all 2^n combinations
   const std::function<void(const int,const int,int*,int)> combos =

+ 2 - 2
include/igl/copyleft/quadprog.cpp

@@ -139,7 +139,7 @@ IGL_INLINE bool igl::copyleft::quadprog(
 #ifdef TRACE_SOLVER
     std::cerr << "Add constraint " << iq << '/';
 #endif
-    int i, j, k;
+    int j, k;
     double cc, ss, h, t1, t2, xny;
     
     /* we have to find the Givens rotation which will reduce the element
@@ -284,7 +284,7 @@ IGL_INLINE bool igl::copyleft::quadprog(
     }
   };
 
-  int i, j, k, l; /* indices */
+  int i, k, l; /* indices */
   int ip, me, mi;
   int n=g0.size();  int p=ce0.size();  int m=ci0.size();  
   MatrixXd R(G.rows(),G.cols()), J(G.rows(),G.cols());

+ 42 - 16
include/igl/file_dialog_open.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
-// 
-// 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 
+//
+// 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 "file_dialog_open.h"
 #include <cstdio>
@@ -13,7 +13,7 @@
   #include <windows.h>
   #undef max
   #undef min
-  
+
   #include <Commdlg.h>
 #endif
 
@@ -21,7 +21,9 @@ IGL_INLINE std::string igl::file_dialog_open()
 {
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   char buffer[FILE_DIALOG_MAX_BUFFER];
-  
+  buffer[0] = '\0';
+  buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0'
+
 #ifdef __APPLE__
   // For apple use applescript hack
   FILE * output = popen(
@@ -32,11 +34,22 @@ IGL_INLINE std::string igl::file_dialog_open()
     "   end tell\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "\" 2>/dev/null | tr -d '\n' ","r");
-  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
+  if (output)
   {
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
 #elif defined _WIN32
-  
+
   // Use native windows file dialog box
   // (code contributed by Tino Weinkauf)
 
@@ -48,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_open()
   ofn.lStructSize = sizeof(ofn);
   ofn.hwndOwner = NULL;
   ofn.lpstrFile = new char[100];
-  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
+  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
   // use the contents of szFile to initialize itself.
   ofn.lpstrFile[0] = '\0';
   ofn.nMaxFile = sizeof(szFile);
@@ -59,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_open()
   ofn.lpstrInitialDir = NULL;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 
-  // Display the Open dialog box. 
+  // Display the Open dialog box.
   int pos = 0;
   if (GetOpenFileName(&ofn)==TRUE)
   {
@@ -68,20 +81,33 @@ IGL_INLINE std::string igl::file_dialog_open()
       buffer[pos] = (char)ofn.lpstrFile[pos];
       pos++;
     }
-  } 
+  }
   buffer[pos] = 0;
 #else
-  
+
   // For linux use zenity
   FILE * output = popen("/usr/bin/zenity --file-selection","r");
-  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
+  if (output)
   {
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
-  
-  if (strlen(buffer) > 0)
+
+  // Replace last '\n' by '\0'
+  if(strlen(buffer) > 0)
   {
-    buffer[strlen(buffer)-1] = 0;
+    buffer[strlen(buffer)-1] = '\0';
   }
+
 #endif
   return std::string(buffer);
 }

+ 38 - 11
include/igl/file_dialog_save.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
-// 
-// 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 
+//
+// 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 "file_dialog_save.h"
 #include <cstdio>
@@ -18,6 +18,9 @@ IGL_INLINE std::string igl::file_dialog_save()
 {
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   char buffer[FILE_DIALOG_MAX_BUFFER];
+  buffer[0] = '\0';
+  buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0'
+
 #ifdef __APPLE__
   // For apple use applescript hack
   // There is currently a bug in Applescript that strips extensions off
@@ -31,8 +34,19 @@ IGL_INLINE std::string igl::file_dialog_save()
     "   end tell\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "\" 2>/dev/null | tr -d '\n' ","r");
-  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
+  if (output)
   {
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
 #elif defined _WIN32
 
@@ -47,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_save()
   ofn.lStructSize = sizeof(ofn);
   ofn.hwndOwner = NULL;//hwnd;
   ofn.lpstrFile = new char[100];
-  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
+  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
   // use the contents of szFile to initialize itself.
   ofn.lpstrFile[0] = '\0';
   ofn.nMaxFile = sizeof(szFile);
@@ -58,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_save()
   ofn.lpstrInitialDir = NULL;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 
-  // Display the Open dialog box. 
+  // Display the Open dialog box.
   int pos = 0;
   if (GetSaveFileName(&ofn)==TRUE)
   {
@@ -73,14 +87,27 @@ IGL_INLINE std::string igl::file_dialog_save()
 #else
   // For every other machine type use zenity
   FILE * output = popen("/usr/bin/zenity --file-selection --save","r");
-  while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL )
+  if (output)
   {
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
-  
-  if (strlen(buffer) > 0)
+
+  // Replace last '\n' by '\0'
+  if(strlen(buffer) > 0)
   {
-    buffer[strlen(buffer)-1] = 0;
+    buffer[strlen(buffer)-1] = '\0';
   }
+
 #endif
   return std::string(buffer);
 }

+ 1 - 0
include/igl/internal_angles.cpp

@@ -127,4 +127,5 @@ template void igl::internal_angles<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen
 template void igl::internal_angles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::internal_angles<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::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::internal_angles<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+template void igl::internal_angles_using_squared_edge_lengths<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 1 - 1
include/igl/jet.cpp

@@ -44,7 +44,7 @@ IGL_INLINE void igl::jet(const T x_in, T & r, T & g, T & b)
     b = (bone - (x - 3. / 8.) / (5. / 8. - 3. / 8.));
   } else if (x<7. / 8.)
   {
-    r = rone;
+    r = T(rone);
     g = (gone - (x - 5. / 8.) / (7. / 8. - 5. / 8.));
     b = 0;
   } else

+ 1 - 0
include/igl/launch_medit.cpp

@@ -56,6 +56,7 @@ IGL_INLINE int igl::launch_medit(
     return system(command.str().c_str());
   }catch(int e)
   {
+    (void)e;
     cerr<<"^"<<__FUNCTION__<<": Calling to medit crashed..."<<endl;
     return -1;
   }

+ 6 - 6
include/igl/opengl/glfw/imgui/ImGuiTraits.h

@@ -26,42 +26,42 @@ template<>
 class ImGuiDataTypeTraits<int>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_S32;
-	static constexpr char format [] = "%d";
+	static constexpr const char *format = "%d";
 };
 
 template<>
 class ImGuiDataTypeTraits<unsigned int>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_U32;
-	static constexpr char format [] = "%u";
+	static constexpr const char *format = "%u";
 };
 
 template<>
 class ImGuiDataTypeTraits<long long>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_S64;
-	static constexpr char format [] = "%lld";
+	static constexpr const char *format = "%lld";
 };
 
 template<>
 class ImGuiDataTypeTraits<unsigned long long>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_U64;
-	static constexpr char format [] = "%llu";
+	static constexpr const char *format = "%llu";
 };
 
 template<>
 class ImGuiDataTypeTraits<float>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_Float;
-	static constexpr char format [] = "%.3f";
+	static constexpr const char *format = "%.3f";
 };
 
 template<>
 class ImGuiDataTypeTraits<double>
 {
 	static constexpr ImGuiDataType value = ImGuiDataType_Double;
-	static constexpr char format [] = "%.6f";
+	static constexpr const char *format = "%.6f";
 };
 
 } // namespace ImGui

+ 7 - 3
include/igl/path_to_executable.cpp

@@ -11,8 +11,11 @@
 #endif
 #if defined(_WIN32)
 #  include <windows.h>
+#else
+  #include <unistd.h>
 #endif
 #include <stdint.h>
+
 IGL_INLINE std::string igl::path_to_executable()
 {
   // http://pastebin.com/ffzzxPzi
@@ -28,10 +31,11 @@ IGL_INLINE std::string igl::path_to_executable()
   {
     path = buffer;
   }
-#elif defined(UNIX)
-  if (readlink("/proc/self/exe", buffer, sizeof(buffer)) == -1)
+#elif defined(UNIX) || defined(unix) || defined(__unix) || defined(__unix__)
+  int byte_count = readlink("/proc/self/exe", buffer, size);
+  if (byte_count  != -1)
   {
-    path = buffer;
+    path = std::string(buffer, byte_count);
   }
 #elif defined(__FreeBSD__)
   int mib[4];

+ 1 - 1
include/igl/signed_distance.cpp

@@ -291,7 +291,7 @@ IGL_INLINE void igl::signed_distance_pseudonormal(
   C.resize(np,3);
   typedef typename AABB<DerivedV,3>::RowVectorDIMS RowVector3S;
 # pragma omp parallel for if(np>1000)
-  for(size_t p = 0;p<np;p++)
+  for(std::ptrdiff_t p = 0;p<np;p++)
   {
     typename DerivedV::Scalar s,sqrd;
     RowVector3S n,c;

+ 15 - 10
include/igl/sort_triangles.cpp

@@ -23,10 +23,10 @@ template <
   typename DerivedFF,
   typename DerivedI>
 IGL_INLINE void igl::sort_triangles(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  const Eigen::PlainObjectBase<DerivedMV> & MV,
-  const Eigen::PlainObjectBase<DerivedP> & P,
+  const Eigen::MatrixBase<DerivedV> & V,
+  const Eigen::MatrixBase<DerivedF> & F,
+  const Eigen::MatrixBase<DerivedMV> & MV,
+  const Eigen::MatrixBase<DerivedP> & P,
   Eigen::PlainObjectBase<DerivedFF> & FF,
   Eigen::PlainObjectBase<DerivedI> & I)
 {
@@ -34,12 +34,17 @@ IGL_INLINE void igl::sort_triangles(
   using namespace std;
 
 
+  typedef typename DerivedV::Scalar Scalar;
   // Barycenter, centroid
-  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
-  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> BC,PBC;
+  Eigen::Matrix<Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
+  Eigen::Matrix<Scalar, DerivedF::RowsAtCompileTime,3> BC;
   barycenter(V,F,BC);
-  D = BC*(MV.transpose()*P.transpose().eval().col(2));
-  
+  Eigen::Matrix<Scalar, DerivedF::RowsAtCompileTime,4> BC4(BC.rows(),4);
+  BC4.leftCols(3) = BC;
+  BC4.col(3).setConstant(1);
+  D = BC4*(
+      MV.template cast<Scalar>().transpose()*
+       P.template cast<Scalar>().transpose().eval().col(2));
   sort(D,1,false,sD,I);
   slice(F,I,1,FF);
 }
@@ -47,6 +52,6 @@ IGL_INLINE void igl::sort_triangles(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instantiation
-template void igl::sort_triangles<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-template void igl::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, 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, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::sort_triangles<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::sort_triangles<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<double, 4, 4, 0, 4, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(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<double, 4, 4, 0, 4, 4> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 4 - 4
include/igl/sort_triangles.h

@@ -29,10 +29,10 @@ namespace igl
     typename DerivedFF,
     typename DerivedI>
   IGL_INLINE void sort_triangles(
-    const Eigen::PlainObjectBase<DerivedV> & V,
-    const Eigen::PlainObjectBase<DerivedF> & F,
-    const Eigen::PlainObjectBase<DerivedMV> & MV,
-    const Eigen::PlainObjectBase<DerivedP> & P,
+    const Eigen::MatrixBase<DerivedV> & V,
+    const Eigen::MatrixBase<DerivedF> & F,
+    const Eigen::MatrixBase<DerivedMV> & MV,
+    const Eigen::MatrixBase<DerivedP> & P,
     Eigen::PlainObjectBase<DerivedFF> & FF,
     Eigen::PlainObjectBase<DerivedI> & I);
 }

+ 2 - 1
python/modules/py_igl_opengl_glfw.cpp

@@ -370,9 +370,10 @@ py::class_<igl::opengl::ViewerCore> viewercore_class(me, "ViewerCore");
     //   viewer.data() = data;
     // })
 
-    .def("data", (igl::opengl::ViewerData & (igl::opengl::glfw::Viewer::*)(int)) &igl::opengl::glfw::Viewer::data,pybind11::return_value_policy::reference)
+    .def("data", (igl::opengl::ViewerData & (igl::opengl::glfw::Viewer::*)(int)) &igl::opengl::glfw::Viewer::data, pybind11::return_value_policy::reference, py::arg("mesh_id")=-1)
     // .def("data", (const igl::opengl::ViewerData & (igl::opengl::glfw::Viewer::*)(int) const) &igl::opengl::glfw::Viewer::data,pybind11::return_value_policy::reference)
 
+    .def("core", (igl::opengl::ViewerCore & (igl::opengl::glfw::Viewer::*)(unsigned)) &igl::opengl::glfw::Viewer::core, pybind11::return_value_policy::reference, py::arg("core_id")=0)
     //.def_readwrite("core", &igl::opengl::glfw::Viewer::core)
     //.def_readwrite("opengl", &igl::opengl::glfw::Viewer::opengl)
 

+ 2 - 2
python/tutorial/103_Events.py

@@ -35,11 +35,11 @@ def key_pressed(viewer, key, modifier):
         # # If a mesh is already displayed, draw_mesh returns an error if the given V and
         # # F have size different than the current ones
         viewer.data().set_mesh(V1, F1)
-        viewer.core.align_camera_center(V1,F1)
+        viewer.core().align_camera_center(V1,F1)
     elif key == ord('2'):
         viewer.data().clear()
         viewer.data().set_mesh(V2, F2)
-        viewer.core.align_camera_center(V2,F2)
+        viewer.core().align_camera_center(V2,F2)
     return False
 
 

+ 1 - 1
python/tutorial/205_Laplacian.py

@@ -101,7 +101,7 @@ def key_pressed(viewer, key, modifier):
     # Send new positions, update normals, recenter
     viewer.data().set_vertices(U)
     viewer.data().compute_normals()
-    viewer.core.align_camera_center(U, F)
+    viewer.core().align_camera_center(U, F)
     return True
 
 

+ 5 - 5
python/tutorial/401_BiharmonicDeformation.py

@@ -35,7 +35,7 @@ b = igl.eigen.MatrixXi()
 def pre_draw(viewer):
     global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b
     # Determine boundary conditions
-    if (viewer.core.is_animating):
+    if (viewer.core().is_animating):
         bc_frac += bc_dir
         bc_dir *= (-1.0 if bc_frac >= 1.0 or bc_frac <= 0.0 else 1.0)
 
@@ -58,7 +58,7 @@ def key_down(viewer, key, mods):
     global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b
 
     if key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
+        viewer.core().is_animating = not viewer.core().is_animating
         return True
     if key == ord('D') or key == ord('d'):
         deformation_field = not deformation_field
@@ -110,13 +110,13 @@ viewer = igl.glfw.Viewer()
 viewer.data().set_mesh(U, F)
 viewer.data().show_lines = False
 viewer.data().set_colors(C)
-# viewer.core.trackball_angle = igl.eigen.Quaterniond(sqrt(2.0),0,sqrt(2.0),0)
-# viewer.core.trackball_angle.normalize()
+# viewer.core().trackball_angle = igl.eigen.Quaterniond(sqrt(2.0),0,sqrt(2.0),0)
+# viewer.core().trackball_angle.normalize()
 
 viewer.callback_pre_draw = pre_draw
 viewer.callback_key_down = key_down
 
-viewer.core.animation_max_fps = 30.0
+viewer.core().animation_max_fps = 30.0
 print("Press [space] to toggle deformation.")
 print("Press 'd' to toggle between biharmonic surface or displacements.")
 viewer.launch()

+ 6 - 6
python/tutorial/402_PolyharmonicDeformation.py

@@ -46,7 +46,7 @@ def pre_draw(viewer):
     viewer.data().set_vertices(U)
     viewer.data().compute_normals()
 
-    if viewer.core.is_animating:
+    if viewer.core().is_animating:
         z_max += z_dir
         z_dir *= (-1.0 if z_max >= 1.0 or z_max <= 0.0 else 1.0)
 
@@ -57,7 +57,7 @@ def key_down(viewer, key, mods):
     global z_max, z_dir, k, resolve, V, U, Z, F, b, bc
 
     if key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
+        viewer.core().is_animating = not viewer.core().is_animating
     elif key == ord('.'):
         k = k + 1
         k = (4 if k > 4 else k)
@@ -102,12 +102,12 @@ viewer = igl.glfw.Viewer()
 viewer.data().set_mesh(U, F)
 viewer.data().show_lines = False
 viewer.data().set_colors(C)
-viewer.core.trackball_angle = igl.eigen.Quaterniond(0.81,-0.58,-0.03,-0.03)
-viewer.core.trackball_angle.normalize()
+viewer.core().trackball_angle = igl.eigen.Quaterniond(0.81,-0.58,-0.03,-0.03)
+viewer.core().trackball_angle.normalize()
 viewer.callback_pre_draw = pre_draw
 viewer.callback_key_down = key_down
-viewer.core.is_animating = True
-viewer.core.animation_max_fps = 30.0
+viewer.core().is_animating = True
+viewer.core().animation_max_fps = 30.0
 print("Press [space] to toggle animation.")
 print("Press '.' to increase k.")
 print("Press ',' to decrease k.")

+ 5 - 5
python/tutorial/403_BoundedBiharmonicWeights.py

@@ -22,7 +22,7 @@ check_dependencies(dependencies)
 def pre_draw(viewer):
     global pose, anim_t, C, BE, P, U, M, anim_t_dir
 
-    if viewer.core.is_animating:
+    if viewer.core().is_animating:
         # Interpolate pose and identity
         anim_pose = igl.RotationList(len(pose))
 
@@ -69,7 +69,7 @@ def key_down(viewer, key, mods):
         selected = min(max(selected, 0), W.cols()-1)
         set_color(viewer)
     elif key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
+        viewer.core().is_animating = not viewer.core().is_animating
 
     return True
 
@@ -146,9 +146,9 @@ if __name__ == "__main__":
     viewer.data().show_lines = False
     viewer.data().show_overlay_depth = False
     viewer.data().line_width = 1
-    viewer.core.trackball_angle.normalize()
+    viewer.core().trackball_angle.normalize()
     viewer.callback_pre_draw = pre_draw
     viewer.callback_key_down = key_down
-    viewer.core.is_animating = False
-    viewer.core.animation_max_fps = 30.0
+    viewer.core().is_animating = False
+    viewer.core().animation_max_fps = 30.0
     viewer.launch()

+ 9 - 9
python/tutorial/404_DualQuaternionSkinning.py

@@ -62,7 +62,7 @@ def pre_draw(viewer):
         viewer.data().set_vertices(U)
         viewer.data().set_edges(CT, BET, sea_green)
         viewer.data().compute_normals()
-        if viewer.core.is_animating:
+        if viewer.core().is_animating:
             anim_t += anim_t_dir
         else:
             recompute = False
@@ -75,7 +75,7 @@ def key_down(viewer, key, mods):
     recompute = True
     if key == ord('D') or key == ord('d'):
         use_dqs = not use_dqs
-        viewer.core.is_animating = False
+        viewer.core().is_animating = False
         animation = False
         if use_dqs:
             print("Switched to Dual Quaternion Skinning")
@@ -83,10 +83,10 @@ def key_down(viewer, key, mods):
             print("Switched to Linear Blend Skinning")
     elif key == ord(' '):
         if animation:
-            viewer.core.is_animating = False
+            viewer.core().is_animating = False
             animation = False
         else:
-            viewer.core.is_animating = True
+            viewer.core().is_animating = True
             animation = True
     return False
 
@@ -111,7 +111,7 @@ if __name__ == "__main__":
     anim_t_dir = 0.015
     use_dqs = False
     recompute = True
-    animation = False  # Flag needed as there is some synchronization problem with viewer.core.is_animating
+    animation = False  # Flag needed as there is some synchronization problem with viewer.core().is_animating
 
     poses = [[]]
 
@@ -140,10 +140,10 @@ if __name__ == "__main__":
     viewer.data().show_lines = False
     viewer.data().show_overlay_depth = False
     viewer.data().line_width = 1
-    viewer.core.trackball_angle.normalize()
+    viewer.core().trackball_angle.normalize()
     viewer.callback_pre_draw = pre_draw
     viewer.callback_key_down = key_down
-    viewer.core.is_animating = False
-    viewer.core.camera_zoom = 2.5
-    viewer.core.animation_max_fps = 30.0
+    viewer.core().is_animating = False
+    viewer.core().camera_zoom = 2.5
+    viewer.core().animation_max_fps = 30.0
     viewer.launch()

+ 4 - 4
python/tutorial/405_AsRigidAsPossible.py

@@ -60,7 +60,7 @@ def pre_draw(viewer):
     viewer.data().set_vertices(U)
     viewer.data().compute_normals()
 
-    if viewer.core.is_animating:
+    if viewer.core().is_animating:
         anim_t += anim_t_dir
 
     return False
@@ -68,7 +68,7 @@ def pre_draw(viewer):
 
 def key_down(viewer, key, mods):
     if key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
+        viewer.core().is_animating = not viewer.core().is_animating
         return True
     return False
 
@@ -105,7 +105,7 @@ viewer.data().set_mesh(U, F)
 viewer.data().set_colors(C)
 viewer.callback_pre_draw = pre_draw
 viewer.callback_key_down = key_down
-viewer.core.is_animating = True
-viewer.core.animation_max_fps = 30.
+viewer.core().is_animating = True
+viewer.core().animation_max_fps = 30.
 print("Press [space] to toggle animation")
 viewer.launch()

+ 2 - 2
python/tutorial/501_HarmonicParam.py

@@ -28,11 +28,11 @@ def key_down(viewer, key, modifier):
     if key == ord('1'):
         # Plot the 3D mesh
         viewer.data().set_mesh(V, F)
-        viewer.core.align_camera_center(V, F)
+        viewer.core().align_camera_center(V, F)
     elif key == ord('2'):
         # Plot the mesh in 2D using the UV coordinates as vertex coordinates
         viewer.data().set_mesh(V_uv, F)
-        viewer.core.align_camera_center(V_uv, F)
+        viewer.core().align_camera_center(V_uv, F)
     viewer.data().compute_normals()
     return False
 

+ 2 - 2
python/tutorial/502_LSCMParam.py

@@ -28,11 +28,11 @@ def key_down(viewer, key, modifier):
     if key == ord('1'):
         # Plot the 3D mesh
         viewer.data().set_mesh(V, F)
-        viewer.core.align_camera_center(V, F)
+        viewer.core().align_camera_center(V, F)
     elif key == ord('2'):
         # Plot the mesh in 2D using the UV coordinates as vertex coordinates
         viewer.data().set_mesh(V_uv, F)
-        viewer.core.align_camera_center(V_uv, F)
+        viewer.core().align_camera_center(V_uv, F)
     viewer.data().compute_normals()
     return False
 

+ 2 - 2
python/tutorial/503_ARAPParam.py

@@ -38,10 +38,10 @@ def key_down(viewer, key, modifier):
 
     if show_uv:
         viewer.data().set_mesh(V_uv, F)
-        viewer.core.align_camera_center(V_uv, F)
+        viewer.core().align_camera_center(V_uv, F)
     else:
         viewer.data().set_mesh(V, F)
-        viewer.core.align_camera_center(V, F)
+        viewer.core().align_camera_center(V, F)
 
     viewer.data().compute_normals()
     return False

+ 1 - 1
python/tutorial/505_MIQ.py

@@ -205,7 +205,7 @@ def key_down(viewer, key, modifier):
 
     viewer.data().set_texture(texture_R, texture_B, texture_G)
 
-    viewer.core.align_camera_center(viewer.data().V, viewer.data().F)
+    viewer.core().align_camera_center(viewer.data().V, viewer.data().F)
 
     return False
 

+ 4 - 4
python/tutorial/606_AmbientOcclusion.py

@@ -43,13 +43,13 @@ def key_down(viewer, key, modifier):
             C.setRow(i, C.row(i) * AO[i, 0])
         viewer.data().set_colors(C)
     elif key == ord('.'):
-        viewer.core.lighting_factor += 0.1
+        viewer.core().lighting_factor += 0.1
     elif key == ord(','):
-        viewer.core.lighting_factor -= 0.1
+        viewer.core().lighting_factor -= 0.1
     else:
         return False
 
-    viewer.core.lighting_factor = min(max(viewer.core.lighting_factor, 0.0), 1.0)
+    viewer.core().lighting_factor = min(max(viewer.core().lighting_factor, 0.0), 1.0)
     return True
 
 
@@ -70,5 +70,5 @@ viewer.data().set_mesh(V, F)
 key_down(viewer, ord('2'), 0)
 viewer.callback_key_down = key_down
 viewer.data().show_lines = False
-viewer.core.lighting_factor = 0.0
+viewer.core().lighting_factor = 0.0
 viewer.launch()

+ 2 - 2
python/tutorial/607_ScreenCapture.py

@@ -29,7 +29,7 @@ def key_down(viewer, key, modifier):
         A = igl.eigen.MatrixXuc(1280, 800)
 
         # Draw the scene in the buffers
-        viewer.core.draw_buffer(viewer.data(), False, R, G, B, A)
+        viewer.core().draw_buffer(viewer.data(), False, R, G, B, A)
 
         # Save it to a PNG
         igl.png.writePNG(R, G, B, A, temp_png)
@@ -56,7 +56,7 @@ def key_down(viewer, key, modifier):
         viewer.data().clear()
         viewer.data().set_mesh(V, F)
         viewer.data().set_uv(UV)
-        viewer.core.align_camera_center(V)
+        viewer.core().align_camera_center(V)
         viewer.data().show_texture = True
 
         # Use the image as a texture

+ 3 - 3
python/tutorial/609_Boolean.py

@@ -50,9 +50,9 @@ def key_down(viewer, key, modifier):
     elif key == ord(','):
         boolean_type = boolean_types[(boolean_types.index(boolean_type) + len(boolean_types) - 1) % len(boolean_types)]
     elif key == ord('['):
-        viewer.core.camera_dnear -= 0.1
+        viewer.core().camera_dnear -= 0.1
     elif key == ord(']'):
-        viewer.core.camera_dnear += 0.1
+        viewer.core().camera_dnear += 0.1
     else:
         return False
 
@@ -88,5 +88,5 @@ if __name__ == "__main__":
 
     viewer.data().show_lines = True
     viewer.callback_key_down = key_down
-    viewer.core.camera_dnear = 3.9
+    viewer.core().camera_dnear = 3.9
     viewer.launch()

+ 1 - 1
python/tutorial/704_SignedDistance.py

@@ -97,7 +97,7 @@ def update_visualization(viewer):
     viewer.data().clear()
     viewer.data().set_mesh(V_vis, F_vis)
     viewer.data().set_colors(C_vis)
-    viewer.core.lighting_factor = overlay
+    viewer.core().lighting_factor = overlay
 
 
 def key_down(viewer, key, modifier):

+ 2 - 2
python/tutorial/707_SweptVolume.py

@@ -33,7 +33,7 @@ def key_down(viewer, key, modifier):
         else:
             viewer.data().set_mesh(V, F)
 
-        viewer.core.is_animating = not show_swept_volume
+        viewer.core().is_animating = not show_swept_volume
         viewer.data().set_face_based(True)
 
     return True
@@ -86,7 +86,7 @@ if __name__ == "__main__":
     viewer = igl.glfw.Viewer()
     viewer.data().set_mesh(V, F)
     viewer.data().set_face_based(True)
-    viewer.core.is_animating = not show_swept_volume
+    viewer.core().is_animating = not show_swept_volume
     viewer.callback_pre_draw = pre_draw
     viewer.callback_key_down = key_down
     viewer.launch()

+ 3 - 3
python/tutorial/708_Picking.py

@@ -25,9 +25,9 @@ def mouse_down(viewer, a, b):
 
     # Cast a ray in the view direction starting from the mouse position
     fid = igl.eigen.MatrixXi(np.array([-1]))
-    coord = igl.eigen.MatrixXd([viewer.current_mouse_x, viewer.core.viewport[3] - viewer.current_mouse_y])
-    hit = igl.unproject_onto_mesh(coord, viewer.core.view,
-      viewer.core.proj, viewer.core.viewport, V, F, fid, bc)
+    coord = igl.eigen.MatrixXd([viewer.current_mouse_x, viewer.core().viewport[3] - viewer.current_mouse_y])
+    hit = igl.unproject_onto_mesh(coord, viewer.core().view,
+      viewer.core().proj, viewer.core().viewport, V, F, fid, bc)
     if hit:
         # paint hit red
         C.setRow(fid[0, 0], igl.eigen.MatrixXd([[1, 0, 0]]))

+ 5 - 5
python/tutorial/709_VectorFieldVisualizer.py

@@ -53,7 +53,7 @@ def representative_to_nrosy(V, F, R, N, Y):
 
 
 def pre_draw(viewer):
-    if not viewer.core.is_animating:
+    if not viewer.core().is_animating:
         return False
 
     global anim_t
@@ -77,7 +77,7 @@ def pre_draw(viewer):
 
 def key_down(viewer, key, modifier):
     if key == ord(' '):
-        viewer.core.is_animating = not viewer.core.is_animating
+        viewer.core().is_animating = not viewer.core().is_animating
         return True
 
     return False
@@ -107,10 +107,10 @@ def main():
     viewer.callback_pre_draw = pre_draw
     viewer.callback_key_down = key_down
 
-    viewer.core.show_lines = False
+    viewer.core().show_lines = False
 
-    viewer.core.is_animating = False
-    viewer.core.animation_max_fps = 30.0
+    viewer.core().is_animating = False
+    viewer.core().animation_max_fps = 30.0
 
     # Paint mesh grayish
     C = igl.eigen.MatrixXd()

+ 10 - 0
tests/CMakeLists.txt

@@ -32,6 +32,16 @@ target_include_directories(libigl_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR})
 set(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data/")
 target_compile_definitions(libigl_tests PUBLIC -DLIBIGL_DATA_DIR="${IGL_TEST_DATA}")
 
+# Silencing some compile warnings
+if(MSVC)
+  target_compile_options(libigl_tests PRIVATE
+    # Type conversion warnings. These can be fixed with some effort and possibly more verbose code.
+    /wd4267 # conversion from 'size_t' to 'type', possible loss of data
+    /wd4244 # conversion from 'type1' to 'type2', possible loss of data
+    /wd4018 # signed/unsigned mismatch
+    /wd4305 # truncation from 'double' to 'float'
+  )
+endif(MSVC)
 
 # Process code in each subdirectories: add in decreasing order of complexity
 # (last added will run first and those should be the fastest tests)

+ 15 - 0
tests/include/igl/path_to_executable.cpp

@@ -0,0 +1,15 @@
+#include <test_common.h>
+#include <igl/path_to_executable.h>
+
+#include <iostream>
+
+
+TEST_CASE("path_to_executable: example", "[igl]")
+{
+  std::string path_to_executable = igl::path_to_executable();
+  REQUIRE(0 < path_to_executable.size());
+  // check if path_to_executable ends with correct file name, on windows .exe suffix is added.
+  std::string executable = "libigl_tests";
+  int pos = path_to_executable.length()-(executable.length() + 4/*".exe"*/);
+  REQUIRE( std::string::npos != path_to_executable.find(executable, pos));
+}

+ 1 - 1
tests/include/igl/qslim.cpp

@@ -19,7 +19,7 @@ TEST_CASE("qslim: cylinder", "[igl]")
   Eigen::VectorXi I,J;
   qslim(V,F,2*axis_devisions,U,G,I,J);
   REQUIRE (U.rows() == axis_devisions*2);
-  double l,u;
+  //double l,u;
   igl::writePLY("qslim-cylinder-vf.ply",V,F);
   igl::writePLY("qslim-cylinder-ug.ply",U,G);
   const auto & hausdorff_lower_bound = [](

+ 23 - 0
tutorial/407_BiharmonicCoordinates/main.cpp

@@ -33,6 +33,9 @@ int main(int argc, char * argv[])
   using namespace Eigen;
   using namespace std;
   using namespace igl;
+  
+  // read the mesh, if the code is prepared outside of tutorial, the TUTORIAL_SHARED_PATH
+  // should be the data folder
   if(!readMESH(TUTORIAL_SHARED_PATH "/octopus-low.mesh",low.V,low.T,low.F))
   {
     cout<<"failed to load mesh"<<endl;
@@ -46,25 +49,43 @@ int main(int argc, char * argv[])
   {
     Eigen::VectorXi b;
     {
+      // this will create a vector from 0 to V.rows()-1 where the gap is 1
       Eigen::VectorXi J = Eigen::VectorXi::LinSpaced(high.V.rows(),0,high.V.rows()-1);
       Eigen::VectorXd sqrD;
       Eigen::MatrixXd _2;
       cout<<"Finding closest points..."<<endl;
+      // using J which is N by 1 instead of a matrix that represents faces of N by 3
+      // so that we will find the closest vertices istead of closest point on the face
+      // so far the two meshes are not seperated. So what we are really doing here
+      // is computing handles from low resolution and use that for the high resolution one
       igl::point_mesh_squared_distance(low.V,high.V,J,sqrD,b,_2);
       assert(sqrD.minCoeff() < 1e-7 && "low.V should exist in high.V");
     }
     // force perfect positioning, rather have popping in low-res than high-res.
     // The correct/elaborate thing to do is express original low.V in terms of
     // linear interpolation (or extrapolation) via elements in (high.V,high.F)
+
+    // this is to replace the vertices on low resolution
+    // with the vertices in high resolution. b is the list of vertices
+    // corresponding to the indices in high resolution which has closest
+    // distance to the points in low resolution
     igl::slice(high.V,b,1,low.V);
+
+
     // list of points --> list of singleton lists
     std::vector<std::vector<int> > S;
+    // S will hav size of low.V.rows() and each list inside will have 1 element
     igl::matrix_to_list(b,S);
     cout<<"Computing weights for "<<b.size()<<
       " handles at "<<high.V.rows()<<" vertices..."<<endl;
     // Technically k should equal 3 for smooth interpolation in 3d, but 2 is
     // faster and looks OK
     const int k = 2;
+
+    // using all the points in low resolution as handles for the region
+    // it will be too expansive to use all the points in high reolution as handles
+    // but since low and high resembles the same thing, using points in low reesolution
+    // will give you similar performance
     igl::biharmonic_coordinates(high.V,high.T,S,k,W);
     cout<<"Reindexing..."<<endl;
     // Throw away interior tet-vertices, keep weights and indices of boundary
@@ -97,6 +118,7 @@ int main(int argc, char * argv[])
   Eigen::SparseMatrix<double> M;
   igl::massmatrix(low.V,low.T,igl::MASSMATRIX_TYPE_DEFAULT,M);
   const size_t n = low.V.rows();
+  // f = ma
   arap_data.f_ext =  M * RowVector3d(0,-9.8,0).replicate(n,1);
   // Random initial velocities to wiggle things
   arap_data.vel = MatrixXd::Random(n,3);
@@ -104,6 +126,7 @@ int main(int argc, char * argv[])
   igl::opengl::glfw::Viewer viewer;
   // Create one huge mesh containing both meshes
   igl::cat(1,low.U,high.U,scene.U);
+  // need to remap the indices since we cat the V matrices
   igl::cat(1,low.F,MatrixXi(high.F.array()+low.V.rows()),scene.F);
   // Color each mesh
   viewer.data().set_mesh(scene.U,scene.F);

+ 11 - 0
tutorial/604_Triangle/main.cpp

@@ -19,15 +19,26 @@ int main(int argc, char *argv[])
   E.resize(8,2);
   H.resize(1,2);
 
+  // create two squares, one with edge length of 4,
+  // one with edge length of 2
+  // both centered at origin
   V << -1,-1, 1,-1, 1,1, -1, 1,
        -2,-2, 2,-2, 2,2, -2, 2;
 
+  // add the edges of the squares
   E << 0,1, 1,2, 2,3, 3,0,
        4,5, 5,6, 6,7, 7,4;
 
+  // specify a point that is inside a closed shape
+  // where we do not want triangulation to happen
   H << 0,0;
 
   // Triangulate the interior
+  // a0.005 means that the area of each triangle should
+  // not be greater than 0.005
+  // q means that no angles will be smaller than 20 degrees
+  // for a detailed set of commands please refer to:
+  // https://www.cs.cmu.edu/~quake/triangle.switch.html
   igl::triangle::triangulate(V,E,H,"a0.005q",V2,F2);
 
   // Plot the generated mesh