瀏覽代碼

Merge branch 'master' of https://github.com/libigl/libigl

Conflicts:
	include/igl/per_vertex_normals.cpp
	include/igl/triangle_triangle_adjacency.cpp

Former-commit-id: 05848e2e96a83859b3cf3b4a0a2ca0381e3c0ec5
Olga Diamanti 10 年之前
父節點
當前提交
b037df0be6

+ 3 - 12
examples/scene-rotation/example.cpp

@@ -32,7 +32,6 @@
 
 #ifdef __APPLE__
 #include <GLUT/glut.h>
-#include <Carbon/Carbon.h>
 #else
 #include <GL/glut.h>
 #endif
@@ -483,14 +482,6 @@ void init_relative()
 }
 
 
-KeyMap keyStates ;
-bool IS_KEYDOWN( uint16_t vKey )
-{
-  uint8_t index = vKey / 32 ;
-  uint8_t shift = vKey % 32 ;
-  return keyStates[index].bigEndianValue & (1 << shift) ;
-}
-
 
 void undo()
 {
@@ -519,9 +510,9 @@ void key(unsigned char key, int mouse_x, int mouse_y)
   using namespace std;
   using namespace igl;
   using namespace Eigen;
-  GetKeys(keyStates);
-  const bool command_down = IS_KEYDOWN(kVK_Command);
-  const bool shift_down = IS_KEYDOWN(kVK_Shift);
+  const int mod = glutGetModifiers();
+  const bool command_down = mod | GLUT_ACTIVE_COMMAND;
+  const bool shift_down = mod | GLUT_ACTIVE_SHIFT;
   switch(key)
   {
     // ESC

+ 1 - 0
include/igl/all_edges.cpp

@@ -48,4 +48,5 @@ IGL_INLINE void igl::all_edges(
 template void igl::all_edges<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::all_edges<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
 template void igl::all_edges<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
+template void igl::all_edges<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 9 - 0
include/igl/boundary_loop.cpp

@@ -21,6 +21,9 @@ IGL_INLINE void igl::boundary_loop(
   using namespace Eigen;
   using namespace igl;
 
+  if(F.rows() == 0)
+    return;
+
   MatrixXd Vdummy(F.maxCoeff()+1,1);
   MatrixXi TT,TTi;
   vector<std::vector<int> > VF, VFi;
@@ -95,6 +98,9 @@ IGL_INLINE void igl::boundary_loop(
   using namespace Eigen;
   using namespace std;
 
+  if(F.rows() == 0)
+    return;
+
   vector<vector<int> > Lall;
   boundary_loop(F,Lall);
 
@@ -122,6 +128,9 @@ IGL_INLINE void igl::boundary_loop(
   using namespace Eigen;
   using namespace std;
 
+  if(F.rows() == 0)
+    return;
+
   vector<int> Lvec;
   boundary_loop(F,Lvec);
 

+ 2 - 1
include/igl/doublearea.cpp

@@ -73,12 +73,13 @@ IGL_INLINE void igl::doublearea(
   }
 }
 
+
 template <
   typename DerivedA,
   typename DerivedB,
   typename DerivedC,
   typename DerivedD>
-IGL_INLINE void doublearea(
+IGL_INLINE void igl::doublearea(
   const Eigen::PlainObjectBase<DerivedA> & A,
   const Eigen::PlainObjectBase<DerivedB> & B,
   const Eigen::PlainObjectBase<DerivedC> & C,

+ 21 - 0
include/igl/frustum.cpp

@@ -0,0 +1,21 @@
+#include "frustum.h"
+template < typename DerivedP>
+IGL_INLINE void igl::frustum(
+  const typename DerivedP::Scalar left,
+  const typename DerivedP::Scalar right,
+  const typename DerivedP::Scalar bottom,
+  const typename DerivedP::Scalar top,
+  const typename DerivedP::Scalar nearVal,
+  const typename DerivedP::Scalar farVal,
+  Eigen::PlainObjectBase<DerivedP> & P)
+{
+  P.setConstant(4,4,0.);
+  P(0,0) = (2.0 * nearVal) / (right - left);
+  P(1,1) = (2.0 * nearVal) / (top - bottom);
+  P(0,2) = (right + left) / (right - left);
+  P(1,2) = (top + bottom) / (top - bottom);
+  P(2,2) = -(farVal + nearVal) / (farVal - nearVal);
+  P(3,2) = -1.0;
+  P(2,3) = -(2.0 * farVal * nearVal) / (farVal - nearVal);
+}
+

+ 44 - 0
include/igl/frustum.h

@@ -0,0 +1,44 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_FRUSTUM_H
+#define IGL_FRUSTUM_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+
+namespace igl 
+{
+  // Implementation of the deprecated glFrustum function.
+  //
+  // Inputs:
+  //   left  coordinate of left vertical clipping plane
+  //   right  coordinate of right vertical clipping plane
+  //   bottom  coordinate of bottom vertical clipping plane
+  //   top  coordinate of top vertical clipping plane
+  //   nearVal  distance to near plane
+  //   farVal  distance to far plane
+  // Outputs:
+  //   P  4x4 perspective matrix
+  template < typename DerivedP>
+  IGL_INLINE void frustum(
+    const typename DerivedP::Scalar left,
+    const typename DerivedP::Scalar right,
+    const typename DerivedP::Scalar bottom,
+    const typename DerivedP::Scalar top,
+    const typename DerivedP::Scalar nearVal,
+    const typename DerivedP::Scalar farVal,
+    Eigen::PlainObjectBase<DerivedP> & P);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "frustum.cpp"
+#endif
+
+#endif
+
+

+ 1 - 1
include/igl/internal_angles.cpp

@@ -48,7 +48,7 @@ IGL_INLINE void igl::internal_angles(
   #  define IGL_OMP_MIN_VALUE 1000
   #endif
   #pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
-  for(long int f = 0;f<m;f++)
+  for(size_t f = 0;f<m;f++)
   {
     for(size_t d = 0;d<3;d++)
     {

+ 2 - 0
include/igl/list_to_matrix.cpp

@@ -153,4 +153,6 @@ template bool igl::list_to_matrix<double, Eigen::Matrix<double, 1, -1, 1, 1, -1>
 template bool igl::list_to_matrix<unsigned long, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > >(std::vector<unsigned long, std::allocator<unsigned long> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template bool igl::list_to_matrix<double, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(std::__1::vector<double, std::__1::allocator<double> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template bool igl::list_to_matrix<float, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > >(std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::Matrix<double, -1, 2, 0, -1, 2>&);
+template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::Matrix<double, -1, 3, 0, -1, 3>&);
 #endif

+ 31 - 0
include/igl/look_at.cpp

@@ -0,0 +1,31 @@
+#include "look_at.h"
+
+template <
+  typename Derivedeye,
+  typename Derivedcenter,
+  typename Derivedup,
+  typename DerivedR>
+IGL_INLINE void igl::look_at(
+  const Eigen::PlainObjectBase<Derivedeye> & eye,
+  const Eigen::PlainObjectBase<Derivedcenter> & center,
+  const Eigen::PlainObjectBase<Derivedup> & up,
+  Eigen::PlainObjectBase<DerivedR> & R)
+{
+  typedef Eigen::Matrix<typename DerivedR::Scalar,3,1> Vector3S;
+  Vector3S f = (center - eye).normalized();
+  Vector3S s = f.cross(up).normalized();
+  Vector3S u = s.cross(f);
+  R = Eigen::Matrix<typename DerivedR::Scalar,4,4>::Identity();
+  R(0,0) = s(0);
+  R(0,1) = s(1);
+  R(0,2) = s(2);
+  R(1,0) = u(0);
+  R(1,1) = u(1);
+  R(1,2) = u(2);
+  R(2,0) =-f(0);
+  R(2,1) =-f(1);
+  R(2,2) =-f(2);
+  R(0,3) =-s.transpose() * eye;
+  R(1,3) =-u.transpose() * eye;
+  R(2,3) = f.transpose() * eye;
+}

+ 42 - 0
include/igl/look_at.h

@@ -0,0 +1,42 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_LOOK_AT_H
+#define IGL_LOOK_AT_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+
+namespace igl 
+{
+  // Implementation of the deprecated gluLookAt function.
+  //
+  // Inputs:
+  //   eye  3-vector of eye position
+  //   center  3-vector of center reference point
+  //   up  3-vector of up vector
+  // Outputs:
+  //   R  4x4 rotation matrix
+  //
+  template <
+    typename Derivedeye,
+    typename Derivedcenter,
+    typename Derivedup,
+    typename DerivedR >
+  IGL_INLINE void look_at(
+    const Eigen::PlainObjectBase<Derivedeye> & eye,
+    const Eigen::PlainObjectBase<Derivedcenter> & center,
+    const Eigen::PlainObjectBase<Derivedup> & up,
+    Eigen::PlainObjectBase<DerivedR> & R);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "look_at.cpp"
+#endif
+
+#endif
+

+ 20 - 0
include/igl/ortho.cpp

@@ -0,0 +1,20 @@
+#include "ortho.h"
+
+template < typename DerivedP>
+IGL_INLINE void igl::ortho(
+  const typename DerivedP::Scalar left,
+  const typename DerivedP::Scalar right,
+  const typename DerivedP::Scalar bottom,
+  const typename DerivedP::Scalar top,
+  const typename DerivedP::Scalar nearVal,
+  const typename DerivedP::Scalar farVal,
+  Eigen::PlainObjectBase<DerivedP> & P)
+{
+  P.setIdentity();
+  P(0,0) = 2. / (right - left);
+  P(1,1) = 2. / (top - bottom);
+  P(2,2) = - 2./ (farVal - nearVal);
+  P(0,3) = - (right + left) / (right - left);
+  P(1,3) = - (top + bottom) / (top - bottom);
+  P(2,3) = - (farVal + nearVal) / (farVal - nearVal);
+}

+ 42 - 0
include/igl/ortho.h

@@ -0,0 +1,42 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_ORTHO_H
+#define IGL_ORTHO_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+
+namespace igl 
+{
+  // Implementation of the deprecated glOrtho function.
+  //
+  // Inputs:
+  //   left  coordinate of left vertical clipping plane
+  //   right  coordinate of right vertical clipping plane
+  //   bottom  coordinate of bottom vertical clipping plane
+  //   top  coordinate of top vertical clipping plane
+  //   nearVal  distance to near plane
+  //   farVal  distance to far plane
+  // Outputs:
+  //   P  4x4 perspective matrix
+  template < typename DerivedP>
+  IGL_INLINE void ortho(
+    const typename DerivedP::Scalar left,
+    const typename DerivedP::Scalar right,
+    const typename DerivedP::Scalar bottom,
+    const typename DerivedP::Scalar top,
+    const typename DerivedP::Scalar nearVal,
+    const typename DerivedP::Scalar farVal,
+    Eigen::PlainObjectBase<DerivedP> & P);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "ortho.cpp"
+#endif
+
+#endif

+ 6 - 4
include/igl/per_vertex_normals.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// 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 "per_vertex_normals.h"
 
@@ -104,4 +104,6 @@ IGL_INLINE void igl::per_vertex_normals(
 template void igl::per_vertex_normals<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::per_vertex_normals<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::per_vertex_normals<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, igl::PerVertexNormalsWeightingType, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+template void igl::per_vertex_normals<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
+template void igl::per_vertex_normals<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 #endif

+ 60 - 49
include/igl/serialize.cpp

@@ -43,7 +43,7 @@ namespace igl
     }
     else
     {
-      std::cerr << "saving binary serialization failed!" << std::endl;
+      std::cerr << "serialization: file " << filename << " not found!" << std::endl;
     }
 
     return success;
@@ -51,12 +51,19 @@ namespace igl
 
   template <typename T>
   IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer)
+  {
+    std::map<std::uintptr_t,IndexedPointerBase*> handler;
+    return serialize(obj,objectName,buffer,0,handler);
+  }
+
+  template <typename T>
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer,size_t offset,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
   {
     // serialize object data
     size_t size = serialization::getByteSize(obj);
     std::vector<char> tmp(size);
     auto it = tmp.begin();
-    serialization::serialize(obj,tmp,it);
+    serialization::serialize(obj,tmp,it,memoryMap);
 
     std::string objectType(typeid(obj).name());
     size_t newObjectSize = tmp.size();
@@ -69,9 +76,9 @@ namespace igl
     std::vector<char>::iterator iter = buffer.begin()+curSize;
 
     // serialize object header (name/type/size)
-    serialization::serialize(objectName,buffer,iter);
-    serialization::serialize(objectType,buffer,iter);
-    serialization::serialize(newObjectSize,buffer,iter);
+    serialization::serialize(objectName,buffer,iter,memoryMap);
+    serialization::serialize(objectType,buffer,iter,memoryMap);
+    serialization::serialize(newObjectSize,buffer,iter,memoryMap);
 
     // copy serialized data to buffer
     iter = std::copy(tmp.begin(),tmp.end(),iter);
@@ -108,7 +115,7 @@ namespace igl
     }
     else
     {
-      std::cerr << "Loading binary serialization failed!" << std::endl;
+      std::cerr << "serialization: file " << filename << " not found!" << std::endl;
     }
 
     return success;
@@ -281,7 +288,7 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
       // data
       std::vector<char> tmp;
@@ -289,7 +296,7 @@ namespace igl
 
       // size
       size_t size = buffer.size();
-      serialization::serialize(tmp.size(),buffer,iter);
+      serialization::serialize(tmp.size(),buffer,iter,memoryMap);
       size_t cur = iter - buffer.begin();
 
       buffer.resize(size+tmp.size());
@@ -320,7 +327,7 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
       //serialization::updateMemoryMap(obj,sizeof(T),memoryMap);
       const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&obj);
@@ -342,12 +349,12 @@ namespace igl
       return getByteSize(obj.length())+obj.length()*sizeof(uint8_t);
     }
 
-    IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.length(),buffer,iter);
+      serialization::serialize(obj.length(),buffer,iter,memoryMap);
       for(const auto& cur : obj)
       {
-        serialization::serialize(cur,buffer,iter);
+        serialization::serialize(cur,buffer,iter,memoryMap);
       }
     }
 
@@ -374,7 +381,7 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
       // data
       std::vector<char> tmp;
@@ -382,7 +389,7 @@ namespace igl
 
       // size
       size_t size = buffer.size();
-      serialization::serialize(tmp.size(),buffer,iter);
+      serialization::serialize(tmp.size(),buffer,iter,memoryMap);
       size_t cur = iter - buffer.begin();
 
       buffer.resize(size+tmp.size());
@@ -415,10 +422,10 @@ namespace igl
     }
 
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.first,buffer,iter);
-      serialization::serialize(obj.second,buffer,iter);
+      serialization::serialize(obj.first,buffer,iter,memoryMap);
+      serialization::serialize(obj.second,buffer,iter,memoryMap);
     }
 
     template <typename T1,typename T2>
@@ -437,13 +444,13 @@ namespace igl
     }
 
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
       size_t size = obj.size();
-      serialization::serialize(size,buffer,iter);
+      serialization::serialize(size,buffer,iter,memoryMap);
       for(const auto& cur : obj)
       {
-        serialization::serialize(cur,buffer,iter);
+        serialization::serialize(cur,buffer,iter,memoryMap);
       }
     }
 
@@ -469,12 +476,12 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.size(),buffer,iter);
+      serialization::serialize(obj.size(),buffer,iter,memoryMap);
       for(const auto& cur : obj)
       {
-        serialization::serialize(cur,buffer,iter);
+        serialization::serialize(cur,buffer,iter,memoryMap);
       }
     }
 
@@ -502,12 +509,12 @@ namespace igl
     }
 
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.size(),buffer,iter);
+      serialization::serialize(obj.size(),buffer,iter,memoryMap);
       for(const auto& cur : obj)
       {
-        serialization::serialize(cur,buffer,iter);
+        serialization::serialize(cur,buffer,iter,memoryMap);
       }
     }
 
