Эх сурвалжийг харах

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

Conflicts:
	include/igl/embree/EmbreeIntersector.h

Former-commit-id: ffdb6e769e0539b34f0e93eaedccc6c3a9a0f3a8
schuellc 10 жил өмнө
parent
commit
433c0acb64
100 өөрчлөгдсөн 2375 нэмэгдсэн , 1385 устгасан
  1. 26 22
      README.md
  2. 15 10
      RELEASE_HISTORY.txt
  3. 1 1
      VERSION.txt
  4. 0 127
      build/Makefile
  5. 0 59
      build/Makefile_bbw
  6. 0 54
      build/Makefile_boolean
  7. 0 45
      build/Makefile_boost
  8. 0 46
      build/Makefile_cgal
  9. 0 45
      build/Makefile_comiso
  10. 0 48
      build/Makefile_embree
  11. 0 45
      build/Makefile_lim
  12. 0 47
      build/Makefile_matlab
  13. 0 54
      build/Makefile_mosek
  14. 0 43
      build/Makefile_png
  15. 0 53
      build/Makefile_svd3x3
  16. 0 45
      build/Makefile_tetgen
  17. 0 45
      build/Makefile_triangle
  18. 0 51
      build/Makefile_viewer
  19. 0 61
      build/Makefile_xml
  20. 0 0
      examples/Makefile.conf
  21. 1 1
      examples/MatlabWorkspace/Makefile
  22. 1 1
      examples/ReAntTweakBar/Makefile
  23. 1 1
      examples/affine/Makefile
  24. 1 1
      examples/ambient-occlusion/Makefile
  25. 1 1
      examples/arap/Makefile
  26. 1 1
      examples/bbw/Makefile
  27. 1 1
      examples/beach-balls/Makefile
  28. 1 1
      examples/camera/Makefile
  29. 1 1
      examples/colored-mesh/Makefile
  30. 33 0
      examples/components/Makefile
  31. 1095 0
      examples/components/example.cpp
  32. 1 1
      examples/convertmesh/Makefile
  33. 1 1
      examples/dmat/Makefile
  34. 1 1
      examples/eigen-gotchas/Makefile
  35. 1 1
      examples/embree/Makefile
  36. 1 1
      examples/example_fun/Makefile
  37. 1 1
      examples/file_contents_as_string/Makefile
  38. 1 1
      examples/flare-eyes/Makefile
  39. 1 1
      examples/get_seconds/Makefile
  40. 1 1
      examples/glslversion/Makefile
  41. 1 1
      examples/glut_speed_test/Makefile
  42. 1 1
      examples/harwell_boeing/Makefile
  43. 1 1
      examples/intersections/Makefile
  44. 1 1
      examples/is_dir/Makefile
  45. 1 1
      examples/marching_cubes/Makefile
  46. 1 1
      examples/meshio/Makefile
  47. 1 1
      examples/mode/Makefile
  48. 1 1
      examples/multi-viewport/Makefile
  49. 1 1
      examples/patches/Makefile
  50. 8 0
      examples/patches/example.cpp
  51. 1 1
      examples/path_tests/Makefile
  52. 1 1
      examples/pathinfo/Makefile
  53. 1 1
      examples/randomly-sample-mesh/Makefile
  54. 1 1
      examples/render_to_png/Makefile
  55. 1 1
      examples/rotate-widget/Makefile
  56. 1 1
      examples/scene-rotation/Makefile
  57. 1 1
      examples/shadow-mapping/Makefile
  58. 1 1
      examples/skeleton-builder/Makefile
  59. 1 1
      examples/skeleton-poser/Makefile
  60. 1 1
      examples/skeleton/Makefile
  61. 1 1
      examples/slice/Makefile
  62. 1 1
      examples/sort/Makefile
  63. 1 1
      examples/sortrows/Makefile
  64. 1 1
      examples/stdin_to_temp/Makefile
  65. 1 1
      examples/svd/Makefile
  66. 1 1
      examples/textured-mesh/Makefile
  67. 1 1
      examples/trackball/Makefile
  68. 1 1
      examples/transparency/Makefile
  69. 1 1
      examples/transpose_blocks/Makefile
  70. 1 1
      examples/upright/Makefile
  71. 522 200
      include/igl/AABB.h
  72. 3 2
      include/igl/ReAntTweakBar.h
  73. 4 0
      include/igl/cgal/mesh_to_cgal_triangle_list.cpp
  74. 4 8
      include/igl/cgal/outer_hull.cpp
  75. 2 2
      include/igl/cocoa_key_to_anttweakbar_key.h
  76. 2 2
      include/igl/embree/EmbreeIntersector.h
  77. 0 4
      include/igl/in_element.h
  78. 0 65
      include/igl/kronecker_product.cpp
  79. 0 40
      include/igl/kronecker_product.h
  80. 19 2
      include/igl/matlab/parse_rhs.cpp
  81. 30 2
      include/igl/matlab/prepare_lhs.cpp
  82. 1 0
      include/igl/point_mesh_squared_distance.cpp
  83. 64 0
      include/igl/pseudonormal_test.cpp
  84. 48 0
      include/igl/pseudonormal_test.h
  85. 56 40
      include/igl/signed_distance.cpp
  86. 14 0
      include/igl/signed_distance.h
  87. 1 0
      include/igl/triangle_triangle_adjacency.cpp
  88. 1 0
      include/igl/winding_number.cpp
  89. 25 22
      index.html
  90. 60 24
      optional/CMakeLists.txt
  91. 27 24
      optional/README.md
  92. 0 0
      optional/index.html
  93. 11 0
      tutorial/704_SignedDistance/CMakeLists.txt
  94. 157 0
      tutorial/704_SignedDistance/main.cpp
  95. 1 0
      tutorial/CMakeLists.txt
  96. 63 0
      tutorial/cmake/FindPNG.cmake
  97. 1 0
      tutorial/cmake/FindTETGEN.cmake
  98. 1 0
      tutorial/cmake/FindTINYXML2.cmake
  99. 1 0
      tutorial/cmake/FindTRIANGLE.cmake
  100. 32 0
      tutorial/cmake/FindYIMG.cmake

+ 26 - 22
README.md

