Browse Source

transparency with sorted primitives example, viewport class, lots more explicits

Former-commit-id: 7433f127dac9438b9b57dded805cee432681e1d3
Alec Jacobson (jalec 11 years ago
parent
commit
840830f753

+ 42 - 42
examples/ReAntTweakBar/example.cpp

@@ -3,7 +3,7 @@
 
   On mac os x compile with:
 
-  g++ -c example.cpp -o example.o 
+  g++ -c example.cpp -o example.o
   g++ -o example example.o -framework OpenGL -framework GLUT -lAntTweakBar
   rm *.o
 
@@ -21,7 +21,7 @@
 //              AntTweakBar: http://www.antisphere.com/Wiki/tools:anttweakbar
 //              OpenGL:      http://www.opengl.org
 //              GLUT:        http://opengl.org/resources/libraries/glut
-//  
+//
 //  @author     Philippe Decaudin - http://www.antisphere.com
 //  @date       2006/05/20
 //
@@ -39,7 +39,7 @@ using namespace igl;
 #include <math.h>
 
 #if defined(_WIN32) || defined(_WIN64)
-//  MiniGLUT.h is provided to avoid the need of having GLUT installed to 
+//  MiniGLUT.h is provided to avoid the need of having GLUT installed to
 //  recompile this example. Do not use it in your own programs, better
 //  install and use the actual GLUT library SDK.
 #   define USE_MINI_GLUT
@@ -88,7 +88,7 @@ void SetQuaternionFromAxisAngle(const float *axis, float angle, float *quat)
   quat[1] = sina2 * axis[1] / norm;
   quat[2] = sina2 * axis[2] / norm;
   quat[3] = (float)cos(0.5f * angle);
-  
+
 }
 
 
@@ -140,15 +140,15 @@ void Display(void)
 {
   float v[4]; // will be used to set light paramters
   float mat[4*4]; // rotation matrix
-  
+
   // Clear frame buffer
   glClearColor(0, 0, 0, 1);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-  
+
   glEnable(GL_DEPTH_TEST);
   glDisable(GL_CULL_FACE);
   glEnable(GL_NORMALIZE);
-  
+
   // Set light
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
@@ -158,15 +158,15 @@ void Display(void)
   glLightfv(GL_LIGHT0, GL_DIFFUSE, v);
   v[0] = -g_LightDirection[0]; v[1] = -g_LightDirection[1]; v[2] = -g_LightDirection[2]; v[3] = 0.0f;
   glLightfv(GL_LIGHT0, GL_POSITION, v);
-  
+
   // Set material
   glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, g_MatAmbient);
   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, g_MatDiffuse);
-  
+
   // Rotate and draw shape
   glPushMatrix();
   glTranslatef(0.5f, -0.3f, 0.0f);
-  if( g_AutoRotate ) 
+  if( g_AutoRotate )
   {
     float axis[3] = { 0, 1, 0 };
     float angle = (float)(glutGet(GLUT_ELAPSED_TIME)-g_RotateTime)/1000.0f;
@@ -179,13 +179,13 @@ void Display(void)
   glScalef(g_Zoom, g_Zoom, g_Zoom);
   glCallList(g_CurrentShape);
   glPopMatrix();
-  
+
   // Draw tweak bars
   TwDraw();
-  
+
   // Present frame buffer
   glutSwapBuffers();
-  
+
   // Recall Display at next frame
   glutPostRedisplay();
 }
@@ -203,7 +203,7 @@ void Reshape(int width, int height)
   glLoadIdentity();
   gluLookAt(0,0,5, 0,0,0, 0,1,0);
   glTranslatef(0, 0.6f, -1);
-  
+
   // Send the new window size to AntTweakBar
   TwWindowSize(width, height);
 }
@@ -211,11 +211,11 @@ void Reshape(int width, int height)
 
 // Function called at exit
 void Terminate(void)