@@ -535,10 +542,10 @@ namespace igl
     }
 
     template<typename T,int R,int C,int P,int MR,int MC>
-    IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.rows(),buffer,iter);
-      serialization::serialize(obj.cols(),buffer,iter);
+      serialization::serialize(obj.rows(),buffer,iter,memoryMap);
+      serialization::serialize(obj.cols(),buffer,iter,memoryMap);
       size_t size = sizeof(T)*obj.rows()*obj.cols();
       auto ptr = reinterpret_cast<const uint8_t*>(obj.data());
       iter = std::copy(ptr,ptr+size,iter);
@@ -566,19 +573,19 @@ namespace igl
     }
 
     template<typename T,int P,typename I>
-    IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj.rows(),buffer,iter);
-      serialization::serialize(obj.cols(),buffer,iter);
-      serialization::serialize(obj.nonZeros(),buffer,iter);
+      serialization::serialize(obj.rows(),buffer,iter,memoryMap);
+      serialization::serialize(obj.cols(),buffer,iter,memoryMap);
+      serialization::serialize(obj.nonZeros(),buffer,iter,memoryMap);
 
       for(int k=0;k<obj.outerSize();++k)
       {
         for(typename Eigen::SparseMatrix<T,P,I>::InnerIterator it(obj,k);it;++it)
         {
-          serialization::serialize(it.row(),buffer,iter);
-          serialization::serialize(it.col(),buffer,iter);
-          serialization::serialize(it.value(),buffer,iter);
+          serialization::serialize(it.row(),buffer,iter,memoryMap);
+          serialization::serialize(it.col(),buffer,iter,memoryMap);
+          serialization::serialize(it.value(),buffer,iter,memoryMap);
         }
       }
     }