@@ -12,27 +12,32 @@ mesh-viewing utilities for OpenGL and GLSL, and many core functions for matrix
 manipulation which make [Eigen](http://eigen.tuxfamily.org) feel a lot more
 like MATLAB.
 
-It is first and foremost a header library. Each header file contains a single
-function. Most are tailored to operate on a generic triangle mesh stored in an
-n-by-3 matrix of vertex positions V and an m-by-3 matrix of triangle indices F.
-The library may also be [compiled](build/) into a statically linked
-library, for faster compile times with your projects.
+It is **a header-only library**. You do not need to compile anything to use,
+just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
+header file contains a single function (e.g. `igl/cotmatrix.h` contains
+`igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
+stored in an n-by-3 matrix of vertex positions V and an m-by-3 matrix of
+triangle indices F. 
+
+_Optionally_ the library may also be [pre-compiled](build/) into a statically
+linked library, for faster compile times with your projects. This only effects
+compile time (run-time performance and behavior is identical). If in doubt, use
+the header-only default mode: (i.e. just include the headers you want to use).
 
 We use the [Eigen](http://eigen.tuxfamily.org) library heavily in our code. Our
-group prototypes a lot in MATLAB, and we have a useful [conversion
-table](matlab-to-eigen.html) from
-MATLAB to libigl/Eigen.
+group prototypes a lot in MATLAB, and we have a useful [MATLAB to libigl+Eigen
+conversion table](matlab-to-eigen.html).
 
 ## Tutorial
 
 As of version 1.0, libigl includes an introductory
-[tutorial](tutorial/tutorial.html) that covers
-its basic functionalities.
+[tutorial](tutorial/tutorial.html) that covers many functionalities.
 
 ## Installation
-Libigl is a *header* library. You do **not** need to build anything to install.
-Simply add `igl/` to your include path and include relevant headers. Here is a
-small "Hello, World" program:
+
+Libigl is a **header-only** library. You do **not** need to build anything to
+install.  Simply add `libigl/include` to your include path and include relevant
+headers.  Here is a small "Hello, World" program:
 
 ```cpp
 #include <igl/cotmatrix.h>
@@ -57,10 +62,10 @@ int main()
 ```
 
 If you save this in `hello.cpp`, then you could compile this with (assuming
-Eigen is installed in /opt/local/include/eigen3):
+Eigen is installed in `/usr/local/include/eigen3`):
 
 ```bash
-gcc -I/opt/local/include/eigen3 -I./igl/ hello.cpp -o hello
+gcc -I/usr/local/include/eigen3 -I./libigl/include/ hello.cpp -o hello
 ```
 
 Running `./hello` would then produce
@@ -86,10 +91,9 @@ GCC 4.7 and clang will work correctly.
 
 ### OpenMP and Windows
 Some of our functions will take advantage of OpenMP if available. However, it
-has come to our attention that Visual Studio + Eigen does not work properly
-with OpenMP. Since OpenMP only improves performance without affecting
-functionality we recommend avoiding OpenMP on Windows or proceeding with
-caution.
+has come to our attention that Visual Studio + Eigen + OpenMP does not work
+properly. Since we use OpenMP only to improve performance, we recommend
+avoiding OpenMP on Windows or proceeding with caution.
 
 ## Download
 You can keep up to date by cloning a read-only copy of our GitHub
@@ -97,9 +101,9 @@ You can keep up to date by cloning a read-only copy of our GitHub
 
 ## Known Issues
 We really heavily on Eigen. Nearly all inputs and outputs are Eigen matrices of
-some kind. However, we currently _only_ support Eigen's default column-major
-ordering. That means, we **do not** expect our code to work for matrices using
-the `Eigen::RowMajor` flag. If you can, change definitions like:
+some kind. However, we currently _only_ officially support Eigen's default
+column-major ordering. That means, we **do not** expect our code to work for
+matrices using the `Eigen::RowMajor` flag. If you can, change definitions like:
 
 ```cpp
 Eigen::Matrix<double, Eigen::Dynamic, 3, Eigen::RowMajor> A;

+ 15 - 10
RELEASE_HISTORY.txt

@@ -1,13 +1,18 @@
-1.1.6  Major boolean robustness fix, drop CGAL dependency for AABB/distances
-1.1.5  Bug fix in booleans
-1.1.4  Edge collapsing and linear program solving
-1.1.3  Bug fixes in active set and boundary_conditions
-1.1.1  PLY file format support
-1.1.0  Mesh boolean operations using CGAL and cork, implementing [Attene 14]
-1.0.3  Bone heat method
-1.0.2  Bug fix in winding number code
-1.0.1  Bug fixes and more CGAL support
-1.0.0  Major beta release: many renames, tutorial, triangle wrapper, org. build
+# Version tracking
+
+Version | Short description
+--------|----------------------------------------------------------------------
+1.1.7   | Switch build for static library to cmake.
+1.1.6   | Major boolean robustness fix, drop CGAL dependency for AABB/distances
+1.1.5   | Bug fix in booleans
+1.1.4   | Edge collapsing and linear program solving
+1.1.3   | Bug fixes in active set and boundary_conditions
+1.1.1   | PLY file format support
+1.1.0   | Mesh boolean operations using CGAL and cork, implementing [Attene 14]
+1.0.3   | Bone heat method
+1.0.2   | Bug fix in winding number code
+1.0.1   | Bug fixes and more CGAL support
+1.0.0   | Major beta release: many renames, tutorial, triangle, org. build
 
 ## Version 1.0 Changes ##
 Our beta release marks our confidence that this library can be used outside of

+ 1 - 1
VERSION.txt

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

+ 0 - 127
build/Makefile

@@ -1,127 +0,0 @@
-.PHONY: all
-all: lib extras examples
-framework: lib extras lib/igl.framework/
-
-# Shared flags etc.
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-$(info Hello, $(IGL_USERNAME)!)
-
-# optimized default settings
-all: LFLAGS +=
-#debug: OPTFLAGS= -g -Wall -Werror
-debug: OPTFLAGS= -g -Wall
-debug: DEBUG=debug
-CFLAGS += $(OPTFLAGS)
-#CFLAGS += -DIGL_NO_OPENGL -DIGL_NO_ANTTWEAKBAR
-# We use well-supported features of c++11
-
-EXTRAS=
-ifeq ($(IGL_WITH_BBW),1)
-	EXTRAS += bbw
-endif
-ifeq ($(IGL_WITH_BOOLEAN),1)
-	EXTRAS += boolean
-endif
-ifeq ($(IGL_WITH_BOOST),1)
-	EXTRAS += boost
-endif
-ifeq ($(IGL_WITH_CGAL),1)
-	EXTRAS += cgal
-endif
-ifeq ($(IGL_WITH_EMBREE),1)
-	EXTRAS += embree
-endif
-ifeq ($(IGL_WITH_COMISO),1)
-	EXTRAS += comiso
-endif
-ifeq ($(IGL_WITH_MATLAB),1)
-	EXTRAS += matlab
-endif
-ifeq ($(IGL_WITH_MOSEK),1)
-	EXTRAS += mosek
-endif
-ifeq ($(IGL_WITH_PNG),1)
-	EXTRAS += png
-endif
-ifeq ($(IGL_WITH_SVD3X3),1)
-	EXTRAS += svd3x3
-endif
-ifeq ($(IGL_WITH_TETGEN),1)
-	# append tetgen extra dir
-	EXTRAS += tetgen
-endif
-ifeq ($(IGL_WITH_VIEWER),1)
-	EXTRAS += viewer
-endif
-ifeq ($(IGL_WITH_XML),1)
-	EXTRAS += xml
-endif
-
-.PHONY: examples
-.PHONY: extras
-debug: lib extras
-lib: ../lib/libigl.a
-examples: lib extras
-	make -C ../examples
-extras:
-	for p in  $(EXTRAS); \
-	do \
-	$(MAKE) -f Makefile_$$p $(DEBUG); \
-	done
-
-
-#############################################################################
-# SOURCE
-#############################################################################
-CPP_FILES=$(wildcard ../include/igl/*.cpp)
-H_FILES=$(wildcard ../include/igl/*.h)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-#############################################################################
-# DEPENDENCIES
-#############################################################################
-INC+=$(OPENGL_INC)
-INC+=$(EIGEN3_INC)
-INC+=$(ANTTWEAKBAR_INC)
-
-.PHONY: obj
-obj:
-	mkdir -p obj
-
-../lib/libigl.a: obj $(OBJ_FILES)
-	mkdir -p ../lib
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: ../include/igl/%.cpp ../include/igl/%.h
-	$(GG) $(CFLAGS) $(AFLAGS) -c -o $@ $< $(INC)
-
-#lib/igl.framework/:
-#	mkdir -p $@
-#	cp lib/*.a $@
-#	mv $@/libigl.a $@/igl
-#	mkdir -p $@/Libraries
-#	mv $@/*.a $@/Libraries
-#	mkdir -p $@/Headers
-#	cp $(H_FILES) $@/Headers
-#	for p in $(EXTRAS); \
-#	do \
-#	mkdir $@/Headers/$$p; \
-#	cp include/igl/$$p/*.h $@/Headers/$$p; \
-#	done
-
-
-clean:
-	rm -rf ../lib/igl.framework/
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libigl.a
-	make -C ../examples clean
-	for p in  $(EXTRA_DIRS); \
-	do \
-	echo "cd $$p" ; \
-	$(MAKE) -C $$p clean; \
-	done

+ 0 - 59
build/Makefile_bbw

@@ -1,59 +0,0 @@
-.PHONY: all
-all: libiglbbw
-debug: libiglbbw
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: OPTFLAGS += -O3 -DNDEBUG $(OPENMP)
-debug: OPTFLAGS += -g -Wall
-CFLAGS += $(OPTFLAGS)
-
-.PHONY: libiglbbw
-libiglbbw: obj ../lib/libiglbbw.a
-
-SRC_DIR=../include/igl/bbw/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-ifdef IGL_NO_MOSEK
-CFLAGS+=-DIGL_NO_MOSEK
-else
-# mosek dependency
-# TODO: linux, 32 bit etc
-ifndef MOSEKPLATFORM
-  MOSEKPLATFORM=osx64x86
-endif
-ifndef MOSEKVERSION
-  MOSEKVERSION=6
-endif
-IGLMOSEK=../mosek/
-IGLMOSEK_INC=-I$(IGLMOSEK)/
-INC+=${IGLMOSEK_INC}
-MOSEK=/usr/local/mosek
-MOSEK_INC=-I$(MOSEK)/$(MOSEKVERSION)/tools/platform/$(MOSEKPLATFORM)/h
-MOSEK_LIB=-L$(MOSEK)/$(MOSEKVERSION)/tools/platform/$(MOSEKPLATFORM)/bin -lmosek64
-INC+=$(MOSEK_INC)
-endif
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglbbw.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	$(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglbbw.a

+ 0 - 54
build/Makefile_boolean

@@ -1,54 +0,0 @@
-include Makefile.conf
-
-.PHONY: all
-all: libiglboolean
-debug: libiglboolean
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG -std=c++11
-debug: CFLAGS += -g -Wall -std=c++11
-
-.PHONY: libiglboolean
-libiglboolean: obj ../lib/libiglboolean.a
-
-SRC_DIR=../include/igl/boolean/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# cork dependency
-#CORK=../external/cork
-#CORK_INC=-I$(cork)/common -I$(cork)/rtcore/
-CORK=../external/cork/
-CORK_INC=-I$(CORK)/include/
-INC+=$(CORK_INC)
-
-# CGAL dependency
-CGAL=$(DEFAULT_PREFIX)
-CGAL_INC=-I$(CGAL)/include
-CGAL_FLAGS=-frounding-math -fsignaling-nans 
-CFLAGS+=$(CGAL_FLAGS)
-INC+=$(CGAL_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglboolean.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglboolean.a

+ 0 - 45
build/Makefile_boost

@@ -1,45 +0,0 @@
-include Makefile.conf
-
-.PHONY: all
-all: libiglboost
-debug: libiglboost
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG
-debug: CFLAGS += -g -Wall 
-
-.PHONY: libiglboost
-libiglboost: obj ../lib/libiglboost.a
-
-SRC_DIR=../include/igl/boost/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# boost dependency
-BOOST=/opt/local/
-BOOST_INC=-I$(BOOST)/include
-INC+=$(BOOST_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglboost.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglboost.a

+ 0 - 46
build/Makefile_cgal

@@ -1,46 +0,0 @@
-
-.PHONY: all
-all: libiglcgal
-debug: libiglcgal
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG 
-debug: CFLAGS += -g -Wall -Werror
-
-.PHONY: libcgal
-libiglcgal: obj ../lib/libiglcgal.a
-
-SRC_DIR=../include/igl/cgal/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# CGAL dependency
-CGAL=$(DEFAULT_PREFIX)
-CGAL_INC=-I$(CGAL)/include
-CGAL_FLAGS=-frounding-math -fsignaling-nans ${OPENMP}
-CFLAGS+=$(CGAL_FLAGS)
-INC+=$(CGAL_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglcgal.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglcgal.a

+ 0 - 45
build/Makefile_comiso

@@ -1,45 +0,0 @@
-include Makefile.conf
-
-.PHONY: all
-all: libiglcomiso
-debug: libiglcomiso
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG -std=c++11
-debug: CFLAGS += -g -Wall -std=c++11
-CFLAGS += -DINCLUDE_TEMPLATES
-
-.PHONY: libiglcomiso
-libiglcomiso: obj ../lib/libiglcomiso.a
-
-SRC_DIR=../include/igl/comiso/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# comiso dependency
-COMISO_INC=-I$(COMISO)/ -I$(COMISO)/gmm/include -I$(COMISO)/../
-INC+=$(COMISO_INC)
-
-obj:
-	mkdir -p obj
-
-../lib/libiglcomiso.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglcomiso.a

+ 0 - 48
build/Makefile_embree

@@ -1,48 +0,0 @@
-include Makefile.conf
-
-.PHONY: all
-all: libiglembree
-debug: libiglembree
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG -std=c++11
-debug: CFLAGS += -g -Wall -std=c++11
-
-.PHONY: libiglembree
-libiglembree: obj ../lib/libiglembree.a
-
-SRC_DIR=../include/igl/embree/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# embree dependency
-#EMBREE=../external/embree
-#EMBREE_INC=-I$(EMBREE)/common -I$(EMBREE)/rtcore/
-EMBREE=../external/embree/
-EMBREE_INC=-I$(EMBREE)/ -I$(EMBREE)/include
-#EMBREE_LIB=-L$(EMBREE)/bin -lrtcore -lsys
-INC+=$(EMBREE_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglembree.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglembree.a

+ 0 - 45
build/Makefile_lim

@@ -1,45 +0,0 @@
-include Makefile.conf
-
-.PHONY: all
-all: libigllim
-debug: libigllim
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG
-debug: CFLAGS += -g -Wall 
-
-.PHONY: libigllim
-libigllim: obj ../lib/libigllim.a
-
-SRC_DIR=../include/igl/lim/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# LIM dependency
-LIM=../external/lim
-LIM_INC=-I$(LIM)
-INC+=$(LIM_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libigllim.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(OPENMP) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libigllim.a

+ 0 - 47
build/Makefile_matlab

@@ -1,47 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG
-debug: CFLAGS += -g -Wall -Werror
-
-.PHONY: all
-all: libiglmatlab
-debug: libiglmatlab
-
-.PHONY: libmatlab
-libiglmatlab: obj ../lib/libiglmatlab.a
-
-SRC_DIR=../include/igl/matlab/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# Matlab dependency
-ifndef MATLAB
-  MATLAB=/Applications/MATLAB_R2014b.app/
-  $(warning MATLAB undefined. Setting MATLAB=${MATLAB})
-endif
-MATLAB_INC=-I$(MATLAB)/extern/include/
-MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -leng
-INC+=$(MATLAB_INC)
-
-obj:
-	mkdir -p obj
-
-../lib/libiglmatlab.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglmatlab.a

+ 0 - 54
build/Makefile_mosek

@@ -1,54 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-
-.PHONY: all
-all: libiglmosek
-debug: libiglmosek
-
-include Makefile.conf
-all: OPTFLAGS += -O3 -DNDEBUG $(OPENMP)
-debug: OPTFLAGS += -g -Wall
-CFLAGS += $(OPTFLAGS)
-
-.PHONY: libiglmosek
-libiglmosek: obj ../lib/libiglmosek.a
-
-SRC_DIR=../include/igl/mosek/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# mosek dependency
-# TODO: linux, 32 bit etc
-ifndef MOSEKPLATFORM
-  MOSEKPLATFORM=osx64x86
-endif
-ifndef MOSEKVERSION
-  MOSEKVERSION=6
-endif
-MOSEK=/usr/local/mosek
-MOSEK_INC=-I$(MOSEK)/$(MOSEKVERSION)/tools/platform/$(MOSEKPLATFORM)/h
-MOSEK_LIB=-L$(MOSEK)/$(MOSEKVERSION)/tools/platform/$(MOSEKPLATFORM)/bin -lmosek64
-INC+=$(MOSEK_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglmosek.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglmosek.a

+ 0 - 43
build/Makefile_png

@@ -1,43 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG 
-debug: CFLAGS += -g -Wall -Werror
-
-.PHONY: all
-all: libiglpng
-debug: libiglpng
-
-.PHONY: libpng
-libiglpng: obj ../lib/libiglpng.a
-
-SRC_DIR=../include/igl/png/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# YIMG dependency
-YIMG=../external/yimg
-YIMG_INC=-I$(YIMG)
-INC+=$(YIMG_INC)
-YIMG_STATIC_LIB=$(YIMG)/libyimg.a
-
-# BOOST dependency
-INC+=-I/opt/local/include/
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglpng.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglpng.a

+ 0 - 53
build/Makefile_svd3x3

@@ -1,53 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-
-.PHONY: all
-all: libiglsvd3x3
-debug: libiglsvd3x3
-
-include Makefile.conf
-all: OPTFLAGS += -O3 -DNDEBUG $(OPENMP)
-debug: OPTFLAGS += -g -Wall
-CFLAGS += $(OPTFLAGS) -std=c++11
-
-.PHONY: libiglsvd3x3
-libiglsvd3x3: obj ../lib/libiglsvd3x3.a
-
-SRC_DIR=../include/igl/svd3x3/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# SVD 
-SINGULAR_VALUE_DECOMPOSITION_INC=\
-	-I../external/Singular_Value_Decomposition/
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC) $(SINGULAR_VALUE_DECOMPOSITION_INC)
-
-# Matlab dependency
-ifndef MATLAB
-  MATLAB=/Applications/MATLAB_R2013b.app/
-  $(warning MATLAB undefined. Setting MATLAB=${MATLAB})
-endif
-MATLAB_INC=-I$(MATLAB)/extern/include/
-MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -leng
-INC+=$(MATLAB_INC)
-
-obj: 
-	mkdir -p obj
-
-../lib/libiglsvd3x3.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	$(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglsvd3x3.a

+ 0 - 45
build/Makefile_tetgen

@@ -1,45 +0,0 @@
-
-.PHONY: all
-all: libigltetgen
-debug: libigltetgen
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG 
-debug: CFLAGS += -g -Wall -Werror
-
-.PHONY: libtetgen
-libigltetgen: obj ../lib/libigltetgen.a
-
-SRC_DIR=../include/igl/tetgen/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# Tetgen dependency
-TETGEN=../external/tetgen
-TETGEN_INC=-I$(TETGEN)
-INC+=$(TETGEN_INC)
-TETGEN_STATIC_LIB=$(TETGEN)/libtet.a
-
-obj: 
-	mkdir -p obj
-
-../lib/libigltetgen.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libigltetgen.a

+ 0 - 45
build/Makefile_triangle

@@ -1,45 +0,0 @@
-
-.PHONY: all
-all: libigltriangle
-debug: libigltriangle
-
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG 
-debug: CFLAGS += -g -Wall -Werror
-
-.PHONY: libtriangle
-libigltriangle: obj ../lib/libigltriangle.a
-
-SRC_DIR=../include/igl/triangle/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY 
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# triangle dependency
-TRIANGLE=../external/triangle
-TRIANGLE_INC=-I$(TRIANGLE)
-INC+=$(TRIANGLE_INC)
-TRIANGLE_STATIC_LIB=$(TRIANGLE)/libtriangle.a
-
-obj: 
-	mkdir -p obj
-
-../lib/libigltriangle.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	g++ $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libigltriangle.a

+ 0 - 51
build/Makefile_viewer

@@ -1,51 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG -fopenmp
-debug: CFLAGS += -g -Wall -Werror -fopenmp
-
-.PHONY: all
-all: libiglviewer
-debug: libiglviewer
-
-.PHONY: libviewer
-libiglviewer: obj ../lib/libiglviewer.a
-
-SRC_DIR=../include/igl/viewer/
-CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY
-
-# Eigen dependency
-EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-INC+=$(EIGEN3_INC)
-
-# GLFW dependency
-ifndef GLFW
-	GLFW=../external/glfw/
-endif
-GLFW_INC=-I$(GLFW)/include
-INC+=$(GLFW_INC)
-ifndef ANTTWEAKBAR
-	ANTTWEAKBAR=../external/AntTweakBar/
-endif
-# Viewer also uses source files from AntTweakBar for font rendering
-ANTTWEAKBAR_INC=-I$(ANTTWEAKBAR)/include -I$(ANTTWEAKBAR)/src
-INC+=$(ANTTWEAKBAR_INC)
-
-obj:
-	mkdir -p obj
-
-../lib/libiglviewer.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
-	$(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglmatlab.a

+ 0 - 61
build/Makefile_xml

@@ -1,61 +0,0 @@
-CFLAGS += -DIGL_STATIC_LIBRARY
-include Makefile.conf
-
-.PHONY: all
-#all:
-#debug:
-all: libiglxml
-debug: libiglxml
-
-include Makefile.conf
-all: CFLAGS += -O3 -DNDEBUG
-debug: CFLAGS += -g -Wall
-
-.PHONY: libiglxml
-libiglxml: obj ../lib/libiglxml.a
-
-#SRC_DIR=../include/igl/xml/
-#CPP_FILES=$(wildcard $(SRC_DIR)*.cpp)
-CPP_FILES=$(wildcard ../include/igl/xml/*.cpp)
-OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))
-
-# include igl headers
-INC+=-I../include/
-
-# EXPECTS THAT CFLAGS IS ALREADY SET APPROPRIATELY
-
-# Eigen dependency
-ifndef EIGEN3_INC
-	EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
-endif
-INC+=$(EIGEN3_INC)
-
-#AntTweakbar dependency
-ANTTWEAKBAR_INC=-I../external/AntTweakBar/include
-
-# xml dependency
-# TODO: linux, 32 bit etc
-TINYXML2=../external/tinyxml2
-TINYXML2_INC=-I$(TINYXML2)
-#TINYXML2_LIB=-L$(TINYXML2) -ltinyxml2
-INC+=$(TINYXML2_INC) $(ANTTWEAKBAR_INC)
-
-# AntTweakBar dependency
-ANTTWEAKBAR_INC=-I../external/AntTweakBar/include
-INC+=$(ANTTWEAKBAR_INC)
-
-#CFLAGS+=-std=c++11
-
-obj:
-	mkdir -p obj
-
-../lib/libiglxml.a: $(OBJ_FILES)
-	rm -f $@
-	ar cqs $@ $(OBJ_FILES)
-
-obj/%.o: ../include/igl/xml/%.cpp 
-	$(GG) $(AFLAGS) $(CFLAGS) -c -o $@ $< $(INC)
-
-clean:
-	rm -f $(OBJ_FILES)
-	rm -f ../lib/libiglxml.a

+ 0 - 0
build/Makefile.conf → examples/Makefile.conf


+ 1 - 1
examples/MatlabWorkspace/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglmatlab
 
 MATLAB_INC=-I$(MATLAB)/extern/include/

+ 1 - 1
examples/ReAntTweakBar/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/affine/Makefile

@@ -3,7 +3,7 @@
 all: example
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 .PHONY: example
 

+ 1 - 1
examples/ambient-occlusion/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglembree
 
 all: example

+ 1 - 1
examples/arap/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglsvd3x3
 
 all: example

+ 1 - 1
examples/bbw/Makefile

@@ -1,4 +1,4 @@
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 CXX=g++
 

+ 1 - 1
examples/beach-balls/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/camera/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/colored-mesh/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 33 - 0
examples/components/Makefile

@@ -0,0 +1,33 @@
+.PHONY: all
+
+# Shared flags etc.
+include ../Makefile.conf
+LIBIGL_LIB+=-liglembree -liglboost
+
+all: obj example
+
+.PHONY: example
+
+CFLAGS+=-g -std=c++11
+
+INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC) $(GLUT_INC) $(EMBREE_INC)
+LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB) $(EMBREE_LIB)
+
+CPP_FILES=$(wildcard ./*.cpp)
+OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o))) 
+
+example: obj $(OBJ_FILES)
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example $(OBJ_FILES) $(LIB)
+
+obj:
+	mkdir -p obj
+
+obj/%.o: %.cpp
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+obj/%.o: %.cpp %.h
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+clean:
+	rm -f $(OBJ_FILES)
+	rm -f example

+ 1095 - 0
examples/components/example.cpp

@@ -0,0 +1,1095 @@
+#include <igl/read_triangle_mesh.h>
+#include <igl/init_render_to_texture.h>
+#include <igl/draw_floor.h>
+#include <igl/report_gl_error.h>
+#include <igl/per_face_normals.h>
+#include <igl/trackball.h>
+#include <igl/snap_to_canonical_view_quat.h>
+#include <igl/REDRUM.h>
+#include <igl/Camera.h>
+#include <igl/ReAntTweakBar.h>
+#include <igl/get_seconds.h>
+#include <igl/jet.h>
+#include <igl/rgb_to_hsv.h>
+#include <igl/hsv_to_rgb.h>
+#include <igl/randperm.h>
+#include <igl/boost/components.h>
+#include <igl/C_STR.h>
+#include <igl/write_triangle_mesh.h>
+#include <igl/two_axis_valuator_fixed_up.h>
+#include <igl/snap_to_fixed_up.h>
+#include <igl/create_shader_program.h>
+
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#ifdef __APPLE__
+#include <GLUT/glut.h>
+#else
+#include <GL/glut.h>
+#endif
+
+#ifndef GLUT_WHEEL_UP
+#define GLUT_WHEEL_UP    3
+#endif
+#ifndef GLUT_WHEEL_DOWN
+#define GLUT_WHEEL_DOWN  4
+#endif
+#ifndef GLUT_WHEEL_RIGHT
+#define GLUT_WHEEL_RIGHT 5
+#endif
+#ifndef GLUT_WHEEL_LEFT
+#define GLUT_WHEEL_LEFT  6
+#endif
+#ifndef GLUT_ACTIVE_COMMAND
+#define GLUT_ACTIVE_COMMAND 8
+#endif
+
+#include <ctime>
+#include <string>
+#include <vector>
+#include <stack>
+#include <iostream>
+
+int cc_hover = -1;
+
+Eigen::MatrixXd V;
+Eigen::VectorXd Vmid,Vmin,Vmax;
+double bbd = 1.0;
+Eigen::MatrixXi F;
+Eigen::VectorXi CC;
+Eigen::MatrixXd N;
+struct State
+{
+  igl::Camera camera;
+  Eigen::VectorXf I;
+  Eigen::Matrix<GLubyte,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> selected;
+  GLuint mask_id;
+} s;
+std::string out_filename;
+
+GLuint pick_tex = 0;
+GLuint pick_fbo = 0;
+GLuint pick_dfbo = 0;
+
+// See README for descriptions
+enum RotationType
+{
+  ROTATION_TYPE_IGL_TRACKBALL = 0,
+  ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP = 1,
+  NUM_ROTATION_TYPES = 2,
+} rotation_type;
+
+enum CenterType
+{
+  CENTER_TYPE_ORBIT = 0,
+  CENTER_TYPE_FPS  = 1,
+  NUM_CENTER_TYPES = 2,
+} center_type = CENTER_TYPE_ORBIT;
+
+
+std::stack<State> undo_stack;
+std::stack<State> redo_stack;
+
+bool wireframe_visible = false;
+bool fill_visible = true;
+
+bool is_rotating = false;
+int down_x,down_y;
+igl::Camera down_camera;
+
+bool is_animating = false;
+double animation_start_time = 0;
+double ANIMATION_DURATION = 0.5;
+Eigen::Quaterniond animation_from_quat;
+Eigen::Quaterniond animation_to_quat;
+
+int width,height;
+Eigen::Vector4f light_pos(-0.1,-0.1,0.9,0);
+
+#define REBAR_NAME "temp.rbr"
+igl::ReTwBar rebar;
+
+// Forward
+void init_components();
+void init_relative();
+
+void push_undo()
+{
+  undo_stack.push(s);
+  // Clear
+  redo_stack = std::stack<State>();
+}
+
+void TW_CALL set_rotation_type(const void * value, void * clientData)
+{
+  using namespace Eigen;
+  using namespace std;
+  using namespace igl;
+  const RotationType old_rotation_type = rotation_type;
+  rotation_type = *(const RotationType *)(value);
+  if(rotation_type == ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP &&
+    old_rotation_type != ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP)
+  {
+    animation_from_quat = s.camera.m_rotation_conj;
+    snap_to_fixed_up(animation_from_quat,animation_to_quat);
+    // start animation
+    animation_start_time = get_seconds();
+    is_animating = true;
+  }
+}
+void TW_CALL get_rotation_type(void * value, void *clientData)
+{
+  RotationType * rt = (RotationType *)(value);
+  *rt = rotation_type;
+}
+
+void reshape(int width, int height)
+{
+  ::width = width;
+  ::height = height;
+  glViewport(0,0,width,height);
+  // Send the new window size to AntTweakBar
+  TwWindowSize(width, height);
+  s.camera.m_aspect = (double)width/(double)height;
+  igl::init_render_to_texture(width,height, pick_tex, pick_fbo, pick_dfbo);
+  igl::report_gl_error("init_render_to_texture: ");
+  glutPostRedisplay();
+}
+
+void push_scene()
+{
+  using namespace igl;
+  using namespace std;
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glLoadIdentity();
+  auto & camera = s.camera;
+  glMultMatrixd(camera.projection().data());
+  glMatrixMode(GL_MODELVIEW);
+  glPushMatrix();
+  glLoadIdentity();
+  gluLookAt(
+    camera.eye()(0), camera.eye()(1), camera.eye()(2),
+    camera.at()(0), camera.at()(1), camera.at()(2),
+    camera.up()(0), camera.up()(1), camera.up()(2));
+  glScaled(2./bbd,2./bbd,2./bbd);
+  glTranslated(-Vmid(0),-Vmid(1),-Vmid(2));
+}
+
+void pop_scene()
+{
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glPopMatrix();
+}
+
+void draw_mesh(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & N,
+  const Eigen::VectorXf & S,
+  const GLuint & S_loc)
+{
+  using namespace Eigen;
+  using namespace std;
+  static Matrix<float,Dynamic,3,RowMajor> VR,NR;
+  static Matrix<int,Dynamic,3,RowMajor> FR;
+  static Matrix<float,Dynamic,1,ColMajor> SR;
+  static GLuint ibo,vbo,sbo,nbo;
+  static bool scene_dirty = true;
+  if(scene_dirty)
+  {
+    VR.resize(F.rows()*3,3);
+    NR.resize(F.rows()*3,3);
+    SR.resize(F.rows()*3,1);
+    FR.resize(F.rows(),3);
+    for(int f = 0;f<F.rows();f++)
+    {
+      for(int c = 0;c<3;c++)
+      {
+        VR.row(3*f+c) = V.row(F(f,c)).cast<float>();
+        SR(3*f+c) = S(F(f,c));
+        NR.row(3*f+c) = N.row(f).cast<float>();
+        FR(f,c) = 3*f+c;
+      }
+    }
+
+    glGenBuffers(1,&ibo);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint)*FR.size(),FR.data(),GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+    glGenBuffers(1,&vbo);
+    glGenBuffers(1,&nbo);
+    glGenBuffers(1,&sbo);
+
+    glBindBuffer(GL_ARRAY_BUFFER,vbo);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(float)*VR.size(),VR.data(),GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER,nbo);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(float)*NR.size(),NR.data(),GL_STATIC_DRAW);
+
+    glBindBuffer(GL_ARRAY_BUFFER,sbo);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(float)*SR.size(),SR.data(),GL_STATIC_DRAW);
+    igl::report_gl_error("glBindBuffer: ");
+
+    scene_dirty = false;
+  }
+
+  glEnableClientState(GL_VERTEX_ARRAY);
+  glBindBuffer(GL_ARRAY_BUFFER,vbo);
+  glVertexPointer(3,GL_FLOAT,0,0);
+  glEnableClientState(GL_NORMAL_ARRAY);
+  glBindBuffer(GL_ARRAY_BUFFER,nbo);   
+  glNormalPointer(GL_FLOAT,0,0);
+
+  glBindBuffer(GL_ARRAY_BUFFER,sbo);   
+  glVertexAttribPointer(S_loc, 1, GL_FLOAT, GL_FALSE, 0, 0);
+  glEnableVertexAttribArray(S_loc);
+
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
+  glDrawElements(GL_TRIANGLES,FR.size(),GL_UNSIGNED_INT,0);
+  glBindBuffer(GL_ARRAY_BUFFER,0);
+}
+
+// Set up double-sided lights
+void lights()
+{
+  using namespace std;
+  using namespace Eigen;
+  glEnable(GL_LIGHTING);
+  glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
+  glEnable(GL_LIGHT0);
+  float WHITE[4] = {1,1,1,1.};
+  float BLACK[4] = {0.,0.,0.,1.};
+  Vector4f pos = light_pos;
+  glLightfv(GL_LIGHT0,GL_AMBIENT,BLACK);
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,WHITE);
+  glLightfv(GL_LIGHT0,GL_SPECULAR,BLACK);
+  glLightfv(GL_LIGHT0,GL_POSITION,pos.data());
+  //glEnable(GL_LIGHT1);
+  //pos(0) *= -1;
+  //pos(1) *= -1;
+  //pos(2) *= -1;
+  //glLightfv(GL_LIGHT1,GL_AMBIENT,BLACK);
+  //glLightfv(GL_LIGHT1,GL_DIFFUSE,NEAR_BLACK);
+  //glLightfv(GL_LIGHT1,GL_SPECULAR,BLACK);
+  //glLightfv(GL_LIGHT1,GL_POSITION,pos.data());
+}
+
+template <int Rows, int Cols>
+GLuint generate_1d_texture(
+  const Eigen::Matrix<GLubyte,Rows,Cols,Eigen::RowMajor> & colors)
+{
+  assert(colors.cols() == 3 && "Seems colors.cols() must be 3");
+  GLuint tex_id = 0;
+  glGenTextures(1,&tex_id);
+  glBindTexture(GL_TEXTURE_1D,tex_id);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  glTexImage1D(GL_TEXTURE_1D, 0, colors.cols(),colors.rows(),
+    0,GL_RGB, GL_UNSIGNED_BYTE,
+    colors.data());
+  igl::report_gl_error("glTexImage1D: ");
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+  glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+  igl::report_gl_error("texture: ");
+  return tex_id;
+}
+ 
+GLuint color_shader(const size_t max_ids, GLuint & scalar_loc, GLuint & tex_id)
+{
+  std::string vertex_shader = R"(
+#version 120
+attribute float scalar_in;
+varying float scalar_out;
+void main()
+{
+  scalar_out = scalar_in;
+  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+}
+)";
+  std::string fragment_shader = R"(
+#version 120
+varying float scalar_out;
+uniform float cmin;
+uniform float cmax;
+uniform sampler1D color_map;
+void main()
+{
+  float scalar_normalized = max(min((scalar_out-cmin)/(cmax-cmin),1.0),0.0);
+  gl_FragColor = texture1D(color_map,scalar_normalized);
+}
+)";
+  Eigen::Matrix<GLubyte,Eigen::Dynamic,3,Eigen::RowMajor> colors(max_ids,3);
+  for(size_t id = 0;id<max_ids;id++)
+  {
+    size_t index = id;
+    size_t re = (index)%(256*256);
+    colors(id,0) = (index-re)/(256*256);
+    index = re;
+    re = index%(256);
+    colors(id,1) = (index-re)/(256);
+    colors(id,2) = re;
+  }
+  tex_id = generate_1d_texture(colors);
+  return igl::create_shader_program(
+    vertex_shader.c_str(), 
+    fragment_shader.c_str(),
+    {{"scalar_in",scalar_loc}}
+    );
+}
+
+
+void display()
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  glClearColor(0.8,0.8,0.8,0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  if(is_animating)
+  {
+    double t = (get_seconds() - animation_start_time)/ANIMATION_DURATION;
+    if(t > 1)
+    {
+      t = 1;
+      is_animating = false;
+    }
+    Quaterniond q = animation_from_quat.slerp(t,animation_to_quat).normalized();
+    auto & camera = s.camera;
+    switch(center_type)
+    {
+      default:
+      case CENTER_TYPE_ORBIT:
+        camera.orbit(q.conjugate());
+        break;
+      case CENTER_TYPE_FPS:
+        camera.turn_eye(q.conjugate());
+        break;
+    }
+  }
+
+  glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  lights();
+  push_scene();
+
+
+  const auto & color_components_shader = [](
+     const GLuint scalar_loc,
+     GLuint & tex_id)->GLuint
+  {
+  std::string vertex_shader = R"(
+#version 120
+attribute float scalar_in;
+varying vec3 normal;
+varying float scalar_out;
+void main()
+{
+  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+  normal = normalize(gl_NormalMatrix * gl_Normal);
+  scalar_out = scalar_in;
+}
+)";
+  std::string fragment_shader = R"(
+#version 120
+varying vec3 normal;
+varying float scalar_out;
+uniform float cmin;
+uniform float cmax;
+uniform float cc_hover;
+uniform sampler1D color_map;
+uniform sampler1D selected_mask;
+void main()
+{
+  float scalar_normalized = max(min((scalar_out-cmin)/(cmax-cmin),1.0),0.0);
+  vec4 texture_color = texture1D(color_map,scalar_normalized);
+  bool is_selected = texture1D(selected_mask,scalar_normalized).x > 0.5;
+  const vec4 selected_color = vec4(1,0.2,0.2,1);
+  if(scalar_out==cc_hover)
+  {
+    texture_color = 0.5*(texture_color + selected_color);
+  }
+  if(is_selected)
+  {
+    texture_color = selected_color;
+  }
+  const float num_lights = 1.0;
+  vec4 diffuse = (1.0/num_lights)*(gl_LightSource[0].diffuse);
+  vec4 ambient = vec4(0,0,0,0);
+  ambient += (1.0/num_lights)*(gl_FrontMaterial.ambient * gl_LightSource[0].ambient);
+  ambient += (1.0/num_lights)*(gl_LightModel.ambient * gl_FrontMaterial.ambient);
+  vec4 color = ambient;
+  // Phong
+  vec3 lightDir = normalize(vec3(gl_LightSource[0].position));
+  vec3 halfVector = gl_LightSource[0].halfVector.xyz;
+  vec3 n = normalize(normal);
+  float NdotL = max(abs(dot(n.xyz,lightDir)), 0.0);  
+  vec4 specular = vec4(0.0,0.0,0.0,0.0);
+  if (NdotL > 0.0) {
+      color += diffuse * NdotL;
+      vec3 halfV = normalize(halfVector);
+      float NdotHV = max(abs(dot(n,halfV)),0.0);
+      specular += gl_FrontMaterial.specular * gl_LightSource[0].specular * pow(NdotHV, gl_FrontMaterial.shininess);
+  }
+  gl_FragColor = color * texture_color + specular;
+}
+
+)";
+
+    typedef Matrix<GLubyte,64,3,RowMajor> Matrix64_3_R_ubyte;
+    typedef Matrix<float,64,3,RowMajor> Matrix64_3_R_float;
+    Matrix64_3_R_ubyte colors;
+    {
+      Matrix64_3_R_float rgb = (Matrix64_3_R_ubyte()<<
+        255,   0,   0,
+        255,  24,   0,
+        255,  48,   0,
+        255,  72,   0,
+        255,  96,   0,
+        255, 120,   0,
+        255, 143,   0,
+        255, 167,   0,
+        255, 191,   0,
+        255, 215,   0,
+        255, 239,   0,
+        247, 255,   0,
+        223, 255,   0,
+        199, 255,   0,
+        175, 255,   0,
+        151, 255,   0,
+        128, 255,   0,
+        104, 255,   0,
+         80, 255,   0,
+         56, 255,   0,
+         32, 255,   0,
+          8, 255,   0,
+          0, 255,  16,
+          0, 255,  40,
+          0, 255,  64,
+          0, 255,  88,
+          0, 255, 112,
+          0, 255, 135,
+          0, 255, 159,
+          0, 255, 183,
+          0, 255, 207,
+          0, 255, 231,
+          0, 255, 255,
+          0, 231, 255,
+          0, 207, 255,
+          0, 183, 255,
+          0, 159, 255,
+          0, 135, 255,
+          0, 112, 255,
+          0,  88, 255,
+          0,  64, 255,
+          0,  40, 255,
+          0,  16, 255,
+          8,   0, 255,
+         32,   0, 255,
+         56,   0, 255,
+         80,   0, 255,
+        104,   0, 255,
+        128,   0, 255,
+        151,   0, 255,
+        175,   0, 255,
+        199,   0, 255,
+        223,   0, 255,
+        247,   0, 255,
+        255,   0, 239,
+        255,   0, 215,
+        255,   0, 191,
+        255,   0, 167,
+        255,   0, 143,
+        255,   0, 120,
+        255,   0,  96,
+        255,   0,  72,
+        255,   0,  48,
+        255,   0,  24).finished().cast<float>()/255.f;
+
+      Matrix64_3_R_float H;
+      rgb_to_hsv(rgb,H);
+      H.col(1) *= 0.1;
+      H.col(2) = (H.col(2).array() + 0.1*(1.-H.col(2).array())).eval();
+      hsv_to_rgb(H,rgb);
+      colors = (rgb*255.).cast<GLubyte>();
+    }
+
+    tex_id = generate_1d_texture(colors);
+
+    GLuint prog_id = igl::create_shader_program(
+      vertex_shader.c_str(), 
+      fragment_shader.c_str(),
+      {{"scalar_in",scalar_loc}}
+      );
+    igl::report_gl_error("create_shader_program: ");
+    return prog_id;
+  };
+  static GLuint scalar_loc = 1;
+  static GLuint tex_id = 0;
+  static GLuint color_components_prog = 
+    color_components_shader(scalar_loc,tex_id);
+
+  // Set material properties
+  glEnable(GL_COLOR_MATERIAL);
+  glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
+  glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,(const GLfloat[]){1,1,1,1});
+  if(wireframe_visible)
+  {
+    glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
+    if(fill_visible)
+    {
+      glColor3f(0,0,0);
+      glUseProgram(0);
+      draw_mesh(V,F,N,s.I,scalar_loc);
+    }else
+    {
+      glUseProgram(color_components_prog);
+      igl::report_gl_error("UseProgram: ");
+      draw_mesh(V,F,N,s.I,scalar_loc);
+    }
+  }
+
+  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glUseProgram(color_components_prog);
+    igl::report_gl_error("use: ");
+  glUniform1f(glGetUniformLocation(color_components_prog,"cmin"),s.I.minCoeff());
+  glUniform1f(glGetUniformLocation(color_components_prog,"cmax"),s.I.maxCoeff());
+  //glUniform1f(glGetUniformLocation(color_components_prog,"cc_selected"),cc_selected);
+  glUniform1f(glGetUniformLocation(color_components_prog,"cc_hover"),cc_hover);
+  glActiveTexture(GL_TEXTURE0);
+  glBindTexture(GL_TEXTURE_1D, tex_id);
+  glUniform1i(glGetUniformLocation(color_components_prog,"color_map"),0);
+  glActiveTexture(GL_TEXTURE1);
+  glBindTexture(GL_TEXTURE_1D, s.mask_id);
+  glUniform1i(glGetUniformLocation(color_components_prog,"selected_mask"),1);
+
+    igl::report_gl_error("unif: ");
+  if(fill_visible)
+  {
+    glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching!
+    glPolygonOffset(1.0, 0);
+  }
+  draw_mesh(V,F,N,s.I,scalar_loc);
+  glPopAttrib();
+  glUseProgram(0);
+
+  // Draw a nice floor
+  glPushMatrix();
+  const double floor_offset =
+    -2./bbd*(V.col(1).maxCoeff()-Vmid(1));
+  glTranslated(0,floor_offset,0);
+  const float GREY[4] = {0.5,0.5,0.6,1.0};
+  const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
+  draw_floor(GREY,DARK_GREY);
+  glPopMatrix();
+
+  pop_scene();
+
+  TwDraw();
+  glutSwapBuffers();
+  if(is_animating)
+  {
+    glutPostRedisplay();
+  }
+}
+
+void mouse_wheel(int wheel, int direction, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  using namespace igl;
+  using namespace Eigen;
+  GLint viewport[4];
+  glGetIntegerv(GL_VIEWPORT,viewport);
+  if(wheel == 0 && TwMouseMotion(mouse_x, viewport[3] - mouse_y))
+  {
+    static double mouse_scroll_y = 0;
+    const double delta_y = 0.125*direction;
+    mouse_scroll_y += delta_y;
+    TwMouseWheel(mouse_scroll_y);
+    return;
+  }
+
+  auto & camera = s.camera;
+  switch(center_type)
+  {
+    case CENTER_TYPE_ORBIT:
+      if(wheel==0)
+      {
+        // factor of zoom change
+        double s = (1.-0.01*direction);
+        //// FOV zoom: just widen angle. This is hardly ever appropriate.
+        //camera.m_angle *= s;
+        //camera.m_angle = min(max(camera.m_angle,1),89);
+        camera.push_away(s);
+      }else
+      {
+        // Dolly zoom:
+        camera.dolly_zoom((double)direction*1.0);
+      }
+      break;
+    default:
+    case CENTER_TYPE_FPS:
+      // Move `eye` and `at`
+      camera.dolly((wheel==0?Vector3d(0,0,1):Vector3d(-1,0,0))*0.1*direction);
+      break;
+  }
+  glutPostRedisplay();
+}
+
+bool pick(const int x, const int y, int & cc_selected)
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  static GLuint scalar_loc = 1;
+  static GLuint tex_id = 0;
+  static const size_t max_ids = s.I.maxCoeff()+1;
+  static GLuint color_shader_prog = color_shader(max_ids,scalar_loc,tex_id);
+  const int pick_s = 0;
+  const int pick_w = pick_s;
+  GLint old_vp[4];
+  glGetIntegerv(GL_VIEWPORT,old_vp);
+  const double pick_ratio = double(pick_w)/double(old_vp[2]);
+  // ceil, cause might otherwise round down to 0
+  const int pick_h = ceil(double(old_vp[3])*pick_ratio);
+  glViewport(
+    x-pick_w,
+    old_vp[3]-y-pick_h,2*pick_w+1,2*pick_h+1);
+  glMatrixMode(GL_PROJECTION);
+  Matrix4d proj;
+  glGetDoublev(GL_PROJECTION_MATRIX,proj.data());
+  glPushMatrix();
+  glLoadIdentity();
+  gluPickMatrix(
+    x,
+    old_vp[3]-y, 
+    pick_w*2+1,
+    pick_h*2+1,
+    old_vp);
+  glMultMatrixd(proj.data());
+  glMatrixMode(GL_MODELVIEW);
+  // Activate color shader
+  glUseProgram(color_shader_prog);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pick_fbo);
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pick_dfbo);
+  // Clear screen
+  glClearColor(0,0,0,0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glEnable(GL_TEXTURE_1D);
+  glBindTexture(GL_TEXTURE_1D, tex_id);
+  glUniform1f(glGetUniformLocation(color_shader_prog,"cmin"),s.I.minCoeff());
+  glUniform1f(glGetUniformLocation(color_shader_prog,"cmax"),s.I.maxCoeff());
+  draw_mesh(V,F,N,s.I,scalar_loc);
+  glPopAttrib();
+
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+  glViewport(old_vp[0],old_vp[1],old_vp[2],old_vp[3]);
+
+  Matrix<GLubyte,1,4> pixel;
+  glReadPixels(x,old_vp[3]-y,1,1,GL_RGBA,GL_UNSIGNED_BYTE,pixel.data());
+
+  glUseProgram(0);
+  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
+  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,0);
+
+  if(pixel(3) == 0)
+  {
+    cc_selected = -1;
+    return false;
+  }
+  cc_selected = pixel(0)*256*256+pixel(1)*256+pixel(2);
+  return true;
+}
+
+void regenerate_mask()
+{
+  if(glIsTexture(s.mask_id))
+  {
+    glDeleteTextures(1,&s.mask_id);
+  }
+  s.mask_id = generate_1d_texture(s.selected);
+}
+
+void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  bool tw_using = TwEventMouseButtonGLUT(glutButton,glutState,mouse_x,mouse_y);
+  int mod = glutGetModifiers();
+  switch(glutButton)
+  {
+    case GLUT_RIGHT_BUTTON:
+    {
+      switch(glutState)
+      {
+        case 1:
+          // up
+          glutSetCursor(GLUT_CURSOR_INHERIT);
+          is_rotating = false;
+          break;
+        case 0:
+          glutSetCursor(GLUT_CURSOR_CYCLE);
+          // collect information for trackball
+          is_rotating = true;
+          down_camera = s.camera;
+          down_x = mouse_x;
+          down_y = mouse_y;
+        break;
+      }
+      break;
+    }
+    case GLUT_LEFT_BUTTON:
+    {
+      switch(glutState)
+      {
+        case 1:
+          // up
+          glutSetCursor(GLUT_CURSOR_INHERIT);
+          is_rotating = false;
+          break;
+        case 0:
+          if(!tw_using)
+          {
+            push_scene();
+            int cc_selected=-1;
+            if(pick(mouse_x,mouse_y,cc_selected))
+            {
+              push_undo();
+              if(!(mod & GLUT_ACTIVE_SHIFT))
+              {
+                s.selected.setConstant(0);
+              }
+              s.selected(cc_selected,0) = 255;
+              regenerate_mask();
+            }else
+            {
+              glutSetCursor(GLUT_CURSOR_CYCLE);
+              // collect information for trackball
+              is_rotating = true;
+              down_camera = s.camera;
+              down_x = mouse_x;
+              down_y = mouse_y;
+            }
+            pop_scene();
+          }
+        break;
+      }
+      break;
+    }
+    // Scroll down
+    case GLUT_WHEEL_DOWN:
+    {
+      mouse_wheel(0,-1,mouse_x,mouse_y);
+      break;
+    }
+    // Scroll up
+    case GLUT_WHEEL_UP:
+    {
+      mouse_wheel(0,1,mouse_x,mouse_y);
+      break;
+    }
+    // Scroll left
+    case GLUT_WHEEL_LEFT:
+    {
+      mouse_wheel(1,-1,mouse_x,mouse_y);
+      break;
+    }
+    // Scroll right
+    case GLUT_WHEEL_RIGHT:
+    {
+      mouse_wheel(1,1,mouse_x,mouse_y);
+      break;
+    }
+  }
+  glutPostRedisplay();
+}
+
+void mouse_move(int mouse_x, int mouse_y)
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  bool tw_using = TwMouseMotion(mouse_x,mouse_y);
+  push_scene();
+  pick(mouse_x,mouse_y,cc_hover);
+  pop_scene();
+  glutPostRedisplay();
+}
+
+void mouse_drag(int mouse_x, int mouse_y)
+{
+  using namespace igl;
+  using namespace std;
+  using namespace Eigen;
+  bool tw_using = TwMouseMotion(mouse_x,mouse_y);
+
+  if(is_rotating)
+  {
+    glutSetCursor(GLUT_CURSOR_CYCLE);
+    Quaterniond q;
+    auto & camera = s.camera;
+    switch(rotation_type)
+    {
+      case ROTATION_TYPE_IGL_TRACKBALL:
+      {
+        // Rotate according to trackball
+        igl::trackball<double>(
+          width,
+          height,
+          2.0,
+          down_camera.m_rotation_conj.coeffs().data(),
+          down_x,
+          down_y,
+          mouse_x,
+          mouse_y,
+          q.coeffs().data());
+          break;
+      }
+      case ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP:
+      {
+        // Rotate according to two axis valuator with fixed up vector
+        two_axis_valuator_fixed_up(
+          width, height,
+          2.0,
+          down_camera.m_rotation_conj,
+          down_x, down_y, mouse_x, mouse_y,
+          q);
+        break;
+      }
+      default:
+        break;
+    }
+    switch(center_type)
+    {
+      default:
+      case CENTER_TYPE_ORBIT:
+        camera.orbit(q.conjugate());
+        break;
+      case CENTER_TYPE_FPS:
+        camera.turn_eye(q.conjugate());
+        break;
+    }
+  }
+  glutPostRedisplay();
+}
+
+void init_relative()
+{
+  using namespace Eigen;
+  using namespace igl;
+  per_face_normals(V,F,N);
+  Vmax = V.colwise().maxCoeff();
+  Vmin = V.colwise().minCoeff();
+  Vmid = 0.5*(Vmax + Vmin);
+  bbd = (Vmax-Vmin).norm();
+}
+
+void init_components()
+{
+  using namespace Eigen;
+  using namespace igl;
+  using namespace std;
+  components(F,CC);
+  s.I = CC.cast<float>();
+  s.selected = Matrix<GLubyte,Dynamic,Dynamic>::Zero(s.I.maxCoeff()+1,3);
+  cout<<"s.selected: "<<s.selected.rows()<<endl;
+  regenerate_mask();
+}
+
+void undo()
+{
+  using namespace std;
+  if(!undo_stack.empty())
+  {
+    redo_stack.push(s);
+    s = undo_stack.top();
+    undo_stack.pop();
+  }
+  regenerate_mask();
+}
+
+void redo()
+{
+  using namespace std;
+  if(!redo_stack.empty())
+  {
+    undo_stack.push(s);
+    s = redo_stack.top();
+    redo_stack.pop();
+  }
+  regenerate_mask();
+}
+
+bool save(const std::string & out_filename)
+{
+  using namespace std;
+  using namespace igl;
+  if(write_triangle_mesh(out_filename,V,F))
+  {
+    cout<<GREENGIN("Saved mesh to `"<<out_filename<<"` successfully.")<<endl;
+    return true;
+  }else
+  {
+    cout<<REDRUM("Failed to save mesh to `"<<out_filename<<"`.")<<endl;
+    return false;
+  }
+}
+
+void TW_CALL saveCB(void * /*clientData*/)
+{
+  save(out_filename);
+}
+
+void key(unsigned char key, int mouse_x, int mouse_y)
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  int mod = glutGetModifiers();
+  switch(key)
+  {
+    // ESC
+    case char(27):
+      rebar.save(REBAR_NAME);
+    // ^C
+    case char(3):
+      exit(0);
+    case 'z':
+    case 'Z':
+      if(mod & GLUT_ACTIVE_COMMAND)
+      {
+        if(mod & GLUT_ACTIVE_SHIFT)
+        {
+          redo();
+        }else
+        {
+          undo();
+        }
+      }else
+      {
+        Quaterniond q;
+        snap_to_canonical_view_quat(s.camera.m_rotation_conj,1.0,q);
+        switch(center_type)
+        {
+          default:
+          case CENTER_TYPE_ORBIT:
+            s.camera.orbit(q.conjugate());
+            break;
+          case CENTER_TYPE_FPS:
+            s.camera.turn_eye(q.conjugate());
+            break;
+        }
+      }
+      break;
+    case 'u':
+        mouse_wheel(0, 1,mouse_x,mouse_y);
+        break;
+    case 'j':
+        mouse_wheel(0,-1,mouse_x,mouse_y);
+        break;
+    default:
+      if(!TwEventKeyboardGLUT(key,mouse_x,mouse_y))
+      {
+        cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+      }
+  }
+
+  glutPostRedisplay();
+}
+
+int main(int argc, char * argv[])
+{
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  string filename = "../shared/truck.obj";
+  switch(argc)
+  {
+    case 3:
+      out_filename = argv[2];
+    case 2:
+      // Read and prepare mesh
+      filename = argv[1];
+      break;
+    default:
+      cerr<<"Usage:"<<endl<<"    ./example input.obj (output.obj)"<<endl;
+      cout<<endl<<"Opening default mesh..."<<endl;
+      break;
+  }
+
+  // print key commands
+  cout<<"[Click] and [drag]  Rotate model using trackball."<<endl;
+  cout<<"[Z,z]               Snap rotation to canonical view."<<endl;
+  cout<<"[Command+Z]         Undo."<<endl;
+  cout<<"[Shift+Command+Z]   Redo."<<endl;
+  cout<<"[^C,ESC]            Exit."<<endl;
+
+  read_triangle_mesh(filename,V,F);
+
+
+  // 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("bar");
+  TwDefine("bar label='Components' size='200 550' text=light alpha='200' color='68 68 68'");
+  rebar.TwAddVarRW("camera_rotation", TW_TYPE_QUAT4D,
+    s.camera.m_rotation_conj.coeffs().data(), "open readonly=true");
+  TwType RotationTypeTW = ReTwDefineEnumFromString("RotationType",
+    "igl_trackball,two-axis-valuator-fixed-up");
+  rebar.TwAddVarCB( "rotation_type", RotationTypeTW,
+    set_rotation_type,get_rotation_type,NULL,"keyIncr=] keyDecr=[");
+  TwType CenterTypeTW = ReTwDefineEnumFromString("CenterType","orbit,fps");
+  rebar.TwAddVarRW("center_type", CenterTypeTW,&center_type,
+    "keyIncr={ keyDecr=}");
+
+  rebar.TwAddVarRW("wireframe_visible",TW_TYPE_BOOLCPP,&wireframe_visible,"key=l");
+  rebar.TwAddVarRW("fill_visible",TW_TYPE_BOOLCPP,&fill_visible,"key=f");
+  if(out_filename != "")
+  {
+    rebar.TwAddButton("save",
+      saveCB,NULL,
+      C_STR("label='Save to `"<<out_filename<<"`' "<<
+      "key=s"));
+  }
+  rebar.load(REBAR_NAME);
+
+
+  animation_from_quat = Quaterniond(1,0,0,0);
+  s.camera.m_rotation_conj = animation_from_quat;
+  animation_start_time = get_seconds();
+
+  glutInitDisplayString( "rgba depth double samples>=8");
+  glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)/2.0,glutGet(GLUT_SCREEN_HEIGHT)/2.0);
+  glutCreateWindow("components");
+  glutDisplayFunc(display);
+  glutReshapeFunc(reshape);
+  glutKeyboardFunc(key);
+  glutMouseFunc(mouse);
+  glutMotionFunc(mouse_drag);
+  glutPassiveMotionFunc(mouse_move);
+
+  init_components();
+  init_relative();
+  regenerate_mask();
+
+  std::cout<<"OpenGL version: "<<glGetString(GL_VERSION)<<std::endl;
+  glutMainLoop();
+
+  return 0;
+}

+ 1 - 1
examples/convertmesh/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: convertmesh
 

+ 1 - 1
examples/dmat/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/eigen-gotchas/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/embree/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/example_fun/Makefile

@@ -3,7 +3,7 @@
 all: example_static example_header_only
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 CFLAGS+=-g
 INC=$(LIBIGL_INC)

+ 1 - 1
examples/file_contents_as_string/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/flare-eyes/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/get_seconds/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/glslversion/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/glut_speed_test/Makefile

@@ -3,7 +3,7 @@
 all: example
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 .PHONY: example
 

+ 1 - 1
examples/harwell_boeing/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/intersections/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB=+liglcgal
 
 all: example

+ 1 - 1
examples/is_dir/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/marching_cubes/Makefile

@@ -5,7 +5,7 @@ all: example
 .PHONY: example
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 CFLAGS+=-g
 inc=$(LIBIGL_INC) $(EIGEN3_INC)

+ 1 - 1
examples/meshio/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/mode/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/multi-viewport/Makefile

@@ -6,7 +6,7 @@ all: example
 
 .PHONY:  example
 
-include ../..//build/Makefile.conf
+include ../Makefile.conf
 
 CFLAGS+=-std=c++11 -g -Wno-deprecated-declarations
 

+ 1 - 1
examples/patches/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 ifdef LIBIGL_USE_STATIC_LIBRARY
 	LIBIGL_LIB+=-liglembree -liglboost
 endif

+ 8 - 0
examples/patches/example.cpp

@@ -1,4 +1,5 @@
 #include <igl/readOBJ.h>
+#include <igl/readPLY.h>
 #include <igl/writeOBJ.h>
 #include <igl/writeOFF.h>
 #include <igl/readWRL.h>
@@ -750,6 +751,13 @@ int main(int argc, char * argv[])
     {
       return 1;
     }
+  }else if(ext == "ply")
+  {
+    // Convert extension to lower case
+    if(!igl::readPLY(filename,vV,vF,vN,vTC))
+    {
+      return 1;
+    }
   }else if(ext == "wrl")
   {
     // Convert extension to lower case

+ 1 - 1
examples/path_tests/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/pathinfo/Makefile

@@ -3,7 +3,7 @@
 all: example
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 .PHONY: example
 

+ 1 - 1
examples/randomly-sample-mesh/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/render_to_png/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglpng
 
 # YIMG dependency

+ 1 - 1
examples/rotate-widget/Makefile

@@ -2,7 +2,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/scene-rotation/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/shadow-mapping/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: obj example
 

+ 1 - 1
examples/skeleton-builder/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglembree
 
 all: obj skeleton_builder

+ 1 - 1
examples/skeleton-poser/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglbbw -liglcgal
 
 all: obj skeleton-poser

+ 1 - 1
examples/skeleton/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglbbw -liglmosek
 
 all: obj example

+ 1 - 1
examples/slice/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/sort/Makefile

@@ -2,7 +2,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/sortrows/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/stdin_to_temp/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/svd/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/textured-mesh/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 LIBIGL_LIB+=-liglpng
 
 all: example

+ 1 - 1
examples/trackball/Makefile

@@ -3,7 +3,7 @@
 all: example
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 .PHONY: example
 

+ 1 - 1
examples/transparency/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/transpose_blocks/Makefile

@@ -1,7 +1,7 @@
 .PHONY: all
 
 # Shared flags etc.
-include ../../build/Makefile.conf
+include ../Makefile.conf
 
 all: example
 

+ 1 - 1
examples/upright/Makefile

@@ -6,7 +6,7 @@ all: upright
 
 .PHONY: upright
 
-include ../..//build/Makefile.conf
+include ../Makefile.conf
 
 INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC)
 LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB)

+ 522 - 200
include/igl/AABB.h

@@ -23,210 +23,252 @@ namespace igl
   template <typename DerivedV, int DIM>
     class AABB 
     {
-      public:
-        typedef typename DerivedV::Scalar Scalar;
-        typedef Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
-        typedef Eigen::Matrix<Scalar,DIM,1> VectorDIMS;
-        typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
-        // Shared pointers are slower...
-        AABB * m_left;
-        AABB * m_right;
-        Eigen::AlignedBox<Scalar,DIM> m_box;
-        // -1 non-leaf
-        int m_primitive;
-        AABB():
-          m_left(NULL), m_right(NULL),
-          m_box(), m_primitive(-1)
-      {}
-        // http://stackoverflow.com/a/3279550/148668
-        AABB(const AABB& other):
-          m_left(other.m_left ? new AABB(*other.m_left) : NULL),
-          m_right(other.m_right ? new AABB(*other.m_right) : NULL),
-          m_box(other.m_box),
-          m_primitive(other.m_primitive)
-          {
-          }
-        // copy-swap idiom
-        friend void swap(AABB& first, AABB& second)
-        {
-          // Enable ADL
-          using std::swap;
-          swap(first.m_left,second.m_left);
-          swap(first.m_right,second.m_right);
-          swap(first.m_box,second.m_box);
-          swap(first.m_primitive,second.m_primitive);
-        }
-        // Pass-by-value (aka copy)
-        AABB& operator=(AABB other)
+public:
+      typedef typename DerivedV::Scalar Scalar;
+      typedef Eigen::Matrix<Scalar,1,DIM> RowVectorDIMS;
+      typedef Eigen::Matrix<Scalar,DIM,1> VectorDIMS;
+      typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
+      // Shared pointers are slower...
+      AABB * m_left;
+      AABB * m_right;
+      Eigen::AlignedBox<Scalar,DIM> m_box;
+      // -1 non-leaf
+      int m_primitive;
+      //Scalar m_max_sqr_d;
+      //int m_depth;
+      AABB():
+        m_left(NULL), m_right(NULL),
+        m_box(), m_primitive(-1)
+        //m_max_sqr_d(std::numeric_limits<double>::infinity()),
+        //m_depth(0)
+    {}
+      // http://stackoverflow.com/a/3279550/148668
+      AABB(const AABB& other):
+        m_left(other.m_left ? new AABB(*other.m_left) : NULL),
+        m_right(other.m_right ? new AABB(*other.m_right) : NULL),
+        m_box(other.m_box),
+        m_primitive(other.m_primitive)
+        //m_max_sqr_d(other.m_max_sqr_d),
+        //m_depth(std::max(
+        //   m_left ? m_left->m_depth + 1 : 0,
+        //   m_right ? m_right->m_depth + 1 : 0))
         {
-          swap(*this,other);
-          return *this;
         }
-        AABB(AABB&& other):
-          // initialize via default constructor
-          AABB() 
+      // copy-swap idiom
+      friend void swap(AABB& first, AABB& second)
+      {
+        // Enable ADL
+        using std::swap;
+        swap(first.m_left,second.m_left);
+        swap(first.m_right,second.m_right);
+        swap(first.m_box,second.m_box);
+        swap(first.m_primitive,second.m_primitive);
+        //swap(first.m_max_sqr_d,second.m_max_sqr_d);
+        //swap(first.m_depth,second.m_depth);
+      }
+      // Pass-by-value (aka copy)
+      AABB& operator=(AABB other)
       {
         swap(*this,other);
+        return *this;
       }
-        // Seems like there should have been an elegant solution to this using
-        // the copy-swap idiom above:
-        inline void deinit()
-        {
-          m_primitive = -1;
-          m_box = Eigen::AlignedBox<Scalar,DIM>();
-          delete m_left;
-          m_left = NULL;
-          delete m_right;
-          m_right = NULL;
-        }
-        ~AABB()
-        {
-          deinit();
-        }
-        // Build an Axis-Aligned Bounding Box tree for a given mesh and given
-        // serialization of a previous AABB tree.
-        //
-        // Inputs:
-        //   V  #V by dim list of mesh vertex positions. 
-        //   Ele  #Ele by dim+1 list of mesh indices into #V. 
-        //   bb_mins  max_tree by dim list of bounding box min corner positions
-        //   bb_maxs  max_tree by dim list of bounding box max corner positions
-        //   elements  max_tree list of element or (not leaf id) indices into Ele
-        //   i  recursive call index {0}
-        template <typename Derivedbb_mins, typename Derivedbb_maxs>
-          inline void init(
-              const Eigen::PlainObjectBase<DerivedV> & V,
-              const Eigen::MatrixXi & Ele, 
-              const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
-              const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
-              const Eigen::VectorXi & elements,
-              const int i = 0);
-        // Wrapper for root with empty serialization
-        inline void init(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::MatrixXi & Ele);
-        // Build an Axis-Aligned Bounding Box tree for a given mesh.
-        //
-        // Inputs:
-        //   V  #V by dim list of mesh vertex positions. 
-        //   Ele  #Ele by dim+1 list of mesh indices into #V. 
-        //   SI  #Ele by dim list revealing for each coordinate where Ele's
-        //     barycenters would be sorted: SI(e,d) = i --> the dth coordinate of
-        //     the barycenter of the eth element would be placed at position i in a
-        //     sorted list.
-        //   I  #I list of indices into Ele of elements to include (for recursive
-        //     calls)
-        // 
+      AABB(AABB&& other):
+        // initialize via default constructor
+        AABB() 
+    {
+      swap(*this,other);
+    }
+      // Seems like there should have been an elegant solution to this using
+      // the copy-swap idiom above:
+      inline void deinit()
+      {
+        m_primitive = -1;
+        m_box = Eigen::AlignedBox<Scalar,DIM>();
+        delete m_left;
+        m_left = NULL;
+        delete m_right;
+        m_right = NULL;
+      }
+      ~AABB()
+      {
+        deinit();
+      }
+      // Build an Axis-Aligned Bounding Box tree for a given mesh and given
+      // serialization of a previous AABB tree.
+      //
+      // Inputs:
+      //   V  #V by dim list of mesh vertex positions. 
+      //   Ele  #Ele by dim+1 list of mesh indices into #V. 
+      //   bb_mins  max_tree by dim list of bounding box min corner positions
+      //   bb_maxs  max_tree by dim list of bounding box max corner positions
+      //   elements  max_tree list of element or (not leaf id) indices into Ele
+      //   i  recursive call index {0}
+      template <typename Derivedbb_mins, typename Derivedbb_maxs>
         inline void init(
             const Eigen::PlainObjectBase<DerivedV> & V,
             const Eigen::MatrixXi & Ele, 
-            const Eigen::MatrixXi & SI,
-            const Eigen::VectorXi & I);
-        // Return whether at leaf node
-        inline bool is_leaf() const;
-        // Find the indices of elements containing given point.
-        //
-        // Inputs:
-        //   V  #V by dim list of mesh vertex positions. **Should be same as used to
-        //     construct mesh.**
-        //   Ele  #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
-        //     construct mesh.**
-        //   q  dim row-vector query position
-        //   first  whether to only return first element containing q
-        // Returns:
-        //   list of indices of elements containing q
-        template <typename Derivedq>
-        inline std::vector<int> find(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::MatrixXi & Ele, 
-            const Eigen::PlainObjectBase<Derivedq> & q,
-            const bool first=false) const;
-
-        // If number of elements m then total tree size should be 2*h where h is
-        // the deepest depth 2^ceil(log(#Ele*2-1))
-        inline int subtree_size() const;
-
-        // Serialize this class into 3 arrays (so we can pass it pack to matlab)
-        //
-        // Outputs:
-        //   bb_mins  max_tree by dim list of bounding box min corner positions
-        //   bb_maxs  max_tree by dim list of bounding box max corner positions
-        //   elements  max_tree list of element or (not leaf id) indices into Ele
-        //   i  recursive call index into these arrays {0}
-        template <typename Derivedbb_mins, typename Derivedbb_maxs>
-          inline void serialize(
-              Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
-              Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
-              Eigen::VectorXi & elements,
-              const int i = 0) const;
-        // Compute squared distance to a query point
-        //
-        // Inputs:
-        //   V  #V by dim list of vertex positions
-        //   Ele  #Ele by dim list of simplex indices
-        //   P  3 list of query point coordinates
-        //   min_sqr_d  current minimum squared distance (only find distances
-        //   less than this)
-        // Outputs:
-        //   I  #P list of facet indices corresponding to smallest distances
-        //   C  #P by 3 list of closest points
-        // Returns squared distance
-        //
-        // Known bugs: currently assumes Elements are triangles regardless of
-        // dimension.
-        inline Scalar squared_distance(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::MatrixXi & Ele, 
-            const RowVectorDIMS & p,
-            int & i,
-            RowVectorDIMS & c) const;
-      private:
-        inline Scalar squared_distance(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::MatrixXi & Ele, 
-            const RowVectorDIMS & p,
-            const Scalar min_sqr_d,
-            int & i,
-            RowVectorDIMS & c) const;
-      public:
-        template <
-          typename DerivedP, 
-                   typename DerivedsqrD, 
-                   typename DerivedI, 
-                   typename DerivedC>
-                     inline void squared_distance(
-                         const Eigen::PlainObjectBase<DerivedV> & V,
-                         const Eigen::MatrixXi & Ele, 
-                         const Eigen::PlainObjectBase<DerivedP> & P,
-                         Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
-                         Eigen::PlainObjectBase<DerivedI> & I,
-                         Eigen::PlainObjectBase<DerivedC> & C) const;
-      private:
-        // Helper function for leaves: works in-place on sqr_d
-        inline void leaf_squared_distance(
-            const Eigen::PlainObjectBase<DerivedV> & V,
-            const Eigen::MatrixXi & Ele, 
-            const RowVectorDIMS & p,
-            Scalar & sqr_d,
-            int & i,
-            RowVectorDIMS & c) const;
-        inline void set_min(
-            const RowVectorDIMS & p,
-            const Scalar sqr_d_candidate,
-            const int i_candidate,
-            const RowVectorDIMS & c_candidate,
-            Scalar & sqr_d,
-            int & i,
-            RowVectorDIMS & c) const;
-      public:
-        template <int SS>
-          static
-          void barycentric_coordinates(
-              const RowVectorDIMS & p, 
-              const RowVectorDIMS & a, 
-              const RowVectorDIMS & b, 
-              const RowVectorDIMS & c,
-              Eigen::Matrix<Scalar,1,SS> & bary);
+            const Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
+            const Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
+            const Eigen::VectorXi & elements,
+            const int i = 0);
+      // Wrapper for root with empty serialization
+      inline void init(
+          const Eigen::PlainObjectBase<DerivedV> & V,
+          const Eigen::MatrixXi & Ele);
+      // Build an Axis-Aligned Bounding Box tree for a given mesh.
+      //
+      // Inputs:
+      //   V  #V by dim list of mesh vertex positions. 
+      //   Ele  #Ele by dim+1 list of mesh indices into #V. 
+      //   SI  #Ele by dim list revealing for each coordinate where Ele's
+      //     barycenters would be sorted: SI(e,d) = i --> the dth coordinate of
+      //     the barycenter of the eth element would be placed at position i in a
+      //     sorted list.
+      //   I  #I list of indices into Ele of elements to include (for recursive
+      //     calls)
+      // 
+      inline void init(
+          const Eigen::PlainObjectBase<DerivedV> & V,
+          const Eigen::MatrixXi & Ele, 
+          const Eigen::MatrixXi & SI,
+          const Eigen::VectorXi & I);
+      // Return whether at leaf node
+      inline bool is_leaf() const;
+      // Find the indices of elements containing given point.
+      //
+      // Inputs:
+      //   V  #V by dim list of mesh vertex positions. **Should be same as used to
+      //     construct mesh.**
+      //   Ele  #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
+      //     construct mesh.**
+      //   q  dim row-vector query position
+      //   first  whether to only return first element containing q
+      // Returns:
+      //   list of indices of elements containing q
+      template <typename Derivedq>
+      inline std::vector<int> find(
+          const Eigen::PlainObjectBase<DerivedV> & V,
+          const Eigen::MatrixXi & Ele, 
+          const Eigen::PlainObjectBase<Derivedq> & q,
+          const bool first=false) const;
+
+      // If number of elements m then total tree size should be 2*h where h is
+      // the deepest depth 2^ceil(log(#Ele*2-1))
+      inline int subtree_size() const;
+
+      // Serialize this class into 3 arrays (so we can pass it pack to matlab)
+      //
+      // Outputs:
+      //   bb_mins  max_tree by dim list of bounding box min corner positions
+      //   bb_maxs  max_tree by dim list of bounding box max corner positions
+      //   elements  max_tree list of element or (not leaf id) indices into Ele
+      //   i  recursive call index into these arrays {0}
+      template <typename Derivedbb_mins, typename Derivedbb_maxs>
+        inline void serialize(
+            Eigen::PlainObjectBase<Derivedbb_mins> & bb_mins,
+            Eigen::PlainObjectBase<Derivedbb_maxs> & bb_maxs,
+            Eigen::VectorXi & elements,
+            const int i = 0) const;
+      // Compute squared distance to a query point
+      //
+      // Inputs:
+      //   V  #V by dim list of vertex positions
+      //   Ele  #Ele by dim list of simplex indices
+      //   P  3 list of query point coordinates
+      //   min_sqr_d  current minimum squared distance (only find distances
+      //   less than this)
+      // Outputs:
+      //   I  #P list of facet indices corresponding to smallest distances
+      //   C  #P by 3 list of closest points
+      // Returns squared distance
+      //
+      // Known bugs: currently assumes Elements are triangles regardless of
+      // dimension.
+      inline Scalar squared_distance(
+          const Eigen::PlainObjectBase<DerivedV> & V,
+          const Eigen::MatrixXi & Ele, 
+          const RowVectorDIMS & p,
+          int & i,
+          RowVectorDIMS & c) const;
+private:
+      inline Scalar squared_distance(
+          const Eigen::PlainObjectBase<DerivedV> & V,
+          const Eigen::MatrixXi & Ele, 
+          const RowVectorDIMS & p,
+          const Scalar min_sqr_d,
+          int & i,
+          RowVectorDIMS & c) const;
+public:
+      template <
+        typename DerivedP, 
+        typename DerivedsqrD, 
+        typename DerivedI, 
+        typename DerivedC>
+      inline void squared_distance(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const Eigen::PlainObjectBase<DerivedP> & P,
+        Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+        Eigen::PlainObjectBase<DerivedI> & I,
+        Eigen::PlainObjectBase<DerivedC> & C) const;
+
+      template < 
+        typename Derivedother_V,
+        typename DerivedsqrD, 
+        typename DerivedI, 
+        typename DerivedC>
+      inline void squared_distance(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const AABB<Derivedother_V,DIM> & other,
+        const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+        const Eigen::MatrixXi & other_Ele, 
+        Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+        Eigen::PlainObjectBase<DerivedI> & I,
+        Eigen::PlainObjectBase<DerivedC> & C) const;
+private:
+      template < 
+        typename Derivedother_V,
+        typename DerivedsqrD, 
+        typename DerivedI, 
+        typename DerivedC>
+      inline Scalar squared_distance_helper(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const AABB<Derivedother_V,DIM> * other,
+        const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+        const Eigen::MatrixXi & other_Ele, 
+        const Scalar min_sqr_d,
+        Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+        Eigen::PlainObjectBase<DerivedI> & I,
+        Eigen::PlainObjectBase<DerivedC> & C) const;
+      // Helper function for leaves: works in-place on sqr_d
+      inline void leaf_squared_distance(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::MatrixXi & Ele, 
+        const RowVectorDIMS & p,
+        Scalar & sqr_d,
+        int & i,
+        RowVectorDIMS & c) const;
+      inline void set_min(
+        const RowVectorDIMS & p,
+        const Scalar sqr_d_candidate,
+        const int i_candidate,
+        const RowVectorDIMS & c_candidate,
+        Scalar & sqr_d,
+        int & i,
+        RowVectorDIMS & c) const;
+public:
+      template <int SS>
+      static
+      inline void barycentric_coordinates(
+        const RowVectorDIMS & p, 
+        const RowVectorDIMS & a, 
+        const RowVectorDIMS & b, 
+        const RowVectorDIMS & c,
+        Eigen::Matrix<Scalar,1,SS> & bary);
+public:
+      EIGEN_MAKE_ALIGNED_OPERATOR_NEW
     };
 }
 
@@ -241,7 +283,9 @@ namespace igl
 #include "sort.h"
 #include "volume.h"
 #include <iostream>
+#include <iomanip>
 #include <limits>
+#include <list>
 
 template <typename DerivedV, int DIM>
   template <typename Derivedbb_mins, typename Derivedbb_maxs>
@@ -273,12 +317,21 @@ inline void igl::AABB<DerivedV,DIM>::init(
       m_left->init( V,Ele,bb_mins,bb_maxs,elements,2*i+1);
       m_right = new AABB();
       m_right->init( V,Ele,bb_mins,bb_maxs,elements,2*i+2);
+      //m_depth = std::max( m_left->m_depth, m_right->m_depth)+1;
     }
   }else
   {
     VectorXi allI = colon<int>(0,Ele.rows()-1);
     MatrixXDIMS BC;
-    barycenter(V,Ele,BC);
+    if(Ele.cols() == 1)
+    {
+      // points
+      BC = V;
+    }else
+    {
+      // Simplices
+      barycenter(V,Ele,BC);
+    }
     MatrixXi SI(BC.rows(),BC.cols());
     {
       MatrixXDIMS _;
@@ -384,15 +437,18 @@ inline void igl::AABB<DerivedV,DIM>::init(
             }
           }
         }
+        //m_depth = 0;
         if(LI.rows()>0)
         {
           m_left = new AABB();
           m_left->init(V,Ele,SI,LI);
+          //m_depth = std::max(m_depth, m_left->m_depth+1);
         }
         if(RI.rows()>0)
         {
           m_right = new AABB();
           m_right->init(V,Ele,SI,RI);
+          //m_depth = std::max(m_depth, m_right->m_depth+1);
         }
       }
   }
@@ -584,7 +640,7 @@ igl::AABB<DerivedV,DIM>::squared_distance(
     const auto & look_left = [&]()
     {
       int i_left;
-      RowVectorDIMS c_left;
+      RowVectorDIMS c_left = c;
       Scalar sqr_d_left = m_left->squared_distance(V,Ele,p,sqr_d,i_left,c_left);
       set_min(p,sqr_d_left,i_left,c_left,sqr_d,i,c);
       looked_left = true;
@@ -592,7 +648,7 @@ igl::AABB<DerivedV,DIM>::squared_distance(
     const auto & look_right = [&]()
     {
       int i_right;
-      RowVectorDIMS c_right;
+      RowVectorDIMS c_right = c;
       Scalar sqr_d_right = m_right->squared_distance(V,Ele,p,sqr_d,i_right,c_right);
       set_min(p,sqr_d_right,i_right,c_right,sqr_d,i,c);
       looked_right = true;
@@ -663,6 +719,269 @@ inline void igl::AABB<DerivedV,DIM>::squared_distance(
   }
 }
 
+template <typename DerivedV, int DIM>
+template < 
+  typename Derivedother_V,
+  typename DerivedsqrD, 
+  typename DerivedI, 
+  typename DerivedC>
+inline void igl::AABB<DerivedV,DIM>::squared_distance(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const AABB<Derivedother_V,DIM> & other,
+  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+  const Eigen::MatrixXi & other_Ele, 
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C) const
+{
+  assert(other_Ele.cols() == 1 && 
+    "Only implemented for other as list of points");
+  assert(other_V.cols() == V.cols() && "other must match this dimension");
+  sqrD.setConstant(other_Ele.rows(),1,std::numeric_limits<double>::infinity());
+  I.resize(other_Ele.rows(),1);
+  C.resize(other_Ele.rows(),other_V.cols());
+  // All points in other_V currently think they need to check against root of
+  // this. The point of using another AABB is to quickly prune chunks of
+  // other_V so that most points just check some subtree of this.
+
+  // This holds a conservative estimate of max(sqr_D) where sqr_D is the
+  // current best minimum squared distance for all points in this subtree
+  double min_sqr_d = std::numeric_limits<double>::infinity();
+  squared_distance_helper(
+    V,Ele,&other,other_V,other_Ele,min_sqr_d,sqrD,I,C);
+}
+
+template <typename DerivedV, int DIM>
+template < 
+  typename Derivedother_V,
+  typename DerivedsqrD, 
+  typename DerivedI, 
+  typename DerivedC>
+inline typename igl::AABB<DerivedV,DIM>::Scalar igl::AABB<DerivedV,DIM>::squared_distance_helper(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::MatrixXi & Ele, 
+  const AABB<Derivedother_V,DIM> * other,
+  const Eigen::PlainObjectBase<Derivedother_V> & other_V,
+  const Eigen::MatrixXi & other_Ele, 
+  const Scalar min_sqr_d,
+  Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
+  Eigen::PlainObjectBase<DerivedI> & I,
+  Eigen::PlainObjectBase<DerivedC> & C) const
+{
+  using namespace std;
+  using namespace Eigen;
+
+  // This implementation is a bit disappointing. There's no major speed up. Any
+  // performance gains seem to come from accidental cache coherency and
+  // diminish for larger "other" (the opposite of what was intended).
+
+  // Base case
+  if(other->is_leaf() && this->is_leaf())
+  {
+    Scalar sqr_d = sqrD(other->m_primitive);
+    int i = I(other->m_primitive);
+    RowVectorDIMS c = C.row(      other->m_primitive);
+    RowVectorDIMS p = other_V.row(other->m_primitive);
+    leaf_squared_distance(V,Ele,p,sqr_d,i,c);
+    sqrD( other->m_primitive) = sqr_d;
+    I(    other->m_primitive) = i;
+    C.row(other->m_primitive) = c;
+    //cout<<"leaf: "<<sqr_d<<endl;
+    //other->m_max_sqr_d = sqr_d;
+    return sqr_d;
+  }
+
+  if(other->is_leaf())
+  {
+    Scalar sqr_d = sqrD(other->m_primitive);
+    int i = I(other->m_primitive);
+    RowVectorDIMS c = C.row(      other->m_primitive);
+    RowVectorDIMS p = other_V.row(other->m_primitive);
+    sqr_d = squared_distance(V,Ele,p,sqr_d,i,c);
+    sqrD( other->m_primitive) = sqr_d;
+    I(    other->m_primitive) = i;
+    C.row(other->m_primitive) = c;
+    //other->m_max_sqr_d = sqr_d;
+    return sqr_d;
+  }
+
+  //// Exact minimum squared distance between arbitary primitives inside this and
+  //// othre's bounding boxes
+  //const auto & min_squared_distance = [&](
+  //  const AABB<DerivedV,DIM> * A,
+  //  const AABB<Derivedother_V,DIM> * B)->Scalar
+  //{
+  //  return A->m_box.squaredExteriorDistance(B->m_box);
+  //};
+
+  if(this->is_leaf())
+  {
+    //if(min_squared_distance(this,other) < other->m_max_sqr_d)
+    if(true)
+    {
+      this->squared_distance_helper(
+        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
+      this->squared_distance_helper(
+        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
+    }else
+    {
+      // This is never reached...
+    }
+    //// we know other is not a leaf
+    //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+    return 0;
+  }
+
+  // FORCE DOWN TO OTHER LEAF EVAL
+  //if(min_squared_distance(this,other) < other->m_max_sqr_d)
+  if(true)
+  {
+    if(true)
+    {
+      this->squared_distance_helper(
+        V,Ele,other->m_left,other_V,other_Ele,0,sqrD,I,C);
+      this->squared_distance_helper(
+        V,Ele,other->m_right,other_V,other_Ele,0,sqrD,I,C);
+    }else // this direction never seems to be faster
+    {
+      this->m_left->squared_distance_helper(
+        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
+      this->m_right->squared_distance_helper(
+        V,Ele,other,other_V,other_Ele,0,sqrD,I,C);
+    }
+  }else
+  {
+    // this is never reached ... :-(
+  }
+  //// we know other is not a leaf
+  //other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+
+  return 0;
+#if false
+
+  // _Very_ conservative approximation of maximum squared distance between
+  // primitives inside this and other's bounding boxes
+  const auto & max_squared_distance = [](
+    const AABB<DerivedV,DIM> * A,
+    const AABB<Derivedother_V,DIM> * B)->Scalar
+  {
+    AlignedBox<Scalar,DIM> combo = A->m_box;
+    combo.extend(B->m_box);
+    return combo.diagonal().squaredNorm();
+  };
+
+  //// other base-case
+  //if(other->is_leaf())
+  //{
+  //  double sqr_d = sqrD(other->m_primitive);
+  //  int i = I(other->m_primitive);
+  //  RowVectorDIMS c = C.row(m_primitive);
+  //  RowVectorDIMS p = other_V.row(m_primitive);
+  //  leaf_squared_distance(V,Ele,p,sqr_d,i,c);
+  //  sqrD(other->m_primitive) = sqr_d;
+  //  I(other->m_primitive) = i;
+  //  C.row(m_primitive) = c;
+  //  return;
+  //}
+  std::vector<const AABB<DerivedV,DIM> * > this_list;
+  if(this->is_leaf())
+  {
+    this_list.push_back(this);
+  }else
+  {
+    assert(this->m_left);
+    this_list.push_back(this->m_left);
+    assert(this->m_right);
+    this_list.push_back(this->m_right);
+  }
+  std::vector<AABB<Derivedother_V,DIM> *> other_list;
+  if(other->is_leaf())
+  {
+    other_list.push_back(other);
+  }else
+  {
+    assert(other->m_left);
+    other_list.push_back(other->m_left);
+    assert(other->m_right);
+    other_list.push_back(other->m_right);
+  }
+
+  //const std::function<Scalar(
+  //  const AABB<Derivedother_V,DIM> * other)
+  //    > max_sqr_d = [&sqrD,&max_sqr_d](const AABB<Derivedother_V,DIM> * other)->Scalar
+  //  {
+  //    if(other->is_leaf())
+  //    {
+  //      return sqrD(other->m_primitive);
+  //    }else
+  //    {
+  //      return std::max(max_sqr_d(other->m_left),max_sqr_d(other->m_right));
+  //    }
+  //  };
+
+  //// Potentially recurse on all pairs, if minimum distance is less than running
+  //// bound
+  //Eigen::Matrix<Scalar,Eigen::Dynamic,1> other_max_sqr_d =
+  //  Eigen::Matrix<Scalar,Eigen::Dynamic,1>::Constant(other_list.size(),1,min_sqr_d);
+  for(size_t child = 0;child<other_list.size();child++)
+  {
+    auto other_tree = other_list[child];
+
+    Eigen::Matrix<Scalar,Eigen::Dynamic,1> this_max_sqr_d(this_list.size(),1);
+    for(size_t t = 0;t<this_list.size();t++)
+    {
+      const auto this_tree = this_list[t];
+      this_max_sqr_d(t) = max_squared_distance(this_tree,other_tree);
+    }
+    if(this_list.size() ==2 &&
+      ( this_max_sqr_d(0) > this_max_sqr_d(1))
+      )
+    {
+      std::swap(this_list[0],this_list[1]);
+      //std::swap(this_max_sqr_d(0),this_max_sqr_d(1));
+    }
+    const Scalar sqr_d = this_max_sqr_d.minCoeff();
+
+
+    for(size_t t = 0;t<this_list.size();t++)
+    {
+      const auto this_tree = this_list[t];
+
+      //const auto mm = max_sqr_d(other_tree);
+      //const Scalar mc = other_max_sqr_d(child);
+      //assert(mc == mm);
+      // Only look left/right in this_list if can possible decrease somebody's
+      // distance in this_tree.
+      const Scalar min_this_other = min_squared_distance(this_tree,other_tree); 
+      if(
+          min_this_other < sqr_d && 
+          min_this_other < other_tree->m_max_sqr_d)
+      {
+        //cout<<"before: "<<other_max_sqr_d(child)<<endl;
+        //other_max_sqr_d(child) = std::min(
+        //  other_max_sqr_d(child),
+        //  this_tree->squared_distance_helper(
+        //    V,Ele,other_tree,other_V,other_Ele,other_max_sqr_d(child),sqrD,I,C));
+        //cout<<"after: "<<other_max_sqr_d(child)<<endl;
+          this_tree->squared_distance_helper(
+            V,Ele,other_tree,other_V,other_Ele,0,sqrD,I,C);
+      }
+    }
+  }
+  //const Scalar ret = other_max_sqr_d.maxCoeff();
+  //const auto mm = max_sqr_d(other);
+  //assert(mm == ret);
+  //cout<<"non-leaf: "<<ret<<endl;
+  //return ret;
+  if(!other->is_leaf())
+  {
+    other->m_max_sqr_d = std::max(other->m_left->m_max_sqr_d,other->m_right->m_max_sqr_d);
+  }
+  return 0;
+#endif
+}
+
 template <typename DerivedV, int DIM>
 inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   const Eigen::PlainObjectBase<DerivedV> & V,
@@ -719,6 +1038,7 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   }
   const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
   {
+    cout<<"pp"<<endl;
     const Scalar sqr_d_s = (p-s).squaredNorm();
     set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
   };
@@ -779,7 +1099,9 @@ inline void igl::AABB<DerivedV,DIM>::set_min(
   RowVectorDIMS & c) const
 {
 #ifndef NDEBUG
-  const Scalar diff = fabs(sqr_d_candidate - (p-c_candidate).squaredNorm());
+  //std::cout<<matlab_format(c_candidate,"c_candidate")<<std::endl;
+  const Scalar pc_norm = (p-c_candidate).squaredNorm();
+  const Scalar diff = fabs(sqr_d_candidate - pc_norm);
   assert(diff<=1e-10 && "distance should match norm of difference");
 #endif
   if(sqr_d_candidate < sqr_d)

+ 3 - 2
include/igl/ReAntTweakBar.h

@@ -276,9 +276,10 @@ namespace igl
 //TW_API int      TW_CALL TwRemoveVar(TwBar *bar, const char *name);
 //TW_API int      TW_CALL TwRemoveAllVars(TwBar *bar);
 
-#ifndef IGL_STATIC_LIBRARY
+// Until AntTweakBar dependency folder exists, this is header-only
+//#ifndef IGL_STATIC_LIBRARY
 #  include "ReAntTweakBar.cpp"
-#endif
+//#endif
 
 #endif
 #endif

+ 4 - 0
include/igl/cgal/mesh_to_cgal_triangle_list.cpp

@@ -38,4 +38,8 @@ IGL_INLINE void igl::mesh_to_cgal_triangle_list(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+template void igl::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+template void igl::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
+template void igl::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epeck>, std::allocator<CGAL::Triangle_3<CGAL::Epeck> > >&);
+template void igl::mesh_to_cgal_triangle_list<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epick>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<CGAL::Triangle_3<CGAL::Epick>, std::allocator<CGAL::Triangle_3<CGAL::Epick> > >&);
 #endif

+ 4 - 8
include/igl/cgal/outer_hull.cpp

@@ -16,6 +16,7 @@
 #include <map>
 #include <queue>
 #include <iostream>
+#include <type_traits>
 #include <CGAL/number_utils.h>
 //#define IGL_OUTER_HULL_DEBUG
 
@@ -525,17 +526,12 @@ IGL_INLINE void igl::outer_hull(
 
 
 #ifdef IGL_STATIC_LIBRARY
-
+// Explicit template specialization
+#undef IGL_STATIC_LIBRARY
 #include <igl/barycenter.cpp>
-template void igl::barycenter<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&);
-
 #include <igl/outer_facet.cpp>
-template void igl::outer_facet<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
-
 #include <igl/cgal/order_facets_around_edges.cpp>
-template std::__1::enable_if<std::is_same<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>::Scalar, CGAL::Lazy_exact_nt<CGAL::Gmpq> >::value, void>::type igl::order_facets_around_edges<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, long, long, bool>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, std::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > > const&, std::__1::vector<std::__1::vector<long, std::__1::allocator<long> >, std::__1::allocator<std::__1::vector<long, std::__1::allocator<long> > > >&, std::__1::vector<std::__1::vector<bool, std::__1::allocator<bool> >, std::__1::allocator<std::__1::vector<bool, std::__1::allocator<bool> > > >&);
-
-// Explicit template specialization
+#define IGL_STATIC_LIBRARY
 template void igl::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 template void igl::outer_hull<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 template void igl::outer_hull<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);

+ 2 - 2
include/igl/cocoa_key_to_anttweakbar_key.h

@@ -22,9 +22,9 @@ namespace igl
   IGL_INLINE int cocoa_key_to_anttweakbar_key(int key);
 }
 
-#ifndef IGL_STATIC_LIBRARY
+//#ifndef IGL_STATIC_LIBRARY
 #  include "cocoa_key_to_anttweakbar_key.cpp"
-#endif
+//#endif
 
 #endif
 #endif

+ 2 - 2
include/igl/embree/EmbreeIntersector.h

@@ -95,7 +95,7 @@ namespace igl
       const Eigen::RowVector3f& direction,
       Hit& hit,
       float tnear = 0,
-      float tfar = -1,
+      float tfar = std::numeric_limits<float>::infinity(),
       int mask = 0xFFFFFFFF) const;
 
     // Given a ray find the first hit
@@ -394,7 +394,7 @@ inline bool igl::EmbreeIntersector::intersectBeam(
   else
     bestHit.t = 0;
 
-  if(hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask) && (hit.gid == geoId || geoId == -1)))
+  if(hasHit = ((intersectRay(origin,direction,hit,tnear,tfar,mask)) && (hit.gid == geoId || geoId == -1)))
     bestHit = hit;
   
   // sample points around actual ray (conservative hitcheck)

+ 0 - 4
include/igl/in_element.h

@@ -44,10 +44,6 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedQ> & Q,
     const AABB<DerivedV,DIM> & aabb,
     Eigen::SparseMatrix<Scalar> & I);
-  //
-  // Example:
-  //   InElementAABB aabb;
-  //   aabb.init(V,Ele);
 };
 
 #ifndef IGL_STATIC_LIBRARY

+ 0 - 65
include/igl/kronecker_product.cpp

@@ -1,65 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#include "kronecker_product.h"
-
-//// Bug in unsupported/Eigen/SparseExtra needs iostream first
-//#include <iostream>
-//#include <unsupported/Eigen/SparseExtra>
-//
-//template <typename Scalar>
-//IGL_INLINE Eigen::SparseMatrix<Scalar> igl::kronecker_product(
-//  const Eigen::SparseMatrix<Scalar> & A,
-//  const Eigen::SparseMatrix<Scalar> & B)
-//{
-//  using namespace Eigen;
-//  using namespace std;
-//
-//  // Convert B in triplets format
-//  MatrixXd B_triplets(B.nonZeros(),3);
-//  int count = 0;
-//  for (int k=0; k<B.outerSize(); ++k)
-//    for (SparseMatrix<double>::InnerIterator it(B,k); it; ++it)
-//      B_triplets.row(count++) << it.row(), it.col(), it.value();
-//
-//  MatrixXd C_triplets(B_triplets.rows()*A.nonZeros(),3);
-//  count = 0;
-//  for (int k=0; k<A.outerSize(); ++k)
-//    for (SparseMatrix<double>::InnerIterator it(A,k); it; ++it)
-//    {
-//      int i = it.row();
-//      int j = it.col();
-//      double v = it.value();
-//
-//      MatrixXd B_triplets_copy = B_triplets;
-//      B_triplets_copy.col(0) = B_triplets_copy.col(0).array() + double(B.rows()*i);
-//      B_triplets_copy.col(1) = B_triplets_copy.col(1).array() + double(B.cols()*j);
-//      B_triplets_copy.col(2) = B_triplets_copy.col(2).array() * v;
-//
-//      C_triplets.block(count*B_triplets.rows(),0,
-//                       B_triplets.rows(), B_triplets.cols()) = B_triplets_copy;
-//
-//      count++;
-//    }
-//
-//  typedef Eigen::Triplet<double> T;
-//  std::vector<T> triplets;
-//  triplets.reserve(C_triplets.rows());
-//  
-//  for(unsigned i=0; i<C_triplets.rows(); ++i)
-//    triplets.push_back(T(C_triplets(i,0),C_triplets(i,1),C_triplets(i,2)));
-//  SparseMatrix<Scalar> C(A.rows()*B.rows(),A.cols()*B.cols());
-//  C.setFromTriplets(triplets.begin(),triplets.end());
-//  
-//  return C;
-//}
-//
-//#ifdef IGL_STATIC_LIBRARY
-//// Explicit template specialization
-//// generated by autoexplicit.sh
-//template Eigen::SparseMatrix<double, 0, int> igl::kronecker_product<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&);
-//#endif

+ 0 - 40
include/igl/kronecker_product.h

@@ -1,40 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_KRONECKERPRODUCT_H
-#define IGL_KRONECKERPRODUCT_H
-
-// Obsolete: Use 
-// #include <unsupported/Eigen/src/KroneckerProduct>
-// ...
-// Eigen::kroneckerProduct(A,B,C);
-
-//#include "igl_inline.h"
-//
-//#include <Eigen/Dense>
-//#include <Eigen/Sparse>
-//
-//namespace igl
-//{
-//  // Computes the Kronecker product between sparse matrices A and B.
-//  //
-//  // Inputs:
-//  //   A  #M by #N sparse matrix
-//  //   B  #P by #Q sparse matrix
-//  // Returns #M*#P by #N*#Q sparse matrix
-//  //
-//  template <typename Scalar>
-//  IGL_INLINE Eigen::SparseMatrix<Scalar> kronecker_product(
-//    const Eigen::SparseMatrix<Scalar> & A,
-//    const Eigen::SparseMatrix<Scalar> & B);
-//}
-//
-//#ifndef IGL_STATIC_LIBRARY
-//#  include "kronecker_product.cpp"
-//#endif
-
-#endif

+ 19 - 2
include/igl/matlab/parse_rhs.cpp

@@ -7,13 +7,30 @@ IGL_INLINE void igl::parse_rhs_double(
     Eigen::PlainObjectBase<DerivedV> & V)
 {
   using namespace std;
+  using namespace Eigen;
   // set number of mesh vertices
   const int n = mxGetM(prhs[0]);
   // set vertex position pointers
   double * Vp = mxGetPr(prhs[0]);
   const int dim = mxGetN(prhs[0]);
-  V.resize(n,dim);
-  copy(Vp,Vp+n*dim,&V.data()[0]);
+
+  typedef typename DerivedV::Scalar Scalar;
+  Matrix<Scalar, DerivedV::ColsAtCompileTime, DerivedV::RowsAtCompileTime, RowMajor> VT;
+  Scalar * V_data;
+  if(DerivedV::IsRowMajor)
+  {
+    VT.resize(dim,n);
+    V_data = VT.data();
+  }else
+  {
+    V.resize(n,dim);
+    V_data = V.data();
+  }
+  copy(Vp,Vp+n*dim,V_data);
+  if(DerivedV::IsRowMajor)
+  {
+    V = VT.transpose();
+  }
 }
 
 template <typename DerivedV>

+ 30 - 2
include/igl/matlab/prepare_lhs.cpp

@@ -6,9 +6,23 @@ IGL_INLINE void igl::prepare_lhs_double(
   mxArray *plhs[])
 {
   using namespace std;
+  using namespace Eigen;
   plhs[0] = mxCreateDoubleMatrix(V.rows(),V.cols(), mxREAL);
   double * Vp = mxGetPr(plhs[0]);
-  copy(&V.data()[0],&V.data()[0]+V.size(),Vp);
+
+  typedef typename DerivedV::Scalar Scalar;
+  const Scalar * V_data;
+  Matrix<Scalar, DerivedV::ColsAtCompileTime, DerivedV::RowsAtCompileTime, RowMajor> VT;
+  if(DerivedV::IsRowMajor)
+  {
+    VT = V.transpose();
+    V_data = VT.data();
+  }else
+  {
+    V_data = V.data();
+  }
+
+  copy(V_data,V_data+V.size(),Vp);
 }
 
 template <typename DerivedV>
@@ -17,9 +31,23 @@ IGL_INLINE void igl::prepare_lhs_logical(
   mxArray *plhs[])
 {
   using namespace std;
+  using namespace Eigen;
   plhs[0] = mxCreateLogicalMatrix(V.rows(),V.cols());
   mxLogical * Vp = static_cast<mxLogical*>(mxGetData(plhs[0]));
-  copy(&V.data()[0],&V.data()[0]+V.size(),Vp);
+
+  typedef typename DerivedV::Scalar Scalar;
+  const Scalar * V_data;
+  Matrix<Scalar, DerivedV::ColsAtCompileTime, DerivedV::RowsAtCompileTime, RowMajor> VT;
+  if(DerivedV::IsRowMajor)
+  {
+    VT = V.transpose();
+    V_data = VT.data();
+  }else
+  {
+    V_data = V.data();
+  }
+
+  copy(V_data,V_data+V.size(),Vp);
 }
 
 template <typename DerivedV>

+ 1 - 0
include/igl/point_mesh_squared_distance.cpp

@@ -29,4 +29,5 @@ IGL_INLINE void igl::point_mesh_squared_distance(
 }
 
 #ifdef IGL_STATIC_LIBRARY
+template void igl::point_mesh_squared_distance<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -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> > const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> 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> >&);
 #endif

+ 64 - 0
include/igl/pseudonormal_test.cpp

@@ -0,0 +1,64 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2014 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 "pseudonormal_test.h"
+#include "AABB.h"
+#include <cassert>
+
+IGL_INLINE void igl::pseudonormal_test(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & FN,
+  const Eigen::MatrixXd & VN,
+  const Eigen::MatrixXd & EN,
+  const Eigen::VectorXi & EMAP,
+  const Eigen::RowVector3d & q,
+  const int f,
+  const Eigen::RowVector3d & c,
+  double & s,
+  Eigen::RowVector3d & n)
+{
+  using namespace Eigen;
+  const auto & qc = q-c;
+  RowVector3d b;
+  AABB<Eigen::MatrixXd,3>::barycentric_coordinates(
+    c,V.row(F(f,0)),V.row(F(f,1)),V.row(F(f,2)),b);
+  // Determine which normal to use
+  const double epsilon = 1e-12;
+  const int type = (b.array()<=epsilon).cast<int>().sum();
+  switch(type)
+  {
+    case 2:
+      // Find vertex
+      for(int x = 0;x<3;x++)
+      {
+        if(b(x)>epsilon)
+        {
+          n = VN.row(F(f,x));
+          break;
+        }
+      }
+      break;
+    case 1:
+      // Find edge
+      for(int x = 0;x<3;x++)
+      {
+        if(b(x)<=epsilon)
+        {
+          n = EN.row(EMAP(F.rows()*x+f));
+          break;
+        }
+      }
+      break;
+    default:
+      assert(false && "all barycentric coords zero.");
+    case 0:
+      n = FN.row(f);
+      break;
+  }
+  s = (qc.dot(n) >= 0 ? 1. : -1.);
+}

+ 48 - 0
include/igl/pseudonormal_test.h

@@ -0,0 +1,48 @@
+// 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_PSEUDONORMAL_TEST_H
+#define IGL_PSEUDONORMAL_TEST_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // Given a mesh (V,F), a query point q, and a point on (V,F) c, determine
+  // whether q is inside (V,F) --> s=-1 or outside (V,F) s=1, based on the
+  // sign of the dot product between (q-c) and n, where n is the normal _at c_,
+  // carefully chosen according to [Bærentzen & Aanæs 2005]
+  //
+  // Inputs:
+  //   V  #V by 3 list of vertex positions
+  //   F  #F by 3 list of triangle indices
+  //   FN  #F by 3 list of triangle normals 
+  //   VN  #V by 3 list of vertex normals (ANGLE WEIGHTING)
+  //   EN  #E by 3 list of edge normals (UNIFORM WEIGHTING)
+  //   EMAP  #F*3 mapping edges in F to E
+  //   q  Query point
+  //   i  index into F to face to which c belongs
+  //   c  Point on (V,F)
+  // Outputs:
+  //   s  sign
+  //   n  normal
+  IGL_INLINE void pseudonormal_test(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::MatrixXd & FN,
+    const Eigen::MatrixXd & VN,
+    const Eigen::MatrixXd & EN,
+    const Eigen::VectorXi & EMAP,
+    const Eigen::RowVector3d & q,
+    const int i,
+    const Eigen::RowVector3d & c,
+    double & s,
+    Eigen::RowVector3d & n);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "pseudonormal_test.cpp"
+#endif
+#endif

+ 56 - 40
include/igl/signed_distance.cpp

@@ -6,11 +6,12 @@
 // 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 "signed_distance.h"
-#include "per_vertex_normals.h"
+#include "get_seconds.h"
 #include "per_edge_normals.h"
 #include "per_face_normals.h"
-#include "get_seconds.h"
+#include "per_vertex_normals.h"
 #include "point_mesh_squared_distance.h"
+#include "pseudonormal_test.h"
 
 
 IGL_INLINE void igl::signed_distance(
@@ -117,6 +118,58 @@ IGL_INLINE double igl::signed_distance_pseudonormal(
   return s*sqrt(sqrd);
 }
 
+IGL_INLINE void igl::signed_distance_pseudonormal(
+  const Eigen::MatrixXd & P,
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const AABB<Eigen::MatrixXd,3> & tree,
+  const Eigen::MatrixXd & FN,
+  const Eigen::MatrixXd & VN,
+  const Eigen::MatrixXd & EN,
+  const Eigen::VectorXi & EMAP,
+  Eigen::VectorXd & S,
+  Eigen::VectorXi & I,
+  Eigen::MatrixXd & C,
+  Eigen::MatrixXd & N)
+{
+  using namespace Eigen;
+  const size_t np = P.rows();
+  S.resize(np,1);
+  I.resize(np,1);
+  N.resize(np,3);
+  C.resize(np,3);
+# pragma omp parallel for if(np>1000)
+  for(size_t p = 0;p<np;p++)
+  {
+    double s,sqrd;
+    RowVector3d n,c;
+    int i = -1;
+    RowVector3d q = P.row(p);
+    signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n);
+    S(p) = s*sqrt(sqrd);
+    I(p) = i;
+    N.row(p) = n;
+    C.row(p) = c;
+  }
+//  igl::AABB<MatrixXd,3> tree_P;
+//  MatrixXi J = VectorXi::LinSpaced(P.rows(),0,P.rows()-1);
+//  tree_P.init(P,J);
+//  tree.squared_distance(V,F,tree_P,P,J,S,I,C);
+//# pragma omp parallel for if(np>1000)
+//  for(size_t p = 0;p<np;p++)
+//  {
+//    RowVector3d c = C.row(p);
+//    RowVector3d q = P.row(p);
+//    const int f = I(p);
+//    double s;
+//    RowVector3d n;
+//    pseudonormal_test(V,F,FN,VN,EN,EMAP,q,f,c,s,n);
+//    N.row(p) = n;
+//    S(p) = s*sqrt(S(p));
+//  }
+
+}
+
 IGL_INLINE void igl::signed_distance_pseudonormal(
   const AABB<Eigen::MatrixXd,3> & tree,
   const Eigen::MatrixXd & V,
@@ -135,44 +188,7 @@ IGL_INLINE void igl::signed_distance_pseudonormal(
   using namespace Eigen;
   using namespace std;
   sqrd = tree.squared_distance(V,F,q,f,c);
-  const auto & qc = q-c;
-  RowVector3d b;
-  AABB<Eigen::MatrixXd,3>::barycentric_coordinates(
-    c,V.row(F(f,0)),V.row(F(f,1)),V.row(F(f,2)),b);
-  // Determine which normal to use
-  const double epsilon = 1e-12;
-  const int type = (b.array()<=epsilon).cast<int>().sum();
-  switch(type)
-  {
-    case 2:
-      // Find vertex
-      for(int x = 0;x<3;x++)
-      {
-        if(b(x)>epsilon)
-        {
-          n = VN.row(F(f,x));
-          break;
-        }
-      }
-      break;
-    case 1:
-      // Find edge
-      for(int x = 0;x<3;x++)
-      {
-        if(b(x)<=epsilon)
-        {
-          n = EN.row(EMAP(F.rows()*x+f));
-          break;
-        }
-      }
-      break;
-    default:
-      assert(false && "all barycentric coords zero.");
-    case 0:
-      n = FN.row(f);
-      break;
-  }
-  s = (qc.dot(n) >= 0 ? 1. : -1.);
+  pseudonormal_test(V,F,FN,VN,EN,EMAP,q,f,c,s,n);
 }
 
 IGL_INLINE double igl::signed_distance_winding_number(

+ 14 - 0
include/igl/signed_distance.h

@@ -7,6 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_SIGNED_DISTANCE_H
 #define IGL_SIGNED_DISTANCE_H
+
 #include "igl_inline.h"
 #include "AABB.h"
 #include "WindingNumberAABB.h"
@@ -90,6 +91,19 @@ namespace igl
     int & i,
     Eigen::RowVector3d & c,
     Eigen::RowVector3d & n);
+  IGL_INLINE void signed_distance_pseudonormal(
+    const Eigen::MatrixXd & P,
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const AABB<Eigen::MatrixXd,3> & tree,
+    const Eigen::MatrixXd & FN,
+    const Eigen::MatrixXd & VN,
+    const Eigen::MatrixXd & EN,
+    const Eigen::VectorXi & EMAP,
+    Eigen::VectorXd & S,
+    Eigen::VectorXi & I,
+    Eigen::MatrixXd & C,
+    Eigen::MatrixXd & N);
 
   // Inputs:
   //   tree  AABB acceleration tree (see cgal/point_mesh_squared_distance.h)

+ 1 - 0
include/igl/triangle_triangle_adjacency.cpp

@@ -239,4 +239,5 @@ template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, 3, 0, -
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::triangle_triangle_adjacency<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::triangle_triangle_adjacency<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<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

+ 1 - 0
include/igl/winding_number.cpp

@@ -213,4 +213,5 @@ IGL_INLINE void igl::winding_number_2(
 // Explicit template specialization
 template void igl::winding_number_2<double>(double const*, int, double const*, int, double const*, int, double*);
 template void igl::winding_number_3<double>(double const*, int, double const*, int, double const*, int, double*);
+template void igl::winding_number_3<double, int>(double const*, int, int const*, int, double const*, int, double*);
 #endif

+ 25 - 22
index.html

@@ -28,28 +28,32 @@ mesh-viewing utilities for OpenGL and GLSL, and many core functions for matrix
 manipulation which make <a href="http://eigen.tuxfamily.org">Eigen</a> feel a lot more
 like MATLAB.</p>
 
-<p>It is first and foremost a header library. Each header file contains a single
-function. Most are tailored to operate on a generic triangle mesh stored in an
-n-by&#8211;3 matrix of vertex positions V and an m-by&#8211;3 matrix of triangle indices F.
-The library may also be <a href="build/">compiled</a> into a statically linked
-library, for faster compile times with your projects.</p>
+<p>It is <strong>a header-only library</strong>. You do not need to compile anything to use,
+just include igl headers (e.g. <code>#include &lt;igl/cotmatrix.h&gt;</code>) and run. Each
+header file contains a single function (e.g. <code>igl/cotmatrix.h</code> contains
+<code>igl::cotmatrix()</code>). Most are tailored to operate on a generic triangle mesh
+stored in an n-by&#8211;3 matrix of vertex positions V and an m-by&#8211;3 matrix of
+triangle indices F. </p>
+
+<p><em>Optionally</em> the library may also be <a href="build/">pre-compiled</a> into a statically
+linked library, for faster compile times with your projects. This only effects
+compile time (run-time performance and behavior is identical). If in doubt, use
+the header-only default mode: (i.e. just include the headers you want to use).</p>
 
 <p>We use the <a href="http://eigen.tuxfamily.org">Eigen</a> library heavily in our code. Our
-group prototypes a lot in MATLAB, and we have a useful <a href="matlab-to-eigen.html">conversion
-table</a> from
-MATLAB to libigl/Eigen.</p>
+group prototypes a lot in MATLAB, and we have a useful <a href="matlab-to-eigen.html">MATLAB to libigl+Eigen
+conversion table</a>.</p>
 
 <h2 id="tutorial">Tutorial</h2>
 
 <p>As of version 1.0, libigl includes an introductory
-<a href="tutorial/tutorial.html">tutorial</a> that covers
-its basic functionalities.</p>
+<a href="tutorial/tutorial.html">tutorial</a> that covers many functionalities.</p>
 
 <h2 id="installation">Installation</h2>
 
-<p>Libigl is a <em>header</em> library. You do <strong>not</strong> need to build anything to install.
-Simply add <code>igl/</code> to your include path and include relevant headers. Here is a
-small &#8220;Hello, World&#8221; program:</p>
+<p>Libigl is a <strong>header-only</strong> library. You do <strong>not</strong> need to build anything to
+install. Simply add <code>libigl/include</code> to your include path and include relevant
+headers. Here is a small &#8220;Hello, World&#8221; program:</p>
 
 <pre><code class="cpp">#include &lt;igl/cotmatrix.h&gt;
 #include &lt;Eigen/Dense&gt;
@@ -73,9 +77,9 @@ int main()
 </code></pre>
 
 <p>If you save this in <code>hello.cpp</code>, then you could compile this with (assuming
-Eigen is installed in /opt/local/include/eigen3):</p>
+Eigen is installed in <code>/usr/local/include/eigen3</code>):</p>
 
-<pre><code class="bash">gcc -I/opt/local/include/eigen3 -I./igl/ hello.cpp -o hello
+<pre><code class="bash">gcc -I/usr/local/include/eigen3 -I./libigl/include/ hello.cpp -o hello
 </code></pre>
 
 <p>Running <code>./hello</code> would then produce</p>
@@ -103,10 +107,9 @@ GCC 4.7 and clang will work correctly.</p>
 <h3 id="openmpandwindows">OpenMP and Windows</h3>
 
 <p>Some of our functions will take advantage of OpenMP if available. However, it
-has come to our attention that Visual Studio + Eigen does not work properly
-with OpenMP. Since OpenMP only improves performance without affecting
-functionality we recommend avoiding OpenMP on Windows or proceeding with
-caution.</p>
+has come to our attention that Visual Studio + Eigen + OpenMP does not work
+properly. Since we use OpenMP only to improve performance, we recommend
+avoiding OpenMP on Windows or proceeding with caution.</p>
 
 <h2 id="download">Download</h2>
 
@@ -116,9 +119,9 @@ caution.</p>
 <h2 id="knownissues">Known Issues</h2>
 
 <p>We really heavily on Eigen. Nearly all inputs and outputs are Eigen matrices of
-some kind. However, we currently <em>only</em> support Eigen&#8217;s default column-major
-ordering. That means, we <strong>do not</strong> expect our code to work for matrices using
-the <code>Eigen::RowMajor</code> flag. If you can, change definitions like:</p>
+some kind. However, we currently <em>only</em> officially support Eigen&#8217;s default
+column-major ordering. That means, we <strong>do not</strong> expect our code to work for
+matrices using the <code>Eigen::RowMajor</code> flag. If you can, change definitions like:</p>
 
 <pre><code class="cpp">Eigen::Matrix&lt;double, Eigen::Dynamic, 3, Eigen::RowMajor&gt; A;
 </code></pre>

+ 60 - 24
CMakeLists.txt → optional/CMakeLists.txt

@@ -4,7 +4,7 @@ project(libigl)
 SET(CMAKE_SKIP_RULE_DEPENDENCY 1)
 
 # SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ../../lib)
-SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/tutorial/cmake)
+SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../tutorial/cmake)
 find_package(EIGEN REQUIRED)
 
 add_definitions(-DIGL_STATIC_LIBRARY)
@@ -23,6 +23,12 @@ if (ANTTWEAKBAR_FOUND)
   include_directories( ${ANT_TWEAK_BAR_INCLUDE_DIR})
 endif(ANTTWEAKBAR_FOUND)
 
+## Check for Boost
+find_package(BOOST QUIET)
+if (Boost_FOUND)
+  include_directories( ${BOOST_INCLUDE_DIR})
+endif(Boost_FOUND)
+
 
 ## Check for CoMiSo, if not available skip the examples that depends on it
 find_package(LIBCOMISO QUIET)
@@ -47,9 +53,11 @@ find_package(CGAL QUIET)
 
 ## Check for mosek
 find_package(MOSEK QUIET)
-if(NOT MOSEK_FOUND)
+if(MOSEK_FOUND)
+  include_directories(${MOSEK_INCLUDE_DIR})
+else(MOSEK_FOUND)
   add_definitions(-DIGL_NO_MOSEK)
-endif(NOT MOSEK_FOUND)
+endif(MOSEK_FOUND)
 
 ## Check for CORK
 find_package(CORK QUIET)
@@ -65,6 +73,14 @@ if(LIM_FOUND)
   include_directories( ${LIM_INCLUDE_DIR})
 endif(LIM_FOUND)
 
+## Check for PNG
+find_package(PNG QUIET)
+if(PNG_FOUND)
+  include_directories( ${PNG_INCLUDE_DIR})
+else(PNG_FOUND)
+  message(STATUS "PNG not found")
+endif(PNG_FOUND)
+
 ## Check for SVD3X3
 find_package(SVD3X3 QUIET)
 if(SVD3X3_FOUND)
@@ -102,27 +118,41 @@ if (OPENMP_FOUND AND NOT WIN32)
   set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
 endif()
 
+## Check for YIMG
+find_package(YIMG QUIET)
+if(YIMG_FOUND)
+  include_directories( ${YIMG_INCLUDE_DIR})
+else(YIMG_FOUND)
+  message(STATUS "YIMG not found")
+endif(YIMG_FOUND)
+
 #### Libigl requires a modern C++ compiler that supports c++11
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 
 #### Compile the core library that depends only on EIGEN ####
 include_directories( ${EIGEN_INCLUDE_DIR})
-include_directories( ${PROJECT_SOURCE_DIR}/include/)
+include_directories( ${PROJECT_SOURCE_DIR}/../include/)
 
 file(GLOB SOURCES
-  "${PROJECT_SOURCE_DIR}/include/igl/*.cpp"
+  "${PROJECT_SOURCE_DIR}/../include/igl/*.cpp"
 )
 
-### HACKS TO CLEAN
-list(REMOVE_ITEM SOURCES ${ui} ${PROJECT_SOURCE_DIR}/include/igl/cocoa_key_to_anttweakbar_key.cpp)
-list(REMOVE_ITEM SOURCES ${ui} ${PROJECT_SOURCE_DIR}/include/igl/ReAntTweakBar.cpp)
-
 add_library(igl STATIC ${SOURCES})
 
+#### Compile the boost part
+if (Boost_FOUND)
+  file(GLOB SOURCES_BOOST
+    "${PROJECT_SOURCE_DIR}/../include/igl/boost/*.cpp"
+  )
+add_library(iglboost STATIC ${SOURCES_BOOST})
+else (Boost_FOUND)
+  message(STATUS "Boost not found.")
+endif (Boost_FOUND)
+
 #### Compile the BBW part
 
 file(GLOB SOURCES_BBW
-  "${PROJECT_SOURCE_DIR}/include/igl/bbw/*.cpp"
+  "${PROJECT_SOURCE_DIR}/../include/igl/bbw/*.cpp"
 )
 
 add_library(iglbbw STATIC ${SOURCES_BBW})
@@ -130,16 +160,15 @@ add_library(iglbbw STATIC ${SOURCES_BBW})
 #### Compile the mosek part (untested)
 if (MOSEK_FOUND)
   file(GLOB SOURCES_MOSEK
-    "${PROJECT_SOURCE_DIR}/include/igl/mosek/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/mosek/*.cpp"
   )
-
 add_library(iglmosek STATIC ${SOURCES_MOSEK})
 endif (MOSEK_FOUND)
 
 #### Compile the cgal part
 if (CGAL_FOUND)
   file(GLOB SOURCES_CGAL
-    "${PROJECT_SOURCE_DIR}/include/igl/cgal/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/cgal/*.cpp"
   )
 
 add_library(iglcgal STATIC ${SOURCES_CGAL})
@@ -150,7 +179,7 @@ if (NOT CORK_FOUND)
 endif(NOT CORK_FOUND)
 
 file(GLOB SOURCES_BOOLEAN
-  "${PROJECT_SOURCE_DIR}/include/igl/boolean/*.cpp"
+  "${PROJECT_SOURCE_DIR}/../include/igl/boolean/*.cpp"
 )
 
 add_library(iglboolean STATIC ${SOURCES_BOOLEAN})
@@ -159,7 +188,7 @@ endif (CGAL_FOUND)
 #### Compile the embree part
 if (EMBREE_FOUND)
   file(GLOB SOURCES_EMBREE
-    "${PROJECT_SOURCE_DIR}/include/igl/embree/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/embree/*.cpp"
   )
 
   add_library(iglembree STATIC ${SOURCES_EMBREE})
@@ -168,7 +197,7 @@ endif (EMBREE_FOUND)
 #### Compile the lim part
 if (LIM_FOUND)
   file(GLOB SOURCES_LIM
-    "${PROJECT_SOURCE_DIR}/include/igl/lim/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/lim/*.cpp"
   )
 
   add_library(igllim STATIC ${SOURCES_LIM})
@@ -177,25 +206,32 @@ endif (LIM_FOUND)
 #### Compile the matlab part
 if (MATLAB_FOUND)
   file(GLOB SOURCES_MATLAB
-    "${PROJECT_SOURCE_DIR}/include/igl/matlab/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/matlab/*.cpp"
   )
 
   add_library(iglmatlab STATIC ${SOURCES_MATLAB})
 endif (MATLAB_FOUND)
 
+#### Compile the png part
+if (PNG_FOUND)
+  file(GLOB SOURCES_PNG
+    "${PROJECT_SOURCE_DIR}/../include/igl/png/*.cpp"
+  )
+  add_library(iglpng STATIC ${SOURCES_PNG})
+endif (PNG_FOUND)
+
 #### Compile the svd3x3 part
 if (SVD3X3_FOUND)
   file(GLOB SOURCES_SVD3X3
-    "${PROJECT_SOURCE_DIR}/include/igl/svd3x3/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/svd3x3/*.cpp"
   )
-
   add_library(iglsvd3x3 STATIC ${SOURCES_SVD3X3})
 endif (SVD3X3_FOUND)
 
 #### Compile the tetgen part
 if (TETGEN_FOUND)
   file(GLOB SOURCES_TETGEN
-    "${PROJECT_SOURCE_DIR}/include/igl/tetgen/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/tetgen/*.cpp"
   )
 
   add_library(igltetgen STATIC ${SOURCES_TETGEN})
@@ -204,7 +240,7 @@ endif (TETGEN_FOUND)
 #### Compile the triangle part
 if (TRIANGLE_FOUND)
   file(GLOB SOURCES_TRIANGLE
-    "${PROJECT_SOURCE_DIR}/include/igl/triangle/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/triangle/*.cpp"
   )
 
   add_library(igltriangle STATIC ${SOURCES_TRIANGLE})
@@ -213,7 +249,7 @@ endif (TRIANGLE_FOUND)
 #### Compile the xml part
 if (TINYXML2_FOUND)
   file(GLOB SOURCES_XML
-    "${PROJECT_SOURCE_DIR}/include/igl/xml/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/xml/*.cpp"
   )
 
   add_library(iglxml STATIC ${SOURCES_XML})
@@ -222,7 +258,7 @@ endif (TINYXML2_FOUND)
 #### Compile the xml part
 if (LIBCOMISO_FOUND)
   file(GLOB SOURCES_COMISO
-    "${PROJECT_SOURCE_DIR}/include/igl/comiso/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/comiso/*.cpp"
   )
 
   add_library(iglcomiso STATIC ${SOURCES_COMISO})
@@ -231,7 +267,7 @@ endif (LIBCOMISO_FOUND)
 #### Compile the viewer
 if (GLFW_FOUND AND ANTTWEAKBAR_FOUND)
   file(GLOB SOURCES_XML
-    "${PROJECT_SOURCE_DIR}/include/igl/viewer/*.cpp"
+    "${PROJECT_SOURCE_DIR}/../include/igl/viewer/*.cpp"
   )
 
   add_library(iglviewer STATIC ${SOURCES_XML})

+ 27 - 24
build/README.md → optional/README.md

@@ -1,9 +1,9 @@
 # Compiling libigl as a static library
 
 > Warning: compiling libigl as a static library is considerably more difficult
-> than using it as a header-only library (see `../README.md` instead). Do it
-> only if you are experienced with C++ and you want to improve your compilation
-> times.
+> than using it as a header-only library (see [../README.md](../) instead). Do
+> it only if you are experienced with C++, cmake and make, and you want to
+> improve your compilation times.
 
 Libigl is developed most often on Mac OS X, though has current users in Linux
 and Windows.
@@ -14,30 +14,27 @@ Libigl may also be compiled to a static library. This is advantageous when
 building a project with libigl, since when used as an header-only library can
 slow down compile times.
 
-To build the entire libigl library producing `lib/libigl.a`, issue:
+To build the entire libigl library producing at least `libigl/lib/libigl.a` and
+possible other (automatically detected) extras, e.g. `libigl/lib/libiglcgal.a`
+from _this current directory_: issue:
 
-    cd build
-    make lib
-
-You may need to edit `Makefile.conf` accordingly. Best to give yourself an
-`IGL_USERNAME` and add a custom install suite for yourself. Then you can enable
-appropriate extras.
-
-#### Extras ####
-Once you've set up an `IGL_USERNAME` and enabled extras within Makefile.conf.
-You can build the extra libraries (into `lib/ligiglpng.a`, `lib/libiglmatlab.a`,
-`lib/libigltetgen.a`, `lib/libiglmosek.a`, etc.) by issuing:
-
-    cd build
-    make extras
+    mkdir -p ../lib
+    cd ../lib
+    cmake -DCMAKE_BUILD_TYPE=Release ..
+    make
 
 #### Examples ####
 You can make a slew of examples by issuing:
 
-    cd build
-    make examples
+    cd ../examples
+    make
 
 #### External ####
+
+> **Deprecation notice** All external libraries will be absorbed by libigl or
+> moved to separate git sub-repositories in the near future. The following
+> instructions are subject to immediate change.
+
 Finally there are a number of external libraries that we include in
 `./external/` because they are either difficult to obtain or they have been
 patched for easier use with libigl. Please see the respective readmes in those
@@ -45,7 +42,7 @@ directories.
 
 
 ##### Installing AntTweakBar #####
-To build the a static AntTweakBar library on Mac OS X issue:
+To build a static AntTweakBar library on Mac OS X issue:
 
     cd external/AntTweakBar/src
     make -f Makefile.osx.igl
@@ -100,6 +97,10 @@ installed at `/usr/X11/lib`.
 
 
 ### Windows (Experimental) ###
+
+> **Deprecation notice** Windows users should run cmake on the `CMakeLists.txt`
+> file in the current directory.
+
 To build a static library (.lib) on windows, open Visual Studio 2010.
 
 - New > Project ...
@@ -325,9 +326,11 @@ Alternatively, you can also compress everything into a single header file:
   `AntTweakBar`, `BLAS`). However, because all
   depencies other than Eigen should be encapsulated between
   `#ifndef` guards (e.g. `#ifndef IGL_NO_OPENGL`, it
-  is possible to ignore certain functions that have such dependencies.</li>
-  <li><strong>Long compile:</strong> Compiling `igl.cpp` takes a long time and isn't easily parallelized (no `make -j12` equivalent).</li>
-  </ul>
+  is possible to ignore certain functions that have such dependencies.
+
+* **Long compile**: 
+  Compiling `igl.cpp` takes a long time and isn't easily parallelized (no `make
+  -j12` equivalent).
 
 Here's a tiny test example using `igl.h` and `igl.cpp`. Save the following in `test.cpp`:
 

+ 0 - 0
build/index.html → optional/index.html


+ 11 - 0
tutorial/704_SignedDistance/CMakeLists.txt

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.6)
+project(704_SignedDistance)
+
+include("../CMakeLists.shared")
+
+set(SOURCES
+${PROJECT_SOURCE_DIR}/main.cpp
+)
+
+add_executable(${PROJECT_NAME}_bin ${SOURCES} ${SHARED_SOURCES})
+target_link_libraries(${PROJECT_NAME}_bin ${SHARED_LIBRARIES})

+ 157 - 0
tutorial/704_SignedDistance/main.cpp

@@ -0,0 +1,157 @@
+#include <igl/cat.h>
+#include <igl/edge_lengths.h>
+#include <igl/parula.h>
+#include <igl/per_edge_normals.h>
+#include <igl/per_face_normals.h>
+#include <igl/per_vertex_normals.h>
+#include <igl/point_mesh_squared_distance.h>
+#include <igl/readMESH.h>
+#include <igl/signed_distance.h>
+#include <igl/slice_mask.h>
+#include <igl/slice_tets.h>
+#include <igl/upsample.h>
+#include <igl/viewer/Viewer.h>
+#include <Eigen/Sparse>
+#include <iostream>
+
+Eigen::MatrixXd V;
+Eigen::MatrixXi T,F;
+igl::AABB<Eigen::MatrixXd,3> tree;
+Eigen::MatrixXd FN,VN,EN;
+Eigen::MatrixXi E;
+Eigen::VectorXi EMAP;
+double max_distance = 1;
+
+double slice_z = 0.5;
+bool overlay = false;
+
+void update_visualization(igl::Viewer & viewer)
+{
+  using namespace Eigen;
+  using namespace std;
+  Eigen::Vector4d plane(
+    0,0,1,-((1-slice_z)*V.col(2).minCoeff()+slice_z*V.col(2).maxCoeff()));
+  MatrixXd V_vis;
+  MatrixXi F_vis;
+  // Extract triangle mesh slice through volume mesh and subdivide nasty
+  // triangles
+  {
+    VectorXi J;
+    SparseMatrix<double> bary;
+    igl::slice_tets(V,T,plane,V_vis,F_vis,J,bary);
+    while(true)
+    {
+      MatrixXd l;
+      igl::edge_lengths(V_vis,F_vis,l);
+      l /= (V_vis.colwise().maxCoeff() - V_vis.colwise().minCoeff()).norm();
+      const double max_l = 0.03;
+      if(l.maxCoeff()<max_l)
+      {
+        break;
+      }
+      Array<bool,Dynamic,1> bad = l.array().rowwise().maxCoeff() > max_l;
+      MatrixXi F_vis_bad, F_vis_good;
+      igl::slice_mask(F_vis,bad,1,F_vis_bad);
+      igl::slice_mask(F_vis,(bad!=true).eval(),1,F_vis_good);
+      igl::upsample(V_vis,F_vis_bad);
+      F_vis = igl::cat(1,F_vis_bad,F_vis_good);
+    }
+  }
+
+  // Compute signed distance
+  VectorXd S_vis;
+  {
+    VectorXi I;
+    MatrixXd N,C;
+    // Bunny is a watertight mesh so use pseudonormal for signing
+    signed_distance_pseudonormal(V_vis,V,F,tree,FN,VN,EN,EMAP,S_vis,I,C,N);
+  }
+  // push to [0,1] range
+  S_vis.array() = 0.5*(S_vis.array()/max_distance)+0.5;
+  MatrixXd C_vis;
+  // color without normalizing
+  igl::parula(S_vis,false,C_vis);
+
+
+  const auto & append_mesh = [&C_vis,&F_vis,&V_vis](
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const RowVector3d & color)
+  {
+    F_vis.conservativeResize(F_vis.rows()+F.rows(),3);
+    F_vis.bottomRows(F.rows()) = F.array()+V_vis.rows();
+    V_vis.conservativeResize(V_vis.rows()+V.rows(),3);
+    V_vis.bottomRows(V.rows()) = V;
+    C_vis.conservativeResize(C_vis.rows()+V.rows(),3);
+    C_vis.bottomRows(V.rows()).rowwise() = color;
+  };
+  if(overlay)
+  {
+    append_mesh(V,F,RowVector3d(0.8,0.8,0.8));
+  }
+  viewer.data.clear();
+  viewer.data.set_mesh(V_vis,F_vis);
+  viewer.data.set_colors(C_vis);
+  viewer.core.lighting_factor = overlay;
+}
+
+bool key_down(igl::Viewer& viewer, unsigned char key, int mod)
+{
+  switch(key)
+  {
+    default:
+      return false;
+    case ' ':
+      overlay ^= true;
+      break;
+    case '.':
+      slice_z = std::min(slice_z+0.01,0.99);
+      break;
+    case ',':
+      slice_z = std::max(slice_z-0.01,0.01);
+      break;
+  }
+  update_visualization(viewer);
+  return true;
+}
+
+int main(int argc, char *argv[])
+{
+  using namespace Eigen;
+  using namespace std;
+
+  cout<<"Usage:"<<endl;
+  cout<<"[space]  toggle showing surface."<<endl;
+  cout<<"'.'/','  push back/pull forward slicing plane."<<endl;
+  cout<<endl;
+
+  // Load mesh: (V,T) tet-mesh of convex hull, F contains original surface
+  // triangles
+  igl::readMESH("../shared/bunny.mesh",V,T,F);
+
+
+  // Encapsulated call to point_mesh_squared_distance to determine bounds
+  {
+    VectorXd sqrD;
+    VectorXi I;
+    MatrixXd C;
+    igl::point_mesh_squared_distance(V,V,F,sqrD,I,C);
+    max_distance = sqrt(sqrD.maxCoeff());
+  }
+
+  // Precompute signed distance AABB tree
+  tree.init(V,F);
+  // Precompute vertex,edge and face normals
+  igl::per_face_normals(V,F,FN);
+  igl::per_vertex_normals(
+    V,F,igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
+  igl::per_edge_normals(
+    V,F,igl::PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
+
+  // Plot the generated mesh
+  igl::Viewer viewer;
+  update_visualization(viewer);
+  viewer.callback_key_down = &key_down;
+  viewer.core.show_lines = false;
+  viewer.launch();
+}

+ 1 - 0
tutorial/CMakeLists.txt

@@ -80,3 +80,4 @@ endif()
 add_subdirectory("701_Statistics")
 add_subdirectory("702_WindingNumber")
 add_subdirectory("703_Decimation")
+add_subdirectory("704_SignedDistance")

+ 63 - 0
tutorial/cmake/FindPNG.cmake

@@ -0,0 +1,63 @@
+# - Find the native PNG includes and library
+#
+
+# This module defines
+#  PNG_INCLUDE_DIR, where to find png.h, etc.
+#  PNG_LIBRARIES, the libraries to link against to use PNG.
+#  PNG_DEFINITIONS - You should ADD_DEFINITONS(${PNG_DEFINITIONS}) before compiling code that includes png library files.
+#  PNG_FOUND, If false, do not try to use PNG.
+# also defined, but not for general use are
+#  PNG_LIBRARY, where to find the PNG library.
+# None of the above will be defined unles zlib can be found.
+# PNG depends on Zlib
+#
+# Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+# See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+
+INCLUDE(FindZLIB)
+
+SET(PNG_FOUND "NO")
+
+IF(ZLIB_FOUND)
+  FIND_PATH(PNG_PNG_INCLUDE_DIR png.h
+  /usr/local/include
+  /usr/include
+  /usr/local/include/libpng             # OpenBSD
+  )
+
+  SET(PNG_NAMES ${PNG_NAMES} png libpng)
+  FIND_LIBRARY(PNG_LIBRARY
+    NAMES ${PNG_NAMES}
+    PATHS /usr/lib64 /usr/lib /usr/local/lib
+  )
+
+  IF (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR)
+      # png.h includes zlib.h. Sigh.
+      SET(PNG_INCLUDE_DIR ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} )
+      SET(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY})
+      SET(PNG_FOUND "YES")
+			SET(HAVE_PNG_H)
+      IF (CYGWIN)
+        IF(BUILD_SHARED_LIBS)
+           # No need to define PNG_USE_DLL here, because it's default for Cygwin.
+        ELSE(BUILD_SHARED_LIBS)
+          SET (PNG_DEFINITIONS -DPNG_STATIC)
+        ENDIF(BUILD_SHARED_LIBS)
+      ENDIF (CYGWIN)
+
+  ENDIF (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR)
+
+ENDIF(ZLIB_FOUND)
+
+IF (PNG_FOUND)
+  IF (NOT PNG_FIND_QUIETLY)
+    MESSAGE(STATUS "Found PNG: ${PNG_LIBRARY}")
+  ENDIF (NOT PNG_FIND_QUIETLY)
+ELSE (PNG_FOUND)
+  IF (PNG_FIND_REQUIRED)
+    MESSAGE(FATAL_ERROR "Could not find PNG library")
+  ENDIF (PNG_FIND_REQUIRED)
+ENDIF (PNG_FOUND)
+
+MARK_AS_ADVANCED(PNG_PNG_INCLUDE_DIR PNG_LIBRARY )

+ 1 - 0
tutorial/cmake/FindTETGEN.cmake

@@ -8,6 +8,7 @@
 FIND_PATH(TETGEN_INCLUDE_DIR tetgen.h
    ${PROJECT_SOURCE_DIR}/../libigl/external/tetgen/
    ${PROJECT_SOURCE_DIR}/../../external/tetgen/
+   ${PROJECT_SOURCE_DIR}/../external/tetgen/
    /usr/include
    /usr/local/include
    NO_DEFAULT_PATH

+ 1 - 0
tutorial/cmake/FindTINYXML2.cmake

@@ -10,6 +10,7 @@ FIND_PATH(TINYXML2_INCLUDE_DIR tinyxml2.h
    /usr/local/include
    ${PROJECT_SOURCE_DIR}/../libigl/external/tinyxml2/
    ${PROJECT_SOURCE_DIR}/../../external/tinyxml2/
+   ${PROJECT_SOURCE_DIR}/../external/tinyxml2/
    ${PROJECT_SOURCE_DIR}/external/tinyxml2/
 )
 

+ 1 - 0
tutorial/cmake/FindTRIANGLE.cmake

@@ -14,6 +14,7 @@ FIND_PATH(TRIANGLE_INCLUDE_DIR triangle.h
    /usr/local/include
    ${PROJECT_SOURCE_DIR}/../libigl/external/triangle/
    ${PROJECT_SOURCE_DIR}/../../external/triangle/
+   ${PROJECT_SOURCE_DIR}/../external/triangle/
    NO_DEFAULT_PATH
 )
 

+ 32 - 0
tutorial/cmake/FindYIMG.cmake

@@ -0,0 +1,32 @@
+# - Try to find the YIMG library
+# Once done this will define
+#
+#  YIMG_FOUND - system has YIMG
+#  YIMG_INCLUDE_DIR - the YIMG include directory
+#  YIMG_LIBRARIES - the YIMG libraries
+
+FIND_PATH(YIMG_INCLUDE_DIR YImage.hpp
+   /usr/include
+   /usr/local/include
+   /opt/local/include
+   $ENV{LIBIGL}/external/yimg
+)
+
+set(YIMG_LIB_DIRS
+   /usr/include
+   /usr/local/include
+   /opt/local/include
+   $ENV{LIBIGL}/external/yimg)
+FIND_LIBRARY( YIMG_LIBRARIES NAMES yimg PATHS ${YIMG_LIB_DIRS})
+
+if(YIMG_INCLUDE_DIR AND YIMG_LIBRARIES)
+   message(STATUS "Found YIMG: ${YIMG_INCLUDE_DIR}")
+   set(YIMG_FOUND "YES")
+else()
+   message(WARNING "could NOT find YIMG")
+   set(YIMG_FOUND "NO")
+endif()
+
+MARK_AS_ADVANCED(YIMG_INCLUDE_DIR YIMG_LIBRARIES)
+
+

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно