Просмотр исходного кода

merge

Former-commit-id: 297a3bc78aa5d14dd93838e880800e2dc116f213
Daniele Panozzo 11 лет назад
Родитель
Сommit
9cf2c31eca

+ 1 - 0
RELEASE_HISTORY.txt

@@ -1,3 +1,4 @@
+0.3.7  Embree2.0 support
 0.3.6  boost extra, patches, mosek 7 support, libiglbbw (mosek optional)
 0.3.6  boost extra, patches, mosek 7 support, libiglbbw (mosek optional)
 0.3.5  More examples, naive primitive sorting
 0.3.5  More examples, naive primitive sorting
 0.3.3  Many more examples, ambient occlusion with Embree.
 0.3.3  Many more examples, ambient occlusion with Embree.

+ 1 - 1
VERSION.txt

@@ -3,4 +3,4 @@
 # Anyone may increment Minor to indicate a small change.
 # Anyone may increment Minor to indicate a small change.
 # Major indicates a large change or large number of changes (upload to website)
 # Major indicates a large change or large number of changes (upload to website)
 # World indicates a substantial change or release
 # World indicates a substantial change or release
-0.3.6
+0.3.7

+ 0 - 3
examples/ambient-occlusion-mex/mexFunction.cpp

@@ -1,10 +1,7 @@
 #include "parse_rhs.h"
 #include "parse_rhs.h"
 
 
 #include <igl/matlab/mexStream.h>
 #include <igl/matlab/mexStream.h>
-#include <igl/matlab/MatlabWorkspace.h>
-#include <igl/embree/EmbreeIntersector.h>
 #include <igl/embree/ambient_occlusion.h>
 #include <igl/embree/ambient_occlusion.h>
-#include <igl/matlab_format.h>
 
 
 #include <igl/read.h>
 #include <igl/read.h>
 #include <igl/per_vertex_normals.h>
 #include <igl/per_vertex_normals.h>

+ 3 - 4
examples/ambient-occlusion/example.cpp

@@ -48,7 +48,7 @@ Eigen::MatrixXd V,N,C,mid;
 Eigen::MatrixXi F;
 Eigen::MatrixXi F;
 // Bounding box diagonal length
 // Bounding box diagonal length
 double bbd;
 double bbd;
-igl::EmbreeIntersector<Eigen::MatrixXd::Scalar,Eigen::MatrixXi::Scalar> * ei;
+igl::EmbreeIntersector ei;
 // Running ambient occlusion
 // Running ambient occlusion
 Eigen::VectorXd S;
 Eigen::VectorXd S;
 int tot_num_samples = 0;
 int tot_num_samples = 0;
@@ -154,7 +154,7 @@ void display()
     }
     }
     VectorXd Si;
     VectorXd Si;
     const int num_samples = 20;
     const int num_samples = 20;
-    ambient_occlusion(*ei,V,N,num_samples,Si);
+    ambient_occlusion(ei,V,N,num_samples,Si);
     S *= (double)tot_num_samples;
     S *= (double)tot_num_samples;
     S += Si*(double)num_samples;
     S += Si*(double)num_samples;
     tot_num_samples += num_samples;
     tot_num_samples += num_samples;
@@ -373,7 +373,7 @@ int main(int argc, char * argv[])
   bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
   bbd = (V.colwise().maxCoeff() - V.colwise().minCoeff()).maxCoeff();
 
 
   // Init embree
   // Init embree
-  ei = new EmbreeIntersector<MatrixXd::Scalar,MatrixXi::Scalar>(V,F);
+  ei.init(V.cast<float>(),F.cast<int>());
 
 
   // Init glut
   // Init glut
   glutInit(&argc,argv);
   glutInit(&argc,argv);
@@ -405,6 +405,5 @@ int main(int argc, char * argv[])
   glutMotionFunc(mouse_drag);
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
   glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
   glutMainLoop();
   glutMainLoop();
-  delete ei;
   return 0;
   return 0;
 }
 }

+ 1 - 1
examples/bbw/main.cpp

@@ -257,7 +257,7 @@ int main(int argc, char * argv[])
   // Default bbw data and flags
   // Default bbw data and flags
   BBWData bbw_data;
   BBWData bbw_data;
   bbw_data.qp_solver = QP_SOLVER_IGL_ACTIVE_SET;
   bbw_data.qp_solver = QP_SOLVER_IGL_ACTIVE_SET;
-  //bbw_data.qp_solver = QP_SOLVER_MOSEK;
+  bbw_data.qp_solver = QP_SOLVER_MOSEK;
   // Weights matrix
   // Weights matrix
   MatrixXd W;
   MatrixXd W;
   if(!bbw(VV,TT,b,bc,bbw_data,W))
   if(!bbw(VV,TT,b,bc,bbw_data,W))

+ 2 - 0
examples/embree/Makefile

@@ -9,6 +9,8 @@ all: example
 .PHONY: example
 .PHONY: example
 
 
 LIBIGL=../../
 LIBIGL=../../
+#LIBIGL_INC=-I$(LIBIGL)/include -DIGL_HEADER_ONLY
+#LIBIGL_LIB=
 LIBIGL_INC=-I$(LIBIGL)/include
 LIBIGL_INC=-I$(LIBIGL)/include
 LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglembree
 LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglembree
 
 

+ 19 - 28
examples/embree/example.cpp

@@ -1,4 +1,3 @@
-#define IGL_HEADER_ONLY
 #include <igl/embree/EmbreeIntersector.h>
 #include <igl/embree/EmbreeIntersector.h>
 #include <igl/OpenGL_convenience.h>
 #include <igl/OpenGL_convenience.h>
 #include <igl/per_face_normals.h>
 #include <igl/per_face_normals.h>
@@ -38,11 +37,11 @@ double bbd;
 // Faces
 // Faces
 Eigen::MatrixXi F;
 Eigen::MatrixXi F;
 // Embree intersection structure
 // Embree intersection structure
-igl::EmbreeIntersector<double,int> * ei;
+igl::EmbreeIntersector ei;
 // Hits collected
 // Hits collected
 std::vector<igl::Hit > hits;
 std::vector<igl::Hit > hits;
 // Ray information, "projection screen" corners
 // Ray information, "projection screen" corners
-Eigen::Vector3d win_s,s,d,dir,NW,NE,SE,SW;
+Eigen::Vector3f win_s,s,d,dir,NW,NE,SE,SW;
 // Textures and framebuffers for "projection screen"
 // Textures and framebuffers for "projection screen"
 GLuint tex_id = 0, fbo_id = 0, dfbo_id = 0;
 GLuint tex_id = 0, fbo_id = 0, dfbo_id = 0;
 
 
@@ -192,18 +191,18 @@ void display()
     glEnable(GL_DEPTH_TEST);
     glEnable(GL_DEPTH_TEST);
     glBegin(GL_LINES);
     glBegin(GL_LINES);
     glColor3f(1,0,0);
     glColor3f(1,0,0);
-    glVertex3dv(s.data());
+    glVertex3fv(s.data());
     glColor3f(1,0,0);
     glColor3f(1,0,0);
-    glVertex3dv(d.data());
+    glVertex3fv(d.data());
     glEnd();
     glEnd();
 
 
     // Draw the start and end points used for ray
     // Draw the start and end points used for ray
     glPointSize(10.0);
     glPointSize(10.0);
     glBegin(GL_POINTS);
     glBegin(GL_POINTS);
     glColor3f(1,0,0);
     glColor3f(1,0,0);
-    glVertex3dv(s.data());
+    glVertex3fv(s.data());
     glColor3f(0,0,1);
     glColor3f(0,0,1);
-    glVertex3dv(d.data());
+    glVertex3fv(d.data());
     glEnd();
     glEnd();
   }
   }
 
 
@@ -246,10 +245,10 @@ void display()
     glColor4f(0,0,0,1.0);
     glColor4f(0,0,0,1.0);
     glPointSize(10.0);
     glPointSize(10.0);
     glBegin(GL_POINTS);
     glBegin(GL_POINTS);
-    glVertex3dv(SW.data());
-    glVertex3dv(SE.data());
-    glVertex3dv(NE.data());
-    glVertex3dv(NW.data());
+    glVertex3fv(SW.data());
+    glVertex3fv(SE.data());
+    glVertex3fv(NE.data());
+    glVertex3fv(NW.data());
     glEnd();
     glEnd();
 
 
     glDisable(GL_LIGHTING);
     glDisable(GL_LIGHTING);
@@ -258,13 +257,13 @@ void display()
     glColor4f(1,1,1,0.7);
     glColor4f(1,1,1,0.7);
     glBegin(GL_QUADS);
     glBegin(GL_QUADS);
     glTexCoord2d(0,0);
     glTexCoord2d(0,0);
-    glVertex3dv(SW.data());
+    glVertex3fv(SW.data());
     glTexCoord2d(1,0);
     glTexCoord2d(1,0);
-    glVertex3dv(SE.data());
+    glVertex3fv(SE.data());
     glTexCoord2d(1,1);
     glTexCoord2d(1,1);
-    glVertex3dv(NE.data());
+    glVertex3fv(NE.data());
     glTexCoord2d(0,1);
     glTexCoord2d(0,1);
-    glVertex3dv(NW.data());
+    glVertex3fv(NW.data());
     glEnd();
     glEnd();
     glBindTexture(GL_TEXTURE_2D, 0);
     glBindTexture(GL_TEXTURE_2D, 0);
     glDisable(GL_TEXTURE_2D);
     glDisable(GL_TEXTURE_2D);
@@ -288,7 +287,7 @@ void display()
     glLoadIdentity();
     glLoadIdentity();
     glPointSize(20.0);
     glPointSize(20.0);
     glBegin(GL_POINTS);
     glBegin(GL_POINTS);
-    glVertex2dv(win_s.data());
+    glVertex2fv(win_s.data());
     glEnd();
     glEnd();
   }
   }
   report_gl_error();
   report_gl_error();