-{ 
+{
   rebar.save(REBAR_NAME);
 
   glDeleteLists(SHAPE_TEAPOT, NUM_SHAPES);
-  
+
   TwTerminate();
 }
 
@@ -224,9 +224,9 @@ void Terminate(void)
 void TW_CALL SetAutoRotateCB(const void *value, void *clientData)
 {
   (void)clientData; // unused
-  
+
   g_AutoRotate = *(const int *)(value); // copy value to g_AutoRotate
-  if( g_AutoRotate!=0 ) 
+  if( g_AutoRotate!=0 )
   {
     // init rotation
     g_RotateTime = glutGet(GLUT_ELAPSED_TIME);
@@ -234,7 +234,7 @@ void TW_CALL SetAutoRotateCB(const void *value, void *clientData)
     g_RotateStart[1] = g_Rotation[1];
     g_RotateStart[2] = g_Rotation[2];
     g_RotateStart[3] = g_Rotation[3];
-    
+
     // make Rotation variable read-only
     TwDefine(" TweakBar/ObjRotation readonly ");
   }
@@ -257,28 +257,28 @@ int main(int argc, char *argv[])
 {
   float axis[] = { 0.7f, 0.7f, 0.0f }; // initial model rotation
   float angle = 0.8f;
-  
+
   // Initialize AntTweakBar
   // (note that AntTweakBar could also be intialized after GLUT, no matter)
   if( !TwInit(TW_OPENGL, NULL) )
   {
-    // A fatal error occured    
+    // A fatal error occured
     fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
     return 1;
   }
-  
+
   // Initialize GLUT
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize(640, 480);
   glutCreateWindow("AntTweakBar simple example using GLUT");
   glutCreateMenu(NULL);
-  
+
   // Set GLUT callbacks
   glutDisplayFunc(Display);
   glutReshapeFunc(Reshape);
   atexit(Terminate);  // Called after glutMainLoop ends
-  
+
   // Set GLUT event callbacks
   // - Directly redirect GLUT mouse button events to AntTweakBar
   glutMouseFunc((GLUTmousebuttonfun)TwEventMouseButtonGLUT);
@@ -293,7 +293,7 @@ int main(int argc, char *argv[])
   // - Send 'glutGetModifers' function pointer to AntTweakBar;
   //   required because the GLUT key event functions do not report key modifiers states.
   TwGLUTModifiersFunc(glutGetModifiers);
-  
+
   // Create some 3D objects (stored in display lists)
   glNewList(SHAPE_TEAPOT, GL_COMPILE);
   glutSolidTeapot(1.0);
@@ -307,40 +307,40 @@ int main(int argc, char *argv[])
   glNewList(SHAPE_SPHERE, GL_COMPILE);
   glutSolidSphere(1.0, 50, 40);
   glEndList();
-  
+
   // Create a tweak bar
   rebar.TwNewBar("TweakBar");
   TwDefine(" GLOBAL help='This example shows how to integrate AntTweakBar with GLUT and OpenGL.' "); // Message added to the help bar.
   TwDefine(" TweakBar size='200 400' color='96 216 224' "); // change default tweak bar size and color
-  
+
   // Add 'g_Zoom' to 'bar': this is a modifable (RW) variable of type TW_TYPE_FLOAT. Its key shortcuts are [z] and [Z].
-  rebar.TwAddVarRW("Zoom", TW_TYPE_FLOAT, &g_Zoom, 
+  rebar.TwAddVarRW("Zoom", TW_TYPE_FLOAT, &g_Zoom,
              " min=0.01 max=2.5 step=0.01 keyIncr=z keyDecr=Z help='Scale the object (1=original size).' ");
-  
+
   // Add 'g_Rotation' to 'bar': this is a variable of type TW_TYPE_QUAT4F which defines the object's orientation
-  rebar.TwAddVarRW("ObjRotation", TW_TYPE_QUAT4F, &g_Rotation, 
+  rebar.TwAddVarRW("ObjRotation", TW_TYPE_QUAT4F, &g_Rotation,
              " label='Object rotation' open help='Change the object orientation.' ");
-  
+
   // Add callback to toggle auto-rotate mode (callback functions are defined above).
-  rebar.TwAddVarCB("AutoRotate", TW_TYPE_BOOL32, SetAutoRotateCB, GetAutoRotateCB, NULL, 
+  rebar.TwAddVarCB("AutoRotate", TW_TYPE_BOOL32, SetAutoRotateCB, GetAutoRotateCB, NULL,
              " label='Auto-rotate' key=space help='Toggle auto-rotate mode.' ");
-  
+
   // Add 'g_LightMultiplier' to 'bar': this is a variable of type TW_TYPE_FLOAT. Its key shortcuts are [+] and [-].
-  rebar.TwAddVarRW("Multiplier", TW_TYPE_DOUBLE, &g_LightMultiplier, 
+  rebar.TwAddVarRW("Multiplier", TW_TYPE_DOUBLE, &g_LightMultiplier,
              " label='Light booster' min=0.1 max=4 step=0.02 keyIncr='+' keyDecr='-' help='Increase/decrease the light power.' ");
-  
+
   // Add 'g_LightDirection' to 'bar': this is a variable of type TW_TYPE_DIR3F which defines the light direction
-  rebar.TwAddVarRW("Light Dir", TW_TYPE_DIR3F, &g_LightDirection, 
+  rebar.TwAddVarRW("Light Dir", TW_TYPE_DIR3F, &g_LightDirection,
              " label='Light direction' open help='Change the light direction.' ");
-  
+
   // Add 'g_MatAmbient' to 'bar': this is a variable of type TW_TYPE_COLOR3F (3 floats color, alpha is ignored)
   // and is inserted into a group named 'Material'.
   rebar.TwAddVarRW("Ambient", TW_TYPE_COLOR3F, &g_MatAmbient, " group='Material' ");
-  
+
   // Add 'g_MatDiffuse' to 'bar': this is a variable of type TW_TYPE_COLOR3F (3 floats color, alpha is ignored)
   // and is inserted into group 'Material'.
   rebar.TwAddVarRW("Diffuse", TW_TYPE_COLOR3F, &g_MatDiffuse, " group='Material' ");
-  
+
   // Add the enum variable 'g_CurrentShape' to 'bar'
   // (before adding an enum variable, its enum type must be declared to AntTweakBar as follow)
   {
@@ -351,7 +351,7 @@ int main(int argc, char *argv[])
     // add 'g_CurrentShape' to 'bar': this is a variable of type ShapeType. Its key shortcuts are [<] and [>].
     rebar.TwAddVarRW("Shape", shapeType, &g_CurrentShape, " keyIncr='<' keyDecr='>' help='Change object shape.' ");
   }
-  
+
   // Store time
   g_RotateTime = glutGet(GLUT_ELAPSED_TIME);
   // Init rotation
@@ -373,10 +373,10 @@ int main(int argc, char *argv[])
   {
     printf("%s ReAntTweakBar file does not exist (yet).\n",REBAR_NAME);
   }
-  
+
   // Call the GLUT main loop
   glutMainLoop();
-  
+
   return 0;
 }
 

+ 14 - 6
examples/pathinfo/example.cpp

@@ -1,5 +1,6 @@
 #define VERBOSE
 #include <igl/pathinfo.h>
+#include <igl/C_STR.h>
 using namespace igl;
 #include <string>
 #include <cstdio>
@@ -16,16 +17,23 @@ int main(int argc, char * argv[])
     return 1;
   }
 
+  const char * format = "%-25s | %-10s %-10s %-10s %-10s\n";
+  printf(format,
+    "input",
+    "dirname",
+    "basename",
+    "extension",
+    "filename");
   string line;
   while( getline(fin, line) )
   {
     string dirname,basename,extension,filename;
     pathinfo(line,dirname,basename,extension,filename);
-    printf("%s -> %s,%s,%s,%s\n",
-      line.c_str(),
-      dirname.c_str(),
-      basename.c_str(),
-      extension.c_str(),
-      filename.c_str());
+    printf(format,
+      C_STR("\""<<line<<"\""),
+      C_STR("\""<<dirname<<"\""),
+      C_STR("\""<<basename<<"\""),
+      C_STR("\""<<extension<<"\""),
+      C_STR("\""<<filename<<"\""));
   }
 }

+ 33 - 0
examples/transparency/Makefile

@@ -0,0 +1,33 @@
+
+.PHONY: all
+
+# Shared flags etc.
+include ../../Makefile.conf
+
+all: example
+
+.PHONY: example
+
+LIBIGL=../../
+LIBIGL_INC=-I$(LIBIGL)/include
+LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglmatlab -liglembree
+
+EIGEN3_INC=-I/opt/local/include/eigen3 -I/opt/local/include/eigen3/unsupported
+
+ANTTWEAKBAR_INC=-I$(LIBIGL)/external/AntTweakBar/include
+ANTTWEAKBAR_LIB=-L$(LIBIGL)/external/AntTweakBar/lib -lAntTweakBar -framework AppKit
+
+MATLAB_INC=-I$(MATLAB)/extern/include/
+MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -lmat -lmex -lstdc++
+
+INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC) $(MATLAB_INC)
+LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB) $(MATLAB_LIB)
+
+example: example.o
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example example.o $(LIB)
+
+example.o: example.cpp
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c example.cpp -o example.o $(INC)
+clean:
+	rm -f example.o
+	rm -f example

+ 344 - 0
examples/transparency/example.cpp

@@ -0,0 +1,344 @@
+#include <igl/OpenGL_convenience.h>
+#include <igl/per_face_normals.h>
+#include <igl/read.h>
+#include <igl/normalize_row_lengths.h>
+#include <igl/draw_mesh.h>
+#include <igl/jet.h>
+#include <igl/material_colors.h>
+#include <igl/draw_floor.h>
+#include <igl/unproject.h>
+#include <igl/quat_to_mat.h>
+#include <igl/trackball.h>
+#include <igl/report_gl_error.h>
+#include <igl/matlab_format.h>
+#include <igl/sort_triangles.h>
+#include <igl/colon.h>
+#include <igl/slice.h>
+#include <igl/report_gl_error.h>
+#include <igl/ReAntTweakBar.h>
+#include <igl/EPS.h>
+
+#ifdef __APPLE__
+#  include <GLUT/glut.h>
+#else
+#  include <GL/glut.h>
+#endif
+#include <Eigen/Core>
+
+#include <vector>
+#include <iostream>
+
+// Width and height of window
+int width,height;
+// Rotation of scene
+float scene_rot[4] = {0,0,0,1};
+// information at mouse down
+float down_scene_rot[4] = {0,0,0,1};
+bool trackball_on = false;
+int down_mouse_x,down_mouse_y;
+// Position of light
+float light_pos[4] = {0.1,0.1,-0.9,0};
+// Vertex positions, normals, colors and centroid
+Eigen::MatrixXd V,N,sorted_N,C,mid;
+Eigen::VectorXi I;
+// Bounding box diagonal length
+double bbd;
+// Faces
+Eigen::MatrixXi F,sorted_F;
+// alpha
+double alpha = 0.2;
+
+#define REBAR_NAME "temp.rbr"
+igl::ReTwBar rebar; // Pointer to the tweak bar
+
+void reshape(int width,int height)
+{
+  using namespace std;
+  // Save width and height
+  ::width = width;
+  ::height = height;
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glViewport(0,0,width,height);
+}
+
+// Set up double-sided lights
+void lights()
+{
+  using namespace std;
+  glEnable(GL_LIGHTING);
+  glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_LIGHT1);
+  float ones[4] = {1.0,1.0,1.0,1.0};
+  float zeros[4] = {0.0,0.0,0.0,0.0};
+  float pos[4];
+  copy(light_pos,light_pos+4,pos);
+  glLightfv(GL_LIGHT0,GL_AMBIENT,zeros);
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,ones);
+  glLightfv(GL_LIGHT0,GL_SPECULAR,zeros);
+  glLightfv(GL_LIGHT0,GL_POSITION,pos);
+  pos[0] *= -1;
+  pos[1] *= -1;
+  pos[2] *= -1;
+  glLightfv(GL_LIGHT1,GL_AMBIENT,zeros);
+  glLightfv(GL_LIGHT1,GL_DIFFUSE,ones);
+  glLightfv(GL_LIGHT1,GL_SPECULAR,zeros);
+  glLightfv(GL_LIGHT1,GL_POSITION,pos);
+}
+
+// Set up projection and model view of scene
+void push_scene()
+{
+  using namespace igl;
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  gluPerspective(45,(double)width/(double)height,1e-2,20);
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+  gluLookAt(0,0,3,0,0,0,0,1,0);
+  glPushMatrix();
+  float mat[4*4];
+  quat_to_mat(scene_rot,mat);
+  glMultMatrixf(mat);
+}
+
+void pop_scene()
+{
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+  glPopMatrix();
+}
+
+// Scale and shift for object
+void push_object()
+{
+  glPushMatrix();
+  glScaled(2./bbd,2./bbd,2./bbd);
+  glTranslated(-mid(0,0),-mid(0,1),-mid(0,2));
+}
+
+void pop_object()
+{
+  glPopMatrix();
+}
+
+void init_C(const Eigen::MatrixXi & F)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  C.resize(F.rows(),3);
+  for(int c = 0;c<F.rows();c++)
+  {
+    C(c,0) = C(c,1) = C(c,2) = (double)c/F.rows();
+    //jet((double)c/F.rows(),C(c,0),C(c,1),C(c,2));
+  }
+}
+
+void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  switch(glutState)
+  {
+    case 1:
+      // up
+      glutSetCursor(GLUT_CURSOR_INHERIT);
+      trackball_on = false;
+      // sort!
+      push_scene();
+      push_object();
+      sort_triangles(V,F,sorted_F,I);
+      slice(N,I,1,sorted_N);
+      init_C(I);
+      pop_object();
+      pop_scene();
+      break;
+    case 0:
+      // down
+      glutSetCursor(GLUT_CURSOR_CYCLE);
+      // collect information for trackball
+      trackball_on = true;
+      copy(scene_rot,scene_rot+4,down_scene_rot);
+      down_mouse_x = mouse_x;
+      down_mouse_y = mouse_y;
+    break;
+  }
+}
+
+const float BG[4] = {190.0/255.0,190.0/255.0,190.0/255.0,0};
+void display()
+{
+  if(sorted_F.size() != F.size())
+  {
+    mouse(0,1,-1,-1);
+  }
+  //using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  glClearColor(BG[0],BG[1],BG[2],0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  // All smooth points
+  glEnable( GL_POINT_SMOOTH );
+
+  lights();
+  push_scene();
+  glEnable(GL_DEPTH_TEST);
+  glDepthFunc(GL_LEQUAL);
+  glEnable(GL_NORMALIZE);
+
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  //glEnable(GL_CULL_FACE);
+  //glCullFace(GL_BACK);
+
+  // Draw a nice floor
+  push_object();
+  glEnable(GL_LIGHTING);
+  glTranslated(0,V.col(1).minCoeff(),0);
+  glScaled(2*bbd,2*bbd,2*bbd);
+  glTranslated(0,-1000*FLOAT_EPS,0);
+  glEnable(GL_CULL_FACE);
+  glCullFace(GL_BACK);
+  draw_floor();
+  pop_object();
+
+  glDisable(GL_CULL_FACE);
+  if(trackball_on)
+  {
+    glEnable(GL_COLOR_MATERIAL);
+    glDisable(GL_LIGHTING);
+  }else
+  {
+    float front[4];
+    copy(GOLD_DIFFUSE,GOLD_DIFFUSE+3,front);
+    float back[4];
+    //copy(FAST_GREEN_DIFFUSE,FAST_GREEN_DIFFUSE+3,back);
+    copy(GOLD_DIFFUSE,GOLD_DIFFUSE+3,back);
+    float amb[4];
+    copy(SILVER_AMBIENT,SILVER_AMBIENT+3,amb);
+    float spec[4];
+    copy(SILVER_SPECULAR,SILVER_SPECULAR+3,spec);
+    front[3] = back[3] = amb[3] = spec[3] = alpha;
+    // Set material properties
+    glDisable(GL_COLOR_MATERIAL);
+    glMaterialfv(GL_FRONT, GL_AMBIENT,  amb);
+    glMaterialfv(GL_FRONT, GL_DIFFUSE,  front);
+    glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
+    glMaterialf (GL_FRONT, GL_SHININESS, 128);
+    glMaterialfv(GL_BACK, GL_AMBIENT,  amb);
+    glMaterialfv(GL_BACK, GL_DIFFUSE,  back);
+    glMaterialfv(GL_BACK, GL_SPECULAR, spec);
+    glMaterialf (GL_BACK, GL_SHININESS, 128);
+    glEnable(GL_LIGHTING);
+  }
+
+  push_object();
+  // Draw the model
+  draw_mesh(V,sorted_F,sorted_N,C);
+  pop_object();
+
+  pop_scene();
+
+  report_gl_error();
+  glutSwapBuffers();
+  glutPostRedisplay();
+}
+
+
+void mouse_drag(int mouse_x, int mouse_y)
+{
+  using namespace igl;
+
+  if(trackball_on)
+  {
+    // Rotate according to trackball
+    trackball<float>(
+      width,
+      height,
+      2,
+      down_scene_rot,
+      down_mouse_x,
+      down_mouse_y,
+      mouse_x,
+      mouse_y,
+      scene_rot);
+  }
+}
+
+void key(unsigned char key, int mouse_x, int mouse_y)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  switch(key)
+  {
+    // Ctrl-c and esc exit
+    case char(3):
+    case char(27):
+      rebar.save(REBAR_NAME);
+      exit(0);
+    default:
+      cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+  }
+
+}
+
+int main(int argc, char * argv[])
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+
+  // init mesh
+  string filename = "/usr/local/igl/libigl/examples/shared/decimated-knight.obj" ;
+  if(argc > 1)
+  {
+    filename = argv[1];
+  }
+  if(!read(filename,V,F))
+  {
+    return 1;
+  }
+
+  // Compute normals, centroid, colors, bounding box diagonal
+  per_face_normals(V,F,N);
+  normalize_row_lengths(N,N);
+  mid = 0.5*(V.colwise().maxCoeff() + V.colwise().minCoeff());
+  bbd =
+    (V.colwise().maxCoeff() -
+    V.colwise().minCoeff()).maxCoeff();
+
+  // Init glut
+  glutInit(&argc,argv);
+
+  if( !TwInit(TW_OPENGL, NULL) )
+  {
+    // A fatal error occured
+    fprintf(stderr, "AntTweakBar initialization failed: %s\n", TwGetLastError());
+    return 1;
+  }
+  // Create a tweak bar
+  rebar.TwNewBar("TweakBar");
+  rebar.TwAddVarRW("scene_rot", TW_TYPE_QUAT4F, &scene_rot, "");
+  rebar.load(REBAR_NAME);
+
+  glutInitDisplayString( "rgba depth double samples>=8 ");
+  glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT));
+  glutCreateWindow("sorted primitives transparency");
+  glutDisplayFunc(display);
+  glutReshapeFunc(reshape);
+  glutKeyboardFunc(key);
+  glutMouseFunc(mouse);
+  glutMotionFunc(mouse_drag);
+
+  glutMainLoop();
+
+  return 0;
+}

