Parcourir la source

merge

Former-commit-id: c2bdf368059f42568fadcf35a6a6027d0fbb62d7
Alec Jacobson il y a 8 ans
Parent
commit
09c724bb35
38 fichiers modifiés avec 719 ajouts et 479 suppressions
  1. 1 1
      .travis.yml
  2. 154 0
      include/igl/HalfEdgeIterator.cpp
  3. 42 88
      include/igl/HalfEdgeIterator.h
  4. 1 0
      include/igl/colon.cpp
  5. 2 2
      include/igl/flip_avoiding_line_search.cpp
  6. 1 0
      include/igl/harmonic.cpp
  7. 3 0
      include/igl/min_quad_with_fixed.cpp
  8. 1 1
      include/igl/readOFF.cpp
  9. 1 0
      include/igl/read_triangle_mesh.cpp
  10. 7 0
      include/igl/slice.cpp
  11. 5 0
      include/igl/slice_into.cpp
  12. 1 1
      include/igl/slim.cpp
  13. 1 1
      include/igl/triangle/triangulate.cpp
  14. 22 21
      include/igl/viewer/OpenGL_state.cpp
  15. 5 73
      include/igl/viewer/ViewerCore.cpp
  16. 71 0
      include/igl/viewer/ViewerCore.h
  17. 56 72
      include/igl/viewer/ViewerData.cpp
  18. 79 3
      include/igl/viewer/ViewerData.h
  19. 2 2
      include/igl/viewer/ViewerPlugin.h
  20. 1 1
      python/CMakeLists.txt
  21. 0 18
      python/modules/py_igl_bbw.cpp
  22. 39 5
      python/modules/py_igl_viewer.cpp
  23. 29 31
      python/modules/py_vector.cpp
  24. 85 69
      python/py_doc.cpp
  25. 3 1
      python/py_doc.h
  26. 2 0
      python/py_igl.cpp
  27. 9 8
      python/py_igl/py_bbw.cpp
  28. 10 10
      python/py_igl/py_boundary_facets.cpp
  29. 9 7
      python/py_igl/py_boundary_loop.cpp
  30. 10 9
      python/py_igl/py_internal_angles.cpp
  31. 9 6
      python/py_igl/py_readMESH.cpp
  32. 11 11
      python/py_igl/py_read_triangle_mesh.cpp
  33. 30 31
      python/py_igl/py_unique.cpp
  34. 1 0
      python/python_shared.cpp
  35. 1 1
      python/tutorial/106_ViewerMenu.py
  36. 1 0
      python/tutorial/306_EigenDecomposition.py
  37. 8 1
      shared/cmake/CMakeLists.txt
  38. 6 5
      tutorial/707_SweptVolume/main.cpp

+ 1 - 1
.travis.yml

@@ -7,7 +7,7 @@ matrix:
       script:
         - git submodule update --init --recursive
         - mkdir external/nanogui/ext/glfw/include/GL
-        - wget -P external/nanogui/ext/glfw/include/GL http://www.opengl.org/registry/api/GL/glcorearb.h
+        - wget --no-check-certificate -P external/nanogui/ext/glfw/include/GL http://www.opengl.org/registry/api/GL/glcorearb.h
         - cd python
         - mkdir build
         - cd build

+ 154 - 0
include/igl/HalfEdgeIterator.cpp

@@ -0,0 +1,154 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 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 "HalfEdgeIterator.h"
+
+template <typename DerivedF>
+IGL_INLINE igl::HalfEdgeIterator<DerivedF>::HalfEdgeIterator(
+    const Eigen::PlainObjectBase<DerivedF>& _F,
+    const Eigen::PlainObjectBase<DerivedF>& _FF,
+    const Eigen::PlainObjectBase<DerivedF>& _FFi,
+    int _fi,
+    int _ei,
+    bool _reverse
+)
+: fi(_fi), ei(_ei), reverse(_reverse), F(_F), FF(_FF), FFi(_FFi)
+{}
+
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipF()
+{
+  if (isBorder())
+    return;
+
+  int fin = (FF)(fi,ei);
+  int ein = (FFi)(fi,ei);
+
+  fi = fin;
+  ei = ein;
+  reverse = !reverse;
+}
+
+
+// Change Edge
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipE()
+{
+  if (!reverse)
+    ei = (ei+2)%3; // ei-1
+  else
+    ei = (ei+1)%3;
+
+  reverse = !reverse;
+}
+
+// Change Vertex
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipV()
+{
+  reverse = !reverse;
+}
+
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::isBorder()
+{
+  return (FF)(fi,ei) == -1;
+}
+
+/*!
+ * Returns the next edge skipping the border
+ *      _________
+ *     /\ c | b /\
+ *    /  \  |  /  \
+ *   / d  \ | / a  \
+ *  /______\|/______\
+ *          v
+ * In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v,
+ * producing the sequence a, b, c, d, a, b, c, ...
+ */
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::NextFE()
+{
+  if ( isBorder() ) // we are on a border
+  {
+    do
+    {
+      flipF();
+      flipE();
+    } while (!isBorder());
+    flipE();
+    return false;
+  }
+  else
+  {
+    flipF();
+    flipE();
+    return true;
+  }
+}
+
+// Get vertex index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Vi()
+{
+  assert(fi >= 0);
+  assert(fi < F.rows());
+  assert(ei >= 0);
+  assert(ei <= 2);
+
+  if (!reverse)
+    return (F)(fi,ei);
+  else
+    return (F)(fi,(ei+1)%3);
+}
+
+// Get face index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Fi()
+{
+  return fi;
+}
+
+// Get edge index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Ei()
+{
+  return ei;
+}
+
+
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::operator==(HalfEdgeIterator& p2)
+{
+  return
+      (
+          (fi == p2.fi) &&
+              (ei == p2.ei) &&
+              (reverse == p2.reverse) &&
+              (F   == p2.F) &&
+              (FF  == p2.FF) &&
+              (FFi == p2.FFi)
+      );
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::HalfEdgeIterator(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, int, int, bool);
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::NextFE();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::Ei();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::Fi();
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::NextFE();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Vi();
+template igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::HalfEdgeIterator(Eigen::PlainObjectBase<Eigen::Matrix<int, -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&, int, int, bool);
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Ei();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Fi();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipE();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipF();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipV();
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::operator==(igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 42 - 88
include/igl/HalfEdgeIterator.h

@@ -17,8 +17,31 @@
 
 namespace igl
 {
-  // HalfEdgeIterator - Fake halfedge for fast and easy navigation on triangle meshes with vertex_triangle_adjacency and
+  // HalfEdgeIterator - Fake halfedge for fast and easy navigation
+  // on triangle meshes with vertex_triangle_adjacency and
   // triangle_triangle adjacency
+  //
+  // Note: this is different to classical Half Edge data structure.
+  //    Instead, it follows cell-tuple in [Brisson, 1989]
+  //    "Representing geometric structures in d dimensions: topology and order."
+  //    This class can achieve local navigation similar to half edge in OpenMesh
+  //    But the logic behind each atom operation is different.
+  //    So this should be more properly called TriangleTupleIterator.
+  //
+  // Each tuple contains information on (face, edge, vertex)
+  //    and encoded by (face, edge \in {0,1,2}, bool reverse)
+  //
+  // Templates:
+  //    DerivedF Matrix Type for F. Has to be explicitly declared.
+  // Inputs:
+  //    F #F by 3 list of "faces"
+  //    FF #F by 3 list of triangle-triangle adjacency.
+  //    FFi #F by 3 list of FF inverse. For FF and FFi, refer to
+  //        "triangle_triangle_adjacency.h"
+  // Usages:
+  //    FlipF/E/V changes solely one actual face/edge/vertex resp.
+  //    NextFE iterates through one-ring of a vertex robustly.
+  //
   template <
     typename DerivedF,
     typename DerivedFF,
@@ -34,46 +57,18 @@ namespace igl
         int _fi,
         int _ei,
         bool _reverse = false
-        )
-    : fi(_fi), ei(_ei), reverse(_reverse), F(_F), FF(_FF), FFi(_FFi)
-    {}
+        );
 
     // Change Face
-    IGL_INLINE void flipF()
-    {
-      if (isBorder())
-        return;
-
-      int fin = (FF)(fi,ei);
-      int ein = (FFi)(fi,ei);
-      int reversen = !reverse;
-
-      fi = fin;
-      ei = ein;
-      reverse = reversen;
-    }
+    IGL_INLINE void flipF();
 
     // Change Edge
-    IGL_INLINE void flipE()
-    {
-      if (!reverse)
-        ei = (ei+2)%3; // ei-1
-      else
-        ei = (ei+1)%3;
-
-      reverse = !reverse;
-    }
+    IGL_INLINE void flipE();
 
     // Change Vertex
-    IGL_INLINE void flipV()
-    {
-      reverse = !reverse;
-    }
+    IGL_INLINE void flipV();
 
-    IGL_INLINE bool isBorder()
-    {
-      return (FF)(fi,ei) == -1;
-    }
+    IGL_INLINE bool isBorder();
 
     /*!
      * Returns the next edge skipping the border
@@ -83,68 +78,23 @@ namespace igl
      *   / d  \ | / a  \
      *  /______\|/______\
      *          v
-     * In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v,
+     * In this example, if a and d are of-border and the pos is iterating
+     counterclockwise, this method iterate through the faces incident on vertex
+     v,
      * producing the sequence a, b, c, d, a, b, c, ...
      */
-    IGL_INLINE bool NextFE()
-    {
-      if ( isBorder() ) // we are on a border
-      {
-        do
-        {
-          flipF();
-          flipE();
-        } while (!isBorder());
-        flipE();
-        return false;
-      }
-      else
-      {
-        flipF();
-        flipE();
-        return true;
-      }
-    }
+    IGL_INLINE bool NextFE();
 
     // Get vertex index
-    IGL_INLINE int Vi()
-    {
-      assert(fi >= 0);
-      assert(fi < F.rows());
-      assert(ei >= 0);
-      assert(ei <= 2);
-
-      if (!reverse)
-        return (*F)(fi,ei);
-      else
-        return (*F)(fi,(ei+1)%3);
-    }
+    IGL_INLINE int Vi();
 
     // Get face index
-    IGL_INLINE int Fi()
-    {
-      return fi;
-    }
+    IGL_INLINE int Fi();
 
     // Get edge index
-    IGL_INLINE int Ei()
-    {
-      return ei;
-    }
-
-
-    IGL_INLINE bool operator==(HalfEdgeIterator& p2)
-    {
-      return
-      (
-       (fi == p2.fi) &&
-       (ei == p2.ei) &&
-       (reverse == p2.reverse) &&
-       (F   == p2.F) &&
-       (FF  == p2.FF) &&
-       (FFi == p2.FFi)
-       );
-    }
+    IGL_INLINE int Ei();
+
+    IGL_INLINE bool operator==(HalfEdgeIterator& p2);
 
   private:
     int fi;
@@ -159,4 +109,8 @@ namespace igl
 
 }
 