@@ -621,12 +628,12 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialization::serialize(obj == nullptr,buffer,iter);
+      serialization::serialize(obj == nullptr,buffer,iter,memoryMap);
 
       if(obj)
-        serialization::serialize(*obj,buffer,iter);
+        serialization::serialize(*obj,buffer,iter,memoryMap);
     }
 
     template <typename T>
@@ -639,32 +646,36 @@ namespace igl
       {
         if(obj)
         {
-          std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
+          std::cout << "serialization: possible memory leak in serialization for '" << typeid(obj).name() << "'" << std::endl;
           obj = nullptr;
         }
       }
       else
       {
         if(obj)
-          std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
-
-        obj = new typename std::remove_pointer<T>::type();
+        {
+          std::cout << "serialization: possible memory corruption in deserialization for '" << typeid(obj).name() << "'" << std::endl;
+        }
+        else
+        {
+          obj = new typename std::remove_pointer<T>::type();
+        }
         serialization::deserialize(*obj,iter);
       }
     }
 
     // std::shared_ptr and std::unique_ptr
 
-    /*template <typename T>
+    template <typename T>
     IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value,size_t>::type getByteSize(const T& obj)
     {
       return getByteSize(obj.get());
     }
 
     template <typename T>
-    IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
-      serialize(obj.get(),buffer,iter);
+      serialize(obj.get(),buffer,iter,memoryMap);
     }
 
     template <template<typename> class T0,typename T1>
@@ -693,7 +704,7 @@ namespace igl
     }
 
     template <typename T>
-    IGL_INLINE void serialize(const std::weak_ptr<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
+    IGL_INLINE void serialize(const std::weak_ptr<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap)
     {
 
     }
@@ -702,7 +713,7 @@ namespace igl
     IGL_INLINE void deserialize(std::weak_ptr<T>& obj,std::vector<char>::const_iterator& iter)
     {
 
-    }*/
+    }
 
     // functions to overload for non-intrusive serialization
     template <typename T>