+ 57 - 0
include/igl/Viewport.h

@@ -0,0 +1,57 @@
+#ifndef IGL_VIEWPORT_H
+#define IGL_VIEWPORT_H
+
+#include "Camera.h"
+
+namespace igl
+{
+  struct Viewport
+  {
+    int x,y,width,height;
+    igl::Camera camera;
+    // Constructors
+    Viewport():
+      x(0),y(0),width(0),height(0),camera(){};
+    Viewport(
+      const int x, 
+      const int y, 
+      const int width,
+      const int height, 
+      const igl::Camera & camera):
+      x(x),
+      y(y),
+      width(width),
+      height(height),
+      camera(camera)
+    {
+    };
+    void reshape(
+      const int x, 
+      const int y, 
+      const int width,
+      const int height)
+    {
+      this->x = x;
+      this->y = y;
+      this->width = width;
+      this->height = height;
+    };
+    // Inputs:
+    //   my  mouse y-coordinate
+    //   wh  window weight
+    // Returns y-coordinate in viewport
+    int mouse_y(const int my,const int wh)
+    {
+      return my - (wh - height - y);
+    }
+    // Inputs:
+    //   mx  mouse x-coordinate
+    // Returns x-coordinate in viewport
+    int mouse_x(const int mx)
+    {
+      return mx - x;
+    }
+  };
+}
+
+#endif

