Browse Source

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

Conflicts:
	build/Makefile.conf
	include/igl/embree/EmbreeIntersector.h
	include/igl/png/render_to_png.cpp

Former-commit-id: deeb0d77a6b67d89514d518c941d0924d8fb0d96
Olga Diamanti 10 years ago
parent
commit
c23bfdc50e
67 changed files with 892 additions and 362 deletions
  1. 21 0
      README.md
  2. 14 14
      build/Makefile.conf
  3. 19 29
      examples/camera/example.cpp
  4. 21 0
      examples/convertmesh/Makefile
  5. 31 0
      examples/convertmesh/convertmesh.cpp
  6. 0 7
      examples/patches/temp.rbr
  7. 48 32
      examples/quicklook-mesh/Info.plist
  8. 2 0
      examples/quicklook-mesh/Makefile
  9. 5 5
      examples/skeleton-builder/Makefile
  10. 5 5
      examples/skeleton-poser/Makefile
  11. 0 0
      examples/skeleton-poser/example.cpp
  12. 1 1
      file-formats/index.html
  13. 1 1
      include/igl/C_STR.h
  14. 30 49
      include/igl/Camera.h
  15. 1 1
      include/igl/STR.h
  16. 9 6
      include/igl/angles.h
  17. 1 1
      include/igl/basename.h
  18. 2 0
      include/igl/boundary_facets.cpp
  19. 5 2
      include/igl/cgal/CGAL_includes.hpp
  20. 58 7
      include/igl/cgal/SelfIntersectMesh.h
  21. 2 0
      include/igl/compile_shader.h
  22. 56 10
      include/igl/create_shader_program.cpp
  23. 20 3
      include/igl/create_shader_program.h
  24. 21 0
      include/igl/deprecated.h
  25. 1 1
      include/igl/dirname.h
  26. 51 50
      include/igl/embree/EmbreeIntersector.h
  27. 13 15
      include/igl/embree/unproject_in_mesh.cpp
  28. 4 1
      include/igl/embree/unproject_in_mesh.h
  29. 2 0
      include/igl/face_occurrences.cpp
  30. 28 0
      include/igl/hsv_to_rgb.cpp
  31. 5 0
      include/igl/hsv_to_rgb.h
  32. 46 0
      include/igl/init_render_to_texture.cpp
  33. 28 0
      include/igl/init_render_to_texture.h
  34. 1 1
      include/igl/is_boundary_edge.cpp
  35. 1 0
      include/igl/jet.cpp
  36. 6 0
      include/igl/list_to_matrix.cpp
  37. 2 0
      include/igl/max_size.cpp
  38. 2 0
      include/igl/min_size.cpp
  39. 21 0
      include/igl/mod.cpp
  40. 30 0
      include/igl/mod.h
  41. 12 1
      include/igl/outer_hull.cpp
  42. 2 0
      include/igl/polygon_mesh_to_triangle_mesh.cpp
  43. 1 0
      include/igl/random_quaternion.cpp
  44. 2 0
      include/igl/readMESH.cpp
  45. 5 0
      include/igl/readOBJ.cpp
  46. 5 2
      include/igl/readOBJ.h
  47. 2 0
      include/igl/readSTL.cpp
  48. 1 0
      include/igl/read_triangle_mesh.cpp
  49. 1 0
      include/igl/read_triangle_mesh.h
  50. 25 0
      include/igl/rgb_to_hsv.cpp
  51. 6 1
      include/igl/rgb_to_hsv.h
  52. 0 11
      include/igl/viewer/Viewer.cpp
  53. 22 39
      include/igl/writeOBJ.cpp
  54. 11 8
      include/igl/writeOBJ.h
  55. 12 27
      include/igl/writeOFF.cpp
  56. 4 0
      include/igl/writeSTL.cpp
  57. 51 0
      include/igl/writeWRL.cpp
  58. 24 0
      include/igl/writeWRL.h
  59. 42 17
      include/igl/write_triangle_mesh.cpp
  60. 16 6
      include/igl/write_triangle_mesh.h
  61. 22 0
      index.html
  62. 1 1
      tutorial/203_CurvatureDirections/main.cpp
  63. 1 1
      tutorial/CMakeLists.shared
  64. 7 5
      tutorial/cmake/FindLIBIGL.cmake
  65. 1 0
      tutorial/style.css
  66. 1 1
      tutorial/tutorial.html.REMOVED.git-id
  67. 1 1
      tutorial/tutorial.md.REMOVED.git-id

+ 21 - 0
README.md