+#ifndef IGL_STATIC_LIBRARY
+#  include "HalfEdgeIterator.cpp"
+#endif
+
 #endif

+ 1 - 0
include/igl/colon.cpp

@@ -57,6 +57,7 @@ template void igl::colon<int, int, int, int>(int, int, int, Eigen::Matrix<int, -
 template void igl::colon<int, long, long>(int, long, Eigen::Matrix<long, -1, 1, 0, -1, 1>&);
 template void igl::colon<int, double, double, double>(int, double, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
 template void igl::colon<double, double, double>(double, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
+template void igl::colon<double, double, double, double>(double, double, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
 #ifdef WIN32
 template void igl::colon<int, long long,long>(int, long long, class Eigen::Matrix<long,-1,1,0,-1,1> &);
 #endif

+ 2 - 2
include/igl/flip_avoiding_line_search.cpp

@@ -64,7 +64,7 @@ namespace igl
     {
       using namespace std;
       double t1,t2;
-      if (a != 0)
+      if (std::abs(a)>1.0e-10)
       {
         double delta_in = pow(b,2) - 4*a*c;
         if (delta_in < 0)
@@ -238,7 +238,7 @@ namespace igl
 
       double d = a_x*b_y*c_z - a_x*b_z*c_y - a_y*b_x*c_z + a_y*b_z*c_x + a_z*b_x*c_y - a_z*b_y*c_x - a_x*b_y*d_z + a_x*b_z*d_y + a_y*b_x*d_z - a_y*b_z*d_x - a_z*b_x*d_y + a_z*b_y*d_x + a_x*c_y*d_z - a_x*c_z*d_y - a_y*c_x*d_z + a_y*c_z*d_x + a_z*c_x*d_y - a_z*c_y*d_x - b_x*c_y*d_z + b_x*c_z*d_y + b_y*c_x*d_z - b_y*c_z*d_x - b_z*c_x*d_y + b_z*c_y*d_x;
 
-      if (a==0)
+      if (std::abs(a)<=1.e-10)
       {
         return get_smallest_pos_quad_zero(b,c,d);
       }

+ 1 - 0
include/igl/harmonic.cpp

@@ -171,4 +171,5 @@ template void igl::harmonic<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Mat
 template bool igl::harmonic<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::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::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 // generated by autoexplicit.sh
 template bool igl::harmonic<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::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::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template bool igl::harmonic<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::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::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 3 - 0
include/igl/min_quad_with_fixed.cpp

@@ -591,4 +591,7 @@ template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, -
 template bool igl::min_quad_with_fixed_precompute<double, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int> const&, bool, igl::min_quad_with_fixed_data<double>&);
 template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template bool igl::min_quad_with_fixed_solve<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(igl::min_quad_with_fixed_data<double> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template bool igl::min_quad_with_fixed<double, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, 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, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 1 - 1
include/igl/readOFF.cpp

@@ -67,7 +67,7 @@ IGL_INLINE bool igl::readOFF(
   while(still_comments)
   {
     fgets(line,1000,off_file);
-    still_comments = line[0] == '#';
+    still_comments = (line[0] == '#' || line[0] == '\n');
   }
   sscanf(line,"%d %d %d",&number_of_vertices,&number_of_faces,&number_of_edges);
   V.resize(number_of_vertices);

+ 1 - 0
include/igl/read_triangle_mesh.cpp

@@ -175,4 +175,5 @@ template bool igl::read_triangle_mesh<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eig
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&);
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, -1, 1, -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, 1, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template bool igl::read_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> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&);
 #endif

+ 7 - 0
include/igl/slice.cpp

@@ -327,4 +327,11 @@ template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix
 template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::DenseBase<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> >&);
 template void igl::slice<Eigen::SparseMatrix<double, 0, int>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::SparseMatrix<double, 0, int>&);
 template void igl::slice<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::slice<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::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::SparseMatrix<int, 0, int>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::SparseMatrix<int, 0, int> >(Eigen::SparseMatrix<int, 0, int> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::SparseMatrix<int, 0, int>&);
+template void igl::slice<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<double, -1, -1, 0, -1, -1> const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
+template void igl::slice<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::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<int, int>(Eigen::SparseMatrix<int, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<int, 0, int>&);
+template void igl::slice<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&);
 #endif

+ 5 - 0
include/igl/slice_into.cpp

@@ -145,4 +145,9 @@ template void igl::slice_into<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Mat
 template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 template void igl::slice_into<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::slice_into<Eigen::SparseMatrix<double, 0, int>, Eigen::SparseMatrix<double, 0, int> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::slice_into<int>(Eigen::SparseMatrix<int, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<int, 0, int>&);
+template void igl::slice_into<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::DenseBase<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> >&);
+template void igl::slice_into<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice_into<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);
+template void igl::slice_into<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 1 - 1
include/igl/slim.cpp