+ 14 - 3
include/igl/barycenter.cpp

@@ -1,9 +1,13 @@
 #include "barycenter.h"
 
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedBC>
 IGL_INLINE void igl::barycenter(
-  const Eigen::MatrixXd & V,
-  const Eigen::MatrixXi & F,
-  Eigen::MatrixXd & BC)
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedBC> & BC)
 {
   BC.setZero(F.rows(),V.cols());
   // Loop over faces
@@ -19,3 +23,10 @@ IGL_INLINE void igl::barycenter(
     BC.row(i) /= double(F.cols());
   }
 }
+
+#ifndef IGL_HEADER_ONLY
+// Explicit instanciation
+template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(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, 4, 0, -1, 4> >&);
+template void igl::barycenter<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&);
+template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::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, 3, 0, -1, 3> >&);
+#endif

+ 7 - 3
include/igl/barycenter.h

@@ -15,10 +15,14 @@ namespace igl
   //   F #F x simplex_size  matrix of indices of triangle corners
   // Output:
   //   BC a #F x dim matrix of 3d vertices
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedBC>
   IGL_INLINE void barycenter(
-      const Eigen::MatrixXd & V,
-      const Eigen::MatrixXi & F,
-      Eigen::MatrixXd & BC);
+      const Eigen::PlainObjectBase<DerivedV> & V,
+      const Eigen::PlainObjectBase<DerivedF> & F,
+      Eigen::PlainObjectBase<DerivedBC> & BC);
 }
 
 #ifdef IGL_HEADER_ONLY