@@ -143,6 +143,27 @@ BibTeX entry:
 }
 ```
 
+## Projects/Universities using libigl
+
+ - [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
+ - Columbia University, [Columbia Computer Graphics Group](http://www.cs.columbia.edu/cg/), USA
+ - [Cornell University](http://www.graphics.cornell.edu/), USA
+ - EPF Lausanne, [Computer Graphics and Geometry Laboratory](http://lgg.epfl.ch/people.php), Switzerland
+ - ETH Zurich, [Interactive Geometry Lab](http://igl.ethz.ch/) and [Advanced Technologies Lab](http://ait.inf.ethz.ch/), Swizterland
+ - George Mason University, [CraGL](http://cs.gmu.edu/~ygingold/), USA
+ - [Hong Kong University of Science and Technology](http://www.ust.hk/), USA
+ - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan 
+ - New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
+ - NYUPoly, [Game Innovation Lab](http://game.engineering.nyu.edu/), USA
+ - [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France
+ - [TU Delft](http://www.tudelft.nl/en/), Netherlands
+ - [Universidade Federal de Santa Catarina](http://mtm.ufsc.br/~leo/), Brazil
+ - [Università della Svizzera Italiana](http://www.usi.ch/en), Switzerland
+ - [University College London](http://vecg.cs.ucl.ac.uk/), England
+ - [University of Cambridge](http://www.cam.ac.uk/), England
+ - [University of Pennsylvania](http://cg.cis.upenn.edu/), USA
+
+
 ## Contact
 
 Libigl is a group endeavor led by [Alec

+ 14 - 14
build/Makefile.conf

@@ -116,9 +116,9 @@ endif
 
 ifeq ($(IGL_USERNAME),olkido)
     IGL_WITH_MATLAB=1
-		IGL_WITH_COMISO=1
-		IGL_WITH_XML=1
-		COMISO=/Users/olkido/Documents/igl/MIQ/src/CoMISo
+	IGL_WITH_COMISO=1
+	IGL_WITH_XML=1
+	COMISO=/Users/olkido/Documents/igl/MIQ/src/CoMISo
 	  IGL_WITH_XML=1
     AFLAGS= -m64
     IGL_WITH_EMBREE=1
@@ -223,24 +223,24 @@ ifndef ANTTWEAKBAR_LIB
 endif
 
 ifndef SINGULAR_VALUE_DECOMPOSITION_INC
-				SINGULAR_VALUE_DECOMPOSITION_INC=\
-				-I$(LIBIGL)/external/Singular_Value_Decomposition/
+	SINGULAR_VALUE_DECOMPOSITION_INC=\
+	-I$(LIBIGL)/external/Singular_Value_Decomposition/
 endif
 
 ifndef TETGEN
 # By default I'm using the libigl version. Adjust accordingly
-				TETGEN=$(LIBIGL)/external/tetgen
-				TETGEN_LIB=-L$(TETGEN) -ligltetgen -ltet 
-				TETGEN_INC=-I$(TETGEN)
+	TETGEN=$(LIBIGL)/external/tetgen
+	TETGEN_LIB=-L$(TETGEN) -ligltetgen -ltet
+	TETGEN_INC=-I$(TETGEN)
 endif
 
 ifndef EMBREE
-				EMBREE=$(LIBIGL)/external/embree
-				EMBREE_INC=-I$(EMBREE)/ -I$(EMBREE)/include
-				EMBREE_LIB=-L$(EMBREE)/build -lembree -lsys
+	EMBREE=$(LIBIGL)/external/embree
+	EMBREE_INC=-I$(EMBREE)/ -I$(EMBREE)/include
+	EMBREE_LIB=-L$(EMBREE)/build -lembree -lsys
 endif
 ifndef YIMG
-				YIMG=$(LIBIGL)/external/yimg
-				YIMG_LIB=-L$(YIMG) -lyimg -lz -L/usr/X11/lib -L$(DEFAULT_PREFIX)/lib -lpng -bind_at_load
-				YIMG_INC=-I/usr/X11/include -I$(YIMG) 
+	YIMG=$(LIBIGL)/external/yimg
+	YIMG_LIB=-L$(YIMG) -lyimg -lz -L/usr/X11/lib -L$(DEFAULT_PREFIX)/lib -lpng -bind_at_load
+	YIMG_INC=-I/usr/X11/include -I$(YIMG)
 endif

+ 19 - 29
examples/camera/example.cpp

@@ -14,6 +14,8 @@
 #include <igl/readOFF.h>
 #include <igl/per_face_normals.h>
 #include <igl/draw_floor.h>
+#include <igl/project.h>
+#include <igl/unproject.h>
 
 #include <Eigen/Core>
 #include <Eigen/Geometry>
@@ -229,26 +231,6 @@ void draw_scene(const igl::Camera & v_camera,
 
   glMatrixMode(GL_PROJECTION);
   glPushMatrix();
-  glLoadIdentity();
-  if(v_camera.m_angle > IGL_CAMERA_MIN_ANGLE)
-  {
-    gluPerspective(v_camera.m_angle,v_camera.m_aspect,v_camera.m_near,v_camera.m_far);
-  }else
-  {
-    glOrtho(
-      -0.5*v_camera.m_aspect,
-      0.5*v_camera.m_aspect,
-      -0.5,
-      0.5,
-      v_camera.m_near,
-      v_camera.m_far);
-  }
-  //{
-  //  Matrix4d m;
-  //  glGetDoublev(GL_PROJECTION_MATRIX,m.data());
-  //  cout<<matlab_format(m,"glu")<<endl;
-  //}
-
   glLoadIdentity();
   glMultMatrixd(v_camera.projection().data());
   //{
@@ -258,14 +240,13 @@ void draw_scene(const igl::Camera & v_camera,
   //}
   glMatrixMode(GL_MODELVIEW);
   glPushMatrix();
-  //glLoadIdentity();
-  //gluLookAt(
-  //  v_camera.eye()(0), v_camera.eye()(1), v_camera.eye()(2),
-  //  v_camera.at()(0), v_camera.at()(1), v_camera.at()(2),
-  //  v_camera.up()(0), v_camera.up()(1), v_camera.up()(2));
   glLoadIdentity();
-  glMultMatrixd(v_camera.inverse().matrix().data());
-
+  gluLookAt(
+    v_camera.eye()(0), v_camera.eye()(1), v_camera.eye()(2),
+    v_camera.at()(0), v_camera.at()(1), v_camera.at()(2),
+    v_camera.up()(0), v_camera.up()(1), v_camera.up()(2));
+  //glLoadIdentity();
+  //glMultMatrixd(v_camera.inverse().matrix().data());
 
   for(int c = 0;c<(int)s.cameras.size();c++)
   {
@@ -431,7 +412,6 @@ void display()
 
   TwDraw();
   glutSwapBuffers();
-  glutPostRedisplay();
 }
 
 
@@ -475,6 +455,7 @@ void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
       camera.dolly((wheel==0?Vector3d(0,0,1):Vector3d(-1,0,0))*0.1*direction);
       break;
   }
+  glutPostRedisplay();
 }
 
 void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
@@ -509,6 +490,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
         break;
       }
       break;
+    }
 #ifdef GLUT_WHEEL_DOWN
     // Scroll down
     case GLUT_WHEEL_DOWN:
@@ -541,8 +523,8 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       break;
     }
 #endif
-    }
   }
+  glutPostRedisplay();
 }
 
 void mouse_drag(int mouse_x, int mouse_y)
@@ -595,6 +577,7 @@ void mouse_drag(int mouse_x, int mouse_y)
         break;
     }
   }
+  glutPostRedisplay();
 }
 
 void key(unsigned char key, int mouse_x, int mouse_y)
@@ -609,6 +592,12 @@ void key(unsigned char key, int mouse_x, int mouse_y)
     // ^C
     case char(3):
       exit(0);
+    case 'o':
+    case 'O':
+      {
+        s.cameras[0].m_orthographic ^= true;
+        break;
+      }
     case 'z':
     case 'Z':
       if(mod & GLUT_ACTIVE_COMMAND)
@@ -628,6 +617,7 @@ void key(unsigned char key, int mouse_x, int mouse_y)
         cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
       }
   }
+  glutPostRedisplay();
 }
 
 int main(int argc, char * argv[])

+ 21 - 0
examples/convertmesh/Makefile

@@ -0,0 +1,21 @@
+.PHONY: all
+
+# Shared flags etc.
+include ../../build/Makefile.conf
+
+all: convertmesh
+
+.PHONY: convertmesh
+
+INC=$(LIBIGL_INC) $(EIGEN3_INC) 
+LIB=$(LIBIGL_LIB) 
+OPTFLAGS+=-O3 -DNDEBUG $(OPENMP)
+
+convertmesh: convertmesh.o
+	g++ $(OPTFLAGS) $(AFLAGS) $(CFLAGS) $(LIB) -o convertmesh convertmesh.o 
+
+convertmesh.o: convertmesh.cpp
+	g++ $(OPTFLAGS) $(AFLAGS) $(CFLAGS) -c convertmesh.cpp -o convertmesh.o $(INC)
+clean:
+	rm -f convertmesh.o
+	rm -f convertmesh

+ 31 - 0
examples/convertmesh/convertmesh.cpp

@@ -0,0 +1,31 @@
+#include <igl/read_triangle_mesh.h>
+#include <igl/write_triangle_mesh.h>
+#include <string>
+#include <iostream>
+int main(int argc, char * argv[])
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  MatrixXd V;
+  MatrixXi F;
+  string in,out;
+  switch(argc)
+  {
+    case 3:
+      in = argv[1];
+      out = argv[2];
+      break;
+    default:
+      cerr<<R"(
+USAGE:
+  convertmesh input.[mesh|obj|off|ply|stl|wrl] output.[mesh|obj|off|ply|stl|wrl]
+
+  Note: .ply and .stl outputs are binary.
+)";
+    return EXIT_FAILURE;
+  }
+  return 
+    read_triangle_mesh(in,V,F) && write_triangle_mesh(out,V,F,false) ? 
+    EXIT_SUCCESS : EXIT_FAILURE;
+}

+ 0 - 7
examples/patches/temp.rbr

@@ -1,7 +0,0 @@
-camera_rotation: TW_TYPE_QUAT4D 0.152085375459856 -0.590495112202136 -0.114509193857288 0.784266029838584
-center_type: CenterType orbit
-wireframe_visible: TW_TYPE_BOOLCPP 1
-fill_visible: TW_TYPE_BOOLCPP 1
-rotation_type: RotationType two-axis-valuator-fixed-up
-orient_method: OrientMethod ambient-occlusion
-

+ 48 - 32
examples/quicklook-mesh/Info.plist

@@ -2,6 +2,8 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>BuildMachineOSBuild</key>
+	<string>13E28</string>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>English</string>
 	<key>CFBundleDocumentTypes</key>
@@ -11,49 +13,63 @@
 			<string>QLGenerator</string>
 			<key>LSItemContentTypes</key>
 			<array>
-				<string>org.mesh</string>
-				<string>org.obj</string>
-				<string>org.off</string>
-				<string>org.ply</string>
-				<string>org.stl</string>
-				<string>org.wrl</string>
+				<string>com.mesh.mesh</string>
+				<string>com.mesh.obj</string>
+				<string>com.mesh.off</string>
+				<string>com.mesh.ply</string>
+				<string>com.mesh.stl</string>
+				<string>com.mesh.wrl</string>
 			</array>
 		</dict>
 	</array>
 	<key>CFBundleExecutable</key>
 	<string>Mesh</string>
-	<key>CFBundleIconFile</key>
-	<string></string>
 	<key>CFBundleIdentifier</key>
-	<string>org.mesh.quicklook</string>
+	<string>com.mesh.quicklook</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
 	<string>Mesh</string>
 	<key>CFBundleShortVersionString</key>
-	<string>1.1</string>
+	<string>1.0.2</string>
 	<key>CFBundleVersion</key>
-	<string>1.2</string>
+	<string>1.0</string>
 	<key>CFPlugInDynamicRegisterFunction</key>
 	<string></string>
 	<key>CFPlugInDynamicRegistration</key>
-	<false/>
+	<string>NO</string>
 	<key>CFPlugInFactories</key>
 	<dict>
-		<key>C00EB589-55DF-45ED-B4B8-8AFFA367CFCF</key>
+		<key>8D269336-626C-4F43-903F-D2F6AE5C4976</key>
 		<string>QuickLookGeneratorPluginFactory</string>
 	</dict>
 	<key>CFPlugInTypes</key>
 	<dict>
 		<key>5E2D9680-5022-40FA-B806-43349622E5B9</key>
 		<array>
-			<string>C00EB589-55DF-45ED-B4B8-8AFFA367CFCF</string>
+			<string>8D269336-626C-4F43-903F-D2F6AE5C4976</string>
 		</array>
 	</dict>
 	<key>CFPlugInUnloadFunction</key>
 	<string></string>
+	<key>DTCompiler</key>
+	<string>com.apple.compilers.llvm.clang.1_0</string>
+	<key>DTPlatformBuild</key>
+	<string>5B1008</string>
+	<key>DTPlatformVersion</key>
+	<string>GM</string>
+	<key>DTSDKBuild</key>
+	<string>13C64</string>
+	<key>DTSDKName</key>
+	<string>macosx10.9</string>
+	<key>DTXcode</key>
+	<string>0511</string>
+	<key>DTXcodeBuild</key>
+	<string>5B1008</string>
+	<key>LSApplicationCategoryType</key>
+	<string></string>
 	<key>NSHumanReadableCopyright</key>
-	<string>Copyright 2013 Alec Jacobson</string>
+	<string>Copyright © 2015 Alec Jacobson</string>
 	<key>QLNeedsToBeRunInMainThread</key>
 	<true/>
 	<key>QLPreviewHeight</key>
@@ -63,18 +79,19 @@
 	<key>QLSupportsConcurrentRequests</key>
 	<true/>
 	<key>QLThumbnailMinimumSize</key>
-	<integer>32</integer>
-	<key>UTImportedTypeDeclarations</key>
+	<integer>10</integer>
+	<key>UTExportedTypeDeclarations</key>
 	<array>
+
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>3d tetrahedral mesh</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.mesh</string>
+			<string>com.mesh.mesh</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://www.ann.jussieu.fr/frey/publications/RT-0253.pdf#page=33</string>
 			<key>UTTypeTagSpecification</key>
@@ -85,16 +102,15 @@
 				</array>
 			</dict>
 		</dict>
-
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>3D model format</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.obj</string>
+			<string>com.mesh.obj</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://en.wikipedia.org/wiki/Wavefront_.obj_file#File_format</string>
 			<key>UTTypeTagSpecification</key>
@@ -105,16 +121,15 @@
 				</array>
 			</dict>
 		</dict>
-
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>PLY 3D file</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.ply</string>
+			<string>com.mesh.ply</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://en.wikipedia.org/wiki/PLY_%28file_format%29</string>
 			<key>UTTypeTagSpecification</key>
@@ -125,16 +140,15 @@
 				</array>
 			</dict>
 		</dict>
-
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>Stereolithography CAD model</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.stl</string>
+			<string>com.mesh.stl</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://en.wikipedia.org/wiki/STL_(file_format)</string>
 			<key>UTTypeTagSpecification</key>
@@ -148,12 +162,12 @@
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>Geomview's polyhedral file format</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.off</string>
+			<string>com.mesh.off</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://tetgen.berlios.de/fformats.off.html</string>
 			<key>UTTypeTagSpecification</key>
@@ -167,12 +181,12 @@
 		<dict>
 			<key>UTTypeConformsTo</key>
 			<array>
-				<string>public.image</string>
+				<string>public.data</string>
 			</array>
 			<key>UTTypeDescription</key>
 			<string>Virtual Reality Modeling Language</string>
 			<key>UTTypeIdentifier</key>
-			<string>org.wrl</string>
+			<string>com.mesh.wrl</string>
 			<key>UTTypeReferenceURL</key>
 			<string>http://en.wikipedia.org/wiki/VRML#WRL_File_Format</string>
 			<key>UTTypeTagSpecification</key>
@@ -183,6 +197,8 @@
 				</array>
 			</dict>
 		</dict>
+
 	</array>
 </dict>
 </plist>
+

+ 2 - 0
examples/quicklook-mesh/Makefile

@@ -28,6 +28,8 @@ MESA_LIB=-L$(MESA)/lib -lOSMesa -lGL
 OBJC_LIB=-lobjc
 
 all: obj Mesh.qlgenerator
+deploy:
+	dylibbundler -od -b -x ./Mesh.qlgenerator/Contents/MacOS/Mesh -d ./Mesh.qlgenerator/Contents/libs -p @loader_path/../libs/
 install:
 	rm -rf /Library/QuickLook/Mesh.qlgenerator
 	cp -R Mesh.qlgenerator /Library/QuickLook/Mesh.qlgenerator

+ 5 - 5
examples/skeleton-builder/Makefile

@@ -4,9 +4,9 @@
 include ../../build/Makefile.conf
 LIBIGL_LIB+=-liglembree
 
-all: obj example
+all: obj skeleton_builder
 
-.PHONY: example
+.PHONY: skeleton_builder
 
 INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC) $(GLUT_INC) ${TETGEN_INC} $(MOSEK_INC) $(EMBREE_INC)
 LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB) $(TETGEN_LIB) $(MOSEK_LIB) $(EMBREE_LIB)
@@ -16,8 +16,8 @@ OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
 
 CFLAGS+=-std=c++11 -g
 
-example: obj $(OBJ_FILES)
-	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example $(LIB) $(OBJ_FILES) 
+skeleton_builder: obj $(OBJ_FILES)
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o skeleton_builder $(LIB) $(OBJ_FILES) 
 
 obj:
 	mkdir -p obj
@@ -30,4 +30,4 @@ obj/%.o: %.cpp %.h
 
 clean:
 	rm -f $(OBJ_FILES)
-	rm -f example
+	rm -f skeleton_builder

+ 5 - 5
examples/skeleton-posing/Makefile → examples/skeleton-poser/Makefile

@@ -4,9 +4,9 @@
 include ../../build/Makefile.conf
 LIBIGL_LIB+=-liglbbw -liglcgal
 
-all: obj example
+all: obj skeleton-poser
 
-.PHONY: example
+.PHONY: skeleton-poser
 
 ifdef IGL_NO_MOSEK
 CFLAGS+=-DIGL_NO_MOSEK
@@ -39,8 +39,8 @@ OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
 
 CFLAGS+=-std=c++11 -g
 
-example: obj $(OBJ_FILES)
-	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example $(LIB) $(OBJ_FILES) 
+skeleton-poser: obj $(OBJ_FILES)
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o skeleton-poser $(LIB) $(OBJ_FILES) 
 
 obj:
 	mkdir -p obj
@@ -53,4 +53,4 @@ obj/%.o: %.cpp %.h
 
 clean:
 	rm -f $(OBJ_FILES)
-	rm -f example
+	rm -f skeleton-poser

+ 0 - 0
examples/skeleton-posing/example.cpp → examples/skeleton-poser/example.cpp


+ 1 - 1
file-formats/index.html

@@ -26,7 +26,7 @@
     href=http://tetgen.berlios.de/fformats.node.html>TetGen</a>, and <a
     href=http://www.cs.berkeley.edu/~jrs/stellar/#fileformats>Stellar</a>.
     </li>
-    <li><a href="http://tetgen.berlios.de/fformats.off.html">.off</a> Geomview's polyhedral file format</li>
+    <li><a href="http://wias-berlin.de/software/tetgen/fformats.off.html">.off</a> Geomview's polyhedral file format</li>
     <li><a
     href="http://en.wikipedia.org/wiki/Wavefront_.obj_file#File_format">.obj</a>
     Wavefront object file format. Usually unsafe to assume anything more than

+ 1 - 1
include/igl/C_STR.h

@@ -14,5 +14,5 @@
 //   func(C_STR("foo"<<1<<"bar"));
 #include <sstream>
 #include <string>
-#define C_STR(X) static_cast<std::ostringstream&>(std::ostringstream().seekp(0) << X).str().c_str()
+#define C_STR(X) static_cast<std::ostringstream&>(std::ostringstream().flush() << X).str().c_str()
 #endif

+ 30 - 49
include/igl/Camera.h

@@ -35,21 +35,16 @@ namespace igl
       //  m_near  near clipping plane {1e-2}
       //  m_far  far clipping plane {100}
       //  m_at_dist  distance of looking at point {1}
+      //  m_orthographic  whether to use othrographic projection {false}
       //  m_rotation_conj  Conjugate of rotation part of rigid transformation of
       //    camera {identity}. Note: we purposefully store the conjugate because
       //    this is what TW_TYPE_QUAT4D is expecting.
       //  m_translation  Translation part of rigid transformation of camera
       //    {(0,0,1)}
       double m_angle, m_aspect, m_near, m_far, m_at_dist;
+      bool m_orthographic;
       Eigen::Quaterniond m_rotation_conj;
       Eigen::Vector3d m_translation;
-    private:
-      // m_at_dist_min_angle  m_at_dist from last time m_angle set to <= IGL_CAMERA_MIN_ANGLE
-      double m_at_dist_min_angle;
-      double m_angle_min_angle;
-    //  // m_last_positive_m_angle
-    //  // m_last_positive_m_angle_m_at_dist
-    //  double m_last_positive_m_angle,m_last_positive_m_angle_m_at_dist;
     public:
       inline Camera();
       inline virtual ~Camera(){}
@@ -154,10 +149,9 @@ namespace igl
 
 inline igl::Camera::Camera():
   m_angle(45.0),m_aspect(1),m_near(1e-2),m_far(100),m_at_dist(1),
+  m_orthographic(false),
   m_rotation_conj(1,0,0,0),
-  m_translation(0,0,1),
-  m_at_dist_min_angle(m_at_dist),
-  m_angle_min_angle(m_angle)
+  m_translation(0,0,1)
 {
 }
 
@@ -165,40 +159,36 @@ inline Eigen::Matrix4d igl::Camera::projection() const
 {
   Eigen::Matrix4d P;
   using namespace std;
+  const double far = m_at_dist + m_far;
+  const double near = m_near;
   // http://stackoverflow.com/a/3738696/148668
-  if(m_angle >= IGL_CAMERA_MIN_ANGLE)
-  {
-    const double yScale = tan(PI*0.5 - 0.5*m_angle*PI/180.);
-    // http://stackoverflow.com/a/14975139/148668
-    const double xScale = yScale/m_aspect;
-    const double far = m_at_dist + m_far;
-    const double near = m_near;
-    P<< 
-      xScale, 0, 0, 0,
-      0, yScale, 0, 0,
-      0, 0, -(far+near)/(far-near), -1,
-      0, 0, -2.*near*far/(far-near), 0;
-    P = P.transpose().eval();
-  }else
+  if(m_orthographic)
   {
     const double f = 0.5;
     const double left = -f*m_aspect;
     const double right = f*m_aspect;
     const double bottom = -f;
     const double top = f;
-    const double near = m_near;
-    const double far = m_at_dist + m_far;
     const double tx = (right+left)/(right-left);
     const double ty = (top+bottom)/(top-bottom);
     const double tz = (far+near)/(far-near);
-    const double z_fix = 
-      0.5/(m_at_dist_min_angle * tan(m_angle_min_angle/2./180.*M_PI))+
-      (-m_at_dist+m_at_dist_min_angle)/m_at_dist_min_angle;
+    const double z_fix = 0.5 /m_at_dist / tan(m_angle*0.5 * (M_PI/180.) );
     P<<
       z_fix*2./(right-left), 0, 0, -tx,
       0, z_fix*2./(top-bottom), 0, -ty,
       0, 0, -z_fix*2./(far-near),  -tz,
       0, 0, 0, 1;
+  }else
+  {
+    const double yScale = tan(PI*0.5 - 0.5*m_angle*PI/180.);
+    // http://stackoverflow.com/a/14975139/148668
+    const double xScale = yScale/m_aspect;
+    P<< 
+      xScale, 0, 0, 0,
+      0, yScale, 0, 0,
+      0, 0, -(far+near)/(far-near), -1,
+      0, 0, -2.*near*far/(far-near), 0;
+    P = P.transpose().eval();
   }
   return P;
 }
@@ -278,34 +268,25 @@ inline void igl::Camera::dolly_zoom(const double da)
   Vector3d old_at = at();
 #endif
   const double old_angle = m_angle;
-  m_angle += da;
-  m_angle = min(89.,max(0.,m_angle));
-  const double eff_angle = (IGL_CAMERA_MIN_ANGLE > m_angle ? IGL_CAMERA_MIN_ANGLE : m_angle);
-  if(old_angle >= IGL_CAMERA_MIN_ANGLE)
+  if(old_angle + da < IGL_CAMERA_MIN_ANGLE)
+  {
+    m_orthographic = true;
+  }else if(old_angle + da > IGL_CAMERA_MIN_ANGLE)
   {
+    m_orthographic = false;
+  }
+  if(!m_orthographic)
+  {
+    m_angle += da;
+    m_angle = min(89.,max(IGL_CAMERA_MIN_ANGLE,m_angle));
     // change in distance
     const double s = 
       (2.*tan(old_angle/2./180.*M_PI)) /
-      (2.*tan(eff_angle/2./180.*M_PI)) ;
+      (2.*tan(m_angle/2./180.*M_PI)) ;
     const double old_at_dist = m_at_dist;
     m_at_dist = old_at_dist * s;
     dolly(Vector3d(0,0,1)*(m_at_dist - old_at_dist));
-    if(eff_angle == IGL_CAMERA_MIN_ANGLE)
-    {
-      m_at_dist_min_angle = m_at_dist;
-      m_angle_min_angle = eff_angle;
-    }
     assert((old_at-at()).squaredNorm() < DOUBLE_EPS);
-  }else if(old_angle < IGL_CAMERA_MIN_ANGLE && m_angle >= IGL_CAMERA_MIN_ANGLE)
-  {
-    // Restore decent length
-    const double z_fix = 
-      // There should be some factor here based on the incoming angle
-      // (m_angle_min_angle) and outgoing angle (m_angle)... For now I set it
-      // to 1. (assumes equality)
-      //0.5/(m_at_dist_min_angle * tan(m_angle_min_angle/2./180.*M_PI))+
-      1.+(-m_at_dist+m_at_dist_min_angle)/m_at_dist_min_angle;
-    m_at_dist = m_at_dist_min_angle / z_fix;
   }
 }
 

+ 1 - 1
include/igl/STR.h

@@ -14,5 +14,5 @@
 //   void func(std::string c);
 // Then you can write:
 //   func(STR("foo"<<1<<"bar"));
-#define STR(X) static_cast<std::ostringstream&>(std::ostringstream().seekp(0) << X).str()
+#define STR(X) static_cast<std::ostringstream&>(std::ostringstream().flush() << X).str()
 #endif 

+ 9 - 6
include/igl/angles.h

@@ -8,13 +8,14 @@
 #ifndef IGL_ANGLES_H
 #define IGL_ANGLES_H
 #ifdef _WIN32
- #pragma message ( "Deprecated. Use igl/internal_angles.h instead" )
+#  pragma message ( "Deprecated. Use igl/internal_angles.h instead" )
 #else
- #warning "Deprecated. Use igl/internal_angles.h instead"
+#  warning "Deprecated. Use igl/internal_angles.h instead"
 #endif
 
 
 #include "igl_inline.h"
+#include "deprecated.h"
 #include <Eigen/Core>
 namespace igl
 {
@@ -30,10 +31,12 @@ namespace igl
   typename DerivedV,
   typename DerivedF,
   typename Derivedtheta>
-  IGL_INLINE void angles(
-  const Eigen::PlainObjectBase<DerivedV>& V,
-  const Eigen::PlainObjectBase<DerivedF>& F,
-  Eigen::PlainObjectBase<Derivedtheta>& theta);
+  IGL_INLINE 
+  IGL_DEPRECATED(
+    void angles(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    Eigen::PlainObjectBase<Derivedtheta>& theta));
 
 }
 

+ 1 - 1
include/igl/basename.h

@@ -13,7 +13,7 @@
 
 namespace igl
 {
-  // Function like PHP's basename
+  // Function like PHP's basename: /etc/sudoers.d --> sudoers.d
   // Input:
   //  path  string containing input path
   // Returns string containing basename (see php's basename)

+ 2 - 0
include/igl/boundary_facets.cpp

@@ -132,6 +132,8 @@ Ret igl::boundary_facets(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);

+ 5 - 2
include/igl/cgal/CGAL_includes.hpp

@@ -8,8 +8,11 @@
 #ifndef IGL_CGAL_INCLUDES_H
 #define IGL_CGAL_INCLUDES_H
 
-// http://www.alecjacobson.com/weblog/?p=4291
-#define CGAL_INTERSECTION_VERSION 1
+// This causes unknown bugs during intersection meshing:
+//// http://www.alecjacobson.com/weblog/?p=4291
+//#define CGAL_INTERSECTION_VERSION 1
+// Use this instead to mute errors resulting from bad CGAL assertions
+#define CGAL_KERNEL_NO_ASSERTIONS
 // Triangle triangle intersection
 #include <CGAL/intersections.h>
 // THIS CANNOT BE INCLUDED IN THE SAME FILE AS <CGAL/intersections.h>

+ 58 - 7
include/igl/cgal/SelfIntersectMesh.h

@@ -217,6 +217,11 @@ namespace igl
         SelfIntersectMesh * SIM, 
         const Box &a, 
         const Box &b);
+      // Annoying wrappers to conver from cgal to double or cgal
+      static inline void to_output_type(const typename Kernel::FT & cgal,double & d);
+      static inline void to_output_type(
+        const typename CGAL::Epeck::FT & cgal,
+        CGAL::Epeck::FT & d);
   };
 }
 
@@ -600,13 +605,7 @@ inline igl::SelfIntersectMesh<
       {
         const Point_3 & p = *nvit;
         // Don't convert via double if output type is same as Kernel
-        if(std::is_same<typename DerivedVV::Scalar,typename Kernel::FT>::value)
-        {
-          VV(V.rows()+i,d) = p[d];
-        }else
-        {
-          VV(V.rows()+i,d) = CGAL::to_double(p[d]);
-        }
+        to_output_type(p[d], VV(V.rows()+i,d));
       }
       i++;
     }
@@ -1213,5 +1212,57 @@ inline void igl::SelfIntersectMesh<
   }
 }
 
+template <
+  typename Kernel,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedIF,
+  typename DerivedJ,
+  typename DerivedIM>
+inline 
+void 
+igl::SelfIntersectMesh<
+  Kernel,
+  DerivedV,
+  DerivedF,
+  DerivedVV,
+  DerivedFF,
+  DerivedIF,
+  DerivedJ,
+  DerivedIM>::to_output_type(
+    const typename Kernel::FT & cgal,
+    double & d)
+{
+  d = CGAL::to_double(cgal);
+}
+
+template <
+  typename Kernel,
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedIF,
+  typename DerivedJ,
+  typename DerivedIM>
+inline 
+void 
+igl::SelfIntersectMesh<
+  Kernel,
+  DerivedV,
+  DerivedF,
+  DerivedVV,
+  DerivedFF,
+  DerivedIF,
+  DerivedJ,
+  DerivedIM>::to_output_type(
+    const typename CGAL::Epeck::FT & cgal,
+    CGAL::Epeck::FT & d)
+{
+  d = cgal;
+}
+
 #endif
 

+ 2 - 0
include/igl/compile_shader.h

@@ -18,6 +18,8 @@ namespace igl
   //     glAttachShader(prog_id,vid);
   //     glAttachShader(prog_id,fid);
   //     glLinkProgram(prog_id);
+  //
+  // Known bugs: seems to be duplicate of `load_shader`
   IGL_INLINE GLuint compile_shader(const GLint type, const char * str);
 }
 #ifndef IGL_STATIC_LIBRARY

+ 56 - 10
include/igl/create_shader_program.cpp

@@ -10,20 +10,22 @@
 
 #include "load_shader.h"
 #include "print_program_info_log.h"
+#include <iostream>
 #include <cstdio>
 
 IGL_INLINE bool igl::create_shader_program(
-  const std::string vert_source,
-  const std::string frag_source,
-  const std::map<std::string,GLuint> attrib,
+  const std::string & geom_source,
+  const std::string & vert_source,
+  const std::string & frag_source,
+  const std::map<std::string,GLuint> & attrib,
   GLuint & id)
 {
+  using namespace std;
   if(vert_source == "" && frag_source == "")
   {
-    fprintf(
-      stderr,
-      "Error: create_shader_program() could not create shader program,"
-      " both .vert and .frag source given were empty\n");
+    cerr<<
+      "create_shader_program() could not create shader program,"
+      " both .vert and .frag source given were empty"<<endl;
     return false;
   }
 
@@ -31,18 +33,29 @@ IGL_INLINE bool igl::create_shader_program(
   id = glCreateProgram();
   if(id == 0)
   {
-    fprintf(
-      stderr,
-      "Error: create_shader_program() could not create shader program.\n");
+    cerr<<"create_shader_program() could not create shader program."<<endl;
     return false;
   }
 
+  if(geom_source != "")
+  {
+    // load vertex shader
+    GLuint g = igl::load_shader(geom_source.c_str(),GL_GEOMETRY_SHADER_EXT);
+    if(g == 0)
+    {
+      cerr<<"geometry shader failed to compile."<<endl;
+      return false;
+    }
+    glAttachShader(id,g);
+  }
+
   if(vert_source != "")
   {
     // load vertex shader
     GLuint v = igl::load_shader(vert_source.c_str(),GL_VERTEX_SHADER);
     if(v == 0)
     {
+      cerr<<"vertex shader failed to compile."<<endl;
       return false;
     }
     glAttachShader(id,v);
@@ -54,6 +67,7 @@ IGL_INLINE bool igl::create_shader_program(
     GLuint f = igl::load_shader(frag_source.c_str(),GL_FRAGMENT_SHADER);
     if(f == 0)
     {
+      cerr<<"fragment shader failed to compile."<<endl;
       return false;
     }
     glAttachShader(id,f);
@@ -78,4 +92,36 @@ IGL_INLINE bool igl::create_shader_program(
 
   return true;
 }
+
+IGL_INLINE bool igl::create_shader_program(
+  const std::string & vert_source,
+  const std::string & frag_source,
+  const std::map<std::string,GLuint> & attrib,
+  GLuint & prog_id)
+{
+  return create_shader_program("",vert_source,frag_source,attrib,prog_id);
+}
+
+
+IGL_INLINE GLuint igl::create_shader_program(
+  const std::string & geom_source,
+  const std::string & vert_source,
+  const std::string & frag_source,
+  const std::map<std::string,GLuint> & attrib)
+{
+  GLuint prog_id = 0;
+  create_shader_program(geom_source,vert_source,frag_source,attrib,prog_id);
+  return prog_id;
+}
+
+IGL_INLINE GLuint igl::create_shader_program(
+  const std::string & vert_source,
+  const std::string & frag_source,
+  const std::map<std::string,GLuint> & attrib)
+{
+  GLuint prog_id = 0;
+  create_shader_program(vert_source,frag_source,attrib,prog_id);
+  return prog_id;
+}
+
 #endif

+ 20 - 3
include/igl/create_shader_program.h

@@ -21,6 +21,8 @@ namespace igl
   // source strings and vertex attributes assigned from a map before linking the
   // shaders to the program, making it ready to use with glUseProgram(id)
   // Inputs:
+  //   geom_source  string containing source code of geometry shader (can be
+  //     "" to mean use default pass-through)
   //   vert_source  string containing source code of vertex shader
   //   frag_source  string containing source code of fragment shader
   //   attrib  map containing table of vertex attribute strings add their
@@ -34,10 +36,25 @@ namespace igl
   //
   // See also: destroy_shader_program
   IGL_INLINE bool create_shader_program(
-    const std::string vert_source,
-    const std::string frag_source,
-    const std::map<std::string,GLuint> attrib,
+    const std::string &geom_source,
+    const std::string &vert_source,
+    const std::string &frag_source,
+    const std::map<std::string,GLuint> &attrib,
     GLuint & id);
+  IGL_INLINE bool create_shader_program(
+    const std::string &vert_source,
+    const std::string &frag_source,
+    const std::map<std::string,GLuint> &attrib,
+    GLuint & id);
+  IGL_INLINE GLuint create_shader_program(
+    const std::string & geom_source,
+    const std::string & vert_source,
+    const std::string & frag_source,
+    const std::map<std::string,GLuint> &attrib);
+  IGL_INLINE GLuint create_shader_program(
+    const std::string & vert_source,
+    const std::string & frag_source,
+    const std::map<std::string,GLuint> &attrib);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 21 - 0
include/igl/deprecated.h

@@ -0,0 +1,21 @@
+#ifndef IGL_DEPRECATED_H
+#define IGL_DEPRECATED_H
+// Macro for marking a function as deprecated.
+// 
+// http://stackoverflow.com/a/295229/148668
+#ifdef __GNUC__
+#define IGL_DEPRECATED(func) func __attribute__ ((deprecated))
+#elif defined(_MSC_VER)
+#define IGL_DEPRECATED(func) __declspec(deprecated) func
+#else
+#pragma message("WARNING: You need to implement IGL_DEPRECATED for this compiler")
+#define IGL_DEPRECATED(func) func
+#endif
+// Usage:
+//
+//     template <typename T> IGL_INLINE void my_func(Arg1 a);
+//
+// becomes 
+//
+//     template <typename T> IGL_INLINE IGL_DEPRECATED(void my_func(Arg1 a));
+#endif

+ 1 - 1
include/igl/dirname.h

@@ -13,7 +13,7 @@
 
 namespace igl
 {
-  // Function like PHP's dirname
+  // Function like PHP's dirname: /etc/passwd --> /etc, 
   // Input:
   //  path  string containing input path
   // Returns string containing dirname (see php's dirname)

+ 51 - 50
include/igl/embree/EmbreeIntersector.h

@@ -1,10 +1,10 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-//
+// 
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 //               2014 Christian Schüller <schuellchr@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 // igl function interface for Embree2.2
 //
@@ -12,22 +12,19 @@
 // * Use igl:Hit instead of embree:Hit (where id0 -> id)
 // * For Embree2.2
 // * Uncomment #define __USE_RAY_MASK__ in platform.h to enable masking
-//
-// TODO: Check for NANs in the input
 
 #ifndef IGL_EMBREE_INTERSECTOR_H
 #define IGL_EMBREE_INTERSECTOR_H
 
+#include "Hit.h"
 #include <Eigen/Geometry>
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 
-#include <vector>
 #include <embree2/rtcore.h>
 #include <embree2/rtcore_ray.h>
 #include <iostream>
-#include "Hit.h"
-#include <iostream>
+#include <vector>
 
 namespace igl
 {
@@ -44,7 +41,7 @@ namespace igl
   public:
     typedef Eigen::Matrix<float,Eigen::Dynamic,3> PointMatrixType;
     typedef Eigen::Matrix<int,Eigen::Dynamic,3> FaceMatrixType;
-  public:
+  public: 
     inline EmbreeIntersector();
   private:
     // Copying and assignment are not allowed.
@@ -52,7 +49,7 @@ namespace igl
     inline EmbreeIntersector & operator=(const EmbreeIntersector &);
   public:
     virtual inline ~EmbreeIntersector();
-
+    
     // Initialize with a given mesh.
     //
     // Inputs:
@@ -81,9 +78,9 @@ namespace igl
     // destruction: no need to call if you just want to init() once and
     // destroy.
     inline void deinit();
-
+  
     // Given a ray find the first hit
-    //
+    // 
     // Inputs:
     //   origin     3d origin point of ray
     //   direction  3d (not necessarily normalized) direction vector of ray
@@ -94,7 +91,7 @@ namespace igl
     //   hit        information about hit
     // Returns true if and only if there was a hit
     inline bool intersectRay(
-      const Eigen::RowVector3f& origin,
+      const Eigen::RowVector3f& origin, 
       const Eigen::RowVector3f& direction,
       Hit& hit,
       float tnear = 0,
@@ -104,7 +101,7 @@ namespace igl
     // Given a ray find the first hit
     // This is a conservative hit test where multiple rays within a small radius
     // will be tested and only the closesest hit is returned.
-    //
+    // 
     // Inputs:
     //   origin     3d origin point of ray
     //   direction  3d (not necessarily normalized) direction vector of ray
@@ -127,7 +124,7 @@ namespace igl
       bool closestHit = true) const;
 
     // Given a ray find all hits in order
-    //
+    // 
     // Inputs:
     //   origin     3d origin point of ray
     //   direction  3d (not necessarily normalized) direction vector of ray
@@ -148,7 +145,7 @@ namespace igl
       int mask = 0xFFFFFFFF) const;
 
     // Given a ray find the first hit
-    //
+    // 
     // Inputs:
     //   a    3d first end point of segment
     //   ab   3d vector from a to other endpoint b
@@ -160,7 +157,7 @@ namespace igl
       const Eigen::RowVector3f& ab,
       Hit &hit,
       int mask = 0xFFFFFFFF) const;
-
+    
   private:
 
     struct Vertex   {float x,y,z,a;};
@@ -264,10 +261,10 @@ inline void igl::EmbreeIntersector::init(
   const std::vector<const FaceMatrixType*>& F,
   const std::vector<int>& masks)
 {
-
+  
   if(initialized)
     deinit();
-
+  
   using namespace std;
   global_init();
 
@@ -276,11 +273,11 @@ inline void igl::EmbreeIntersector::init(
     std::cerr << "Embree: No geometry specified!";
     return;
   }
-
+  
   // create a scene
   scene = rtcNewScene(RTC_SCENE_ROBUST | RTC_SCENE_HIGH_QUALITY,RTC_INTERSECT1);
 
-  for(int g=0;g<V.size();g++)
+  for(int g=0;g<(int)V.size();g++)
   {
     // create triangle mesh geometry in that scene
     geomID = rtcNewTriangleMesh(scene,RTC_GEOMETRY_STATIC,F[g]->rows(),V[g]->rows(),1);
@@ -309,7 +306,7 @@ inline void igl::EmbreeIntersector::init(
   }
 
   rtcCommit(scene);
-
+  
   if(rtcGetError() != RTC_NO_ERROR)
       std::cerr << "Embree: An error occured while initializing the provided geometry!" << endl;
 #ifdef IGL_VERBOSE
@@ -329,14 +326,21 @@ igl::EmbreeIntersector
 
 void igl::EmbreeIntersector::deinit()
 {
-  rtcDeleteScene(scene);
+  if(scene)
+  {
+    rtcDeleteScene(scene);
 
-  if(rtcGetError() != RTC_NO_ERROR)
-      std::cerr << "Embree: An error occured while resetting!" << std::endl;
+    if(rtcGetError() != RTC_NO_ERROR)
+    {
+        std::cerr << "Embree: An error occured while resetting!" << std::endl;
+    }
 #ifdef IGL_VERBOSE
-  else
-    std::cerr << "Embree: geometry removed." << std::endl;
+    else
+    {
+      std::cerr << "Embree: geometry removed." << std::endl;
+    }
 #endif
+  }
 }
 
 inline bool igl::EmbreeIntersector::intersectRay(
@@ -348,16 +352,16 @@ inline bool igl::EmbreeIntersector::intersectRay(
   int mask) const
 {
   RTCRay ray;
-  createRay(ray, origin,direction,tnear,std::numeric_limits<float>::infinity(),mask);
-
+  createRay(ray, origin,direction,tnear,tfar,mask);
+  
   // shot ray
   rtcIntersect(scene,ray);
 #ifdef IGL_VERBOSE
   if(rtcGetError() != RTC_NO_ERROR)
       std::cerr << "Embree: An error occured while resetting!" << std::endl;
 #endif
-
-  if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
+  
+  if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
   {
     hit.id = ray.primID;
     hit.gid = ray.geomID;
@@ -371,7 +375,7 @@ inline bool igl::EmbreeIntersector::intersectRay(
 }
 
 inline bool igl::EmbreeIntersector::intersectBeam(
-      const Eigen::RowVector3f& origin,
+      const Eigen::RowVector3f& origin, 
       const Eigen::RowVector3f& direction,
       Hit& hit,
       float tnear,
@@ -388,21 +392,18 @@ inline bool igl::EmbreeIntersector::intersectBeam(
   else
     bestHit.t = 0;
 
-  hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask) && (hit.gid == geoId || geoId == -1));
-  if(hasHit)
+  if((hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask)) && (hit.gid == geoId || geoId == -1)))
     bestHit = hit;
-
+  
   // sample points around actual ray (conservative hitcheck)
   float eps= 1e-5;
   int density = 4;
-
-  Eigen::RowVector3f up; up.setRandom(1,3);
-  while (fabs(direction.cross(up).norm()) < 1e-5)
-    up.setRandom(1,3);
+        
+  Eigen::RowVector3f up(0,1,0);
   Eigen::RowVector3f offset = direction.cross(up).normalized();
 
   Eigen::Matrix3f rot = Eigen::AngleAxis<float>(2*3.14159265358979/density,direction).toRotationMatrix();
-
+        
   for(int r=0;r<density;r++)
   {
     if(intersectRay(origin+offset*eps,direction,hit,tnear,tfar,mask) && ((closestHit && (hit.t < bestHit.t)) || (!closestHit && (hit.t > bestHit.t))) && (hit.gid == geoId || geoId == -1))
@@ -417,10 +418,10 @@ inline bool igl::EmbreeIntersector::intersectBeam(
   return hasHit;
 }
 
-inline bool
+inline bool 
 igl::EmbreeIntersector
 ::intersectRay(
-  const Eigen::RowVector3f& origin,
+  const Eigen::RowVector3f& origin, 
   const Eigen::RowVector3f& direction,
   std::vector<Hit > &hits,
   int& num_rays,
@@ -451,7 +452,7 @@ igl::EmbreeIntersector
     ray.instID = RTC_INVALID_GEOMETRY_ID;
     num_rays++;
     rtcIntersect(scene,ray);
-    if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
+    if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
     {
       // Hit self again, progressively advance
       if(ray.primID == last_id0 || ray.tfar <= min_t)
@@ -489,7 +490,7 @@ igl::EmbreeIntersector
     }
     else
       break; // no more hits
-
+    
     if(hits.size()>1000 && !large_hits_warned)
     {
       std::cout<<"Warning: Large number of hits..."<<endl;
@@ -498,10 +499,10 @@ igl::EmbreeIntersector
       {
         std::cout<<(hit->id+1)<<" ";
       }
-
+      
       std::cout.precision(std::numeric_limits< double >::digits10);
       std::cout<<"[ ";
-
+      
       for(vector<Hit>::iterator hit = hits.begin(); hit != hits.end(); hit++)
       {
         std::cout<<(hit->t)<<endl;;
@@ -517,16 +518,16 @@ igl::EmbreeIntersector
   return hits.empty();
 }
 
-inline bool
+inline bool 
 igl::EmbreeIntersector
 ::intersectSegment(const Eigen::RowVector3f& a, const Eigen::RowVector3f& ab, Hit &hit, int mask) const
 {
   RTCRay ray;
   createRay(ray,a,ab,0,1.0,mask);
-
+  
   rtcIntersect(scene,ray);
 
-  if(ray.geomID != RTC_INVALID_GEOMETRY_ID)
+  if((unsigned)ray.geomID != RTC_INVALID_GEOMETRY_ID)
   {
     hit.id = ray.primID;
     hit.gid = ray.geomID;

+ 13 - 15
include/igl/embree/unproject_in_mesh.cpp

@@ -52,17 +52,16 @@ IGL_INLINE int igl::unproject_in_mesh(
     case 0:
       break;
     case 1:
-    default:
-  {
+    {
       obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
       break;
     }
-    // case 2:
-    // default:
-    // {
-    //   obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
-    //   break;
-    // }
+    case 2:
+    default:
+    {
+      obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
+      break;
+    }
   }
   return hits.size();
 }
@@ -99,17 +98,16 @@ IGL_INLINE int igl::unproject_in_mesh(
     case 0:
       break;
     case 1:
-    default:
     {
       obj = (s + dir*hits[0].t).cast<typename Derivedobj::Scalar>();
       break;
     }
-    // case 2:
-    // default:
-    // {
-    //   obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
-    //   break;
-    // }
+    case 2:
+    default:
+    {
+      obj = 0.5*((s + dir*hits[0].t) + (s + dir*hits[1].t)).cast<typename Derivedobj::Scalar>();
+      break;
+    }
   }
   return hits.size();
 }

+ 4 - 1
include/igl/embree/unproject_in_mesh.h

@@ -20,7 +20,10 @@ namespace igl
 
   #ifndef IGL_OPENGL_4
   // Unproject a screen location (using current opengl viewport, projection, and
-  // model view) to a 3D position
+  // model view) to a 3D position _inside_ a given mesh. If the ray through the
+  // given screen location (x,y) _hits_ the mesh more than twice then the 3D
+  // midpoint between the first two hits is return. If it hits once, then that
+  // point is return. If it does not hit the mesh then obj is not set.
   //
   // Inputs:
   //    x  x-coordinate of mouse location

+ 2 - 0
include/igl/face_occurrences.cpp

@@ -52,5 +52,7 @@ IGL_INLINE void igl::face_occurrences(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+// generated by autoexplicit.sh
+template void igl::face_occurrences<unsigned int, int>(std::vector<std::vector<unsigned int, std::allocator<unsigned int> >, std::allocator<std::vector<unsigned int, std::allocator<unsigned int> > > > const&, std::vector<int, std::allocator<int> >&);
 template void igl::face_occurrences<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<int, std::allocator<int> >&);
 #endif

+ 28 - 0
include/igl/hsv_to_rgb.cpp

@@ -41,3 +41,31 @@ IGL_INLINE void igl::hsv_to_rgb(
   case 5: r = v; g = p; b = q; break;
   }
 }
+
+template <typename DerivedH, typename DerivedR>
+void igl::hsv_to_rgb(
+  const Eigen::PlainObjectBase<DerivedH> & H,
+  Eigen::PlainObjectBase<DerivedR> & R)
+{
+  assert(H.cols() == 3);
+  R.resize(H.rows(),H.cols());
+  for(typename DerivedH::Index r = 0;r<H.rows();r++)
+  {
+    typename DerivedH::Scalar hsv[3];
+    hsv[0] = H(r,0);
+    hsv[1] = H(r,1);
+    hsv[2] = H(r,2);
+    typename DerivedR::Scalar rgb[] = {0,0,0};
+    hsv_to_rgb(hsv,rgb);
+    R(r,0) = rgb[0];
+    R(r,1) = rgb[1];
+    R(r,2) = rgb[2];
+  }
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template void igl::hsv_to_rgb<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::hsv_to_rgb<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
+template void igl::hsv_to_rgb<Eigen::Matrix<unsigned char, 64, 3, 1, 64, 3>, Eigen::Matrix<unsigned char, 64, 3, 1, 64, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<unsigned char, 64, 3, 1, 64, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned char, 64, 3, 1, 64, 3> >&);
+template void igl::hsv_to_rgb<Eigen::Matrix<float, 64, 3, 1, 64, 3>, Eigen::Matrix<float, 64, 3, 1, 64, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 64, 3, 1, 64, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 64, 3, 1, 64, 3> >&);
+#endif

+ 5 - 0
include/igl/hsv_to_rgb.h

@@ -8,6 +8,7 @@
 #ifndef IGL_HSV_TO_RGB_H
 #define IGL_HSV_TO_RGB_H
 #include "igl_inline.h"
+#include <Eigen/Core>
 namespace igl
 {
   // Convert RGB to HSV
@@ -26,6 +27,10 @@ namespace igl
   IGL_INLINE void hsv_to_rgb( 
     const T & h, const T & s, const T & v, 
     T & r, T & g, T & b);
+  template <typename DerivedH, typename DerivedR>
+  void hsv_to_rgb(
+    const Eigen::PlainObjectBase<DerivedH> & H,
+    Eigen::PlainObjectBase<DerivedR> & R);
 };
 
 #ifndef IGL_STATIC_LIBRARY

+ 46 - 0
include/igl/init_render_to_texture.cpp

@@ -0,0 +1,46 @@
+#include "init_render_to_texture.h"
+#include <cassert>
+
+IGL_INLINE void igl::init_render_to_texture(
+  const size_t width,
+  const size_t height,
+  GLuint & tex_id,
+  GLuint & fbo_id,
+  GLuint & dfbo_id)
+{
+  using namespace std;
+  // Delete if already exists
+  glDeleteTextures(1,&tex_id);
+  glDeleteFramebuffersEXT(1,&fbo_id);
+  glDeleteFramebuffersEXT(1,&dfbo_id);
+  // http://www.opengl.org/wiki/Framebuffer_Object_Examples#Quick_example.2C_render_to_texture_.282D.29
+  glGenTextures(1, &tex_id);
+  glBindTexture(GL_TEXTURE_2D, tex_id);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  //NULL means reserve texture memory, but texels are undefined
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, width, height, 0, GL_BGRA, GL_FLOAT, NULL);
+  glBindTexture(GL_TEXTURE_2D, 0);
+  glGenFramebuffersEXT(1, &fbo_id);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
+  //Attach 2D texture to this FBO
+  glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex_id, 0);
+
+  glGenRenderbuffersEXT(1, &dfbo_id);
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, dfbo_id);
+  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
+  //Attach depth buffer to FBO (for this example it's not really needed, but if
+  //drawing a 3D scene it would be necessary to attach something)
+  glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, dfbo_id);
+
+  //Does the GPU support current FBO configuration?
+  GLenum status;
+  status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+  assert(status == GL_FRAMEBUFFER_COMPLETE_EXT);
+  // Unbind to clean up
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+}
+

+ 28 - 0
include/igl/init_render_to_texture.h

@@ -0,0 +1,28 @@
+#ifndef IGL_INIT_RENDER_TO_TEXTURE_H
+#define IGL_INIT_RENDER_TO_TEXTURE_H
+#include "igl_inline.h"
+#include "OpenGL_convenience.h"
+#include <cstdlib>
+namespace igl
+{
+  // Create a texture+framebuffer+depthbuffer triplet bound for rendering into
+  // the texture;
+  //
+  // Inputs:
+  //   width  image width
+  //   height image height
+  // Outputs:
+  //   tex_id  id of the texture
+  //   fbo_id  id of the frame buffer object
+  //   dfbo_id  id of the depth frame buffer object
+  IGL_INLINE void init_render_to_texture(
+    const size_t width,
+    const size_t height,
+    GLuint & tex_id,
+    GLuint & fbo_id,
+    GLuint & dfbo_id);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "init_render_to_texture.cpp"
+#endif
+#endif

+ 1 - 1
include/igl/is_boundary_edge.cpp

@@ -107,7 +107,7 @@ void igl::is_boundary_edge(
   // Look of occurances of 1
   for(int e = 0;e<E.rows();e++)
   {
-    B(e) = (N(EMAP(e)) == 1);
+    B(e) = N(e) == 1;
   }
 }
 

+ 1 - 0
include/igl/jet.cpp

@@ -134,4 +134,5 @@ template void igl::jet<float>(float, float*);
 template void igl::jet<Eigen::Array<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Array<double, -1, 1, 0, -1, 1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::jet<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::jet<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&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::jet<float>(float, float&, float&, float&);
 #endif

+ 6 - 0
include/igl/list_to_matrix.cpp

@@ -124,6 +124,12 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector<T > & V,Mat & M)
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::list_to_matrix<unsigned int, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > >(std::vector<std::vector<unsigned int, std::allocator<unsigned int> >, std::allocator<std::vector<unsigned int, std::allocator<unsigned int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<float, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > >(std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
+template bool igl::list_to_matrix<double, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
 template bool igl::list_to_matrix<double, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::vector<double, std::allocator<double> > const&, Eigen::Matrix<double, -1, 1, 0, -1, 1>&);
 // generated by autoexplicit.sh
 template bool igl::list_to_matrix<int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);

+ 2 - 0
include/igl/max_size.cpp

@@ -27,6 +27,8 @@ IGL_INLINE int igl::max_size(const std::vector<T> & V)
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template int igl::max_size<std::vector<unsigned int, std::allocator<unsigned int> > >(std::vector<std::vector<unsigned int, std::allocator<unsigned int> >, std::allocator<std::vector<unsigned int, std::allocator<unsigned int> > > > const&);
+// generated by autoexplicit.sh
 template int igl::max_size<std::vector<int, std::allocator<int> > >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&);
 // generated by autoexplicit.sh
 template int igl::max_size<std::vector<double, std::allocator<double> > >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&);

+ 2 - 0
include/igl/min_size.cpp

@@ -33,6 +33,8 @@ IGL_INLINE int igl::min_size(const std::vector<T> & V)
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template int igl::min_size<std::vector<unsigned int, std::allocator<unsigned int> > >(std::vector<std::vector<unsigned int, std::allocator<unsigned int> >, std::allocator<std::vector<unsigned int, std::allocator<unsigned int> > > > const&);
+// generated by autoexplicit.sh
 template int igl::min_size<std::vector<int, std::allocator<int> > >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&);
 // generated by autoexplicit.sh
 template int igl::min_size<std::vector<double, std::allocator<double> > >(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > const&);

+ 21 - 0
include/igl/mod.cpp

@@ -0,0 +1,21 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "mod.h"
+
+template <typename DerivedA, typename DerivedB>
+IGL_INLINE void igl::mod(
+  const Eigen::PlainObjectBase<DerivedA> & A,
+  const int base,
+  Eigen::PlainObjectBase<DerivedB> & B)
+{
+  B.resize(A.rows(),A.cols());
+  for(int i = 0;i<B.size();i++)
+  {
+    *(B.data()+i) = (*(A.data()+i))%base;
+  }
+}

+ 30 - 0
include/igl/mod.h

@@ -0,0 +1,30 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
+// 
+// This Source Code Form is subject to the terms of the Mozilla Public License 
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_MOD_H
+#define IGL_MOD_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Compute elementwise mod: B = A % base
+  //
+  // Inputs:
+  //    A  m by n matrix
+  //    base  number to mod against
+  // Outputs:
+  //    B  m by n matrix
+  template <typename DerivedA, typename DerivedB>
+  IGL_INLINE void mod(
+    const Eigen::PlainObjectBase<DerivedA> & A,
+    const int base,
+    Eigen::PlainObjectBase<DerivedB> & B);
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "mod.cpp"
+#endif
+#endif

+ 12 - 1
include/igl/outer_hull.cpp

@@ -32,7 +32,6 @@ IGL_INLINE void igl::outer_hull(
 {
   using namespace Eigen;
   using namespace std;
-  using namespace igl;
   typedef typename DerivedF::Index Index;
   Matrix<Index,DerivedF::RowsAtCompileTime,1> C;
   typedef Matrix<typename DerivedV::Scalar,Dynamic,DerivedV::ColsAtCompileTime> MatrixXV;
@@ -106,6 +105,18 @@ IGL_INLINE void igl::outer_hull(
       // Angle between n and f
       const RowVector3N & n = N.row(f);
       di_I(fei,0) = M_PI - atan2( eVp.cross(n).dot(eV), eVp.dot(n));
+#ifdef IGL_OUTER_HULL_DEBUG
+      if(di_I(fei,0) != di_I(fei,0) )
+      {
+        cout<<"NaN from face: "<<(f+1)<<endl;
+        cout<<"  n: "<<n<<endl;
+        cout<<"  eVp: "<<eVp<<endl;
+        cout<<"  eV: "<<eV<<endl;
+        cout<<"  eVp x n . eV: "<<(eVp.cross(n).dot(eV))<<endl;
+        cout<<"  eVp . n: "<<(eVp.dot(n))<<endl;
+      }
+#endif
+      assert(di_I(fei,0) == di_I(fei,0) && "NaN Alert!");
       if(!cons[fei])
       {
         di_I(fei,0) = di_I(fei,0) + M_PI;

+ 2 - 0
include/igl/polygon_mesh_to_triangle_mesh.cpp

@@ -68,6 +68,8 @@ IGL_INLINE void igl::polygon_mesh_to_triangle_mesh(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template void igl::polygon_mesh_to_triangle_mesh<int, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
 template void igl::polygon_mesh_to_triangle_mesh<int, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template void igl::polygon_mesh_to_triangle_mesh<int, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 1 - 0
include/igl/random_quaternion.cpp

@@ -20,4 +20,5 @@ IGL_INLINE Eigen::Quaternion<Scalar> igl::random_quaternion()
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+template Eigen::Quaternion<double, 0> igl::random_quaternion<double>();
 #endif

+ 2 - 0
include/igl/readMESH.cpp

@@ -465,6 +465,8 @@ IGL_INLINE bool igl::readMESH(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::readMESH<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
+// generated by autoexplicit.sh
 template bool igl::readMESH<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 // generated by autoexplicit.sh
 template bool igl::readMESH<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);

+ 5 - 0
include/igl/readOBJ.cpp

@@ -309,6 +309,11 @@ IGL_INLINE bool igl::readOBJPoly(
   Eigen::PlainObjectBase<DerivedT>& TC,
   Eigen::PlainObjectBase<DerivedF>& FTC)
 {
+#ifdef _WIN32
+ #pragma message ( "Deprecated. Use `readOBJ` with vector args instead" )
+#else
+ #warning "Deprecated. Use `readOBJ` with vector args instead"
+#endif
   std::vector<std::vector<double> > vV,vTC,vN;
   std::vector<std::vector<Index> > vF,vFTC,vFN;
   bool success = igl::readOBJ(str,vV,vTC,vN,vF,vFTC,vFN);

+ 5 - 2
include/igl/readOBJ.h

@@ -8,6 +8,7 @@
 #ifndef IGL_READOBJ_H
 #define IGL_READOBJ_H
 #include "igl_inline.h"
+#include "deprecated.h"
 // History:
 //  return type changed from void to bool  Alec 18 Sept 2011
 //  added pure vector of vectors version that has much more support Alec 31 Oct
@@ -98,14 +99,16 @@ namespace igl
     typename DerivedF, 
     typename DerivedT, 
     typename Index>
-  IGL_INLINE bool readOBJPoly(
+  IGL_INLINE 
+  IGL_DEPRECATED(
+  bool readOBJPoly(
     const std::string str,
     Eigen::PlainObjectBase<DerivedV>& V,
     std::vector<std::vector<Index> >& F,
     Eigen::PlainObjectBase<DerivedV>& CN,
     Eigen::PlainObjectBase<DerivedF>& FN,
     Eigen::PlainObjectBase<DerivedT>& TC,
-    Eigen::PlainObjectBase<DerivedF>& FTC);
+    Eigen::PlainObjectBase<DerivedF>& FTC));
   
   //! Read a mesh from an ascii obj file
   // Inputs:

+ 2 - 0
include/igl/readSTL.cpp

@@ -222,6 +222,8 @@ close_true:
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::readSTL<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+// generated by autoexplicit.sh
 template bool igl::readSTL<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 template bool igl::readSTL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);

+ 1 - 0
include/igl/read_triangle_mesh.cpp

@@ -147,4 +147,5 @@ IGL_INLINE bool igl::read_triangle_mesh(
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::read_triangle_mesh<double, int>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
 template bool igl::read_triangle_mesh<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::string, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template bool igl::read_triangle_mesh<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
 #endif

+ 1 - 0
include/igl/read_triangle_mesh.h

@@ -32,6 +32,7 @@ namespace igl
   // Outputs:
   //   V  eigen double matrix #V by 3
   //   F  eigen int matrix #F by 3
+  // Returns true iff success
   template <typename Scalar, typename Index>
   IGL_INLINE bool read_triangle_mesh(
     const std::string str,

+ 25 - 0
include/igl/rgb_to_hsv.cpp

@@ -70,8 +70,33 @@ IGL_INLINE void igl::rgb_to_hsv(const R * rgb, H * hsv)
   }
 }
 
+
+template <typename DerivedR,typename DerivedH>
+IGL_INLINE void igl::rgb_to_hsv(
+  const Eigen::PlainObjectBase<DerivedR> & R,
+  Eigen::PlainObjectBase<DerivedH> & H)
+{
+  assert(R.cols() == 3);
+  H.resize(R.rows(),R.cols());
+  for(typename DerivedR::Index r = 0;r<R.rows();r++)
+  {
+    typename DerivedR::Scalar rgb[3];
+    rgb[0] = R(r,0);
+    rgb[1] = R(r,1);
+    rgb[2] = R(r,2);
+    typename DerivedH::Scalar hsv[] = {0,0,0};
+    rgb_to_hsv(rgb,hsv);
+    H(r,0) = hsv[0];
+    H(r,1) = hsv[1];
+    H(r,2) = hsv[2];
+  }
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit instanciation
 template void igl::rgb_to_hsv<float, double>(float const*, double*);
 template void igl::rgb_to_hsv<double, double>(double const*, double*);
+template void igl::rgb_to_hsv<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::rgb_to_hsv<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
+template void igl::rgb_to_hsv<Eigen::Matrix<float, 64, 3, 1, 64, 3>, Eigen::Matrix<float, 64, 3, 1, 64, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<float, 64, 3, 1, 64, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 64, 3, 1, 64, 3> >&); 
 #endif

+ 6 - 1
include/igl/rgb_to_hsv.h

@@ -1,6 +1,6 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
-// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2015 Alec Jacobson <alecjacobson@gmail.com>
 // 
 // This Source Code Form is subject to the terms of the Mozilla Public License 
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
@@ -8,6 +8,7 @@
 #ifndef IGL_RGB_TO_HSV_H
 #define IGL_RGB_TO_HSV_H
 #include "igl_inline.h"
+#include <Eigen/Core>
 namespace igl
 {
   // Convert RGB to HSV
@@ -22,6 +23,10 @@ namespace igl
   //   v  value value ([0,1])
   template <typename R,typename H>
   IGL_INLINE void rgb_to_hsv(const R * rgb, H * hsv);
+  template <typename DerivedR,typename DerivedH>
+  IGL_INLINE void rgb_to_hsv(
+    const Eigen::PlainObjectBase<DerivedR> & R,
+    Eigen::PlainObjectBase<DerivedH> & H);
 };
 
 #ifndef IGL_STATIC_LIBRARY

+ 0 - 11
include/igl/viewer/Viewer.cpp

@@ -425,17 +425,6 @@ namespace igl
     // Per face
     data.set_face_based(false);
 
-    // C-style callbacks
-    callback_init         = 0;
-    callback_pre_draw     = 0;
-    callback_post_draw    = 0;
-    callback_mouse_down   = 0;
-    callback_mouse_up     = 0;
-    callback_mouse_move   = 0;
-    callback_mouse_scroll = 0;
-    callback_key_down     = 0;
-    callback_key_up       = 0;
-
     callback_init_data          = 0;
     callback_pre_draw_data      = 0;
     callback_post_draw_data     = 0;

+ 22 - 39
include/igl/writeOBJ.cpp

@@ -14,45 +14,6 @@
 #include <cstdio>
 #include <cassert>
 
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::writeOBJ(
-  const std::string str,
-  const Eigen::PlainObjectBase<DerivedV>& V,
-  const Eigen::PlainObjectBase<DerivedF>& F)
-{
-  assert(V.cols() == 3 && "V should have 3 columns");
-  std::ofstream s(str.c_str());
-  s.precision(std::numeric_limits<double>::digits10 + 1);
-
-  if(!s.is_open())
-  {
-    fprintf(stderr,"IOError: writeOBJ() could not open %s\n",str.c_str());
-    return false;
-  }
-
-  for(int i=0;i<(int)V.rows();++i)
-  {
-    s << "v " << V(i,0) << " " << V(i,1) << " " << V(i,2) << std::endl;
-  }
-
-  for(int i=0;i<(int)F.rows();++i)
-  {
-    s << "f ";
-    for(int c =0;c<(int)F.cols();++c)
-    {
-      if(c>0)
-      {
-        s<<" ";
-      }
-      s<< F(i,c)+1;
-    }
-    s<<std::endl;
-  }
-
-  s.close();
-  return true;
-}
-
 template <typename DerivedV, typename DerivedF, typename DerivedT>
 IGL_INLINE bool igl::writeOBJ(
   const std::string str,
@@ -128,6 +89,28 @@ IGL_INLINE bool igl::writeOBJ(
   fclose(obj_file);
   return true;
 }
+
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE bool igl::writeOBJ(
+  const std::string str,
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F)
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(V.cols() == 3 && "V should have 3 columns");
+  ofstream s(str);
+  if(!s.is_open())
+  {
+    fprintf(stderr,"IOError: writeOBJ() could not open %s\n",str.c_str());
+    return false;
+  }
+  s<<
+    V.format(IOFormat(FullPrecision,DontAlignCols," ","\n","v ","","","\n"))<<
+    (F.array()+1).format(IOFormat(FullPrecision,DontAlignCols," ","\n","f ","","","\n"));
+  return true;
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh

+ 11 - 8
include/igl/writeOBJ.h

@@ -19,15 +19,13 @@ namespace igl
   // Write a mesh in an ascii obj file
   // Inputs:
   //   str  path to outputfile
-  //   V  eigen double matrix #V by 3 (mesh vertices)
-  //   F  eigen int matrix #F by 3 (mesh indices)
+  //   V  #V by 3 mesh vertex positions
+  //   F  #F by 3|4 mesh indices into V
+  //   CN #CN by 3 normal vectors
+  //   FN  #F by 3|4 corner normal indices into CN
+  //   TC  #TC by 2|3 texture coordinates
+  //   FTC #F by 3|4 corner texture coord indices into TC
   // Returns true on success, false on error
-  template <typename DerivedV, typename DerivedF>
-  IGL_INLINE bool writeOBJ(
-    const std::string str,
-    const Eigen::PlainObjectBase<DerivedV>& V,
-    const Eigen::PlainObjectBase<DerivedF>& F);
-  
   template <typename DerivedV, typename DerivedF, typename DerivedT>
   IGL_INLINE bool writeOBJ(
     const std::string str,
@@ -37,6 +35,11 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedF>& FN,
     const Eigen::PlainObjectBase<DerivedT>& TC,
     const Eigen::PlainObjectBase<DerivedF>& FTC);
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE bool writeOBJ(
+    const std::string str,
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F);
 
 }
 

+ 12 - 27
include/igl/writeOFF.cpp

@@ -7,6 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "writeOFF.h"
 #include <cstdio>
+#include <fstream>
 
 // write mesh to an ascii off file
 template <typename DerivedV, typename DerivedF>
@@ -15,39 +16,23 @@ IGL_INLINE bool igl::writeOFF(
   const Eigen::PlainObjectBase<DerivedV>& V,
   const Eigen::PlainObjectBase<DerivedF>& F)
 {
-  FILE *fp = fopen (fname.c_str(), "w");
-
-
-  if (!fp)
+  using namespace std;
+  using namespace Eigen;
+  assert(V.cols() == 3 && "V should have 3 columns");
+  ofstream s(fname);
+  if(!s.is_open())
   {
-      fprintf (stderr, "writeOFF(): could not open file %s", fname.c_str());
+    fprintf(stderr,"IOError: writeOFF() could not open %s\n",fname.c_str());
     return false;
   }
 
-  fprintf (fp, "OFF\n%d %d 0\n",  (int) V.rows(), (int) F.rows());
-
-  for (int i = 0; i < V.rows(); i++)
-  {
-    fprintf(
-      fp,
-      "%0.17g %0.17g %0.17g\n",
-      (double)V(i,0),
-      (double)V(i,1),
-      (double)V(i,2));
-  }
-
-//  for (int i = 0; i < F.rows(); i++)
-//      fprintf (fp, "3 %d %d %d\n", F(i,0), F(i,1), F(i,2));
-  for (int i = 0; i < (int)F.rows(); i++)
-  {
-    fprintf (fp, "%d", (int)F.cols());
-    for (int j = 0; j < (int)F.cols(); j++)
-      fprintf (fp, " %d", (int)F(i,j));
-    fprintf (fp, "\n");
-  }
-  fclose (fp);
+  s<<
+    "OFF\n"<<V.rows()<<" "<<F.rows()<<" 0\n"<<
+    V.format(IOFormat(FullPrecision,DontAlignCols," ","\n","","","","\n"))<<
+    (F.array()).format(IOFormat(FullPrecision,DontAlignCols," ","\n","3 ","","","\n"));
   return true;
 }
+
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh

+ 4 - 0
include/igl/writeSTL.cpp

@@ -107,3 +107,7 @@ IGL_INLINE bool igl::writeSTL(
 {
   return writeSTL(filename,V,F, Eigen::PlainObjectBase<DerivedV>(), ascii);
 }
+
+#ifdef IGL_STATIC_LIBRARY
+template bool igl::writeSTL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool);
+#endif

+ 51 - 0
include/igl/writeWRL.cpp

@@ -0,0 +1,51 @@
+#include "writeWRL.h"
+#include <iostream>
+#include <fstream>
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE bool igl::writeWRL(
+  const std::string & str,
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F)
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(V.cols() == 3 && "V should have 3 columns");
+  assert(F.cols() == 3 && "F should have 3 columns");
+  ofstream s(str);
+  if(!s.is_open())
+  {
+    cerr<<"IOError: writeWRL() could not open "<<str<<endl;
+    return false;
+  }
+  // Append column of -1 to F
+  Matrix<typename DerivedF::Scalar,Dynamic,4> FF(F.rows(),4);
+  FF.leftCols(3) = F;
+  FF.col(3).setConstant(-1);
+
+  s<<R"(
+DEF default Transform {
+translation 0 0 0
+children [
+Shape {
+geometry DEF default-FACES IndexedFaceSet {
+ccw TRUE
+)"<<
+    V.format(
+      IOFormat(
+        FullPrecision,
+        DontAlignCols,
+        " ",",\n","","",
+        "coord DEF default-COORD Coordinate { point [ \n","]\n}\n"))<<
+    FF.format(
+      IOFormat(
+        FullPrecision,
+        DontAlignCols,
+        ",","\n","","",
+        "coordIndex [ \n"," ]\n"))<<
+    "}\n}\n]\n}\n";
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+template bool igl::writeWRL<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+#endif

+ 24 - 0
include/igl/writeWRL.h

@@ -0,0 +1,24 @@
+#ifndef IGL_WRITE_WRL_H
+#define IGL_WRITE_WRL_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <string>
+namespace igl
+{
+  // Write mesh to a .wrl file
+  //
+  // Inputs:
+  //   str  path to .wrl file
+  //   V  #V by 3 list of vertex positions
+  //   F  #F by 3 list of triangle indices
+  // Returns true iff succes
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE bool writeWRL(
+    const std::string & str,
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F);
+}
+#ifndef IGL_STATIC_LIBRARY
+#include "writeWRL.cpp"
+#endif
+#endif

+ 42 - 17
include/igl/write_triangle_mesh.cpp

@@ -6,9 +6,13 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "write_triangle_mesh.h"
-
+#include "pathinfo.h"
+#include "writeMESH.h"
 #include "writeOBJ.h"
 #include "writeOFF.h"
+#include "writePLY.h"
+#include "writeSTL.h"
+#include "writeWRL.h"
 
 #include <iostream>
 
@@ -16,27 +20,48 @@ template <typename DerivedV, typename DerivedF>
 IGL_INLINE bool igl::write_triangle_mesh(
   const std::string str,
   const Eigen::PlainObjectBase<DerivedV>& V,
-  const Eigen::PlainObjectBase<DerivedF>& F)
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  const bool ascii)
 {
   using namespace std;
-  const char* p;
-  for (p = str.c_str(); *p != '\0'; p++)
-    ;
-  while (*p != '.')
-    p--;
-
-  if (!strcmp(p, ".obj") || !strcmp(p, ".OBJ"))
-    return igl::writeOBJ(str,V,F);
-
-  if (!strcmp(p, ".off") || !strcmp(p, ".OFF"))
-    return igl::writeOFF(str,V,F);
-
-  cerr<<"^write Unsupported extension: "<<string(p)<<endl;
-  return false;
+  // dirname, basename, extension and filename
+  string d,b,e,f;
+  pathinfo(str,d,b,e,f);
+  // Convert extension to lower case
+  std::transform(e.begin(), e.end(), e.begin(), ::tolower);
+  if(e == "mesh")
+  {
+    assert(ascii && ".mesh only supports ascii");
+    Eigen::MatrixXi _1;
+    return writeMESH(str,V,_1,F);
+  }else if(e == "obj")
+  {
+    assert(ascii && ".obj only supports ascii");
+    return writeOBJ(str,V,F);
+  }else if(e == "off")
+  {
+    assert(ascii && ".off only supports ascii");
+    return writeOFF(str,V,F);
+  }else if(e == "ply")
+  {
+    return writePLY(str,V,F,ascii);
+  }else if(e == "stl")
+  {
+    return writeSTL(str,V,F,ascii);
+  }else if(e == "wrl")
+  {
+    assert(ascii && ".wrl only supports ascii");
+    return writeWRL(str,V,F);
+  }else
+  {
+    assert("Unsupported file format");
+    cerr<<"Unsupported file format: ."<<e<<endl;
+    return false;
+  }
 }
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
-template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
+template bool igl::write_triangle_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, const bool);
 #endif

+ 16 - 6
include/igl/write_triangle_mesh.h

@@ -14,14 +14,24 @@
 
 namespace igl
 {
-  // write mesh to an ascii file with automatic detection of file format. supported: obj, off)
-  // Known Bugs:
-  //  Does not correctly find file extensions: myfile.foo.off
+  // write mesh to a file with automatic detection of file format.  supported:
+  // obj, off, stl, wrl, ply, mesh). 
+  // 
+  // Templates:
+  //   Scalar  type for positions and vectors (will be read as double and cast
+  //     to Scalar)
+  //   Index  type for indices (will be read as int and cast to Index)
+  // Inputs:
+  //   str  path to file
+  //   V  eigen double matrix #V by 3
+  //   F  eigen int matrix #F by 3
+  // Returns true iff success
   template <typename DerivedV, typename DerivedF>
   IGL_INLINE bool write_triangle_mesh(
-                        const std::string str,
-                        const Eigen::PlainObjectBase<DerivedV>& V,
-                        const Eigen::PlainObjectBase<DerivedF>& F);
+    const std::string str,
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    const bool ascii = true);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 22 - 0
index.html

@@ -161,6 +161,28 @@ BibTeX entry:</p>
 }
 </code></pre>
 
+<h2 id="projectsuniversitiesusinglibigl">Projects/Universities using libigl</h2>
+
+<ul>
+<li><a href="http://esotericsoftware.com/">Spine by Esoteric Software</a> is an animation tool dedicated to 2D characters.</li>
+<li>Columbia University, <a href="http://www.cs.columbia.edu/cg/">Columbia Computer Graphics Group</a>, USA</li>
+<li><a href="http://www.graphics.cornell.edu/">Cornell University</a>, USA</li>
+<li>EPF Lausanne, <a href="http://lgg.epfl.ch/people.php">Computer Graphics and Geometry Laboratory</a>, Switzerland</li>
+<li>ETH Zurich, <a href="http://igl.ethz.ch/">Interactive Geometry Lab</a> and <a href="http://ait.inf.ethz.ch/">Advanced Technologies Lab</a>, Swizterland</li>
+<li>George Mason University, <a href="http://cs.gmu.edu/~ygingold/">CraGL</a>, USA</li>
+<li><a href="http://www.ust.hk/">Hong Kong University of Science and Technology</a>, USA</li>
+<li><a href="http://www.nii.ac.jp/en/">National Institute of Informatics</a>, Japan</li>
+<li>New York University, <a href="http://mrl.nyu.edu/">Media Research Lab</a>, USA</li>
+<li>NYUPoly, <a href="http://game.engineering.nyu.edu/">Game Innovation Lab</a>, USA</li>
+<li><a href="http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html">Telecom ParisTech</a>, Paris, France</li>
+<li><a href="http://www.tudelft.nl/en/">TU Delft</a>, Netherlands</li>
+<li><a href="http://mtm.ufsc.br/~leo/">Universidade Federal de Santa Catarina</a>, Brazil</li>
+<li><a href="http://www.usi.ch/en">Università della Svizzera Italiana</a>, Switzerland</li>
+<li><a href="http://vecg.cs.ucl.ac.uk/">University College London</a>, England</li>
+<li><a href="http://www.cam.ac.uk/">University of Cambridge</a>, England</li>
+<li><a href="http://cg.cis.upenn.edu/">University of Pennsylvania</a>, USA</li>
+</ul>
+
 <h2 id="contact">Contact</h2>
 
 <p>Libigl is a group endeavor led by <a href="http://www.cs.columbia.edu/~jacobson/">Alec

+ 1 - 1
tutorial/203_CurvatureDirections/main.cpp

@@ -17,7 +17,7 @@ int main(int argc, char *argv[])
 {
   using namespace Eigen;
   std::string filename = "../shared/fertility.off";
-  if(argc>=1)
+  if(argc>1)
   {
     filename = argv[1];
   }

+ 1 - 1
tutorial/CMakeLists.shared

@@ -45,7 +45,7 @@ if(NOT APPLE)
 endif(NOT APPLE)
 
 include_directories( ${EIGEN_INCLUDE_DIR})
-include_directories( ${LIBIGL_INCLUDE_DIR})
+include_directories( ${LIBIGL_INCLUDE_DIRS})
 include_directories( ${GLFW_INCLUDE_DIR})
 include_directories(
 	/usr/local/include

+ 7 - 5
tutorial/cmake/FindLIBIGL.cmake

@@ -2,7 +2,8 @@
 # Once done this will define
 #
 #  LIBIGL_FOUND - system has LIBIGL
-#  LIBIGL_INCLUDE_DIR - the LIBIGL include directory
+#  LIBIGL_INCLUDE_DIR - **the** LIBIGL include directory
+#  LIBIGL_INCLUDE_DIRS - LIBIGL include directories
 #  LIBIGL_SOURCES - the LIBIGL source files
 if(NOT LIBIGL_FOUND)
 
@@ -22,7 +23,7 @@ FIND_PATH(LIBIGL_INCLUDE_DIR igl/readOBJ.h
 
 if(LIBIGL_INCLUDE_DIR)
    set(LIBIGL_FOUND TRUE)
-   set(LIBIGL_INCLUDE_DIR ${LIBIGL_INCLUDE_DIR}  ${LIBIGL_INCLUDE_DIR}/../external/Singular_Value_Decomposition)
+   set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIR}  ${LIBIGL_INCLUDE_DIR}/../external/Singular_Value_Decomposition)
    #set(LIBIGL_SOURCES
    #   ${LIBIGL_INCLUDE_DIR}/igl/viewer/Viewer.cpp
    #)
@@ -33,6 +34,7 @@ if(LIBIGL_USE_STATIC_LIBRARY)
   set(LIBIGL_LIB_DIRS
    /usr/lib
    /usr/local/lib
+   $ENV{LIBIGL}/lib
    $ENV{LIBIGLROOT}/lib
    $ENV{LIBIGL_ROOT}/lib
    $ENV{LIBIGL_DIR}/lib
@@ -59,7 +61,7 @@ if(LIBIGL_USE_STATIC_LIBRARY)
 #  endif(NOT LIBIGLMOSEK_LIBRARY)
   set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLMOSEK_LIBRARY})
 #if(MOSEK_FOUND)
-#    set(LIBIGL_INCLUDE_DIR ${LIBIGL_INCLUDE_DIR}  ${MOSEK_INCLUDE_DIR})
+#    set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIRS}  ${MOSEK_INCLUDE_DIR})
 #    set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${MOSEK_LIBRARIES})
 #  else(MOSEK_FOUND)
 #    set(LIBIGL_FOUND FALSE)
@@ -103,7 +105,7 @@ if(LIBIGL_USE_STATIC_LIBRARY)
   set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${LIBIGLMATLAB_LIBRARY})
   find_package(Matlab REQUIRED)
   if(MATLAB_FOUND)
-    set(LIBIGL_INCLUDE_DIR ${LIBIGL_INCLUDE_DIR}  ${MATLAB_INCLUDE_DIR})
+    set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIRS}  ${MATLAB_INCLUDE_DIR})
     set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES}  ${MATLAB_LIBRARIES})
   else(MATLAB_FOUND)
     set(LIBIGL_FOUND FALSE)
@@ -167,6 +169,6 @@ else(LIBIGL_FOUND)
    endif(LIBIGL_FIND_REQUIRED)
 endif(LIBIGL_FOUND)
 
-MARK_AS_ADVANCED(LIBIGL_INCLUDE_DIR LIBIGL_LIBRARIES IGL_VIEWER_SOURCES)
+MARK_AS_ADVANCED(LIBIGL_INCLUDE_DIRS LIBIGL_INCLUDE_DIR LIBIGL_LIBRARIES IGL_VIEWER_SOURCES)
 
 endif(NOT LIBIGL_FOUND)

+ 1 - 0
tutorial/style.css

@@ -36,6 +36,7 @@ body
   border-right: 1px solid #888;
   width: 765px;
   text-align: left;
+  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 
 }
 
 img

+ 1 - 1
tutorial/tutorial.html.REMOVED.git-id

@@ -1 +1 @@
-900b8dc7f6ad3537d8481c2a5f165a7316984ee0
+9ae5490d9bba6bec788d89d0cc640430b4f08677

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-054e6d64d269f8d6558f76fed3dc3cc000de37b0
+bc88dcbd6ca6506b1df471d68a7c8d353432a105