@@ -714,7 +725,7 @@ namespace igl
     template <typename T>
     IGL_INLINE void deserialize(T& obj,const std::vector<char>& buffer)
     {
-      std::cerr << typeid(obj).name() << " is not drserializable: derive from igl::Serializable or overload the function igl::serialization::deserialize(T& obj, const std::vector<char>& buffer)" << std::endl;
+      std::cerr << typeid(obj).name() << " is not deserializable: derive from igl::Serializable or overload the function igl::serialization::deserialize(T& obj, const std::vector<char>& buffer)" << std::endl;
     }
 
     // helper functions

+ 17 - 15
include/igl/serialize.h

@@ -74,6 +74,8 @@ namespace igl
   IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite = false);
   template <typename T>
   IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
+  template <typename T>
+  IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer,size_t offset,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
 
   // Deserializes the given data from a file or buffer back to the provided object
   //
@@ -245,7 +247,7 @@ namespace igl
     template <typename T>
     IGL_INLINE typename std::enable_if<!is_serializable<T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
     IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
@@ -253,20 +255,20 @@ namespace igl
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
     // std::string
     IGL_INLINE size_t getByteSize(const std::string& obj);
-    IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     IGL_INLINE void deserialize(std::string& obj,std::vector<char>::const_iterator& iter);
 
     // SerializableBase
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);    
 
@@ -275,7 +277,7 @@ namespace igl
     template <typename T1,typename T2>
     IGL_INLINE size_t getByteSize(const std::pair<T1,T2>& obj);
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T1,typename T2>
     IGL_INLINE void deserialize(std::pair<T1,T2>& obj,std::vector<char>::const_iterator& iter);
 
@@ -283,7 +285,7 @@ namespace igl
     template <typename T1,typename T2>
     IGL_INLINE size_t getByteSize(const std::vector<T1,T2>& obj);
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T1,typename T2>
     IGL_INLINE void deserialize(std::vector<T1,T2>& obj,std::vector<char>::const_iterator& iter);
 
@@ -291,7 +293,7 @@ namespace igl
     template <typename T>
     IGL_INLINE size_t getByteSize(const std::set<T>& obj);
     template <typename T>
-    IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
     IGL_INLINE void deserialize(std::set<T>& obj,std::vector<char>::const_iterator& iter);
 
@@ -299,7 +301,7 @@ namespace igl
     template <typename T1,typename T2>
     IGL_INLINE size_t getByteSize(const std::map<T1,T2>& obj);
     template <typename T1,typename T2>
-    IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T1,typename T2>
     IGL_INLINE void deserialize(std::map<T1,T2>& obj,std::vector<char>::const_iterator& iter);
 
@@ -307,14 +309,14 @@ namespace igl
     template<typename T,int R,int C,int P,int MR,int MC>
     IGL_INLINE size_t getByteSize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj);
     template<typename T,int R,int C,int P,int MR,int MC>
-    IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template<typename T,int R,int C,int P,int MR,int MC>
     IGL_INLINE void deserialize(Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>::const_iterator& iter);
 
     template<typename T,int P,typename I>
     IGL_INLINE size_t getByteSize(const Eigen::SparseMatrix<T,P,I>& obj);
     template<typename T,int P,typename I>
-    IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template<typename T,int P,typename I>
     IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>::const_iterator& iter);
 
@@ -322,15 +324,15 @@ namespace igl
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_pointer<T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
     IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
 
     // std::shared_ptr and std::unique_ptr
-    /*template <typename T>
+    template <typename T>
     IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value,size_t>::type getByteSize(const T& obj);
     template <typename T>
-    IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <template<typename> class T0, typename T1>
     IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T0<T1> >::value>::type deserialize(T0<T1>& obj,std::vector<char>::const_iterator& iter);
 
@@ -338,9 +340,9 @@ namespace igl
     template <typename T>
     IGL_INLINE size_t getByteSize(const std::weak_ptr<T>& obj);
     template <typename T>
-    IGL_INLINE void serialize(const std::weak_ptr<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
+    IGL_INLINE void serialize(const std::weak_ptr<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter,std::map<std::uintptr_t,IndexedPointerBase*>& memoryMap);
     template <typename T>
-    IGL_INLINE void deserialize(std::weak_ptr<T>& obj,std::vector<char>::const_iterator& iter);*/
+    IGL_INLINE void deserialize(std::weak_ptr<T>& obj,std::vector<char>::const_iterator& iter);
 
     // functions to overload for non-intrusive serialization
     template <typename T>

+ 25 - 30
include/igl/slice.cpp

@@ -38,42 +38,37 @@ IGL_INLINE void igl::slice(
   assert(C.minCoeff() >= 0);
   assert(C.maxCoeff() < xn);
 
-  // Build reindexing maps for columns and rows, -1 means not in map
-  std::vector<std::vector<int> > RI;
-  RI.resize(xm);
-  for(int i = 0;i<ym;i++)
-  {
-    RI[R(i)].push_back(i);
-  }
-  std::vector<std::vector<int> > CI;
-  CI.resize(xn);
-  // initialize to -1
-  for(int i = 0;i<yn;i++)
+  // initialize row and col permutation vectors
+  Eigen::VectorXi rowIndexVec = Eigen::VectorXi::LinSpaced(xm,0,xm);
+  Eigen::VectorXi rowPermVec  = Eigen::VectorXi::LinSpaced(xm,0,xm);
+  for(int i=0;i<ym;i++)
   {
-    CI[C(i)].push_back(i);
+    int pos = rowIndexVec.coeffRef(R(i));
+    if(pos != i)
+    {
+      int& val = rowPermVec.coeffRef(i);
+      std::swap(rowIndexVec.coeffRef(val),rowIndexVec.coeffRef(R(i)));
+      std::swap(rowPermVec.coeffRef(i),rowPermVec.coeffRef(pos));
+    }
   }
-  // Resize output
-  Eigen::SparseMatrix<T, Eigen::RowMajor> dyn_Y(ym,yn);
-  // Take a guess at the number of nonzeros (this assumes uniform distribution
-  // not banded or heavily diagonal)
-  dyn_Y.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn));
-  // Iterate over outside
-  for(int k=0; k<X.outerSize(); ++k)
+  Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,int> rowPerm(rowIndexVec);
+
+  Eigen::VectorXi colIndexVec = Eigen::VectorXi::LinSpaced(xn,0,xn);
+  Eigen::VectorXi colPermVec = Eigen::VectorXi::LinSpaced(xn,0,xn);
+  for(int i=0;i<yn;i++)
   {
-    // Iterate over inside
-    for(typename Eigen::SparseMatrix<T>::InnerIterator it (X,k); it; ++it)
+    int pos = colIndexVec.coeffRef(C(i));
+    if(pos != i)
     {
-      std::vector<int>::iterator rit, cit;
-      for(rit = RI[it.row()].begin();rit != RI[it.row()].end(); rit++)
-      {
-        for(cit = CI[it.col()].begin();cit != CI[it.col()].end(); cit++)
-        {
-          dyn_Y.coeffRef(*rit,*cit) = it.value();
-        }
-      }
+      int& val = colPermVec.coeffRef(i);
+      std::swap(colIndexVec.coeffRef(val),colIndexVec.coeffRef(C(i)));
+      std::swap(colPermVec.coeffRef(i),colPermVec.coeffRef(pos));
     }
   }
-  Y = Eigen::SparseMatrix<T>(dyn_Y);
+  Eigen::PermutationMatrix<Eigen::Dynamic,Eigen::Dynamic,int> colPerm(colPermVec);
+
+  Eigen::SparseMatrix<T> M = (rowPerm * X);
+  Y = (M * colPerm).block(0,0,ym,yn);
 }
 
 template <typename Mat>

+ 1 - 3
include/igl/slice.h

@@ -1,7 +1,7 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
-// 
+//
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
@@ -14,8 +14,6 @@
 
 namespace igl
 {
-  // THIS MAY HAVE BEEN SUPERSEDED BY EIGEN'S select FUNCTION
-  // 
   // Act like the matlab X(row_indices,col_indices) operator
   // 
   // Inputs:

+ 1 - 0
include/igl/triangle_triangle_adjacency.cpp

@@ -209,4 +209,5 @@ template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, 2, 0, -1,
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -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<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::triangle_triangle_adjacency<Eigen::Matrix<int, -1, -1, 0, -1, -1>, long, long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&, std::vector<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >, std::allocator<std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > > > >&);
 #endif

+ 2 - 0
include/igl/unique_edge_map.cpp

@@ -40,4 +40,6 @@ IGL_INLINE void igl::unique_edge_map(
 // Explicit template specialization
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
 template void igl::unique_edge_map<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, std::vector<std::vector<long, std::allocator<long> >, std::allocator<std::vector<long, std::allocator<long> > > >&);
+template void igl::unique_edge_map<Eigen::Matrix<int, -1, -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>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
+template void igl::unique_edge_map<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 #endif 

+ 1 - 0
include/igl/view_axis.cpp

@@ -37,6 +37,7 @@ IGL_INLINE void igl::view_axis(Eigen::PlainObjectBase<DerivedV> & V)
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template instanciation
 template void igl::view_axis<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
+template void igl::view_axis<Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
 #endif
 
 #endif

+ 4 - 2
include/igl/view_axis.h

@@ -13,6 +13,8 @@
 namespace igl
 {
   // Determines the view axis or depth axis of the current gl matrix
+  // Inputs:
+  //   mv pointer to modelview matrix
   // Outputs:
   //   x  pointer to x-coordinate in scene coordinates of the un-normalized
   //     viewing axis 
@@ -20,11 +22,11 @@ namespace igl
   //     viewing axis 
   //   z  pointer to z-coordinate in scene coordinates of the un-normalized
   //     viewing axis
-  //   mv pointer to modelview matrix
   //
   // Note: View axis is returned *UN-normalized*
-  IGL_INLINE void view_axis(double * x, double * y, double * z);
   IGL_INLINE void view_axis(const double * mv, double * x, double * y, double * z);
+  // Extract mv from current GL state.
+  IGL_INLINE void view_axis(double * x, double * y, double * z);
   template <typename DerivedV>
   IGL_INLINE void view_axis(Eigen::PlainObjectBase<DerivedV> & V);
 };

+ 4 - 0
include/igl/viewer/Viewer.h

@@ -44,6 +44,10 @@ namespace igl
     IGL_INLINE int launch(std::string filename = "");
     IGL_INLINE void init();
 
+    // Stores command line arguments
+    int argc;
+    char **argv;
+
     // Stores all the viewing options
     igl::ViewerCore core;
 

+ 102 - 93
include/igl/viewer/ViewerCore.cpp

@@ -8,95 +8,14 @@
 
 #include "ViewerCore.h"
 #include <igl/quat_to_mat.h>
+#include <igl/look_at.h>
+#include <igl/frustum.h>
+#include <igl/ortho.h>
 #include <igl/massmatrix.h>
 #include <igl/barycenter.h>
 #include <Eigen/Geometry>
 #include <iostream>
 
-
-IGL_INLINE Eigen::Matrix4f lookAt (
-                        const Eigen::Vector3f& eye,
-                        const Eigen::Vector3f& center,
-                        const Eigen::Vector3f& up)
-{
-  Eigen::Vector3f f = (center - eye).normalized();
-  Eigen::Vector3f s = f.cross(up).normalized();
-  Eigen::Vector3f u = s.cross(f);
-
-  Eigen::Matrix4f Result = Eigen::Matrix4f::Identity();
-  Result(0,0) = s(0);
-  Result(0,1) = s(1);
-  Result(0,2) = s(2);
-  Result(1,0) = u(0);
-  Result(1,1) = u(1);
-  Result(1,2) = u(2);
-  Result(2,0) =-f(0);
-  Result(2,1) =-f(1);
-  Result(2,2) =-f(2);
-  Result(0,3) =-s.transpose() * eye;
-  Result(1,3) =-u.transpose() * eye;
-  Result(2,3) = f.transpose() * eye;
-  return Result;
-}
-
-IGL_INLINE Eigen::Matrix4f ortho(
-                       const float left,
-                       const float right,
-                       const float bottom,
-                       const float top,
-                       const float zNear,
-                       const float zFar
-                       )
-{
-  Eigen::Matrix4f Result = Eigen::Matrix4f::Identity();
-  Result(0,0) = 2.0f / (right - left);
-  Result(1,1) = 2.0f / (top - bottom);
-  Result(2,2) = - 2.0f / (zFar - zNear);
-  Result(0,3) = - (right + left) / (right - left);
-  Result(1,3) = - (top + bottom) / (top - bottom);
-  Result(2,3) = - (zFar + zNear) / (zFar - zNear);
-  return Result;
-}
-
-IGL_INLINE Eigen::Matrix4f frustum(
-                         const float left,
-                         const float right,
-                         const float bottom,
-                         const float top,
-                         const float nearVal,
-                         const float farVal)
-{
-  Eigen::Matrix4f Result = Eigen::Matrix4f::Zero();
-  Result(0,0) = (2.0f * nearVal) / (right - left);
-  Result(1,1) = (2.0f * nearVal) / (top - bottom);
-  Result(0,2) = (right + left) / (right - left);
-  Result(1,2) = (top + bottom) / (top - bottom);
-  Result(2,2) = -(farVal + nearVal) / (farVal - nearVal);
-  Result(3,2) = -1.0f;
-  Result(2,3) = -(2.0f * farVal * nearVal) / (farVal - nearVal);
-  return Result;
-}
-
-IGL_INLINE Eigen::Matrix4f scale(const Eigen::Matrix4f& m,
-                       const Eigen::Vector3f& v)
-{
-  Eigen::Matrix4f Result;
-  Result.col(0) = m.col(0).array() * v(0);
-  Result.col(1) = m.col(1).array() * v(1);
-  Result.col(2) = m.col(2).array() * v(2);
-  Result.col(3) = m.col(3);
-  return Result;
-}
-
-IGL_INLINE Eigen::Matrix4f translate(
-                          const Eigen::Matrix4f& m,
-                          const Eigen::Vector3f& v)
-{
-  Eigen::Matrix4f Result = m;
-  Result.col(3) = m.col(0).array() * v(0) + m.col(1).array() * v(1) + m.col(2).array() * v(2) + m.col(3).array();
-  return Result;
-}
-
 #ifdef ENABLE_SERIALIZATION
 #include <igl/serialize.h>
 namespace igl {
@@ -139,6 +58,7 @@ namespace igl {
       SERIALIZE_MEMBER(show_vertid);
       SERIALIZE_MEMBER(show_faceid);
       SERIALIZE_MEMBER(show_texture);
+      SERIALIZE_MEMBER(depth_test);
 
       SERIALIZE_MEMBER(point_size);
       SERIALIZE_MEMBER(line_width);
@@ -219,7 +139,10 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
   using namespace std;
   using namespace Eigen;
 
-  glEnable(GL_DEPTH_TEST);
+  if (depth_test)
+    glEnable(GL_DEPTH_TEST);
+  else
+    glDisable(GL_DEPTH_TEST);
 
   /* Bind and potentially refresh mesh/line/point data */
   if (data.dirty)
@@ -237,9 +160,7 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
   proj  = Eigen::Matrix4f::Identity();
 
   // Set view
-  view = lookAt(Eigen::Vector3f(camera_eye[0], camera_eye[1], camera_eye[2]),
-                Eigen::Vector3f(camera_center[0], camera_center[1], camera_center[2]),
-                Eigen::Vector3f(camera_up[0], camera_up[1], camera_up[2]));
+  look_at( camera_eye, camera_center, camera_up, view);
 
   float width  = viewport(2);
   float height = viewport(3);
@@ -249,13 +170,13 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
   {
     float length = (camera_eye - camera_center).norm();
     float h = tan(camera_view_angle/360.0 * M_PI) * (length);
-    proj = ortho(-h*width/height, h*width/height, -h, h, camera_dnear, camera_dfar);
+    ortho(-h*width/height, h*width/height, -h, h, camera_dnear, camera_dfar,proj);
   }
   else
   {
     float fH = tan(camera_view_angle / 360.0 * M_PI) * camera_dnear;
     float fW = fH * (double)width/(double)height;
-    proj = frustum(-fW, fW, -fH, fH, camera_dnear, camera_dfar);
+    frustum(-fW, fW, -fH, fH, camera_dnear, camera_dfar,proj);
   }
   // end projection
 
@@ -267,9 +188,10 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
     for (unsigned j=0;j<4;++j)
       model(i,j) = mat[i+4*j];
 
-  model = scale(model, Eigen::Vector3f(camera_zoom,camera_zoom,camera_zoom));
-  model = scale(model, Eigen::Vector3f(model_zoom,model_zoom,model_zoom));
-  model = translate(model, Eigen::Vector3f(model_translation[0],model_translation[1],model_translation[2]));
+  // Why not just use Eigen::Transform<double,3,Projective> for model...?
+  model.topLeftCorner(3,3)*=camera_zoom;
+  model.topLeftCorner(3,3)*=model_zoom;
+  model.col(3).head(3) += model.topLeftCorner(3,3)*model_translation;
 
   // Send transformations to the GPU
   GLint modeli = opengl.shader_mesh.uniform("model");
@@ -391,6 +313,92 @@ IGL_INLINE void igl::ViewerCore::draw(ViewerData& data, OpenGL_state& opengl)
 
 }
 
+IGL_INLINE void igl::ViewerCore::draw_buffer(ViewerData& data,
+                            OpenGL_state& opengl,
+                            Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& R,
+                            Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& G,
+                            Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& B,
+                            Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& A)
+{
+  assert(R.rows() == G.rows() && G.rows() == B.rows() && B.rows() == A.rows());
+  assert(R.cols() == G.cols() && G.cols() == B.cols() && B.cols() == A.cols());
+  
+  int x = R.rows();
+  int y = R.cols();
+  
+  // Create frame buffer
+  GLuint frameBuffer;
+  glGenFramebuffers(1, &frameBuffer);
+  glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+  // Create texture to hold color buffer
+  GLuint texColorBuffer;
+  glGenTextures(1, &texColorBuffer);
+  glBindTexture(GL_TEXTURE_2D, texColorBuffer);
+  
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  
+  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);
+  
+  // Create Renderbuffer Object to hold depth and stencil buffers
+  GLuint rboDepthStencil;
+  glGenRenderbuffers(1, &rboDepthStencil);
+  glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
+  glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, x, y);
+  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
+
+  assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+  glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
+
+  // Clear the buffer
+  glClearColor(0.f, 0.f, 0.f, 0.f);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  // Save old viewport
+  Eigen::Vector4f viewport_ori = viewport;
+  viewport << 0,0,x,y;
+  
+  // Draw
+  draw(data,opengl);
+  
+  // Restore viewport
+  viewport = viewport_ori;
+  
+  // Copy back in the given Eigen matrices
+  GLubyte* pixels = (GLubyte*)calloc(x*y*4,sizeof(GLubyte));
+  glReadPixels
+  (
+   0, 0,
+   x, y,
+   GL_RGBA, GL_UNSIGNED_BYTE, pixels
+   );
+    
+  int count = 0;
+  for (unsigned j=0; j<y; ++j)
+  {
+    for (unsigned i=0; i<x; ++i)
+    {
+      R(i,j) = pixels[count*4+0];
+      G(i,j) = pixels[count*4+1];
+      B(i,j) = pixels[count*4+2];
+      A(i,j) = pixels[count*4+3];
+      ++count;
+    }
+  }
+  
+  // Clean up
+  free(pixels);
+  glBindFramebuffer(GL_FRAMEBUFFER, 0);
+  glDeleteRenderbuffers(1, &rboDepthStencil);
+  glDeleteTextures(1, &texColorBuffer);
+  glDeleteFramebuffers(1, &frameBuffer);
+}
+
+
 IGL_INLINE igl::ViewerCore::ViewerCore()
 {
   // Default shininess
@@ -430,6 +438,7 @@ IGL_INLINE igl::ViewerCore::ViewerCore()
   show_vertid = false;
   show_faceid = false;
   show_texture = false;
+  depth_test = true;
 
   // Default point size / line width
   point_size = 30;

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

@@ -57,6 +57,12 @@ public:
 
   // Draw everything
   IGL_INLINE void draw(ViewerData& data, OpenGL_state& opengl);
+  IGL_INLINE void draw_buffer(ViewerData& data,
+                              OpenGL_state& opengl,
+                              Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& R,
+                              Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& G,
+                              Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& B,
+                              Eigen::Matrix<char,Eigen::Dynamic,Eigen::Dynamic>& A);
 
   // ------------------- Properties
 
@@ -104,6 +110,7 @@ public:
   bool show_vertid;
   bool show_faceid;
   bool invert_normals;
+  bool depth_test;
 
   // Point size / line width
   float point_size;

+ 1 - 1
tutorial/cmake/FindEMBREE.cmake

@@ -44,5 +44,5 @@ IF (EMBREE_FOUND)
    )
    SET(EMBREE_INCLUDE_DIRS ${EMBREE_INCLUDE_DIR} ${EMBREE_INCLUDE_DIR}/embree)
 ELSE (EMBREE_FOUND)
-    message(FATAL_ERROR "could NOT find EMBREE")
+    message(STATUS "could NOT find EMBREE")
 ENDIF (EMBREE_FOUND)