+ 29 - 29
include/igl/canonical_quaternions.h

@@ -20,35 +20,35 @@ namespace igl
   const float YZ_PLANE_QUAT_F[4] = {-0.5,-0.5,-0.5,0.5};
   const float CANONICAL_VIEW_QUAT_F[][4] = 
     {
-      {             0,             0,             0,             1},
-      {             0,             0, SQRT_2_OVER_2, SQRT_2_OVER_2},
-      {             0,             0,             1,             0},
-      {             0,             0, SQRT_2_OVER_2,-SQRT_2_OVER_2},
-  
-      {             0,            -1,             0,             0},
-      {-SQRT_2_OVER_2, SQRT_2_OVER_2,             0,             0},
-      {            -1,             0,             0,             0},
-      {-SQRT_2_OVER_2,-SQRT_2_OVER_2,             0,             0},
-  
-      {          -0.5,          -0.5,          -0.5,           0.5},
-      {             0,-SQRT_2_OVER_2,             0, SQRT_2_OVER_2},
-      {           0.5,          -0.5,           0.5,           0.5},
-      { SQRT_2_OVER_2,             0, SQRT_2_OVER_2,             0},
-  
-      { SQRT_2_OVER_2,             0,-SQRT_2_OVER_2,             0},
-      {           0.5,           0.5,          -0.5,           0.5},
-      {             0, SQRT_2_OVER_2,             0, SQRT_2_OVER_2},
-      {          -0.5,           0.5,           0.5,           0.5},
-  
-      {             0, SQRT_2_OVER_2, SQRT_2_OVER_2,             0},
-      {          -0.5,           0.5,           0.5,          -0.5},
-      {-SQRT_2_OVER_2,             0,             0,-SQRT_2_OVER_2},
-      {          -0.5,          -0.5,          -0.5,          -0.5},
-  
-      {-SQRT_2_OVER_2,             0,             0, SQRT_2_OVER_2},
-      {          -0.5,          -0.5,           0.5,           0.5},
-      {             0,-SQRT_2_OVER_2, SQRT_2_OVER_2,             0},
-      {           0.5,          -0.5,           0.5,          -0.5}
+      {             0,             0,             0,             1}, // 0
+      {             0,             0, SQRT_2_OVER_2, SQRT_2_OVER_2}, // 1
+      {             0,             0,             1,             0}, // 2
+      {             0,             0, SQRT_2_OVER_2,-SQRT_2_OVER_2}, // 3
+
+      {             0,            -1,             0,             0}, // 4
+      {-SQRT_2_OVER_2, SQRT_2_OVER_2,             0,             0}, // 5
+      {            -1,             0,             0,             0}, // 6
+      {-SQRT_2_OVER_2,-SQRT_2_OVER_2,             0,             0}, // 7
+
+      {          -0.5,          -0.5,          -0.5,           0.5}, // 8
+      {             0,-SQRT_2_OVER_2,             0, SQRT_2_OVER_2}, // 9
+      {           0.5,          -0.5,           0.5,           0.5}, // 10
+      { SQRT_2_OVER_2,             0, SQRT_2_OVER_2,             0}, // 11
+
+      { SQRT_2_OVER_2,             0,-SQRT_2_OVER_2,             0}, // 12
+      {           0.5,           0.5,          -0.5,           0.5}, // 13
+      {             0, SQRT_2_OVER_2,             0, SQRT_2_OVER_2}, // 14
+      {          -0.5,           0.5,           0.5,           0.5}, // 15
+
+      {             0, SQRT_2_OVER_2, SQRT_2_OVER_2,             0}, // 16
+      {          -0.5,           0.5,           0.5,          -0.5}, // 17
+      {-SQRT_2_OVER_2,             0,             0,-SQRT_2_OVER_2}, // 18
+      {          -0.5,          -0.5,          -0.5,          -0.5}, // 19
+
+      {-SQRT_2_OVER_2,             0,             0, SQRT_2_OVER_2}, // 20
+      {          -0.5,          -0.5,           0.5,           0.5}, // 21
+      {             0,-SQRT_2_OVER_2, SQRT_2_OVER_2,             0}, // 22
+      {           0.5,          -0.5,           0.5,          -0.5}  // 23
     };
 #  undef SQRT_2_OVER_2
 