@@ -405,7 +405,7 @@ namespace igl
       else
       { // seems like CG performs much worse for 2D and way better for 3D
         Eigen::VectorXd guess(uv.rows() * s.dim);
-        for (int i = 0; i < s.dim; i++) for (int j = 0; j < s.dim; j++) guess(uv.rows() * i + j) = uv(i, j); // flatten vector
+        for (int i = 0; i < s.v_num; i++) for (int j = 0; j < s.dim; j++) guess(uv.rows() * j + i) = uv(i, j); // flatten vector
         ConjugateGradient<Eigen::SparseMatrix<double>, Eigen::Lower | Upper> solver;
         solver.setTolerance(1e-8);
         Uc = solver.compute(L).solveWithGuess(s.rhs, guess);

+ 1 - 1
include/igl/triangle/triangulate.cpp

@@ -94,7 +94,7 @@ IGL_INLINE void igl::triangle::triangulate(
   assert(H.size() == 0 || H.cols() == 2);
 
   // Prepare the flags
-  string full_flags = flags + "pz" + (EM.size() || VM.size() ? "B" : "");
+  string full_flags = flags + "pz" + (EM.size() || VM.size() ? "" : "B");
 
   typedef Map< Matrix<double,Dynamic,Dynamic,RowMajor> > MapXdr;
   typedef Map< Matrix<int,Dynamic,Dynamic,RowMajor> > MapXir;

+ 22 - 21
include/igl/viewer/OpenGL_state.cpp

@@ -176,7 +176,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
     if (dirty & ViewerData::DIRTY_AMBIENT)
     {
-      V_ambient_vbo.resize(3,data.F.rows()*3);
+      V_ambient_vbo.resize(4,data.F.rows()*3);
       for (unsigned i=0; i<data.F.rows();++i)
         for (unsigned j=0;j<3;++j)
           V_ambient_vbo.col (i*3+j) = data.F_material_ambient.row(i).transpose().cast<float>();
@@ -184,7 +184,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
     if (dirty & ViewerData::DIRTY_DIFFUSE)
     {
-      V_diffuse_vbo.resize(3,data.F.rows()*3);
+      V_diffuse_vbo.resize(4,data.F.rows()*3);
       for (unsigned i=0; i<data.F.rows();++i)
         for (unsigned j=0;j<3;++j)
           V_diffuse_vbo.col (i*3+j) = data.F_material_diffuse.row(i).transpose().cast<float>();
@@ -192,7 +192,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
 
     if (dirty & ViewerData::DIRTY_SPECULAR)
     {
-      V_specular_vbo.resize(3,data.F.rows()*3);
+      V_specular_vbo.resize(4,data.F.rows()*3);
       for (unsigned i=0; i<data.F.rows();++i)
         for (unsigned j=0;j<3;++j)
           V_specular_vbo.col(i*3+j) = data.F_material_specular.row(i).transpose().cast<float>();
@@ -232,12 +232,13 @@ IGL_INLINE void igl::viewer::OpenGL_state::set_data(const igl::viewer::ViewerDat
   {
     tex_u = data.texture_R.rows();
     tex_v = data.texture_R.cols();
-    tex.resize(data.texture_R.size()*3);
+    tex.resize(data.texture_R.size()*4);
     for (unsigned i=0;i<data.texture_R.size();++i)
     {
-      tex(i*3+0) = data.texture_R(i);
-      tex(i*3+1) = data.texture_G(i);
-      tex(i*3+2) = data.texture_B(i);
+      tex(i*4+0) = data.texture_R(i);
+      tex(i*4+1) = data.texture_G(i);
+      tex(i*4+2) = data.texture_B(i);
+      tex(i*4+3) = data.texture_A(i);
     }
   }
 
@@ -295,7 +296,7 @@ IGL_INLINE void igl::viewer::OpenGL_state::bind_mesh()
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_u, tex_v, 0, GL_RGB, GL_UNSIGNED_BYTE, tex.data());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data());
   }
   glUniform1i(shader_mesh.uniform("tex"), 0);
   dirty &= ~ViewerData::DIRTY_MESH;
@@ -370,14 +371,14 @@ IGL_INLINE void igl::viewer::OpenGL_state::init()
   "in vec3 normal;"
   "out vec3 position_eye;"
   "out vec3 normal_eye;"
-  "in vec3 Ka;"
-  "in vec3 Kd;"
-  "in vec3 Ks;"
+  "in vec4 Ka;"
+  "in vec4 Kd;"
+  "in vec4 Ks;"
   "in vec2 texcoord;"
   "out vec2 texcoordi;"
-  "out vec3 Kai;"
-  "out vec3 Kdi;"
-  "out vec3 Ksi;"
+  "out vec4 Kai;"
+  "out vec4 Kdi;"
+  "out vec4 Ksi;"
 
   "void main()"
   "{"
@@ -403,9 +404,9 @@ IGL_INLINE void igl::viewer::OpenGL_state::init()
   "vec3 Ls = vec3 (1, 1, 1);"
   "vec3 Ld = vec3 (1, 1, 1);"
   "vec3 La = vec3 (1, 1, 1);"
-  "in vec3 Ksi;"
-  "in vec3 Kdi;"
-  "in vec3 Kai;"
+  "in vec4 Ksi;"
+  "in vec4 Kdi;"
+  "in vec4 Kai;"
   "in vec2 texcoordi;"
   "uniform sampler2D tex;"
   "uniform float specular_exponent;"
@@ -414,22 +415,22 @@ IGL_INLINE void igl::viewer::OpenGL_state::init()
   "out vec4 outColor;"
   "void main()"
   "{"
-  "vec3 Ia = La * Kai;"    // ambient intensity
+  "vec3 Ia = La * vec3(Kai);"    // ambient intensity
 
   "vec3 light_position_eye = vec3 (view * vec4 (light_position_world, 1.0));"
   "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, normal_eye);"
   "float clamped_dot_prod = max (dot_prod, 0.0);"
-  "vec3 Id = Ld * Kdi * clamped_dot_prod;"    // Diffuse intensity
+  "vec3 Id = Ld * vec3(Kdi) * clamped_dot_prod;"    // Diffuse intensity
 
   "vec3 reflection_eye = reflect (-direction_to_light_eye, 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 * Ksi * specular_factor;"    // specular intensity
-  "vec4 color = vec4(lighting_factor * (Is + Id) + Ia, 1.0) + vec4((1.0-lighting_factor) * Kdi,1.0);"
+  "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;"
   "}";

+ 5 - 73
include/igl/viewer/ViewerCore.cpp

@@ -17,77 +17,6 @@
 #include <Eigen/Geometry>
 #include <iostream>
 
-#ifdef ENABLE_SERIALIZATION
-#include <igl/serialize.h>
-namespace igl {
-  namespace serialization {
-
-    IGL_INLINE void serialization(bool s,igl::viewer::ViewerCore& obj,std::vector<char>& buffer)
-    {
-      SERIALIZE_MEMBER(shininess);
-
-      SERIALIZE_MEMBER(background_color);
-      SERIALIZE_MEMBER(line_color);
-
-      SERIALIZE_MEMBER(light_position);
-      SERIALIZE_MEMBER(lighting_factor);
-
-      SERIALIZE_MEMBER(trackball_angle);
-      SERIALIZE_MEMBER(rotation_type);
-
-      SERIALIZE_MEMBER(model_zoom);
-      SERIALIZE_MEMBER(model_translation);
-
-      SERIALIZE_MEMBER(model_zoom_uv);
-      SERIALIZE_MEMBER(model_translation_uv);
-
-      SERIALIZE_MEMBER(camera_zoom);
-      SERIALIZE_MEMBER(orthographic);
-      SERIALIZE_MEMBER(camera_view_angle);
-      SERIALIZE_MEMBER(camera_dnear);
-      SERIALIZE_MEMBER(camera_dfar);
-      SERIALIZE_MEMBER(camera_eye);
-      SERIALIZE_MEMBER(camera_center);
-      SERIALIZE_MEMBER(camera_up);
-
-      SERIALIZE_MEMBER(show_faces);
-      SERIALIZE_MEMBER(show_lines);
-      SERIALIZE_MEMBER(invert_normals);
-      SERIALIZE_MEMBER(show_overlay);
-      SERIALIZE_MEMBER(show_overlay_depth);
-      SERIALIZE_MEMBER(show_vertid);
-      SERIALIZE_MEMBER(show_faceid);
-      SERIALIZE_MEMBER(show_texture);
-      SERIALIZE_MEMBER(depth_test);
-
-      SERIALIZE_MEMBER(point_size);
-      SERIALIZE_MEMBER(line_width);
-      SERIALIZE_MEMBER(is_animating);
-      SERIALIZE_MEMBER(animation_max_fps);
-
-      SERIALIZE_MEMBER(object_scale);
-
-      SERIALIZE_MEMBER(viewport);
-      SERIALIZE_MEMBER(view);
-      SERIALIZE_MEMBER(model);
-      SERIALIZE_MEMBER(proj);
-    }
-
-    template<>
-    IGL_INLINE void serialize(const igl::viewer::ViewerCore& obj,std::vector<char>& buffer)
-    {
-      serialization(true,const_cast<igl::viewer::ViewerCore&>(obj),buffer);
-    }
-
-    template<>
-    IGL_INLINE void deserialize(igl::viewer::ViewerCore& obj,const std::vector<char>& buffer)
-    {
-      serialization(false,obj,const_cast<std::vector<char>&>(buffer));
-    }
-  }
-}
-#endif
-
 IGL_INLINE void igl::viewer::ViewerCore::align_camera_center(
   const Eigen::MatrixXd& V,
   const Eigen::MatrixXi& F)
@@ -164,8 +93,8 @@ IGL_INLINE void igl::viewer::ViewerCore::clear_framebuffers()
 }
 
 IGL_INLINE void igl::viewer::ViewerCore::draw(
-  ViewerData& data, 
-  OpenGL_state& opengl, 
+  ViewerData& data,
+  OpenGL_state& opengl,
   bool update_matrices)
 {
   using namespace std;
@@ -176,6 +105,9 @@ IGL_INLINE void igl::viewer::ViewerCore::draw(
   else
     glDisable(GL_DEPTH_TEST);
 
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
   /* Bind and potentially refresh mesh/line/point data */
   if (data.dirty)
   {

+ 71 - 0
include/igl/viewer/ViewerCore.h

@@ -168,6 +168,77 @@ public:
 }
 }
 
+#ifdef ENABLE_SERIALIZATION
+#include <igl/serialize.h>
+namespace igl {
+	namespace serialization {
+
+		inline void serialization(bool s, igl::viewer::ViewerCore& obj, std::vector<char>& buffer)
+		{
+			SERIALIZE_MEMBER(shininess);
+
+			SERIALIZE_MEMBER(background_color);
+			SERIALIZE_MEMBER(line_color);
+
+			SERIALIZE_MEMBER(light_position);
+			SERIALIZE_MEMBER(lighting_factor);
+
+			SERIALIZE_MEMBER(trackball_angle);
+			SERIALIZE_MEMBER(rotation_type);
+
+			SERIALIZE_MEMBER(model_zoom);
+			SERIALIZE_MEMBER(model_translation);
+
+			SERIALIZE_MEMBER(model_zoom_uv);
+			SERIALIZE_MEMBER(model_translation_uv);
+
+			SERIALIZE_MEMBER(camera_zoom);
+			SERIALIZE_MEMBER(orthographic);
+			SERIALIZE_MEMBER(camera_view_angle);
+			SERIALIZE_MEMBER(camera_dnear);
+			SERIALIZE_MEMBER(camera_dfar);
+			SERIALIZE_MEMBER(camera_eye);
+			SERIALIZE_MEMBER(camera_center);
+			SERIALIZE_MEMBER(camera_up);
+
+			SERIALIZE_MEMBER(show_faces);
+			SERIALIZE_MEMBER(show_lines);
+			SERIALIZE_MEMBER(invert_normals);
+			SERIALIZE_MEMBER(show_overlay);
+			SERIALIZE_MEMBER(show_overlay_depth);
+			SERIALIZE_MEMBER(show_vertid);
+			SERIALIZE_MEMBER(show_faceid);
+			SERIALIZE_MEMBER(show_texture);
+			SERIALIZE_MEMBER(depth_test);
+
+			SERIALIZE_MEMBER(point_size);
+			SERIALIZE_MEMBER(line_width);
+			SERIALIZE_MEMBER(is_animating);
+			SERIALIZE_MEMBER(animation_max_fps);
+
+			SERIALIZE_MEMBER(object_scale);
+
+			SERIALIZE_MEMBER(viewport);
+			SERIALIZE_MEMBER(view);
+			SERIALIZE_MEMBER(model);
+			SERIALIZE_MEMBER(proj);
+		}
+
+		template<>
+		inline void serialize(const igl::viewer::ViewerCore& obj, std::vector<char>& buffer)
+		{
+			serialization(true, const_cast<igl::viewer::ViewerCore&>(obj), buffer);
+		}
+
+		template<>
+		inline void deserialize(igl::viewer::ViewerCore& obj, const std::vector<char>& buffer)
+		{
+			serialization(false, obj, const_cast<std::vector<char>&>(buffer));
+		}
+  }
+}
+#endif
+
 #ifndef IGL_STATIC_LIBRARY
 #  include "ViewerCore.cpp"
 #endif

+ 56 - 72
include/igl/viewer/ViewerData.cpp

@@ -15,60 +15,6 @@
 #include <igl/parula.h>
 #include <igl/per_vertex_normals.h>
 
-#ifdef ENABLE_SERIALIZATION
-#include <igl/serialize.h>
-namespace igl {
-  namespace serialization {
-
-    IGL_INLINE void serialization(bool s,igl::viewer::ViewerData& obj,std::vector<char>& buffer)
-    {
-      SERIALIZE_MEMBER(V);
-      SERIALIZE_MEMBER(F);
-
-      SERIALIZE_MEMBER(F_normals);
-      SERIALIZE_MEMBER(F_material_ambient);
-      SERIALIZE_MEMBER(F_material_diffuse);
-      SERIALIZE_MEMBER(F_material_specular);
-
-      SERIALIZE_MEMBER(V_normals);
-      SERIALIZE_MEMBER(V_material_ambient);
-      SERIALIZE_MEMBER(V_material_diffuse);
-      SERIALIZE_MEMBER(V_material_specular);
-
-      SERIALIZE_MEMBER(V_uv);
-      SERIALIZE_MEMBER(F_uv);
-
-      SERIALIZE_MEMBER(texture_R);
-      SERIALIZE_MEMBER(texture_G);
-      SERIALIZE_MEMBER(texture_B);
-
-      SERIALIZE_MEMBER(lines);
-      SERIALIZE_MEMBER(points);
-
-      SERIALIZE_MEMBER(labels_positions);
-      SERIALIZE_MEMBER(labels_strings);
-
-      SERIALIZE_MEMBER(dirty);
-
-      SERIALIZE_MEMBER(face_based);
-    }
-
-    template<>
-    IGL_INLINE void serialize(const igl::viewer::ViewerData& obj,std::vector<char>& buffer)
-    {
-      serialization(true,const_cast<igl::viewer::ViewerData&>(obj),buffer);
-    }
-
-    template<>
-    IGL_INLINE void deserialize(igl::viewer::ViewerData& obj,const std::vector<char>& buffer)
-    {
-      serialization(false,obj,const_cast<std::vector<char>&>(buffer));
-      obj.dirty = igl::viewer::ViewerData::DIRTY_ALL;
-    }
-  }
-}
-#endif
-
 IGL_INLINE igl::viewer::ViewerData::ViewerData()
 : dirty(DIRTY_ALL)
 {
@@ -164,27 +110,31 @@ IGL_INLINE void igl::viewer::ViewerData::set_colors(const Eigen::MatrixXd &C)
   // Ambient color should be darker color
   const auto ambient = [](const MatrixXd & C)->MatrixXd
   {
-    return 0.1*C;
+    MatrixXd T = 0.1*C;
+    T.col(3) = C.col(3);
+    return T;
   };
   // Specular color should be a less saturated and darker color: dampened
   // highlights
   const auto specular = [](const MatrixXd & C)->MatrixXd
   {
     const double grey = 0.3;
-    return grey+0.1*(C.array()-grey);
+    MatrixXd T = grey+0.1*(C.array()-grey);
+    T.col(3) = C.col(3);
+    return T;
   };
   if (C.rows() == 1)
   {
     for (unsigned i=0;i<V_material_diffuse.rows();++i)
     {
-      V_material_diffuse.row(i) = C.row(0);
+      V_material_diffuse.row(i) << C.row(0),1;
     }
     V_material_ambient = ambient(V_material_diffuse);
     V_material_specular = specular(V_material_diffuse);
 
     for (unsigned i=0;i<F_material_diffuse.rows();++i)
     {
-      F_material_diffuse.row(i) = C.row(0);
+      F_material_diffuse.row(i) << C.row(0),1;
     }
     F_material_ambient = ambient(F_material_diffuse);
     F_material_specular = specular(F_material_diffuse);
@@ -192,14 +142,20 @@ IGL_INLINE void igl::viewer::ViewerData::set_colors(const Eigen::MatrixXd &C)
   else if (C.rows() == V.rows())
   {
     set_face_based(false);
-    V_material_diffuse = C;
+    for (unsigned i=0;i<V_material_diffuse.rows();++i)
+    {
+      V_material_diffuse.row(i) << C.row(i),1;
+    }
     V_material_ambient = ambient(V_material_diffuse);
     V_material_specular = specular(V_material_diffuse);
   }
   else if (C.rows() == F.rows())
   {
     set_face_based(true);
-    F_material_diffuse = C;
+    for (unsigned i=0;i<F_material_diffuse.rows();++i)
+    {
+      F_material_diffuse.row(i) << C.row(i),1;
+    }
     F_material_ambient = ambient(F_material_diffuse);
     F_material_specular = specular(F_material_diffuse);
   }
@@ -239,6 +195,20 @@ IGL_INLINE void igl::viewer::ViewerData::set_texture(
   texture_R = R;
   texture_G = G;
   texture_B = B;
+  texture_A = Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>::Constant(R.rows(),R.cols(),255);
+  dirty |= DIRTY_TEXTURE;
+}
+
+IGL_INLINE void igl::viewer::ViewerData::set_texture(
+  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)
+{
+  texture_R = R;
+  texture_G = G;
+  texture_B = B;
+  texture_A = A;
   dirty |= DIRTY_TEXTURE;
 }
 
@@ -345,13 +315,13 @@ IGL_INLINE void igl::viewer::ViewerData::clear()
   V                       = Eigen::MatrixXd (0,3);
   F                       = Eigen::MatrixXi (0,3);
 
-  F_material_ambient      = Eigen::MatrixXd (0,3);
-  F_material_diffuse      = Eigen::MatrixXd (0,3);
-  F_material_specular     = Eigen::MatrixXd (0,3);
+  F_material_ambient      = Eigen::MatrixXd (0,4);
+  F_material_diffuse      = Eigen::MatrixXd (0,4);
+  F_material_specular     = Eigen::MatrixXd (0,4);
 
-  V_material_ambient      = Eigen::MatrixXd (0,3);
-  V_material_diffuse      = Eigen::MatrixXd (0,3);
-  V_material_specular     = Eigen::MatrixXd (0,3);
+  V_material_ambient      = Eigen::MatrixXd (0,4);
+  V_material_diffuse      = Eigen::MatrixXd (0,4);
+  V_material_specular     = Eigen::MatrixXd (0,4);
 
   F_normals               = Eigen::MatrixXd (0,3);
   V_normals               = Eigen::MatrixXd (0,3);
@@ -376,9 +346,22 @@ IGL_INLINE void igl::viewer::ViewerData::compute_normals()
 
 IGL_INLINE void igl::viewer::ViewerData::uniform_colors(Eigen::Vector3d ambient, Eigen::Vector3d diffuse, Eigen::Vector3d specular)
 {
-  V_material_ambient.resize(V.rows(),3);
-  V_material_diffuse.resize(V.rows(),3);
-  V_material_specular.resize(V.rows(),3);
+  Eigen::Vector4d ambient4;
+  Eigen::Vector4d diffuse4;
+  Eigen::Vector4d specular4;
+
+  ambient4 << ambient, 1;
+  diffuse4 << diffuse, 1;
+  specular4 << specular, 1;
+
+  uniform_colors(ambient4,diffuse4,specular4);
+}
+
+IGL_INLINE void igl::viewer::ViewerData::uniform_colors(Eigen::Vector4d ambient, Eigen::Vector4d diffuse, Eigen::Vector4d specular)
+{
+  V_material_ambient.resize(V.rows(),4);
+  V_material_diffuse.resize(V.rows(),4);
+  V_material_specular.resize(V.rows(),4);
 
   for (unsigned i=0; i<V.rows();++i)
   {
@@ -387,9 +370,9 @@ IGL_INLINE void igl::viewer::ViewerData::uniform_colors(Eigen::Vector3d ambient,
     V_material_specular.row(i) = specular;
   }
 
-  F_material_ambient.resize(F.rows(),3);
-  F_material_diffuse.resize(F.rows(),3);
-  F_material_specular.resize(F.rows(),3);
+  F_material_ambient.resize(F.rows(),4);
+  F_material_diffuse.resize(F.rows(),4);
+  F_material_specular.resize(F.rows(),4);
 
   for (unsigned i=0; i<F.rows();++i)
   {
@@ -434,5 +417,6 @@ IGL_INLINE void igl::viewer::ViewerData::grid_texture()
 
   texture_G = texture_R;
   texture_B = texture_R;
+  texture_A = Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>::Constant(texture_R.rows(),texture_R.cols(),255);
   dirty |= DIRTY_TEXTURE;
 }

+ 79 - 3
include/igl/viewer/ViewerData.h

@@ -83,6 +83,20 @@ public:
     const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& G,
     const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>& B);
 
+  // Set the texture associated with the mesh.
+  //
+  // Inputs:
+  //   R  width by height image matrix of red channel
+  //   G  width by height image matrix of green channel
+  //   B  width by height image matrix of blue channel
+  //   A  width by height image matrix of alpha channel
+  //
+  IGL_INLINE void set_texture(
+    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);
+
   // Sets points given a list of point vertices. In constrast to `set_points`
   // this will (purposefully) clober existing points.
   //
@@ -90,7 +104,7 @@ public:
   //   P  #P by 3 list of vertex positions
   //   C  #P|1 by 3 color(s)
   IGL_INLINE void set_points(
-    const Eigen::MatrixXd& P,  
+    const Eigen::MatrixXd& P,
     const Eigen::MatrixXd& C);
   IGL_INLINE void add_points(const Eigen::MatrixXd& P,  const Eigen::MatrixXd& C);
   // Sets edges given a list of edge vertices and edge indices. In constrast
@@ -109,10 +123,16 @@ public:
 
   // Assigns uniform colors to all faces/vertices
   IGL_INLINE void uniform_colors(
-    Eigen::Vector3d ambient, 
-    Eigen::Vector3d diffuse, 
+    Eigen::Vector3d ambient,
+    Eigen::Vector3d diffuse,
     Eigen::Vector3d specular);
 
+  // Assigns uniform colors to all faces/vertices
+  IGL_INLINE void uniform_colors(
+    Eigen::Vector4d ambient,
+    Eigen::Vector4d diffuse,
+    Eigen::Vector4d specular);
+
   // Generates a default grid texture
   IGL_INLINE void grid_texture();
 
@@ -141,6 +161,7 @@ public:
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_R;
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_G;
   Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_B;
+  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_A;
 
   // Overlays
 
@@ -171,6 +192,61 @@ public:
 }
 }
 
+#ifdef ENABLE_SERIALIZATION
+#include <igl/serialize.h>
+namespace igl {
+	namespace serialization {
+
+		inline void serialization(bool s, igl::viewer::ViewerData& obj, std::vector<char>& buffer)
+		{
+			SERIALIZE_MEMBER(V);
+			SERIALIZE_MEMBER(F);
+
+			SERIALIZE_MEMBER(F_normals);
+			SERIALIZE_MEMBER(F_material_ambient);
+			SERIALIZE_MEMBER(F_material_diffuse);
+			SERIALIZE_MEMBER(F_material_specular);
+
+			SERIALIZE_MEMBER(V_normals);
+			SERIALIZE_MEMBER(V_material_ambient);
+			SERIALIZE_MEMBER(V_material_diffuse);
+			SERIALIZE_MEMBER(V_material_specular);
+
+			SERIALIZE_MEMBER(V_uv);
+			SERIALIZE_MEMBER(F_uv);
+
+			SERIALIZE_MEMBER(texture_R);
+			SERIALIZE_MEMBER(texture_G);
+			SERIALIZE_MEMBER(texture_B);
+      SERIALIZE_MEMBER(texture_A);
+
+			SERIALIZE_MEMBER(lines);
+			SERIALIZE_MEMBER(points);
+
+			SERIALIZE_MEMBER(labels_positions);
+			SERIALIZE_MEMBER(labels_strings);
+
+			SERIALIZE_MEMBER(dirty);
+
+			SERIALIZE_MEMBER(face_based);
+		}
+
+		template<>
+		inline void serialize(const igl::viewer::ViewerData& obj, std::vector<char>& buffer)
+		{
+			serialization(true, const_cast<igl::viewer::ViewerData&>(obj), buffer);
+		}
+
+		template<>
+		inline void deserialize(igl::viewer::ViewerData& obj, const std::vector<char>& buffer)
+		{
+			serialization(false, obj, const_cast<std::vector<char>&>(buffer));
+			obj.dirty = igl::viewer::ViewerData::DIRTY_ALL;
+		}
+	}
+}
+#endif
+
 #ifndef IGL_STATIC_LIBRARY
 #  include "ViewerData.cpp"
 #endif

+ 2 - 2
include/igl/viewer/ViewerPlugin.h

@@ -158,12 +158,12 @@ protected:
 #ifdef ENABLE_SERIALIZATION
 namespace serialization
 {
-  IGL_INLINE void serialize(const ViewerPlugin& obj,std::vector<char>& buffer)
+  inline void serialize(const ViewerPlugin& obj,std::vector<char>& buffer)
   {
     obj.serialize(buffer);
   }
 
-  IGL_INLINE void deserialize(ViewerPlugin& obj,const std::vector<char>& buffer)
+  inline void deserialize(ViewerPlugin& obj,const std::vector<char>& buffer)
   {
     obj.deserialize(buffer);
   }

+ 1 - 1
python/CMakeLists.txt

@@ -205,7 +205,7 @@ endif()
 
 if (LIBIGL_WITH_PYTHON AND LIBIGL_WITH_NANOGUI)
   # Copy the nanogui python lib after compilation
-  get_target_property(NANOGUI_LIB nanogui_python LOCATION)
+  get_target_property(NANOGUI_LIB nanogui-python LOCATION)
   add_custom_target(copy ALL)
   add_custom_command(
         TARGET copy

+ 0 - 18
python/modules/py_igl_bbw.cpp

@@ -1,18 +0,0 @@
-//#include <Eigen/Geometry>
-//#include <Eigen/Dense>
-//#include <Eigen/Sparse>
-
-
-#include "../python_shared.h"
-
-#include <igl/bbw.h>
-
-
-void python_export_igl_bbw(py::module &me) {
-
-  py::module m = me.def_submodule(
-    "bbw", "Wrappers for libigl functions that use bbw");
-
-  #include "../py_igl/py_bbw.cpp"
-
-}

+ 39 - 5
python/modules/py_igl_viewer.cpp

@@ -58,7 +58,23 @@ py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
        (void (igl::viewer::ViewerData::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi&)) &igl::viewer::ViewerData::set_uv
     )
 
-    .def("set_texture", &igl::viewer::ViewerData::set_texture)
+    .def("set_texture",
+       (void (igl::viewer::ViewerData::*) (
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&,
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&,
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&)
+       ) &igl::viewer::ViewerData::set_texture
+    )
+
+    .def("set_texture",
+       (void (igl::viewer::ViewerData::*) (
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&,
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&,
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&,
+         const Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic>&)
+       ) &igl::viewer::ViewerData::set_texture
+    )
+
     .def("set_points", &igl::viewer::ViewerData::set_points)
     .def("add_points", &igl::viewer::ViewerData::add_points)
     .def("set_edges", &igl::viewer::ViewerData::set_edges)
@@ -74,10 +90,28 @@ py::enum_<igl::viewer::ViewerData::DirtyFlags>(viewerdata_class, "DirtyFlags")
 
     .def("uniform_colors", [] (igl::viewer::ViewerData& data, const Eigen::MatrixXd& ambient, const Eigen::MatrixXd& diffuse, const Eigen::MatrixXd& specular)
     {
-      assert_is_Vector3("ambient",ambient);
-      assert_is_Vector3("diffuse",diffuse);
-      assert_is_Vector3("specular",specular);
-      data.uniform_colors(ambient,diffuse, specular);
+      if (ambient.cols() == 3)
+      {
+        assert_is_Vector3("ambient",ambient);
+        assert_is_Vector3("diffuse",diffuse);
+        assert_is_Vector3("specular",specular);
+        Eigen::Vector3d vambient = ambient;
+        Eigen::Vector3d vdiffuse = diffuse;
+        Eigen::Vector3d vspecular = specular;
+        data.uniform_colors(vambient,vdiffuse, vspecular);
+      }
+
+      if (ambient.cols() == 4)
+      {
+        assert_is_Vector4("ambient",ambient);
+        assert_is_Vector4("diffuse",diffuse);
+        assert_is_Vector4("specular",specular);
+        Eigen::Vector4d vambient = ambient;
+        Eigen::Vector4d vdiffuse = diffuse;
+        Eigen::Vector4d vspecular = specular;
+        data.uniform_colors(vambient,vdiffuse,vspecular);
+      }
+
     })
 
     .def("grid_texture", &igl::viewer::ViewerData::grid_texture)

+ 29 - 31
python/modules/py_vector.cpp

@@ -7,14 +7,13 @@
 
 /// Creates Python bindings for a dynamic Eigen matrix
 template <typename Type>
-py::class_<Type> bind_eigen_2(py::module &m, const char *name,
-                                py::object parent = py::object()) {
+py::class_<Type> bind_eigen_2(py::module &m, const char *name) {
     typedef typename Type::Scalar Scalar;
 
     /* Many Eigen functions are templated and can't easily be referenced using
        a function pointer, thus a big portion of the binding code below
        instantiates Eigen code using small anonymous wrapper functions */
-    py::class_<Type> matrix(m, name, parent);
+    py::class_<Type> matrix(m, name, py::buffer_protocol());
 
     matrix
         /* Constructors */
@@ -24,6 +23,26 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
             new (&m) Type(1, 1);
             m(0, 0) = f;
         })
+        .def("__init__", [](Type &m, py::buffer b) {
+            py::buffer_info info = b.request();
+            if (info.format != py::format_descriptor<Scalar>::format())
+                throw std::runtime_error("Incompatible buffer format!");
+            if (info.ndim == 1) {
+                new (&m) Type(info.shape[0], 1);
+                memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+            } else if (info.ndim == 2) {
+                if (info.strides[0] == sizeof(Scalar)) {
+                    new (&m) Type(info.shape[0], info.shape[1]);
+                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+                } else {
+                    new (&m) Type(info.shape[1], info.shape[0]);
+                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
+                    m.transposeInPlace();
+                }
+            } else {
+                throw std::runtime_error("Incompatible buffer dimension!");
+            }
+        })
         .def("__init__", [](Type &m, std::vector<std::vector< Scalar> >& b) {
           if (b.size() == 0)
           {
@@ -66,26 +85,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
 
           return;
         })
-        .def("__init__", [](Type &m, py::buffer b) {
-            py::buffer_info info = b.request();
-            if (info.format != py::format_descriptor<Scalar>::value)
-                throw std::runtime_error("Incompatible buffer format!");
-            if (info.ndim == 1) {
-                new (&m) Type(info.shape[0], 1);
-                memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
-            } else if (info.ndim == 2) {
-                if (info.strides[0] == sizeof(Scalar)) {
-                    new (&m) Type(info.shape[0], info.shape[1]);
-                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
-                } else {
-                    new (&m) Type(info.shape[1], info.shape[0]);
-                    memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size());
-                    m.transposeInPlace();
-                }
-            } else {
-                throw std::runtime_error("Incompatible buffer dimension!");
-            }
-        })
+
 
         /* Size query functions */
         .def("size", [](const Type &m) { return m.size(); })
@@ -319,7 +319,7 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
                 m.data(),                /* Pointer to buffer */
                 sizeof(Scalar),          /* Size of one scalar */
                 /* Python struct-style format descriptor */
-                py::format_descriptor<Scalar>::value,
+                py::format_descriptor<Scalar>::format(),
                 2,                       /* Number of dimensions */
                 { (size_t) m.rows(),     /* Buffer dimensions */
                   (size_t) m.cols() },
@@ -347,14 +347,13 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
 
 /// Creates Python bindings for a dynamic Eigen sparse order-2 tensor (i.e. a matrix)
 template <typename Type>
-py::class_<Type> bind_eigen_sparse_2(py::module &m, const char *name,
-                                py::object parent = py::object()) {
+py::class_<Type> bind_eigen_sparse_2(py::module &m, const char *name) {
     typedef typename Type::Scalar Scalar;
 
     /* Many Eigen functions are templated and can't easily be referenced using
        a function pointer, thus a big portion of the binding code below
        instantiates Eigen code using small anonymous wrapper functions */
-    py::class_<Type> matrix(m, name, parent);
+    py::class_<Type> matrix(m, name, py::buffer_protocol());
 
     matrix
         /* Constructors */
@@ -532,14 +531,13 @@ py::class_<Type> bind_eigen_sparse_2(py::module &m, const char *name,
 
 /// Creates Python bindings for a diagonal Eigen sparse order-2 tensor (i.e. a matrix)
 template <typename Type>
-py::class_<Type> bind_eigen_diagonal_2(py::module &m, const char *name,
-                                py::object parent = py::object()) {
+py::class_<Type> bind_eigen_diagonal_2(py::module &m, const char *name) {
     typedef typename Type::Scalar Scalar;
 
     /* Many Eigen functions are templated and can't easily be referenced using
        a function pointer, thus a big portion of the binding code below
        instantiates Eigen code using small anonymous wrapper functions */
-    py::class_<Type> matrix(m, name, parent);
+    py::class_<Type> matrix(m, name, py::buffer_protocol());
 
     matrix
         /* Constructors */
@@ -632,7 +630,7 @@ void python_export_vector(py::module &m) {
 
     /* Bindings for MatrixXi */
     bind_eigen_2<Eigen::MatrixXi> (me, "MatrixXi");
-//    py::implicitly_convertible<py::buffer, Eigen::MatrixXi>();
+    //py::implicitly_convertible<py::buffer, Eigen::MatrixXi>();
     //py::implicitly_convertible<double, Eigen::MatrixXi>();
 
     /* Bindings for MatrixXb */

+ 85 - 69
python/py_doc.cpp

@@ -88,27 +88,26 @@ const char *__doc_igl_barycentric_to_global = R"igl_Qu8mg5v7(// Converts barycen
   // bc: #Xx3 Barycentric coordinates, one row per point
   //
   // Output:
-  // #X: #Xx3 3D coordinates of all points in bc
-  //   )igl_Qu8mg5v7";
+  // #X: #Xx3 3D coordinates of all points in bc)igl_Qu8mg5v7";
 const char *__doc_igl_bbw = R"igl_Qu8mg5v7(// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
-    // set of boundary conditions
-    //
-    // Templates
-    //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
-    //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
-    //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
-    //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
-    //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
-    // Inputs:
-    //   V  #V by dim vertex positions
-    //   Ele  #Elements by simplex-size list of element indices
-    //   b  #b boundary indices into V
-    //   bc #b by #W list of boundary values
-    //   data  object containing options, intial guess --> solution and results
-    // Outputs:
-    //   W  #V by #W list of *unnormalized* weights to normalize use
-    //    igl::normalize_row_sums(W,W);
-    // Returns true on success, false on failure)igl_Qu8mg5v7";
+  // set of boundary conditions
+  //
+  // Templates
+  //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
+  //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
+  //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
+  //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
+  //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
+  // Inputs:
+  //   V  #V by dim vertex positions
+  //   Ele  #Elements by simplex-size list of element indices
+  //   b  #b boundary indices into V
+  //   bc #b by #W list of boundary values
+  //   data  object containing options, intial guess --> solution and results
+  // Outputs:
+  //   W  #V by #W list of *unnormalized* weights to normalize use
+  //    igl::normalize_row_sums(W,W);
+  // Returns true on success, false on failure)igl_Qu8mg5v7";
 const char *__doc_igl_boundary_conditions = R"igl_Qu8mg5v7(// Compute boundary conditions for automatic weights computation. This
   // function expects that the given mesh (V,Ele) has sufficient samples
   // (vertices) exactly at point handle locations and exactly along bone and
@@ -128,7 +127,11 @@ const char *__doc_igl_boundary_conditions = R"igl_Qu8mg5v7(// Compute boundary c
   //     (notice the #b != #weights in general because #b will include all the
   //     intermediary samples along each bone, etc.. The ordering of the
   //     weights corresponds to [P;BE]
-  // Returns true if boundary conditions make sense)igl_Qu8mg5v7";
+  // Returns false if boundary conditions are suspicious:
+  //   P and BE are empty
+  //   bc is empty
+  //   some column of bc doesn't have a 0 (assuming bc has >1 columns)
+  //   some column of bc doesn't have a 1 (assuming bc has >1 columns))igl_Qu8mg5v7";
 const char *__doc_igl_boundary_facets = R"igl_Qu8mg5v7(// BOUNDARY_FACETS Determine boundary faces (edges) of tetrahedra (triangles)
   // stored in T (analogous to qptoolbox's `outline` and `boundary_faces`).
   //
@@ -161,7 +164,7 @@ const char *__doc_igl_cat = R"igl_Qu8mg5v7(// Perform concatenation of a two mat
   // Inputs:
   //   A  first input matrix
   //   B  second input matrix
-  //   dim  dimension along which to concatenate, 0 or 1
+  //   dim  dimension along which to concatenate, 1 or 2
   // Outputs:
   //   C  output matrix
   //   )igl_Qu8mg5v7";
@@ -394,9 +397,7 @@ const char *__doc_igl_cotmatrix = R"igl_Qu8mg5v7(// Constructs the cotangent sti
   // **minus** the sum of off-diagonal entries. The diagonal entries are
   // therefore in general negative and the matrix is **negative** semi-definite
   // (immediately, -L is **positive** semi-definite)
-  //
-  // Known bugs: off by 1e-16 on regular grid. I think its a problem of
-  // arithmetic order in cotmatrix_entries.h: C(i,e) = (arithmetic)/dblA/4)igl_Qu8mg5v7";
+  //)igl_Qu8mg5v7";
 const char *__doc_igl_covariance_scatter_matrix = R"igl_Qu8mg5v7(// Construct the covariance scatter matrix for a given arap energy
   // Inputs:
   //   V  #V by Vdim list of initial domain positions
@@ -514,14 +515,21 @@ const char *__doc_igl_edge_lengths = R"igl_Qu8mg5v7(// Constructs a list of leng
   //     for tets, columns correspond to edges
   //     [3 0],[3 1],[3 2],[1 2],[2 0],[0 1]
   //)igl_Qu8mg5v7";
-const char *__doc_igl_edge_topology = R"igl_Qu8mg5v7(// Initialize Edges and their topological relations
+const char *__doc_igl_edge_topology = R"igl_Qu8mg5v7(// Initialize Edges and their topological relations (assumes an edge-manifold
+  // mesh)
   //
   // Output:
   // EV  : #Ex2, Stores the edge description as pair of indices to vertices
   // FE : #Fx3, Stores the Triangle-Edge relation
   // EF : #Ex2: Stores the Edge-Triangle relation
   //
-  // TODO: This seems to be a duplicate of edge_flaps.h)igl_Qu8mg5v7";
+  // TODO: This seems to be a inferior duplicate of edge_flaps.h:
+  //   - unused input parameter V
+  //   - roughly 2x slower than edge_flaps
+  //   - outputs less information: edge_flaps reveals corner opposite edge
+  //   - FE uses non-standard and ambiguous order: FE(f,c) is merely an edge
+  //     incident on corner c of face f. In contrast, edge_flaps's EMAP(f,c) reveals
+  //     the edge _opposite_ corner c of face f)igl_Qu8mg5v7";
 const char *__doc_igl_eigs = R"igl_Qu8mg5v7(See eigs for the documentation.)igl_Qu8mg5v7";
 const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(// Compute ambient occlusion per given point
     //
@@ -533,23 +541,6 @@ const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(// Compute ambie
     //    S  #P list of ambient occlusion values between 1 (fully occluded) and
     //      0 (not occluded)
     //)igl_Qu8mg5v7";
-const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient each component (identified by C) of a mesh (V,F) using ambient
-    // occlusion such that the front side is less occluded than back side, as
-    // described in "A Simple Method for Correcting Facet Orientations in
-    // Polygon Meshes Based on Ray Casting" [Takayama et al. 2014].
-    //
-    // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices
-    //   rays_total  Total number of rays that will be shot
-    //   rays_minimum  Minimum number of rays that each patch should receive
-    //   facet_wise  Decision made for each face independently, no use of patches
-    //     (i.e., each face is treated as a patch)
-    //   use_parity  Use parity mode
-    //   is_verbose  Verbose output to cout
-    // Outputs:
-    //   I  #F list of whether face has been flipped
-    //   C  #F list of patch ID (output of bfs_orient > manifold patches))igl_Qu8mg5v7";
 const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(// Project the point cloud V_source onto the triangle mesh
     // V_target,F_target. 
     // A ray is casted for every vertex in the direction specified by 
@@ -567,6 +558,23 @@ const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(// Project
     // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are 
     // the barycentric coordinates wrt the first two edges of the triangle
     // To convert to standard global coordinates, see barycentric_to_global.h)igl_Qu8mg5v7";
+const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient each component (identified by C) of a mesh (V,F) using ambient
+    // occlusion such that the front side is less occluded than back side, as
+    // described in "A Simple Method for Correcting Facet Orientations in
+    // Polygon Meshes Based on Ray Casting" [Takayama et al. 2014].
+    //
+    // Inputs:
+    //   V  #V by 3 list of vertex positions
+    //   F  #F by 3 list of triangle indices
+    //   rays_total  Total number of rays that will be shot
+    //   rays_minimum  Minimum number of rays that each patch should receive
+    //   facet_wise  Decision made for each face independently, no use of patches
+    //     (i.e., each face is treated as a patch)
+    //   use_parity  Use parity mode
+    //   is_verbose  Verbose output to cout
+    // Outputs:
+    //   I  #F list of whether face has been flipped
+    //   C  #F list of patch ID (output of bfs_orient > manifold patches))igl_Qu8mg5v7";
 const char *__doc_igl_find_cross_field_singularities = R"igl_Qu8mg5v7(// Inputs:
   //   V                #V by 3 eigen Matrix of mesh vertex 3D positions
   //   F                #F by 3 eigen Matrix of face (quad) indices
@@ -643,7 +651,7 @@ const char *__doc_igl_get_seconds = R"igl_Qu8mg5v7(// Return the current time in
   //    cout<<"part 2: "<<tictoc()<<endl;
   //    ... // etc)igl_Qu8mg5v7";
 const char *__doc_igl_grad = R"igl_Qu8mg5v7(// Gradient of a scalar function defined on piecewise linear elements (mesh)
-  // is constant on each triangle i,j,k:
+  // is constant on each triangle [tetrahedron] i,j,k:
   // grad(Xijk) = (Xj-Xi) * (Vi - Vk)^R90 / 2A + (Xk-Xi) * (Vj - Vi)^R90 / 2A
   // where Xi is the scalar value at vertex i, Vi is the 3D position of vertex
   // i, and A is the area of triangle (i,j,k). ^R90 represent a rotation of
@@ -682,6 +690,23 @@ const char *__doc_igl_internal_angles = R"igl_Qu8mg5v7(// Compute internal angle
   //
   // Known Issues:
   //   if poly-size ≠ 3 then dim must equal 3.)igl_Qu8mg5v7";
+const char *__doc_igl_internal_angles_using_squared_edge_lengths = R"igl_Qu8mg5v7(// Inputs:
+  //   L_sq  #F by 3 list of squared edge lengths
+  // Output:
+  //   K  #F by poly-size eigen Matrix of internal angles
+  //     for triangles, columns correspond to edges [1,2],[2,0],[0,1]
+  //
+  // Note:
+  //   Usage of internal_angles_using_squared_edge_lengths is preferred to internal_angles_using_squared_edge_lengths)igl_Qu8mg5v7";
+const char *__doc_igl_internal_angles_using_edge_lengths = R"igl_Qu8mg5v7(// Inputs:
+  //   L  #F by 3 list of edge lengths
+  // Output:
+  //   K  #F by poly-size eigen Matrix of internal angles
+  //     for triangles, columns correspond to edges [1,2],[2,0],[0,1]
+  //
+  // Note:
+  //   Usage of internal_angles_using_squared_edge_lengths is preferred to internal_angles_using_squared_edge_lengths
+  //   This function is deprecated and probably will be removed in future versions)igl_Qu8mg5v7";
 const char *__doc_igl_invert_diag = R"igl_Qu8mg5v7(// Templates:
   //   T  should be a eigen sparse matrix primitive type like int or double
   // Inputs:
@@ -1050,7 +1075,7 @@ const char *__doc_igl_readOBJ = R"igl_Qu8mg5v7(// Read a mesh from an ascii obj
   //   FTC  #F list of face indices into vertex texture coordinates
   //   FN  #F list of face indices into vertex normals
   // Returns true on success, false on errors)igl_Qu8mg5v7";
-const char *__doc_igl_readOFF = R"igl_Qu8mg5v7(// Read a mesh from an ascii obj file, filling in vertex positions, normals
+const char *__doc_igl_readOFF = R"igl_Qu8mg5v7(// Read a mesh from an ascii OFF file, filling in vertex positions, normals
   // and texture coordinates. Mesh may have faces of any number of degree
   //
   // Templates:
@@ -1062,10 +1087,8 @@ const char *__doc_igl_readOFF = R"igl_Qu8mg5v7(// Read a mesh from an ascii obj
   // Outputs:
   //   V  double matrix of vertex positions  #V by 3
   //   F  #F list of face indices into vertex positions
-  //   TC  double matrix of texture coordinats #TC by 2
-  //   FTC  #F list of face indices into vertex texture coordinates
-  //   N  double matrix of corner normals #N by 3
-  //   FN  #F list of face indices into vertex normals
+  //   N  list of vertex normals #V by 3
+  //   C  list of rgb color values per vertex #V by 3
   // Returns true on success, false on errors)igl_Qu8mg5v7";
 const char *__doc_igl_readTGF = R"igl_Qu8mg5v7(// READTGF
   //
@@ -1279,8 +1302,6 @@ const char *__doc_igl_triangle_triangulate = R"igl_Qu8mg5v7(// Triangulate the i
     // Outputs:
     //   V2  #V2 by 2  coordinates of the vertives of the generated triangulation
     //   F2  #F2 by 3  list of indices forming the faces of the generated triangulation
-    //
-    // TODO: expose the option to prevent Steiner points on the boundary
     //)igl_Qu8mg5v7";
 const char *__doc_igl_unique = R"igl_Qu8mg5v7(// Act like matlab's [C,IA,IC] = unique(X)
   //
@@ -1319,24 +1340,16 @@ const char *__doc_igl_unproject_onto_mesh = R"igl_Qu8mg5v7(// Unproject a screen
   //    fid  id of the first face hit
   //    bc  barycentric coordinates of hit
   // Returns true if there's a hit)igl_Qu8mg5v7";
-const char *__doc_igl_upsample = R"igl_Qu8mg5v7(// Subdivide a mesh without moving vertices: loop subdivision but odd
-  // vertices stay put and even vertices are just edge midpoints
-  // 
-  // Templates:
-  //   MatV  matrix for vertex positions, e.g. MatrixXd
-  //   MatF  matrix for vertex positions, e.g. MatrixXi
+const char *__doc_igl_upsample = R"igl_Qu8mg5v7(// Subdivide without moving vertices: Given the triangle mesh [V, F],
+  // where n_verts = V.rows(), computes newV and a sparse matrix S s.t.
+  // [newV, newF] is the subdivided mesh where newV = S*V.
+  //
   // Inputs:
-  //   V  #V by dim  mesh vertices
-  //   F  #F by 3  mesh triangles
+  //   n_verts  an integer (number of mesh vertices)
+  //   F  an m by 3 matrix of integers of triangle faces
   // Outputs:
-  //   NV new vertex positions, V is guaranteed to be at top
-  //   NF new list of face indices
-  //
-  // NOTE: V should not be the same as NV,
-  // NOTE: F should not be the same as NF, use other proto
-  //
-  // Known issues:
-  //   - assumes (V,F) is edge-manifold.)igl_Qu8mg5v7";
+  //   S  a sparse matrix (will become the subdivision matrix)
+  //   newF  a matrix containing the new faces)igl_Qu8mg5v7";
 const char *__doc_igl_winding_number = R"igl_Qu8mg5v7(// WINDING_NUMBER Compute the sum of solid angles of a triangle/tetrahedron
   // described by points (vectors) V
   //
@@ -1393,4 +1406,7 @@ const char *__doc_igl_writeOBJ = R"igl_Qu8mg5v7(// Write a mesh in an ascii obj
   //   FN  #F by 3|4 corner normal indices into CN
   //   TC  #TC by 2|3 texture coordinates
   //   FTC #F by 3|4 corner texture coord indices into TC
-  // Returns true on success, false on error)igl_Qu8mg5v7";
+  // Returns true on success, false on error
+  //
+  // Known issues: Horrifyingly, this does not have the same order of
+  // parameters as readOBJ.)igl_Qu8mg5v7";

+ 3 - 1
python/py_doc.h

@@ -38,8 +38,8 @@ extern const char *__doc_igl_edge_lengths;
 extern const char *__doc_igl_edge_topology;
 extern const char *__doc_igl_eigs;
 extern const char *__doc_igl_embree_ambient_occlusion;
-extern const char *__doc_igl_embree_reorient_facets_raycast;
 extern const char *__doc_igl_embree_line_mesh_intersection;
+extern const char *__doc_igl_embree_reorient_facets_raycast;
 extern const char *__doc_igl_find_cross_field_singularities;
 extern const char *__doc_igl_fit_rotations;
 extern const char *__doc_igl_fit_rotations_planar;
@@ -52,6 +52,8 @@ extern const char *__doc_igl_grad;
 extern const char *__doc_igl_harmonic;
 extern const char *__doc_igl_hsv_to_rgb;
 extern const char *__doc_igl_internal_angles;
+extern const char *__doc_igl_internal_angles_using_squared_edge_lengths;
+extern const char *__doc_igl_internal_angles_using_edge_lengths;
 extern const char *__doc_igl_invert_diag;
 extern const char *__doc_igl_is_irregular_vertex;
 extern const char *__doc_igl_jet;

+ 2 - 0
python/py_igl.cpp

@@ -13,6 +13,7 @@
 #include <igl/barycenter.h>
 #include <igl/barycentric_coordinates.h>
 #include <igl/barycentric_to_global.h>
+#include <igl/bbw.h>
 #include <igl/boundary_conditions.h>
 #include <igl/boundary_facets.h>
 #include <igl/boundary_loop.h>
@@ -107,6 +108,7 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_barycenter.cpp"
 #include "py_igl/py_barycentric_coordinates.cpp"
 #include "py_igl/py_barycentric_to_global.cpp"
+#include "py_igl/py_bbw.cpp"
 #include "py_igl/py_boundary_conditions.cpp"
 #include "py_igl/py_boundary_facets.cpp"
 #include "py_igl/py_boundary_loop.cpp"

+ 9 - 8
python/py_igl/py_bbw.cpp

@@ -1,13 +1,14 @@
 // Wrap the BBWData class
-py::class_<iglData > BBWData(m, "BBWData");
+py::class_<igl::BBWData > BBWData(m, "BBWData");
 
 BBWData
 .def(py::init<>())
-.def_readwrite("partition_unity", &iglData::partition_unity)
-.def_readwrite("W0", &iglData::W0)
-.def_readwrite("active_set_params", &iglData::active_set_params)
-.def_readwrite("verbosity", &iglData::verbosity)
-.def("print", [](iglData& data)
+.def_readwrite("partition_unity", &igl::BBWData::partition_unity)
+.def_readwrite("W0", &igl::BBWData::W0)
+.def_readwrite("active_set_params", &igl::BBWData::active_set_params)
+.def_readwrite("verbosity", &igl::BBWData::verbosity)
+
+.def("print", [](igl::BBWData& data)
 {
     return data.print();
 })
@@ -19,7 +20,7 @@ m.def("bbw", []
   const Eigen::MatrixXi& Ele,
   const Eigen::MatrixXi& b,
   const Eigen::MatrixXd& bc,
-  iglData& data,
+  igl::BBWData& data,
   Eigen::MatrixXd& W
 )
 {
@@ -27,6 +28,6 @@ m.def("bbw", []
   Eigen::VectorXi bv;
   if (b.size() != 0)
     bv = b;
-  return igl(V, Ele, bv, bc, data, W);
+  return igl::bbw(V, Ele, bv, bc, data, W);
 }, __doc_igl_bbw,
 py::arg("V"), py::arg("Ele"), py::arg("b"), py::arg("bc"), py::arg("data"), py::arg("W"));

+ 10 - 10
python/py_igl/py_boundary_facets.cpp

@@ -1,13 +1,3 @@
-m.def("boundary_facets", []
-(
-  const std::vector<std::vector<int> > & T,
-  std::vector<std::vector<int> > & F
-)
-{
-  return igl::boundary_facets(T,F);
-}, __doc_igl_boundary_facets,
-py::arg("T"), py::arg("F"));
-
 m.def("boundary_facets", []
 (
   const Eigen::MatrixXi& T,
@@ -28,3 +18,13 @@ m.def("boundary_facets", []
   return F;
 }, __doc_igl_boundary_facets,
 py::arg("T"));
+
+m.def("boundary_facets", []
+(
+  const std::vector<std::vector<int> > & T,
+  std::vector<std::vector<int> > & F
+)
+{
+  return igl::boundary_facets(T,F);
+}, __doc_igl_boundary_facets,
+py::arg("T"), py::arg("F"));

+ 9 - 7
python/py_igl/py_boundary_loop.cpp

@@ -1,17 +1,19 @@
 m.def("boundary_loop", []
 (
   const Eigen::MatrixXi& F,
-  std::vector<std::vector<int> >& L
+  Eigen::MatrixXi& L
 )
 {
-  return igl::boundary_loop(F,L);
+  Eigen::VectorXi T;
+  igl::boundary_loop(F,T);
+  L = T;
 }, __doc_igl_boundary_loop,
 py::arg("F"), py::arg("L"));
 
 m.def("boundary_loop", []
 (
   const Eigen::MatrixXi& F,
-  std::vector<int>& L
+  std::vector<std::vector<int> >& L
 )
 {
   return igl::boundary_loop(F,L);
@@ -21,11 +23,11 @@ py::arg("F"), py::arg("L"));
 m.def("boundary_loop", []
 (
   const Eigen::MatrixXi& F,
-  Eigen::MatrixXi& L
+  std::vector<int>& L
 )
 {
-  Eigen::VectorXi T;
-  igl::boundary_loop(F,T);
-  L = T;
+  return igl::boundary_loop(F,L);
 }, __doc_igl_boundary_loop,
 py::arg("F"), py::arg("L"));
+
+

+ 10 - 9
python/py_igl/py_internal_angles.cpp

@@ -21,13 +21,14 @@ m.def("internal_angles_using_squared_edge_lengths", []
 }, __doc_igl_internal_angles,
 py::arg("L_sq"), py::arg("K"));
 
-m.def("internal_angles_using_edge_lengths", []
-(
-  const Eigen::MatrixXd& L,
-  Eigen::MatrixXd& K
-)
-{
-  return igl::internal_angles_using_edge_lengths(L, K);
-}, __doc_igl_internal_angles,
-py::arg("L"), py::arg("K"));
+//m.def("internal_angles_using_edge_lengths", []
+//(
+//  const Eigen::MatrixXd& L,
+//  Eigen::MatrixXd& K
+//)
+//{
+//  return igl::internal_angles_using_edge_lengths(L, K);
+//}, __doc_igl_internal_angles,
+//py::arg("L"), py::arg("K"));
+
 

+ 9 - 6
python/py_igl/py_readMESH.cpp

@@ -1,24 +1,27 @@
 m.def("readMESH", []
 (
   const std::string mesh_file_name,
-  std::vector<std::vector<double> > & V,
-  std::vector<std::vector<int> > & T,
-  std::vector<std::vector<int> > & F
+  Eigen::MatrixXd& V,
+  Eigen::MatrixXi& T,
+  Eigen::MatrixXi& F
 )
 {
   return igl::readMESH(mesh_file_name, V, T, F);
 }, __doc_igl_readMESH,
 py::arg("mesh_file_name"), py::arg("V"), py::arg("T"), py::arg("F"));
 
+
 m.def("readMESH", []
 (
   const std::string mesh_file_name,
-  Eigen::MatrixXd& V,
-  Eigen::MatrixXi& T,
-  Eigen::MatrixXi& F
+  std::vector<std::vector<double> > & V,
+  std::vector<std::vector<int> > & T,
+  std::vector<std::vector<int> > & F
 )
 {
   return igl::readMESH(mesh_file_name, V, T, F);
 }, __doc_igl_readMESH,
 py::arg("mesh_file_name"), py::arg("V"), py::arg("T"), py::arg("F"));
 
+
+

+ 11 - 11
python/py_igl/py_read_triangle_mesh.cpp

@@ -1,14 +1,3 @@
-m.def("read_triangle_mesh", []
-(
-  const std::string str,
-  std::vector<std::vector<double> >& V,
-  std::vector<std::vector<int> >& F
-)
-{
-  return igl::read_triangle_mesh(str,V,F);
-}, __doc_igl_read_triangle_mesh,
-py::arg("str"), py::arg("V"), py::arg("F"));
-
 m.def("read_triangle_mesh", []
 (
   const std::string str,
@@ -34,3 +23,14 @@ m.def("read_triangle_mesh", []
   return igl::read_triangle_mesh(str,V,F,dir,base,ext,name);
 }, __doc_igl_read_triangle_mesh,
 py::arg("str"), py::arg("V"), py::arg("F"), py::arg("dir"), py::arg("base"), py::arg("ext"), py::arg("name"));
+
+m.def("read_triangle_mesh", []
+(
+  const std::string str,
+  std::vector<std::vector<double> >& V,
+  std::vector<std::vector<int> >& F
+)
+{
+  return igl::read_triangle_mesh(str,V,F);
+}, __doc_igl_read_triangle_mesh,
+py::arg("str"), py::arg("V"), py::arg("F"));

+ 30 - 31
python/py_igl/py_unique.cpp

@@ -1,25 +1,3 @@
-m.def("unique", []
-(
-  const std::vector<double> & A,
-  std::vector<double> & C,
-  std::vector<size_t> & IA,
-  std::vector<size_t> & IC
-)
-{
-  return igl::unique(A,C,IA,IC);
-}, __doc_igl_unique,
-py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
-
-m.def("unique", []
-(
-  const std::vector<double> & A,
-  std::vector<double> & C
-)
-{
-  return igl::unique(A,C);
-}, __doc_igl_unique,
-py::arg("A"), py::arg("C"));
-
 m.def("unique", []
 (
   const Eigen::MatrixXd& A,
@@ -54,15 +32,10 @@ m.def("unique_rows", []
 }, __doc_igl_unique,
 py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
 
-
-
-// int
-
-
 m.def("unique", []
 (
-  const std::vector<int> & A,
-  std::vector<int> & C,
+  const std::vector<double> & A,
+  std::vector<double> & C,
   std::vector<size_t> & IA,
   std::vector<size_t> & IC
 )
@@ -73,14 +46,18 @@ py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
 
 m.def("unique", []
 (
-  const std::vector<int> & A,
-  std::vector<int> & C
+  const std::vector<double> & A,
+  std::vector<double> & C
 )
 {
   return igl::unique(A,C);
 }, __doc_igl_unique,
 py::arg("A"), py::arg("C"));
 
+
+// int
+
+
 m.def("unique", []
 (
   const Eigen::MatrixXi& A,
@@ -114,3 +91,25 @@ m.def("unique_rows", []
   return igl::unique_rows(A,C,IA,IC);
 }, __doc_igl_unique,
 py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const std::vector<int> & A,
+  std::vector<int> & C,
+  std::vector<size_t> & IA,
+  std::vector<size_t> & IC
+)
+{
+  return igl::unique(A,C,IA,IC);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC"));
+
+m.def("unique", []
+(
+  const std::vector<int> & A,
+  std::vector<int> & C
+)
+{
+  return igl::unique(A,C);
+}, __doc_igl_unique,
+py::arg("A"), py::arg("C"));

+ 1 - 0
python/python_shared.cpp

@@ -90,6 +90,7 @@ PYBIND11_PLUGIN(pyigl) {
            edge_topology
            eigs
            embree_ambient_occlusion
+           embree_line_mesh_intersection
            embree_reorient_facets_raycast
            find_cross_field_singularities
            fit_rotations

+ 1 - 1
python/tutorial/106_ViewerMenu.py

@@ -52,7 +52,7 @@ def viewer_init(viewer):
     viewer.ngui.addButton("Print Hello", cb)
 
     #Add an additional menu window
-    viewer.ngui.addWindow(nanogui.Vector2i(220, 10), "New Window")
+    viewer.ngui.addWindow((220, 10), "New Window")
 
     # add accessor
     viewer.ngui.addDoubleVariable("double", *make_accessors("float_variable"))

+ 1 - 0
python/tutorial/306_EigenDecomposition.py

@@ -60,6 +60,7 @@ def key_down(viewer, key, mod):
         viewer.data.compute_normals()
         viewer.data.set_colors(C)
         return True
+    return False
 
 
 viewer.callback_key_down = key_down

+ 8 - 1
shared/cmake/CMakeLists.txt

@@ -338,13 +338,20 @@ if(LIBIGL_WITH_OPENGL)
   endif()
   list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_OPENGL_EXTRA_LIBRARIES})
 
+  list(APPEND LIBIGL_EXTRA_LIBRARIES ${LIBIGL_OPENGL_EXTRA_LIBRARIES})
+
   if(LIBIGL_WITH_OPENGL_GLFW)
     set(GLFW_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glfw/include")
     if(NOT APPLE)
       list(APPEND GLFW_INCLUDE_DIRS "${NANOGUI_DIR}/ext/glew/include")
     endif()
 
-    add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
+    # Note: if add_subdirectory("${NANOGUI_DIR}" "nanogui") runs below it will
+    # add GLFW as a side-effect; in this case, CMake will complain about
+    # duplicates if we add them here.
+    if (NOT (LIBIGL_WITH_VIEWER AND LIBIGL_WITH_NANOGUI))
+        add_subdirectory("${NANOGUI_DIR}/ext/glfw" "glfw")
+    endif()
     set(LIBIGL_OPENGL_GLFW_EXTRA_LIBRARIES "glfw" ${GLFW_LIBRARIES})
     if(LIBIGL_USE_STATIC_LIBRARY)
       CompileIGL_Module("opengl/glfw" "")

+ 6 - 5
tutorial/707_SweptVolume/main.cpp

@@ -69,11 +69,12 @@ int main(int argc, char * argv[])
           if(show_swept_volume)
           {
             viewer.data.set_mesh(SV,SF);
-            viewer.data.uniform_colors(
-              {SILVER_AMBIENT[0], SILVER_AMBIENT[1], SILVER_AMBIENT[2]},
-              {SILVER_DIFFUSE[0], SILVER_DIFFUSE[1], SILVER_DIFFUSE[2]},
-              {SILVER_SPECULAR[0], SILVER_SPECULAR[1], SILVER_SPECULAR[2]});
-          }else
+            Eigen::Vector3d ambient = Eigen::Vector3d(SILVER_AMBIENT[0], SILVER_AMBIENT[1], SILVER_AMBIENT[2]);
+            Eigen::Vector3d diffuse = Eigen::Vector3d(SILVER_DIFFUSE[0], SILVER_DIFFUSE[1], SILVER_DIFFUSE[2]);
+            Eigen::Vector3d specular = Eigen::Vector3d(SILVER_SPECULAR[0], SILVER_SPECULAR[1], SILVER_SPECULAR[2]);
+            viewer.data.uniform_colors(ambient,diffuse,specular);
+          }
+          else
           {
             viewer.data.set_mesh(V,F);
           }