@@ -317,8 +316,8 @@ void mouse_move(int mouse_x, int mouse_y)
   push_scene();
   push_scene();
   push_object();
   push_object();
   // Unproject mouse at 0 depth and some positive depth
   // Unproject mouse at 0 depth and some positive depth
-  win_s = Vector3d(mouse_x,height-mouse_y,0);
-  Vector3d win_d(mouse_x,height-mouse_y,1);
+  win_s = Vector3f(mouse_x,height-mouse_y,0);
+  Vector3f win_d(mouse_x,height-mouse_y,1);
   unproject(win_s,s);
   unproject(win_s,s);
   unproject(win_d,d);
   unproject(win_d,d);
   pop_object();
   pop_object();
@@ -327,7 +326,7 @@ void mouse_move(int mouse_x, int mouse_y)
   // Shoot ray at unprojected mouse in view direction
   // Shoot ray at unprojected mouse in view direction
   dir = d-s;
   dir = d-s;
   int num_rays_shot;
   int num_rays_shot;
-  ei->intersectRay(s,dir,hits,num_rays_shot);
+  ei.intersectRay(s,dir,hits,num_rays_shot);
   for(vector<igl::Hit>::iterator hit = hits.begin();
   for(vector<igl::Hit>::iterator hit = hits.begin();
       hit != hits.end();
       hit != hits.end();
       hit++)
       hit++)
@@ -417,12 +416,6 @@ void mouse_drag(int mouse_x, int mouse_y)
 }
 }
 
 
 
 
-void cleanup()
-{
-  using namespace std;
-  delete ei;
-}
-
 void key(unsigned char key, int mouse_x, int mouse_y)
 void key(unsigned char key, int mouse_x, int mouse_y)
 {
 {
   using namespace std;
   using namespace std;
@@ -431,7 +424,6 @@ void key(unsigned char key, int mouse_x, int mouse_y)
     // Ctrl-c and esc exit
     // Ctrl-c and esc exit
     case char(3):
     case char(3):
     case char(27):
     case char(27):
-      cleanup();
       exit(0);
       exit(0);
     default:
     default:
       cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
       cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
@@ -471,7 +463,7 @@ int main(int argc, char * argv[])
     V.colwise().minCoeff()).maxCoeff();
     V.colwise().minCoeff()).maxCoeff();
 
 
   // Init embree
   // Init embree
-  ei = new EmbreeIntersector<double,int>(V,F);
+  ei.init(V.cast<float>(),F.cast<int>());
 
 
   // Init glut
   // Init glut
   glutInit(&argc,argv);
   glutInit(&argc,argv);
@@ -485,6 +477,5 @@ int main(int argc, char * argv[])
   glutMotionFunc(mouse_drag);
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc(mouse_move);
   glutPassiveMotionFunc(mouse_move);
   glutMainLoop();
   glutMainLoop();
-  cleanup();
   return 0;
   return 0;
 }
 }

+ 143 - 22
examples/patches/example.cpp

@@ -30,6 +30,8 @@
 #include <igl/orient_outward.h>
 #include <igl/orient_outward.h>
 #include <igl/embree/orient_outward_ao.h>
 #include <igl/embree/orient_outward_ao.h>
 #include <igl/unique_simplices.h>
 #include <igl/unique_simplices.h>
+#include <igl/C_STR.h>
+#include <igl/write.h>
 
 
 #include <Eigen/Core>
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 #include <Eigen/Geometry>
@@ -54,6 +56,7 @@
 #include <stack>
 #include <stack>
 #include <iostream>
 #include <iostream>
 
 
+int cc_selected = -1;
 
 
 Eigen::MatrixXd V;
 Eigen::MatrixXd V;
 Eigen::VectorXd Vmid,Vmin,Vmax;
 Eigen::VectorXd Vmid,Vmin,Vmax;
@@ -66,6 +69,7 @@ struct State
   Eigen::MatrixXd N;
   Eigen::MatrixXd N;
   Eigen::MatrixXd C;
   Eigen::MatrixXd C;
 } s;
 } s;
+std::string out_filename;
 
 
 // See README for descriptions
 // See README for descriptions
 enum RotationType
 enum RotationType
@@ -75,6 +79,13 @@ enum RotationType
   NUM_ROTATION_TYPES = 2,
   NUM_ROTATION_TYPES = 2,
 } rotation_type;
 } rotation_type;
 
 
+enum OrientMethod
+{
+  ORIENT_METHOD_OUTWARD = 0,
+  ORIENT_METHOD_AO = 1,
+  NUM_ORIENT_METHODS = 2,
+} orient_method = ORIENT_METHOD_AO;
+
 std::stack<State> undo_stack;
 std::stack<State> undo_stack;
 std::stack<State> redo_stack;
 std::stack<State> redo_stack;
 
 
@@ -97,6 +108,10 @@ Eigen::Vector4f light_pos(-0.1,-0.1,0.9,0);
 #define REBAR_NAME "temp.rbr"
 #define REBAR_NAME "temp.rbr"
 igl::ReTwBar rebar;
 igl::ReTwBar rebar;
 
 
+// Forward
+void init_patches();
+void init_relative();
+
 void push_undo()
 void push_undo()
 {
 {
   undo_stack.push(s);
   undo_stack.push(s);
@@ -112,6 +127,23 @@ void TW_CALL set_camera_rotation(const void * value, void *clientData)
   std::copy(quat,quat+4,s.camera.rotation);
   std::copy(quat,quat+4,s.camera.rotation);
 }
 }
 
 
+void TW_CALL set_orient_method(const void * value, void * clientData)
+{
+  const OrientMethod old_orient_method = orient_method;
+  orient_method = *(const OrientMethod *)value;
+  if(orient_method != old_orient_method)
+  {
+    init_patches();
+    init_relative();
+  }
+}
+
+void TW_CALL get_orient_method(void * value, void *clientData)
+{
+  OrientMethod * om = (OrientMethod *)(value);
+  *om = orient_method;
+}
+
 void TW_CALL set_rotation_type(const void * value, void * clientData)
 void TW_CALL set_rotation_type(const void * value, void * clientData)
 {
 {
   using namespace Eigen;
   using namespace Eigen;
@@ -299,6 +331,38 @@ void display()
     {
     {
       draw_mesh(V,F,s.N,s.C);
       draw_mesh(V,F,s.N,s.C);
     }
     }
+  
+    // visualize selected patch
+    glLineWidth(10);
+    glBegin(GL_TRIANGLES);
+    glColor3d(0, 0, 0);
+    // loop over faces
+    for(int i = 0; i<F.rows();i++)
+    {
+      if (CC(i) != cc_selected) continue;
+      // loop over corners of triangle
+      for(int j = 0;j<3;j++)
+      {
+        glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
+      }
+    }
+    glEnd();
+    glLineWidth(1);
+    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+    glBegin(GL_TRIANGLES);
+    glColor3d(1, 0, 0);
+    // loop over faces
+    for(int i = 0; i<F.rows();i++)
+    {
+      if (CC(i) != cc_selected) continue;
+      // loop over corners of triangle
+      glNormal3d(s.N(i,0),s.N(i,1),s.N(i,2));
+      for(int j = 0;j<3;j++)
+      {
+        glVertex3d(V(F(i,j),0),V(F(i,j),1),V(F(i,j),2));
+      }
+    }
+    glEnd();
   }
   }
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
   if(fill_visible)
   if(fill_visible)
@@ -539,20 +603,20 @@ void init_patches()
   }
   }
   bfs_orient(F,F,CC);
   bfs_orient(F,F,CC);
   VectorXi I;
   VectorXi I;
-  char c;
-  cout << "use ambient occlusion to determine patch orientation? (y/n):";
-  cin >> c;
-  if (c == 'y')
-  {
-    orient_outward_ao(V,F,CC,F.rows() * 100,F,I);
-  }
-  else
+  switch(orient_method)
   {
   {
-    orient_outward(V,F,CC,F,I);
+    case ORIENT_METHOD_AO:
+      cout<<"orient_outward_ao()"<<endl;
+      orient_outward_ao(V,F,CC,100, F.rows() * 100,F,I);
+      break;
+    case ORIENT_METHOD_OUTWARD:
+    default:
+      cout<<"orient_outward()"<<endl;
+      orient_outward(V,F,CC,F,I);
+      break;
   }
   }
   double num_cc = (double)CC.maxCoeff()+1.0;
   double num_cc = (double)CC.maxCoeff()+1.0;
   cout<<"There are "<<num_cc<<" 'manifold/orientable' patches of faces."<<endl;
   cout<<"There are "<<num_cc<<" 'manifold/orientable' patches of faces."<<endl;
-  randomly_color(CC,s.C);
 }
 }
 
 
 void undo()
 void undo()
@@ -577,6 +641,26 @@ void redo()
   }
   }
 }
 }
 
 
+bool save(const std::string & out_filename)
+{
+  using namespace std;
+  using namespace igl;
+  if(write(out_filename,V,F))
+  {
+    cout<<GREENGIN("Saved mesh to `"<<out_filename<<"` successfully.")<<endl;
+    return true;
+  }else
+  {
+    cout<<REDRUM("Failed to save mesh to `"<<out_filename<<"`.")<<endl;
+    return false;
+  }
+}
+
+void TW_CALL saveCB(void * /*clientData*/)
+{
+  save(out_filename);
+}
+
 void key(unsigned char key, int mouse_x, int mouse_y)
 void key(unsigned char key, int mouse_x, int mouse_y)
 {
 {
   using namespace std;
   using namespace std;
@@ -594,6 +678,7 @@ void key(unsigned char key, int mouse_x, int mouse_y)
       {
       {
         push_undo();
         push_undo();
         s.N *= -1.0;
         s.N *= -1.0;
+        F = F.rowwise().reverse().eval();
         break;
         break;
       }
       }
     case 'z':
     case 'z':
@@ -617,6 +702,17 @@ void key(unsigned char key, int mouse_x, int mouse_y)
           s.camera.rotation);
           s.camera.rotation);
         break;
         break;
       }
       }
+    case 'u':
+        mouse_wheel(0, 1,mouse_x,mouse_y);
+        break;
+    case 'j':
+        mouse_wheel(0,-1,mouse_x,mouse_y);
+        break;
+    case 'n':
+      cc_selected = (cc_selected + 1) % (CC.maxCoeff() + 2);
+      cout << "selected cc: " << cc_selected << endl;
+      glutPostRedisplay();
+      break;
     default:
     default:
       if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
       if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
       {
       {
@@ -632,21 +728,25 @@ int main(int argc, char * argv[])
   using namespace Eigen;
   using namespace Eigen;
   using namespace igl;
   using namespace igl;
   string filename = "../shared/truck.obj";
   string filename = "../shared/truck.obj";
-  if(argc < 2)
+  switch(argc)
   {
   {
-    cerr<<"Usage:"<<endl<<"    ./example input.obj"<<endl;
-    cout<<endl<<"Opening default mesh..."<<endl;
-  }else
-  {
-    // Read and prepare mesh
-    filename = argv[1];
+    case 3:
+      out_filename = argv[2];
+    case 2:
+      // Read and prepare mesh
+      filename = argv[1];
+      break;
+    default:
+      cerr<<"Usage:"<<endl<<"    ./example input.obj (output.obj)"<<endl;
+      cout<<endl<<"Opening default mesh..."<<endl;
+      break;
   }
   }
 
 
   // print key commands
   // print key commands
   cout<<"[Click] and [drag]  Rotate model using trackball."<<endl;
   cout<<"[Click] and [drag]  Rotate model using trackball."<<endl;
   cout<<"[Z,z]               Snap rotation to canonical view."<<endl;
   cout<<"[Z,z]               Snap rotation to canonical view."<<endl;
-  cout<<"[⌘ Z]               Undo."<<endl;
-  cout<<"[⇧ ⌘ Z]             Redo."<<endl;
+  cout<<"[Command+Z]         Undo."<<endl;
+  cout<<"[Shift+Command+Z]   Redo."<<endl;
   cout<<"[^C,ESC]            Exit."<<endl;
   cout<<"[^C,ESC]            Exit."<<endl;
 
 
   // dirname, basename, extension and filename
   // dirname, basename, extension and filename
@@ -703,8 +803,8 @@ int main(int argc, char * argv[])
   F = F_unique;
   F = F_unique;
 
 
   init_patches();
   init_patches();
-
   init_relative();
   init_relative();
+  randomly_color(CC,s.C);
 
 
   // Init glut
   // Init glut
   glutInit(&argc,argv);
   glutInit(&argc,argv);
@@ -715,7 +815,8 @@ int main(int argc, char * argv[])
     return 1;
     return 1;
   }
   }
   // Create a tweak bar
   // Create a tweak bar
-  rebar.TwNewBar("TweakBar");
+  rebar.TwNewBar("bar");
+  TwDefine("bar label='Patches' size='200 550' text=light alpha='200' color='68 68 68'");
   rebar.TwAddVarCB("camera_rotation", TW_TYPE_QUAT4D, set_camera_rotation,get_camera_rotation, NULL, "open readonly=true");
   rebar.TwAddVarCB("camera_rotation", TW_TYPE_QUAT4D, set_camera_rotation,get_camera_rotation, NULL, "open readonly=true");
   TwEnumVal RotationTypesEV[NUM_ROTATION_TYPES] = 
   TwEnumVal RotationTypesEV[NUM_ROTATION_TYPES] = 
   {
   {
@@ -729,9 +830,29 @@ int main(int argc, char * argv[])
         NUM_ROTATION_TYPES);
         NUM_ROTATION_TYPES);
   rebar.TwAddVarCB( "rotation_type", RotationTypeTW,
   rebar.TwAddVarCB( "rotation_type", RotationTypeTW,
     set_rotation_type,get_rotation_type,NULL,"keyIncr=] keyDecr=[");
     set_rotation_type,get_rotation_type,NULL,"keyIncr=] keyDecr=[");
+  TwEnumVal OrientMethodEV[NUM_ORIENT_METHODS] = 
+  {
+    {ORIENT_METHOD_OUTWARD,"outward"},
+    {ORIENT_METHOD_AO,"ambient occlusion"}
+  };
+  TwType OrientMethodTW = 
+    ReTwDefineEnum(
+        "OrientMethod", 
+        OrientMethodEV, 
+        NUM_ROTATION_TYPES);
+  rebar.TwAddVarCB( "orient_method", OrientMethodTW,
+    set_orient_method,get_orient_method,NULL,"keyIncr=< keyDecr=>");
+
   rebar.TwAddVarRW("wireframe_visible",TW_TYPE_BOOLCPP,&wireframe_visible,"key=l");
   rebar.TwAddVarRW("wireframe_visible",TW_TYPE_BOOLCPP,&wireframe_visible,"key=l");
   rebar.TwAddVarRW("fill_visible",TW_TYPE_BOOLCPP,&fill_visible,"key=f");
   rebar.TwAddVarRW("fill_visible",TW_TYPE_BOOLCPP,&fill_visible,"key=f");
-  rebar.TwAddButton("randomize colors",randomize_colors,NULL,"key=c");
+  rebar.TwAddButton("randomize_colors",randomize_colors,NULL,"key=c");
+  if(out_filename != "")
+  {
+    rebar.TwAddButton("save",
+      saveCB,NULL,
+      C_STR("label='Save to `"<<out_filename<<"`' "<<
+      "key=s"));
+  }
   rebar.load(REBAR_NAME);
   rebar.load(REBAR_NAME);
 
 
 
 

+ 20 - 0
examples/patches/example.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example.vcxproj", "{7F5B7683-7531-481C-8997-6221D7170894}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{7F5B7683-7531-481C-8997-6221D7170894}.Debug|Win32.ActiveCfg = Debug|Win32
+		{7F5B7683-7531-481C-8997-6221D7170894}.Debug|Win32.Build.0 = Debug|Win32
+		{7F5B7683-7531-481C-8997-6221D7170894}.Release|Win32.ActiveCfg = Release|Win32
+		{7F5B7683-7531-481C-8997-6221D7170894}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 54 - 33
examples/patches/example.vcxproj

@@ -20,14 +20,14 @@
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <UseDebugLibraries>true</UseDebugLibraries>
     <PlatformToolset>v110</PlatformToolset>
     <PlatformToolset>v110</PlatformToolset>
-    <CharacterSet>Unicode</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
     <PlatformToolset>v110</PlatformToolset>
     <PlatformToolset>v110</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>Unicode</CharacterSet>
+    <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
   <ImportGroup Label="ExtensionSettings">
@@ -58,7 +58,7 @@
       <Optimization>Disabled</Optimization>
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>IGL_HEADER_ONLY;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>IGL_HEADER_ONLY;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <AdditionalIncludeDirectories>C:\Users\kenshi\dev\igl_hg\ext_toolboxes\embree-1.1beta\rtcore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\external\embree;..\..\external\embree\embree;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <OpenMPSupport>true</OpenMPSupport>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>
@@ -71,49 +71,70 @@
       <WarningLevel>Level3</WarningLevel>
       <WarningLevel>Level3</WarningLevel>
       <PrecompiledHeader>
       <PrecompiledHeader>
       </PrecompiledHeader>
       </PrecompiledHeader>
-      <Optimization>MaxSpeed</Optimization>
+      <Optimization>Disabled</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <PreprocessorDefinitions>IGL_HEADER_ONLY;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions>IGL_HEADER_ONLY;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <AdditionalIncludeDirectories>C:\Users\kenshi\dev\igl_hg\ext_toolboxes\embree-1.1beta\rtcore;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\..\external\embree;..\..\external\embree\embree;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <OpenMPSupport>true</OpenMPSupport>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
     </ClCompile>
     <Link>
     <Link>
       <SubSystem>Console</SubSystem>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
+      <OptimizeReferences>false</OptimizeReferences>
     </Link>
     </Link>
   </ItemDefinitionGroup>
   </ItemDefinitionGroup>
   <ItemGroup>
   <ItemGroup>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\filename.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\library.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\platform.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\stl\string.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sync\condition.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sync\mutex.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sysinfo.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\taskscheduler_standard.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\thread.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2_builder.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2_intersector.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb_builder.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb_intersector.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4_builder.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4_intersector.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\accel.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\alloc.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\heuristic_binning.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\heuristic_spatial.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\primrefgen.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter_fallback.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter_parallel.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\stat.cpp" />
+    <ClCompile Include="..\..\..\kt84\dbg.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\heuristic_binning.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\heuristic_spatial.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\primrefgen.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter_fallback.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter_parallel.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector1.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector4.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector8.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4i\bvh4i.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4i\bvh4i_intersector1.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_builder.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector1.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector4.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector8.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector1.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector1_avx.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_chunk.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_hybrid.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_single.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_chunk.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_hybrid.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_single.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh8\bvh8.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\bvh8\bvh8_intersector1.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\accel.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\alloc.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\registry_accel.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\registry_builder.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\registry_intersector.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\common\stat.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\embree.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\geometry\triangle_mesh.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\geometry\virtual_scene.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\filename.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\platform.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\stl\string.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\sync\condition.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\sync\mutex.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\sysinfo.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler_mic.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler_sys.cpp" />
+    <ClCompile Include="..\..\external\embree\embree\sys\thread.cpp" />
     <ClCompile Include="example.cpp" />
     <ClCompile Include="example.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>

+ 117 - 62
examples/patches/example.vcxproj.filters

@@ -2,100 +2,155 @@
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="example.cpp" />
     <ClCompile Include="example.cpp" />
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2_builder.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\primrefgen.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2_intersector.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh2\bvh2.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter_fallback.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4_intersector.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\splitter_parallel.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\heuristic_binning.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4\bvh4_builder.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\builders\heuristic_spatial.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb_intersector.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector4.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector8.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\bvh4mb\bvh4mb_builder.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter_fallback.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh2\bvh2_intersector1.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter_parallel.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_chunk.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\stat.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_hybrid.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\accel.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector4_single.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\alloc.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_chunk.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\heuristic_binning.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_hybrid.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\heuristic_spatial.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector8_single.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\primrefgen.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\rtcore\common\splitter.cpp">
-      <Filter>embree-1.1beta\rtcore</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector1.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\platform.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4\bvh4_intersector1_avx.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sysinfo.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4i\bvh4i.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\taskscheduler_standard.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4i\bvh4i_intersector1.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\thread.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector1.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\filename.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector4.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\library.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_intersector8.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\stl\string.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sync\mutex.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh4mb\bvh4mb_builder.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="..\..\..\ext_toolboxes\embree-1.1beta\common\sys\sync\condition.cpp">
-      <Filter>embree-1.1beta\common</Filter>
+    <ClCompile Include="..\..\external\embree\embree\bvh8\bvh8.cpp">
+      <Filter>embree</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\bvh8\bvh8_intersector1.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\registry_intersector.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\stat.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\accel.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\alloc.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\registry_accel.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\common\registry_builder.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\geometry\virtual_scene.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\geometry\triangle_mesh.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler_mic.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\taskscheduler_sys.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\thread.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\filename.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\platform.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\sysinfo.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\stl\string.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\sync\mutex.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\sys\sync\condition.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\external\embree\embree\embree.cpp">
+      <Filter>embree</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\kt84\dbg.cpp" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Filter Include="igl">
     <Filter Include="igl">
       <UniqueIdentifier>{53eff656-6473-409c-9ad5-cac1983d91e1}</UniqueIdentifier>
       <UniqueIdentifier>{53eff656-6473-409c-9ad5-cac1983d91e1}</UniqueIdentifier>
     </Filter>
     </Filter>
-    <Filter Include="embree-1.1beta">
-      <UniqueIdentifier>{6d281f01-62c5-4083-90e7-1e9d55cf793c}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="embree-1.1beta\rtcore">
-      <UniqueIdentifier>{ded8eb8e-e3c8-4405-9234-dd048cbb197d}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="embree-1.1beta\common">
-      <UniqueIdentifier>{0c5327d6-c9c7-4e16-a8e3-d3ae7f7b42d9}</UniqueIdentifier>
+    <Filter Include="embree">
+      <UniqueIdentifier>{6a04be79-a793-4c4a-a5c0-5d40f1f2ca7f}</UniqueIdentifier>
     </Filter>
     </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>

+ 4 - 3
examples/patches/temp.rbr

@@ -1,5 +1,6 @@
-wireframe_visible: TW_TYPE_BOOLCPP 1
+wireframe_visible: TW_TYPE_BOOLCPP 0
 fill_visible: TW_TYPE_BOOLCPP 1
 fill_visible: TW_TYPE_BOOLCPP 1
-camera_rotation: TW_TYPE_QUAT4D 0.20801 0.244181 0.0537125 0.945633
-rotation_type: RotationType two axis fixed up
+camera_rotation: TW_TYPE_QUAT4D 0.416858 0.0264188 -0.0596578 0.906627
+rotation_type: RotationType igl trackball
+orient_method: OrientMethod ambient occlusion
 
 

+ 2 - 1
examples/quicklook-mesh/Makefile

@@ -16,7 +16,8 @@ LIBIGL_INC=-I $(LIBIGL)/include
 # http://www.alecjacobson.com/weblog/?p=2827
 # http://www.alecjacobson.com/weblog/?p=2827
 GLU=/usr/local/
 GLU=/usr/local/
 GLU_INC=-I$(GLU)/include
 GLU_INC=-I$(GLU)/include
-GLU_LIB=-L$(GLU)/lib -lGLU
+#GLU_LIB=-L$(GLU)/lib -lGLU
+GLU_LIB=$(GLU)/lib/libGLU.a
 
 
 MESA=/opt/local/
 MESA=/opt/local/
 MESA_INC=-I$(MESA)/include
 MESA_INC=-I$(MESA)/include

+ 7 - 1
examples/quicklook-mesh/README

@@ -22,4 +22,10 @@ Install Mesa3D using macports.
 
 
     sudo port install mesa
     sudo port install mesa
 
 
-Then re-install mesa's GLU à la http://www.alecjacobson.com/weblog/?p=2827
+Then re-install GLU à la http://www.alecjacobson.com/weblog/?p=2827
+
+= Note about Mesa =
+
+If things look weird (too far away, blank, etc.) then maybe you should
+reinstall GLU. It seems that the version of GLU that comes with macports' mesa
+is buggy/corrupted.

+ 5 - 7
include/igl/Viewport.h

@@ -10,14 +10,12 @@ namespace igl
     int x,y,width,height;
     int x,y,width,height;
     igl::Camera camera;
     igl::Camera camera;
     // Constructors
     // Constructors
-    Viewport():
-      x(0),y(0),width(0),height(0),camera(){};
     Viewport(
     Viewport(
-      const int x, 
-      const int y, 
-      const int width,
-      const int height, 
-      const igl::Camera & camera):
+      const int x=0, 
+      const int y=0, 
+      const int width=0,
+      const int height=0, 
+      const igl::Camera & camera = igl::Camera()):
       x(x),
       x(x),
       y(y),
       y(y),
       width(width),
       width(width),

+ 109 - 63
include/igl/embree/EmbreeIntersector.h

@@ -9,31 +9,52 @@
 
 
 #include "Hit.h"
 #include "Hit.h"
 #include <Eigen/Core>
 #include <Eigen/Core>
-#include <embree/include/embree.h>
-#include <embree/include/intersector1.h>
-#include <embree/common/ray.h>
+#include "Embree_convenience.h"
 #include <vector>
 #include <vector>
 
 
 namespace igl
 namespace igl
 {
 {
-  template <
-  typename Scalar,
-  typename Index>
   class EmbreeIntersector
   class EmbreeIntersector
   {
   {
-    typedef Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> PointMatrixType;
-    typedef Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>  FaceMatrixType;
-    typedef Eigen::Matrix<Scalar,1,3> RowVector3;
   public:
   public:
-    // V  #V by 3 list of vertex positions
-    // F  #F by 3 list of Oriented triangles
-    EmbreeIntersector(
-      const PointMatrixType & V = PointMatrixType(),
-      const FaceMatrixType & F = FaceMatrixType(),
+    // Initialize embree engine. This will be called on instance `init()`
+    // calls. If already inited then this function does nothing: it is harmless
+    // to call more than once.
+    static inline void global_init();
+  private:
+    // Deinitialize the embree engine. This should probably never be called by
+    // the user. Hence it's private. Do you really want to do this?
+    static inline void global_deinit();
+  public:
+    typedef Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic> PointMatrixType;
+    typedef Eigen::Matrix<int,Eigen::Dynamic,Eigen::Dynamic>  FaceMatrixType;
+    typedef Eigen::Matrix<float,1,3> RowVector3;
+  public:
+    inline EmbreeIntersector();
+  private:
+    // Copying and assignment are not allowed.
+    inline EmbreeIntersector(const EmbreeIntersector & that);
+    inline EmbreeIntersector operator=(const EmbreeIntersector &);
+  public:
+    virtual inline ~EmbreeIntersector();
+      
+    // Initialize with a given mesh.
+    //
+    // Inputs:
+    //   V  #V by 3 list of vertex positions
+    //   F  #F by 3 list of Oriented triangles
+    // Side effects:
+    //   The first time this is ever called the embree engine is initialized.
+    inline void init(
+      const PointMatrixType & V,
+      const FaceMatrixType & F,
       const char* structure = "default",
       const char* structure = "default",
       const char* builder = "default",
       const char* builder = "default",
       const char* traverser = "default");
       const char* traverser = "default");
-    virtual ~EmbreeIntersector();
+    // Deinitialize embree datasctructures for current mesh.  Also called on
+    // destruction: no need to call if you just want to init() once and
+    // destroy.
+    inline void deinit();
   
   
     // Given a ray find the first hit
     // Given a ray find the first hit
     // 
     // 
@@ -43,7 +64,7 @@ namespace igl
     // Output:
     // Output:
     //   hit        information about hit
     //   hit        information about hit
     // Returns true if and only if there was a hit
     // Returns true if and only if there was a hit
-    bool intersectRay(
+    inline bool intersectRay(
       const RowVector3& origin, 
       const RowVector3& origin, 
       const RowVector3& direction,
       const RowVector3& direction,
       Hit& hit,
       Hit& hit,
@@ -59,7 +80,7 @@ namespace igl
     //   hit        information about hit
     //   hit        information about hit
     //   num_rays   number of rays shot (at least one)
     //   num_rays   number of rays shot (at least one)
     // Returns true if and only if there was a hit
     // Returns true if and only if there was a hit
-    bool intersectRay(
+    inline bool intersectRay(
       const RowVector3& origin,
       const RowVector3& origin,
       const RowVector3& direction,
       const RowVector3& direction,
       std::vector<Hit > &hits,
       std::vector<Hit > &hits,
@@ -75,7 +96,7 @@ namespace igl
     // Output:
     // Output:
     //   hit  information about hit
     //   hit  information about hit
     // Returns true if and only if there was a hit
     // Returns true if and only if there was a hit
-    bool intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const;
+    inline bool intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const;
     
     
   private:
   private:
     embree::RTCGeometry* mesh;
     embree::RTCGeometry* mesh;
@@ -87,41 +108,78 @@ namespace igl
 
 
 // Implementation
 // Implementation
 #include <igl/EPS.h>
 #include <igl/EPS.h>
+// This unfortunately cannot be a static field of EmbreeIntersector because it
+// would depend on the template and then we might end up with initializing
+// embree twice. If only there was a way to ask embree if it's already
+// initialized...
+namespace igl
+{
+  // Keeps track of whether the **Global** Embree intersector has been
+  // initialized. This should never been done at the global scope.
+  static bool EmbreeIntersector_inited = false;
+}
 
 
 template <typename RowVector3>
 template <typename RowVector3>
 inline embree::Vector3f toVector3f(const RowVector3 &p) { return embree::Vector3f((float)p[0], (float)p[1], (float)p[2]); }
 inline embree::Vector3f toVector3f(const RowVector3 &p) { return embree::Vector3f((float)p[0], (float)p[1], (float)p[2]); }
 
 
-template <
-typename Scalar,
-typename Index>
-igl::EmbreeIntersector < Scalar, Index>
-::EmbreeIntersector(const PointMatrixType & V,
-                    const FaceMatrixType & F,
-                    const char* structure,
-                    const char* builder,
-                    const char* traverser)
-  :
-    mesh(NULL),
-    triangles(NULL),
-    vertices(NULL),
-    intersector(NULL)
+inline void igl::EmbreeIntersector::global_init()
 {
 {
-  using namespace std;
-  static bool inited = false;
-  if(!inited)
+  if(!EmbreeIntersector_inited)
   {
   {
     embree::rtcInit();
     embree::rtcInit();
 #ifdef IGL_VERBOSE
 #ifdef IGL_VERBOSE
     embree::rtcSetVerbose(3);
     embree::rtcSetVerbose(3);
 #endif
 #endif
     embree::rtcStartThreads();
     embree::rtcStartThreads();
-    inited = true;
+    EmbreeIntersector_inited = true;
   }
   }
+}
+
+inline void igl::EmbreeIntersector::global_deinit()
+{
+  EmbreeIntersector_inited = false;
+  embree::rtcStopThreads();
+  embree::rtcExit();
+  embree::rtcFreeMemory();
+}
+
+inline igl::EmbreeIntersector::EmbreeIntersector()
+  :
+  mesh(NULL),
+  triangles(NULL),
+  vertices(NULL),
+  intersector(NULL)
+{
+}
+
+inline igl::EmbreeIntersector::EmbreeIntersector(
+  const EmbreeIntersector & that)
+{
+  assert(false && "Copying EmbreeIntersector is not allowed");
+}
+
+inline igl::EmbreeIntersector igl::EmbreeIntersector::operator=(
+  const EmbreeIntersector & that)
+{
+  assert(false && "Assigning an EmbreeIntersector is not allowed");
+  return *this;
+}
+
 
 
-   if(V.size() == 0 || F.size() == 0)
-   {
-     return;
-   }
+inline void igl::EmbreeIntersector::init(
+  const PointMatrixType & V,
+  const FaceMatrixType & F,
+  const char* structure,
+  const char* builder,
+  const char* traverser)
+{
+  using namespace std;
+  global_init();
+
+  if(V.size() == 0 || F.size() == 0)
+  {
+    return;
+  }
   
   
   mesh = embree::rtcNewTriangleMesh(F.rows(),V.rows(),structure);
   mesh = embree::rtcNewTriangleMesh(F.rows(),V.rows(),structure);
 
 
@@ -147,25 +205,19 @@ igl::EmbreeIntersector < Scalar, Index>
   intersector = embree::rtcQueryIntersector1(mesh,traverser);
   intersector = embree::rtcQueryIntersector1(mesh,traverser);
 }
 }
 
 
-template <
-typename Scalar,
-typename Index>
-igl::EmbreeIntersector < Scalar, Index>
+igl::EmbreeIntersector
 ::~EmbreeIntersector()
 ::~EmbreeIntersector()
+{
+  deinit();
+}
+
+void igl::EmbreeIntersector::deinit()
 {
 {
   embree::rtcDeleteIntersector1(intersector);
   embree::rtcDeleteIntersector1(intersector);
   embree::rtcDeleteGeometry(mesh);
   embree::rtcDeleteGeometry(mesh);
-//  embree::rtcStopThreads();
-//  embree::rtcExit();
-//  embree::rtcFreeMemory();
 }
 }
 
 
-template <
-typename Scalar,
-typename Index>
-bool 
-igl::EmbreeIntersector< Scalar, Index>
-::intersectRay(
+inline bool igl::EmbreeIntersector::intersectRay(
   const RowVector3& origin,
   const RowVector3& origin,
   const RowVector3& direction,
   const RowVector3& direction,
   Hit& hit,
   Hit& hit,
@@ -187,11 +239,8 @@ igl::EmbreeIntersector< Scalar, Index>
   return false;
   return false;
 }
 }
 
 
-template <
-typename Scalar,
-typename Index>
-bool 
-igl::EmbreeIntersector < Scalar, Index>
+inline bool 
+igl::EmbreeIntersector
 ::intersectRay(
 ::intersectRay(
   const RowVector3& origin, 
   const RowVector3& origin, 
   const RowVector3& direction,
   const RowVector3& direction,
@@ -285,11 +334,8 @@ igl::EmbreeIntersector < Scalar, Index>
   return hits.empty();
   return hits.empty();
 }
 }
 
 
-template <
-typename Scalar,
-typename Index>
-bool 
-igl::EmbreeIntersector < Scalar, Index>
+inline bool 
+igl::EmbreeIntersector
 ::intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const
 ::intersectSegment(const RowVector3& a, const RowVector3& ab, Hit &hit) const
 {
 {
   embree::Ray ray(toVector3f(a), toVector3f(ab), embree::zero, embree::one);
   embree::Ray ray(toVector3f(a), toVector3f(ab), embree::zero, embree::one);

+ 3 - 1
include/igl/embree/Embree_convenience.h

@@ -16,7 +16,9 @@
 // This is a hack
 // This is a hack
 #  pragma GCC system_header
 #  pragma GCC system_header
 #endif
 #endif
-#include <common/ray.h>
+#include <embree/include/embree.h>
+#include <embree/include/intersector1.h>
+#include <embree/common/ray.h>
 #ifdef __GNUC__
 #ifdef __GNUC__
 #  if __GNUC__ >= 4
 #  if __GNUC__ >= 4
 #    if __GNUC_MINOR__ >= 6
 #    if __GNUC_MINOR__ >= 6

+ 10 - 16
include/igl/embree/ambient_occlusion.cpp

@@ -4,13 +4,11 @@
 #include <igl/EPS.h>
 #include <igl/EPS.h>
 
 
 template <
 template <
-  typename Scalar,
-  typename Index,
   typename DerivedP,
   typename DerivedP,
   typename DerivedN,
   typename DerivedN,
   typename DerivedS >
   typename DerivedS >
 void igl::ambient_occlusion(
 void igl::ambient_occlusion(
-  const igl::EmbreeIntersector<Scalar,Index> & ei,
+  const igl::EmbreeIntersector & ei,
   const Eigen::PlainObjectBase<DerivedP> & P,
   const Eigen::PlainObjectBase<DerivedP> & P,
   const Eigen::PlainObjectBase<DerivedN> & N,
   const Eigen::PlainObjectBase<DerivedN> & N,
   const int num_samples,
   const int num_samples,
@@ -26,14 +24,14 @@ void igl::ambient_occlusion(
   // loop over mesh vertices
   // loop over mesh vertices
   for(int p = 0;p<n;p++)
   for(int p = 0;p<n;p++)
   {
   {
-    const Vector3d origin = P.row(p);
-    const Vector3d normal = N.row(p);
+    const Vector3f origin = P.row(p).template cast<float>();
+    const Vector3f normal = N.row(p).template cast<float>();
     int num_hits = 0;
     int num_hits = 0;
-    MatrixXd D = random_dir_stratified(num_samples);
+    MatrixXf D = random_dir_stratified(num_samples).cast<float>();
     for(int s = 0;s<num_samples;s++)
     for(int s = 0;s<num_samples;s++)
     {
     {
       //Vector3d d = random_dir();
       //Vector3d d = random_dir();
-      Vector3d d = D.row(s);
+      Vector3f d = D.row(s);
       if(d.dot(normal) < 0)
       if(d.dot(normal) < 0)
       {
       {
         // reverse ray
         // reverse ray
@@ -66,18 +64,14 @@ void igl::ambient_occlusion(
 {
 {
   using namespace igl;
   using namespace igl;
   using namespace Eigen;
   using namespace Eigen;
-  EmbreeIntersector<
-    typename DerivedV::Scalar,
-    typename DerivedF::Scalar > * ei = new EmbreeIntersector<
-    typename DerivedV::Scalar,
-    typename DerivedF::Scalar >(V,F);
-  ambient_occlusion(*ei,P,N,num_samples,S);
-  delete ei;
+  EmbreeIntersector ei;
+  ei.init(V.template cast<float>(),F.template cast<int>());
+  ambient_occlusion(ei,P,N,num_samples,S);
 }
 }
 
 
 #ifndef IGL_HEADER_ONLY
 #ifndef IGL_HEADER_ONLY
 // Explicit template instanciation
 // Explicit template instanciation
-template void igl::ambient_occlusion<double, int, 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::EmbreeIntersector<double, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-template void igl::ambient_occlusion<double, int, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::EmbreeIntersector<double, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::ambient_occlusion<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::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::ambient_occlusion<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>, Eigen::Matrix<double, -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> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::ambient_occlusion<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>, Eigen::Matrix<double, -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> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 1 - 6
include/igl/embree/ambient_occlusion.h

@@ -5,9 +5,6 @@
 namespace igl
 namespace igl
 {
 {
   // Forward define
   // Forward define
-  template <
-    typename Scalar,
-    typename Index>
   class EmbreeIntersector;
   class EmbreeIntersector;
   // Compute ambient occlusion per given point
   // Compute ambient occlusion per given point
   //
   //
@@ -20,13 +17,11 @@ namespace igl
   //      (not occluded)
   //      (not occluded)
   //
   //
   template <
   template <
-    typename Scalar,
-    typename Index,
     typename DerivedP,
     typename DerivedP,
     typename DerivedN,
     typename DerivedN,
     typename DerivedS >
     typename DerivedS >
   void ambient_occlusion(
   void ambient_occlusion(
-    const igl::EmbreeIntersector<Scalar,Index> & ei,
+    const igl::EmbreeIntersector & ei,
     const Eigen::PlainObjectBase<DerivedP> & P,
     const Eigen::PlainObjectBase<DerivedP> & P,
     const Eigen::PlainObjectBase<DerivedN> & N,
     const Eigen::PlainObjectBase<DerivedN> & N,
     const int num_samples,
     const int num_samples,

+ 6 - 3
include/igl/embree/bone_visible.cpp

@@ -26,8 +26,8 @@ IGL_INLINE void igl::bone_visible(
   FF.resize(F.rows()*2,F.cols());
   FF.resize(F.rows()*2,F.cols());
   FF << F, F.rowwise().reverse();
   FF << F, F.rowwise().reverse();
   // Initialize intersector
   // Initialize intersector
-  const EmbreeIntersector<double,int> ei = 
-        EmbreeIntersector<double,int>(V,FF);
+  EmbreeIntersector ei;
+  ei.init(V.template cast<float>(),FF.template cast<int>());
   const double sd_norm = (s-d).norm();
   const double sd_norm = (s-d).norm();
   // Embree seems to be parallel when constructing but not when tracing rays
   // Embree seems to be parallel when constructing but not when tracing rays
 #pragma omp parallel for
 #pragma omp parallel for
@@ -68,7 +68,10 @@ IGL_INLINE void igl::bone_visible(
     // perhaps 1.0 should be 1.0-epsilon, or actually since we checking the
     // perhaps 1.0 should be 1.0-epsilon, or actually since we checking the
     // incident face, perhaps 1.0 should be 1.0+eps
     // incident face, perhaps 1.0 should be 1.0+eps
     const Vector3d dir = (Vv-projv)*1.0;
     const Vector3d dir = (Vv-projv)*1.0;
-    if(ei.intersectSegment(projv,dir, hit))
+    if(ei.intersectSegment(
+       projv.template cast<float>(),
+       dir.template cast<float>(), 
+       hit))
     {
     {
       // mod for double sided lighting
       // mod for double sided lighting
       const int fi = hit.id % F.rows();
       const int fi = hit.id % F.rows();

+ 126 - 70
include/igl/embree/orient_outward_ao.cpp

@@ -1,28 +1,23 @@
 #include "orient_outward_ao.h"
 #include "orient_outward_ao.h"
 #include "../per_face_normals.h"
 #include "../per_face_normals.h"
-#include "../barycenter.h"
 #include "../doublearea.h"
 #include "../doublearea.h"
-#include "../matlab_format.h"
-#include "ambient_occlusion.h"
+#include "../random_dir.h"
 #include "EmbreeIntersector.h"
 #include "EmbreeIntersector.h"
 #include <iostream>
 #include <iostream>
 #include <random>
 #include <random>
-#include <omp.h>
 
 
 template <
 template <
   typename DerivedV, 
   typename DerivedV, 
   typename DerivedF, 
   typename DerivedF, 
   typename DerivedC, 
   typename DerivedC, 
-  typename Scalar,
-  typename Index,
   typename DerivedFF, 
   typename DerivedFF, 
   typename DerivedI>
   typename DerivedI>
 IGL_INLINE void igl::orient_outward_ao(
 IGL_INLINE void igl::orient_outward_ao(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedC> & C,
   const Eigen::PlainObjectBase<DerivedC> & C,
-  const igl::EmbreeIntersector<Scalar,Index> & ei,
-  const int num_samples,
+  const int min_num_rays_per_component,
+  const int total_num_rays,
   Eigen::PlainObjectBase<DerivedFF> & FF,
   Eigen::PlainObjectBase<DerivedFF> & FF,
   Eigen::PlainObjectBase<DerivedI> & I)
   Eigen::PlainObjectBase<DerivedI> & I)
 {
 {
@@ -32,6 +27,9 @@ IGL_INLINE void igl::orient_outward_ao(
   assert(F.cols() == 3);
   assert(F.cols() == 3);
   assert(V.cols() == 3);
   assert(V.cols() == 3);
   
   
+  EmbreeIntersector ei;
+  ei.init(V.template cast<float>(),F);
+  
   // number of faces
   // number of faces
   const int m = F.rows();
   const int m = F.rows();
   // number of patches
   // number of patches
@@ -43,71 +41,138 @@ IGL_INLINE void igl::orient_outward_ao(
   }
   }
   
   
   // face normal
   // face normal
-  PlainObjectBase<DerivedV> N;
+  MatrixXd N;
   per_face_normals(V,F,N);
   per_face_normals(V,F,N);
   
   
-  // random number generator/distribution for each thread
-  int max_threads = omp_get_max_threads();
-  
-  // prng
-  vector<mt19937> engine(max_threads);
-  for (int i = 0; i < max_threads; ++i)
-      engine[i].seed(time(0) * (i + 1));
-  
-  // discrete distribution for random selection of faces with probability proportional to their areas
+  // face area
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   doublearea(V,F,A);
   doublearea(V,F,A);
-  double minarea = A.minCoeff();
-  Matrix<int, Dynamic, 1> A_int = (A * 100.0 / minarea).template cast<int>();       // only integer is allowed for weight
-  auto ddist_func = [&] (double i) { return A_int(static_cast<int>(i)); };
-  vector<discrete_distribution<int>> ddist(max_threads, discrete_distribution<int>(m, 0, m, ddist_func));      // simple ctor of (Iter, Iter) not provided by the stupid VC11 impl...
-  
-  // uniform real between in [0, 1]
-  vector<uniform_real_distribution<double>> rdist(max_threads);
+  double area_min = A.minCoeff();
+  double area_total = A.sum();
   
   
-  //// occlusion count per component: +1 when front ray is occluded, -1 when back ray is occluded
-  // occlussion count per component, per back/front: C(c,0) --> number of
-  // front-side rays occluded, C(c,1) --> number of back-side rays occluded
-  Matrix<int, Dynamic, 2> C_occlude_count;
-  C_occlude_count.setZero(num_cc, 2);
+  // determine number of rays per component according to its area
+  VectorXd area_per_component;
+  area_per_component.setZero(num_cc);
+  for (int f = 0; f < m; ++f)
+  {
+    area_per_component(C(f)) += A(f);
+  }
+  VectorXi num_rays_per_component;
+  num_rays_per_component.setZero(num_cc);
+  for (int c = 0; c < num_cc; ++c)
+  {
+    num_rays_per_component(c) = max<int>(min_num_rays_per_component, static_cast<int>(total_num_rays * area_per_component(c) / area_total));
+  }
   
   
-#pragma omp parallel for
-  for (int i = 0; i < num_samples; ++i)
+  // generate all the rays
+  cout << "generating rays... ";
+  uniform_real_distribution<float> rdist;
+  mt19937 prng;
+  prng.seed(0);
+  vector<int     > ray_face;
+  vector<Vector3f> ray_ori;
+  vector<Vector3f> ray_dir;
+  ray_face.reserve(total_num_rays);
+  ray_ori .reserve(total_num_rays);
+  ray_dir .reserve(total_num_rays);
+  for (int c = 0; c < num_cc; ++c)
   {
   {
-    int thread_num = omp_get_thread_num();
-    int f     = ddist[thread_num](engine[thread_num]);   // select face with probability proportional to face area
-    double t0 = rdist[thread_num](engine[thread_num]);
-    double t1 = rdist[thread_num](engine[thread_num]);
-    double t2 = rdist[thread_num](engine[thread_num]);
-    double t_sum = t0 + t1 + t2;
-    t0 /= t_sum;
-    t1 /= t_sum;
-    t2 /= t_sum;
-    RowVector3d p = t0 * V.row(F(f,0)) + t1 * V.row(F(f,1)) + t1 * V.row(F(f,2));
-    RowVector3d n = N.row(f);
-    //bool is_backside = rdist[thread_num](engine[thread_num]) < 0.5;
-    // Loop over front or back side
-    for(int s = 0;s<2;s++)
+    vector<int> CF;     // set of faces per component
+    vector<int> CF_area;
+    for (int f = 0; f < m; ++f)
     {
     {
-      if(s==1)
+      if (C(f)==c)
       {
       {
-          n *= -1;
+        CF.push_back(f);
+        CF_area.push_back(static_cast<int>(100 * A(f) / area_min));
       }
       }
-      Matrix<typename DerivedV::Scalar,Dynamic,1> S;
-      ambient_occlusion(ei, p, n, 1, S);
-      if (S(0) > 0)
-      {
-#pragma omp atomic
-        C_occlude_count(C(f),s)++;
+    }
+    // discrete distribution for random selection of faces with probability proportional to their areas
+    auto ddist_func = [&] (double i) { return CF_area[static_cast<int>(i)]; };
+    discrete_distribution<int> ddist(CF.size(), 0, CF.size(), ddist_func);      // simple ctor of (Iter, Iter) not provided by the stupid VC11 impl...
+    for (int i = 0; i < num_rays_per_component[c]; ++i)
+    {
+      int f     = CF[ddist(prng)];    // select face with probability proportional to face area
+      float t0 = rdist(prng);        // random barycentric coordinate
+      float t1 = rdist(prng);
+      float t2 = rdist(prng);
+      float t_sum = t0 + t1 + t2;
+      t0 /= t_sum;
+      t1 /= t_sum;
+      t2 /= t_sum;
+      Vector3f p = t0 * V.row(F(f,0)).template cast<float>().eval()       // be careful with the index!!!
+                 + t1 * V.row(F(f,1)).template cast<float>().eval()
+                 + t2 * V.row(F(f,2)).template cast<float>().eval();
+      Vector3f n = N.row(f).cast<float>();
+      assert(n != Vector3f::Zero());
+      // random direction in hemisphere around n (avoid too grazing angle)
+      Vector3f d;
+      while (true) {
+        d = random_dir().cast<float>();
+        float ndotd = n.dot(d);
+        if (fabsf(ndotd) < 0.1f)
+        {
+          continue;
+        }
+        if (ndotd < 0)
+        {
+          d *= -1.0f;
+        }
+        break;
       }
       }
+      ray_face.push_back(f);
+      ray_ori .push_back(p);
+      ray_dir .push_back(d);
+    }
+  }
+  
+  // per component voting: first=front, second=back
+  vector<pair<float, float>> C_vote_distance(num_cc, make_pair(0, 0));     // sum of distance between ray origin and intersection
+  vector<pair<int  , int  >> C_vote_infinity(num_cc, make_pair(0, 0));     // number of rays reaching infinity
+  
+  cout << "shooting rays... ";
+#pragma omp parallel for
+  for (int i = 0; i < (int)ray_face.size(); ++i)
+  {
+    int      f = ray_face[i];
+    Vector3f o = ray_ori [i];
+    Vector3f d = ray_dir [i];
+    int c = C(f);
+    
+    // shoot ray toward front & back
+    vector<Hit> hits_front;
+    vector<Hit> hits_back;
+    int num_rays_front;
+    int num_rays_back;
+    ei.intersectRay(o,  d, hits_front, num_rays_front);
+    ei.intersectRay(o, -d, hits_back , num_rays_back );
+    if (!hits_front.empty() && hits_front[0].id == f) hits_front.erase(hits_front.begin());
+    if (!hits_back .empty() && hits_back [0].id == f) hits_back .erase(hits_back .begin());
+    
+    if (hits_front.empty())
+    {
+#pragma omp atomic
+      C_vote_infinity[c].first++;
+    } else {
+#pragma omp atomic
+      C_vote_distance[c].first += hits_front[0].t;
+    }
+    
+    if (hits_back.empty())
+    {
+#pragma omp atomic
+      C_vote_infinity[c].second++;
+    } else {
+#pragma omp atomic
+      C_vote_distance[c].second += hits_back[0].t;
     }
     }
-
   }
   }
   
   
   for(int c = 0;c<num_cc;c++)
   for(int c = 0;c<num_cc;c++)
   {
   {
-    //I(c) = C_occlude_count(c) > 0;
-    I(c) = C_occlude_count(c,0) > C_occlude_count(c,1);
+    I(c) = C_vote_infinity[c].first == C_vote_infinity[c].second &&
+           C_vote_distance[c].first <  C_vote_distance[c].second ||
+           C_vote_infinity[c].first <  C_vote_infinity[c].second;
   }
   }
   // flip according to I
   // flip according to I
   for(int f = 0;f<m;f++)
   for(int f = 0;f<m;f++)
@@ -117,9 +182,10 @@ IGL_INLINE void igl::orient_outward_ao(
       FF.row(f) = FF.row(f).reverse().eval();
       FF.row(f) = FF.row(f).reverse().eval();
     }
     }
   }
   }
+  cout << "done!\n";
 }
 }
 
 
-// EmbreeIntersector generated on the fly
+// Call with default parameters
 template <
 template <
   typename DerivedV, 
   typename DerivedV, 
   typename DerivedF, 
   typename DerivedF, 
@@ -130,23 +196,13 @@ IGL_INLINE void igl::orient_outward_ao(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedC> & C,
   const Eigen::PlainObjectBase<DerivedC> & C,
-  const int num_samples,
   Eigen::PlainObjectBase<DerivedFF> & FF,
   Eigen::PlainObjectBase<DerivedFF> & FF,
   Eigen::PlainObjectBase<DerivedI> & I)
   Eigen::PlainObjectBase<DerivedI> & I)
 {
 {
-  using namespace igl;
-  using namespace Eigen;
-  // Both sides
-  MatrixXi F2;
-  F2.resize(F.rows()*2,F.cols());
-  F2 << F, F.rowwise().reverse().eval();
-  EmbreeIntersector<
-    typename DerivedV::Scalar,
-    typename DerivedF::Scalar > ei(V,F2);
-  return orient_outward_ao(V, F, C, ei, num_samples, FF, I);
+  return orient_outward_ao(V, F, C, 100, F.rows() * 100, FF, I);
 }
 }
 
 
 #ifndef IGL_HEADER_ONLY
 #ifndef IGL_HEADER_ONLY
 // Explicit template specialization
 // Explicit template specialization
-template void igl::orient_outward_ao<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::orient_outward_ao<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif
 #endif

+ 8 - 16
include/igl/embree/orient_outward_ao.h

@@ -4,20 +4,15 @@
 #include <Eigen/Core>
 #include <Eigen/Core>
 namespace igl
 namespace igl
 {
 {
-  // Forward define
-  template <
-    typename Scalar,
-    typename Index>
-  class EmbreeIntersector;
   // Orient each component (identified by C) of a mesh (V,F) using ambient occlusion 
   // 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
   // such that the front side is less occluded than back side
   //
   //
   // Inputs:
   // Inputs:
-  //   V            #V by 3 list of vertex positions
-  //   F            #F by 3 list of triangle indices
-  //   C            #F list of components
-  //   ei           EmbreeIntersector containing (V,F)
-  //   num_samples  total number of rays to be shot
+  //   V                            #V by 3 list of vertex positions
+  //   F                            #F by 3 list of triangle indices
+  //   C                            #F list of components
+  //   min_num_rays_per_component   Each component receives at least this number of rays
+  //   total_num_rays               Total number of rays that will be shot
   // Outputs:
   // Outputs:
   //   FF  #F by 3 list of new triangle indices such that FF(~I,:) = F(~I,:) and
   //   FF  #F by 3 list of new triangle indices such that FF(~I,:) = F(~I,:) and
   //     FF(I,:) = fliplr(F(I,:)) (OK if &FF = &F)
   //     FF(I,:) = fliplr(F(I,:)) (OK if &FF = &F)
@@ -26,20 +21,18 @@ namespace igl
     typename DerivedV, 
     typename DerivedV, 
     typename DerivedF, 
     typename DerivedF, 
     typename DerivedC, 
     typename DerivedC, 
-    typename Scalar,
-    typename Index,
     typename DerivedFF, 
     typename DerivedFF, 
     typename DerivedI>
     typename DerivedI>
   IGL_INLINE void orient_outward_ao(
   IGL_INLINE void orient_outward_ao(
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::PlainObjectBase<DerivedF> & F,
     const Eigen::PlainObjectBase<DerivedF> & F,
     const Eigen::PlainObjectBase<DerivedC> & C,
     const Eigen::PlainObjectBase<DerivedC> & C,
-    const igl::EmbreeIntersector<Scalar,Index> & ei,
-    const int num_samples,
+    const int min_num_rays_per_component,
+    const int total_num_rays,
     Eigen::PlainObjectBase<DerivedFF> & FF,
     Eigen::PlainObjectBase<DerivedFF> & FF,
     Eigen::PlainObjectBase<DerivedI> & I);
     Eigen::PlainObjectBase<DerivedI> & I);
   
   
-  // EmbreeIntersector generated on the fly
+  // Call with default number of rays
   template <
   template <
     typename DerivedV, 
     typename DerivedV, 
     typename DerivedF, 
     typename DerivedF, 
@@ -50,7 +43,6 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::PlainObjectBase<DerivedV> & V,
     const Eigen::PlainObjectBase<DerivedF> & F,
     const Eigen::PlainObjectBase<DerivedF> & F,
     const Eigen::PlainObjectBase<DerivedC> & C,
     const Eigen::PlainObjectBase<DerivedC> & C,
-    const int num_samples,
     Eigen::PlainObjectBase<DerivedFF> & FF,
     Eigen::PlainObjectBase<DerivedFF> & FF,
     Eigen::PlainObjectBase<DerivedI> & I);
     Eigen::PlainObjectBase<DerivedI> & I);
 };
 };

+ 8 - 11
include/igl/embree/unproject_in_mesh.cpp

@@ -4,13 +4,11 @@
 #include <vector>
 #include <vector>
 
 
 template <
 template <
-  typename Scalar,
-  typename Index,
   typename Derivedobj>
   typename Derivedobj>
 int igl::unproject_in_mesh(
 int igl::unproject_in_mesh(
   const int x,
   const int x,
   const int y,
   const int y,
-  const igl::EmbreeIntersector<Scalar,Index> & ei,
+  const igl::EmbreeIntersector & ei,
   Eigen::PlainObjectBase<Derivedobj> & obj)
   Eigen::PlainObjectBase<Derivedobj> & obj)
 {
 {
   std::vector<igl::Hit> hits;
   std::vector<igl::Hit> hits;
@@ -18,13 +16,11 @@ int igl::unproject_in_mesh(
 }
 }
 
 
 template <
 template <
-  typename Scalar,
-  typename Index,
   typename Derivedobj>
   typename Derivedobj>
 int igl::unproject_in_mesh(
 int igl::unproject_in_mesh(
   const int x,
   const int x,
   const int y,
   const int y,
-  const igl::EmbreeIntersector<Scalar,Index> & ei,
+  const igl::EmbreeIntersector & ei,
   Eigen::PlainObjectBase<Derivedobj> & obj,
   Eigen::PlainObjectBase<Derivedobj> & obj,
   std::vector<igl::Hit > & hits)
   std::vector<igl::Hit > & hits)
 {
 {
@@ -32,10 +28,10 @@ int igl::unproject_in_mesh(
   using namespace std;
   using namespace std;
   using namespace Eigen;
   using namespace Eigen;
   // Source and direction on screen
   // Source and direction on screen
-  Vector3d win_s = Vector3d(x,y,0);
-  Vector3d win_d(x,y,1);
+  Vector3f win_s = Vector3f(x,y,0);
+  Vector3f win_d(x,y,1);
   // Source, destination and direction in world
   // Source, destination and direction in world
-  Vector3d s,d,dir;
+  Vector3f s,d,dir;
   unproject(win_s,s);
   unproject(win_s,s);
   unproject(win_d,d);
   unproject(win_d,d);
   dir = d-s;
   dir = d-s;
@@ -49,13 +45,13 @@ int igl::unproject_in_mesh(
       break;
       break;
     case 1:
     case 1:
     {
     {
-      obj = s + dir*hits[0].t;
+      obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
       break;
       break;
     }
     }
     case 2:
     case 2:
     default:
     default:
     {
     {
-      obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t));
+      obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
       break;
       break;
     }
     }
   }
   }
@@ -63,4 +59,5 @@ int igl::unproject_in_mesh(
 }
 }
 
 
 #ifndef IGL_HEADER_ONLY
 #ifndef IGL_HEADER_ONLY
+template int igl::unproject_in_mesh<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(int, int, igl::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&, std::vector<igl::Hit, std::allocator<igl::Hit> >&);
 #endif
 #endif

+ 2 - 9
include/igl/embree/unproject_in_mesh.h

@@ -9,9 +9,6 @@
 namespace igl
 namespace igl
 {
 {
   // Forward define
   // Forward define
-  template <
-    typename Scalar,
-    typename Index>
   class EmbreeIntersector;
   class EmbreeIntersector;
   // Unproject a screen location (using current opengl viewport, projection, and
   // Unproject a screen location (using current opengl viewport, projection, and
   // model view) to a 3D position 
   // model view) to a 3D position 
@@ -25,23 +22,19 @@ namespace igl
   // Returns number of hits
   // Returns number of hits
   //
   //
   template <
   template <
-    typename Scalar,
-    typename Index,
     typename Derivedobj>
     typename Derivedobj>
   int unproject_in_mesh(
   int unproject_in_mesh(
     const int x,
     const int x,
     const int y,
     const int y,
-    const igl::EmbreeIntersector<Scalar,Index> & ei,
+    const igl::EmbreeIntersector & ei,
     Eigen::PlainObjectBase<Derivedobj> & obj);
     Eigen::PlainObjectBase<Derivedobj> & obj);
 
 
   template <
   template <
-    typename Scalar,
-    typename Index,
     typename Derivedobj>
     typename Derivedobj>
   int unproject_in_mesh(
   int unproject_in_mesh(
     const int x,
     const int x,
     const int y,
     const int y,
-    const igl::EmbreeIntersector<Scalar,Index> & ei,
+    const igl::EmbreeIntersector & ei,
     Eigen::PlainObjectBase<Derivedobj> & obj,
     Eigen::PlainObjectBase<Derivedobj> & obj,
     std::vector<igl::Hit > & hits);
     std::vector<igl::Hit > & hits);
 }
 }

+ 2 - 1
include/igl/orient_outward.cpp

@@ -36,7 +36,8 @@ IGL_INLINE void igl::orient_outward(
   PlainObjectBase<DerivedV> N,BC,BCmean;
   PlainObjectBase<DerivedV> N,BC,BCmean;
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   Matrix<typename DerivedV::Scalar,Dynamic,1> A;
   VectorXd totA(num_cc), dot(num_cc);
   VectorXd totA(num_cc), dot(num_cc);
-  per_face_normals(V,F,N);
+  Matrix<typename DerivedV::Scalar,3,1> Z(1,1,1);
+  per_face_normals(V,F,Z.normalized(),N);
   barycenter(V,F,BC);
   barycenter(V,F,BC);
   doublearea(V,F,A);
   doublearea(V,F,A);
   BCmean.setConstant(num_cc,3,0);
   BCmean.setConstant(num_cc,3,0);

+ 20 - 9
include/igl/per_face_normals.cpp

@@ -2,11 +2,12 @@
 #include <Eigen/Geometry>
 #include <Eigen/Geometry>
 
 
 #define SQRT_ONE_OVER_THREE 0.57735026918962573
 #define SQRT_ONE_OVER_THREE 0.57735026918962573
-template <typename DerivedV, typename DerivedF>
+template <typename DerivedV, typename DerivedF, typename DerivedZ, typename DerivedN>
 IGL_INLINE void igl::per_face_normals(
 IGL_INLINE void igl::per_face_normals(
   const Eigen::PlainObjectBase<DerivedV>& V,
   const Eigen::PlainObjectBase<DerivedV>& V,
   const Eigen::PlainObjectBase<DerivedF>& F,
   const Eigen::PlainObjectBase<DerivedF>& F,
-  Eigen::PlainObjectBase<DerivedV> & N)
+  const Eigen::PlainObjectBase<DerivedZ> & Z,
+  Eigen::PlainObjectBase<DerivedN> & N)
 {
 {
   N.resize(F.rows(),3);
   N.resize(F.rows(),3);
   // loop over faces
   // loop over faces
@@ -17,20 +18,30 @@ IGL_INLINE void igl::per_face_normals(
     Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 = V.row(F(i,1)) - V.row(F(i,0));
     Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v1 = V.row(F(i,1)) - V.row(F(i,0));
     Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v2 = V.row(F(i,2)) - V.row(F(i,0));
     Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v2 = V.row(F(i,2)) - V.row(F(i,0));
     N.row(i) = v1.cross(v2);//.normalized();
     N.row(i) = v1.cross(v2);//.normalized();
-    if(N.row(i).sum() == 0)
+    typename DerivedV::Scalar r = N.row(i).norm();
+    if(r == 0)
     {
     {
-      N(i,0) = SQRT_ONE_OVER_THREE;
-      N(i,1) = SQRT_ONE_OVER_THREE;
-      N(i,2) = SQRT_ONE_OVER_THREE;
+      N.row(i) = Z;
     }else
     }else
     {
     {
-      N.row(i) = N.row(i).normalized().eval();
+      N.row(i) /= r;
     }
     }
   }
   }
 }
 }
+
+template <typename DerivedV, typename DerivedF, typename DerivedN>
+IGL_INLINE void igl::per_face_normals(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedN> & N)
+{
+  using namespace Eigen;
+  Matrix<typename DerivedN::Scalar,3,1> Z(0,0,0);
+  return per_face_normals(V,F,Z,N);
+}
+
 #ifndef IGL_HEADER_ONLY
 #ifndef IGL_HEADER_ONLY
 // Explicit template specialization
 // Explicit template specialization
-// generated by autoexplicit.sh
 template void igl::per_face_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_face_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_face_normals<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&);
+template void igl::per_face_normals<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -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, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif
 #endif

+ 16 - 3
include/igl/per_face_normals.h

@@ -7,14 +7,27 @@ namespace igl
   // Compute face normals via vertex position list, face list
   // Compute face normals via vertex position list, face list
   // Inputs:
   // Inputs:
   //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
   //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3 eigne Matrix of face (triangle) indices
+  //   F  #F by 3 eigen Matrix of face (triangle) indices
+  //   Z  3 vector normal given to faces with degenerate normal.
   // Output:
   // Output:
   //   N  #F by 3 eigen Matrix of mesh face (triangle) 3D normals
   //   N  #F by 3 eigen Matrix of mesh face (triangle) 3D normals
-  template <typename DerivedV, typename DerivedF>
+  //
+  // Example:
+  //   // Give degenerate faces (1/3,1/3,1/3)^0.5
+  //   per_face_normals(V,F,Vector3d(1,1,1).normalized(),N);
+  template <typename DerivedV, typename DerivedF, typename DerivedZ, typename DerivedN>
   IGL_INLINE void per_face_normals(
   IGL_INLINE void per_face_normals(
     const Eigen::PlainObjectBase<DerivedV>& V,
     const Eigen::PlainObjectBase<DerivedV>& V,
     const Eigen::PlainObjectBase<DerivedF>& F,
     const Eigen::PlainObjectBase<DerivedF>& F,
-    Eigen::PlainObjectBase<DerivedV> & N);
+    const Eigen::PlainObjectBase<DerivedZ> & Z,
+    Eigen::PlainObjectBase<DerivedN> & N);
+  // Wrapper with Z = (0,0,0). Note that this means that row norms will be zero
+  // (i.e. not 1) for degenerate normals.
+  template <typename DerivedV, typename DerivedF, typename DerivedN>
+  IGL_INLINE void per_face_normals(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    Eigen::PlainObjectBase<DerivedN> & N);
 }
 }
 
 
 #ifdef IGL_HEADER_ONLY
 #ifdef IGL_HEADER_ONLY

+ 0 - 15
include/igl/per_vertex_normals.cpp

@@ -12,21 +12,6 @@ IGL_INLINE void igl::per_vertex_normals(
   Eigen::PlainObjectBase<DerivedV> PFN;
   Eigen::PlainObjectBase<DerivedV> PFN;
   igl::per_face_normals(V,F,PFN);
   igl::per_face_normals(V,F,PFN);
   return igl::per_vertex_normals(V,F,PFN,N);
   return igl::per_vertex_normals(V,F,PFN,N);
-
-  //// Resize for output
-  //N = Eigen::PlainObjectBase<DerivedV>::Zero(V.rows(),3);
-
-  //// loop over faces
-  //for(int i = 0; i < F.rows();i++)
-  //{
-  //  // throw normal at each corner
-  //  for(int j = 0; j < 3;j++)
-  //  {
-  //    N.row(F(i,j)) += PFN.row(i);
-  //  }
-  //}
-  //// normalize each row
-  //igl::normalize_row_lengths(N,N);
 }
 }
 
 
 template <typename DerivedV, typename DerivedF>
 template <typename DerivedV, typename DerivedF>

+ 1 - 0
include/igl/unproject.cpp

@@ -53,6 +53,7 @@ IGL_INLINE Eigen::PlainObjectBase<Derivedwin> igl::unproject(
 template int igl::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
 template int igl::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
 template int igl::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
 template int igl::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
 template Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > igl::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&);
 template Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > igl::unproject<Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> > const&);
+template int igl::unproject<Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
 #endif
 #endif
 
 
 #endif
 #endif