+ 20 - 0
include/igl/embree/EmbreeIntersector.h

@@ -5,8 +5,28 @@
 #undef near
 #undef far
 
+// Why are these in quotes? isn't that a bad idea?
+#ifdef __GNUC__
+// This is how it should be done
+#  if __GNUC__ >= 4
+#    if __GNUC_MINOR__ >= 6
+#      pragma GCC diagnostic push
+#      pragma GCC diagnostic ignored "-Weffc++"
+#    endif
+#  endif
+// This is a hack
+#  pragma GCC system_header
+#endif
 #include "common/intersector.h"
 #include "common/accel.h"
+#ifdef __GNUC__
+#  if __GNUC__ >= 4
+#    if __GNUC_MINOR__ >= 6
+#      pragma GCC diagnostic pop
+#    endif
+#  endif
+#endif
+
 #include <vector>
 //#include "types.h"
 

+ 4 - 0
include/igl/embree/ambient_occlusion.h

@@ -36,4 +36,8 @@ namespace igl
 
 
 };
+#ifdef IGL_HEADER_ONLY
+#  include "ambient_occlusion.cpp"
+#endif
+
 #endif

+ 1 - 0
include/igl/jet.cpp

@@ -93,4 +93,5 @@ void igl::jet(const T x, T & r, T & g, T & b)
 
 #ifndef IGL_NO_HEADER
 template void igl::jet<double>(double, double*);
+template void igl::jet<double>(double, double&, double&, double&);
 #endif

+ 3 - 0
include/igl/matlab_format.cpp

@@ -95,4 +95,7 @@ template Eigen::WithFormat<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const igl::ma
 template Eigen::WithFormat<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 template Eigen::WithFormat<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 template Eigen::WithFormat<Eigen::Array<int, -1, 1, 0, -1, 1> > const igl::matlab_format<Eigen::Array<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Array<int, -1, 1, 0, -1, 1> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+template Eigen::WithFormat<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const igl::matlab_format<Eigen::Matrix<double, 4, 4, 0, 4, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 4, 0, 4, 4> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+template Eigen::WithFormat<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const igl::matlab_format<Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
+template Eigen::WithFormat<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const igl::matlab_format<Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >);
 #endif

+ 2 - 1
include/igl/project.cpp

@@ -68,7 +68,8 @@ IGL_INLINE int igl::project(
   const Eigen::PlainObjectBase<Derivedobj> & obj,
   Eigen::PlainObjectBase<Derivedwin> & win)
 {
-  return igl::project(obj(0),obj(1),obj(2),&win(0),&win(1),&win(2));
+  return igl::project(obj(0),obj(1),obj(2),
+      &win(0),&win(1),&win(2));
 }
 
 #ifndef IGL_HEADER_ONLY

+ 1 - 0
include/igl/round.cpp

@@ -29,4 +29,5 @@ IGL_INLINE void igl::round(
 #ifndef IGL_HEADER_ONLY
 // Explicit instanciation
 template void igl::round<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<double, -1, -1, 0, -1, -1> >&);
+template void igl::round<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
 #endif

+ 5 - 4
include/igl/slice.cpp

@@ -69,12 +69,12 @@ IGL_INLINE void igl::slice(
   Y = Eigen::SparseMatrix<T>(dyn_Y);
 }
 
-template <typename T>
+template <typename Mat>
 IGL_INLINE void igl::slice(
-  const Eigen::SparseMatrix<T>& X,
+  const Mat& X,
   const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
   const int dim,
-  Eigen::SparseMatrix<T>& Y)
+  Mat& Y)
 {
   Eigen::VectorXi C;
   switch(dim)
@@ -167,5 +167,6 @@ template void igl::slice<Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainO
 // generated by autoexplicit.sh
 template void igl::slice<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::SparseMatrix<double, 0, int>&);
 template void igl::slice<Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-template void igl::slice<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::slice<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::slice<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif

+ 5 - 3
include/igl/slice.h

@@ -27,12 +27,14 @@ namespace igl
   //
   // Inputs:
   //   dim  dimension to slice in 1 or 2, dim=1 --> X(R,:), dim=2 --> X(:,R)
-  template <typename T>
+  //
+  // Note: For now this is just a cheap wrapper.
+  template <typename Mat>
   IGL_INLINE void slice(
-    const Eigen::SparseMatrix<T>& X,
+    const Mat& X,
     const Eigen::Matrix<int,Eigen::Dynamic,1> & R,
     const int dim,
-    Eigen::SparseMatrix<T>& Y);
+    Mat& Y);
 
   template <typename DerivedX>
   IGL_INLINE void slice(

+ 2 - 0
include/igl/sort.cpp

@@ -214,4 +214,6 @@ template void igl::sort<SortableRow<Eigen::Matrix<double, -1, 1, 0, -1, 1> > >(s
 template void igl::sort2<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&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort2<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&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort_new<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&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::sort<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&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::sort<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 153 - 0
include/igl/sort_triangles.cpp

@@ -0,0 +1,153 @@
+#include "sort_triangles.h"
+#include "barycenter.h"
+#include "sort.h"
+#include "sortrows.h"
+#include "slice.h"
+#include "round.h"
+#include "colon.h"
+#include "matlab_format.h"
+#include "OpenGL_convenience.h"
+
+#include <iostream>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedMV,
+  typename DerivedP,
+  typename DerivedFF,
+  typename DerivedI>
+IGL_INLINE void igl::sort_triangles(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const Eigen::PlainObjectBase<DerivedMV> & MV,
+  const Eigen::PlainObjectBase<DerivedP> & P,
+  Eigen::PlainObjectBase<DerivedFF> & FF,
+  Eigen::PlainObjectBase<DerivedI> & I)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+
+
+  // Barycenter, centroid
+  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
+  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> BC,PBC;
+  barycenter(V,F,BC);
+  D = BC*(MV.transpose()*P.transpose().eval().col(2));
+  sort(D,1,false,sD,I);
+
+  //// Closest corner
+  //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
+  //D.setConstant(F.rows(),1,-1e26);
+  //for(int c = 0;c<3;c++)
+  //{
+  //  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
+  //  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> DC;
+  //  C.resize(F.rows(),4);
+  //  for(int f = 0;f<F.rows();f++)
+  //  {
+  //    C(f,0) = V(F(f,c),0);
+  //    C(f,1) = V(F(f,c),1);
+  //    C(f,2) = V(F(f,c),2);
+  //    C(f,3) = 1;
+  //  }
+  //  DC = C*(MV.transpose()*P.transpose().eval().col(2));
+  //  D = (DC.array()>D.array()).select(DC,D).eval();
+  //}
+  //sort(D,1,false,sD,I);
+
+  //// Closest corner with tie breaks
+  //Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,3> D,sD,ssD;
+  //D.resize(F.rows(),3);
+  //for(int c = 0;c<3;c++)
+  //{
+  //  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,4> C;
+  //  C.resize(F.rows(),4);
+  //  for(int f = 0;f<F.rows();f++)
+  //  {
+  //    C(f,0) = V(F(f,c),0);
+  //    C(f,1) = V(F(f,c),1);
+  //    C(f,2) = V(F(f,c),2);
+  //    C(f,3) = 1;
+  //  }
+  //  D.col(c) = C*(MV.transpose()*P.transpose().eval().col(2));
+  //}
+  //VectorXi _;
+  //sort(D,2,false,sD,_);
+  //sortrows(sD,false,ssD,I);
+
+
+  slice(F,I,1,FF);
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedFF,
+  typename DerivedI>
+void igl::sort_triangles(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedFF> & FF,
+  Eigen::PlainObjectBase<DerivedI> & I)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  // Put model, projection, and viewport matrices into double arrays
+  Matrix4d MV;
+  Matrix4d P;
+  glGetDoublev(GL_MODELVIEW_MATRIX,  MV.data());
+  glGetDoublev(GL_PROJECTION_MATRIX, P.data());
+  if(V.cols() == 3)
+  {
+    Matrix<typename DerivedV::Scalar, DerivedV::RowsAtCompileTime,4> hV;
+    hV.resize(V.rows(),4);
+    hV.block(0,0,V.rows(),V.cols()) = V;
+    hV.col(3).setConstant(1);
+    return sort_triangles(hV,F,MV,P,FF,I);
+  }else
+  {
+    return sort_triangles(V,F,MV,P,FF,I);
+  }
+}
+
+
+#include "project.h"
+#include <iostream>
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedFF,
+  typename DerivedI>
+void igl::sort_triangles_slow(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DerivedFF> & FF,
+  Eigen::PlainObjectBase<DerivedI> & I)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  // Barycenter, centroid
+  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,1> D,sD;
+  Eigen::Matrix<typename DerivedV::Scalar, DerivedF::RowsAtCompileTime,3> BC;
+  D.resize(F.rows(),3);
+  barycenter(V,F,BC);
+  for(int f = 0;f<F.rows();f++)
+  {
+    Eigen::Matrix<typename DerivedV::Scalar, 3,1> bc,pbc;
+    bc = BC.row(f);
+    project(bc,pbc);
+    D(f) = pbc(2);
+  }
+  sort(D,1,false,sD,I);
+  slice(F,I,1,FF);
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template instanciation
+template void igl::sort_triangles<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::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::sort_triangles_slow<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::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> >&);
+#endif

+ 57 - 0
include/igl/sort_triangles.h

@@ -0,0 +1,57 @@
+#ifndef IGL_SORT_TRIANGLES_H
+#define IGL_SORT_TRIANGLES_H
+
+#include "igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  // Inputs:
+  //   V  #V by **4** list of homogeneous vertex positions
+  //   F  #F by 3 list of triangle indices
+  //   MV  4 by 4 model view matrix
+  //   P  4 by 4 projection matrix
+  // Outputs:
+  //   FF  #F by 3 list of sorted triangles indices
+  //   I  #F list of sorted indices
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedMV,
+    typename DerivedP,
+    typename DerivedFF,
+    typename DerivedI>
+  IGL_INLINE void sort_triangles(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const Eigen::PlainObjectBase<DerivedMV> & MV,
+    const Eigen::PlainObjectBase<DerivedP> & P,
+    Eigen::PlainObjectBase<DerivedFF> & FF,
+    Eigen::PlainObjectBase<DerivedI> & I);
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedFF,
+    typename DerivedI>
+  IGL_INLINE void sort_triangles(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedFF> & FF,
+    Eigen::PlainObjectBase<DerivedI> & I);
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedFF,
+    typename DerivedI>
+  IGL_INLINE void sort_triangles_slow(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    Eigen::PlainObjectBase<DerivedFF> & FF,
+    Eigen::PlainObjectBase<DerivedI> & I);
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "sort_triangles.cpp"
+#endif
+
+#endif

+ 2 - 0
include/igl/sortrows.cpp

@@ -77,4 +77,6 @@ IGL_INLINE void igl::sortrows(
 template void igl::sortrows<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::sortrows<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::sortrows<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::sortrows<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif