diff --git a/external/AntTweakBar/src/Makefile.osx.igl b/external/AntTweakBar/src/Makefile.osx.igl
index 809cc77a6..2747a600d 100755
--- a/external/AntTweakBar/src/Makefile.osx.igl
+++ b/external/AntTweakBar/src/Makefile.osx.igl
@@ -13,12 +13,16 @@ OUT_DIR = ../lib
#OUT_DIR = ../lib/debug
#BASE = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks
+ifndef CXX
CXX = gcc
+endif
#CXXFLAGS = $(CXXCFG) -Wall -fPIC -fno-strict-aliasing -D_MACOSX -ObjC++ -D__PLACEMENT_NEW_INLINE
CXXFLAGS = $(CXXCFG) -Wall -fPIC -fno-strict-aliasing -D_MACOSX -x objective-c++ -D__PLACEMENT_NEW_INLINE
INCPATH = -I../include -I/usr/local/include -I/usr/X11R6/include -I/usr/include
#-I$(BASE)/OpenGL.framework/Headers/ -I$(BASE)/GLUT.framework/Headers/ -I$(BASE)/AppKit.framework/Headers/
+ifndef LINK
LINK = gcc
+endif
#LIBS = -L/usr/X11R6/lib -L. -lglfw -lGL -lGLU -lX11 -lXxf86vm -lXext -lpthread -lm
#LIBS = -L/usr/X11R6/lib -lGL -lX11 -lXxf86vm -lXext -lpthread -lm
LIBS = -framework OpenGL -framework GLUT -framework AppKit
@@ -40,7 +44,9 @@ NO_STDERR = 2> /dev/null
# name of the application:
+ifndef TARGET
TARGET = AntTweakBar
+endif
# source files without extension:
SRC_FILES = TwColors.cpp TwFonts.cpp TwOpenGL.cpp TwOpenGLCore.cpp TwBar.cpp TwMgr.cpp LoadOGL.cpp LoadOGLCore.cpp TwEventGLFW.c TwEventGLUT.c TwEventSDL.c TwEventSDL12.c TwEventSDL13.c TwEventSFML.cpp
diff --git a/include/igl/boolean/MeshBooleanType.h b/include/igl/boolean/MeshBooleanType.h
index e12ce6542..035bbfa47 100644
--- a/include/igl/boolean/MeshBooleanType.h
+++ b/include/igl/boolean/MeshBooleanType.h
@@ -1,14 +1,17 @@
#ifndef MESH_BOOLEAN_TYPE_H
#define MESH_BOOLEAN_TYPE_H
-enum MeshBooleanType
+namespace igl
{
- MESH_BOOLEAN_TYPE_UNION = 0,
- MESH_BOOLEAN_TYPE_INTERSECT = 1,
- MESH_BOOLEAN_TYPE_MINUS = 2,
- MESH_BOOLEAN_TYPE_XOR = 3,
- MESH_BOOLEAN_TYPE_RESOLVE = 4,
- NUM_MESH_BOOLEAN_TYPES = 5
+ enum MeshBooleanType
+ {
+ MESH_BOOLEAN_TYPE_UNION = 0,
+ MESH_BOOLEAN_TYPE_INTERSECT = 1,
+ MESH_BOOLEAN_TYPE_MINUS = 2,
+ MESH_BOOLEAN_TYPE_XOR = 3,
+ MESH_BOOLEAN_TYPE_RESOLVE = 4,
+ NUM_MESH_BOOLEAN_TYPES = 5
+ };
};
#endif
diff --git a/include/igl/boolean/from_cork_mesh.cpp b/include/igl/boolean/from_cork_mesh.cpp
index 674173e70..7c15262cf 100644
--- a/include/igl/boolean/from_cork_mesh.cpp
+++ b/include/igl/boolean/from_cork_mesh.cpp
@@ -31,6 +31,7 @@ IGL_INLINE void igl::from_cork_mesh(
#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
template void igl::from_cork_mesh, Eigen::Matrix >(CorkTriMesh const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
+template void igl::from_cork_mesh, Eigen::Matrix >(CorkTriMesh const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
#endif
#endif
diff --git a/include/igl/boolean/mesh_boolean.cpp b/include/igl/boolean/mesh_boolean.cpp
index 9cb69ad5f..6ba4308b4 100644
--- a/include/igl/boolean/mesh_boolean.cpp
+++ b/include/igl/boolean/mesh_boolean.cpp
@@ -11,7 +11,8 @@ template <
typename DerivedVB,
typename DerivedFB,
typename DerivedVC,
- typename DerivedFC>
+ typename DerivedFC,
+ typename DerivedJ>
IGL_INLINE void igl::mesh_boolean(
const Eigen::PlainObjectBase & VA,
const Eigen::PlainObjectBase & FA,
@@ -19,15 +20,17 @@ IGL_INLINE void igl::mesh_boolean(
const Eigen::PlainObjectBase & FB,
const MeshBooleanType & type,
Eigen::PlainObjectBase & VC,
- Eigen::PlainObjectBase & FC)
+ Eigen::PlainObjectBase & FC,
+ Eigen::PlainObjectBase & J)
{
const std::function &,
const Eigen::Matrix&,
Eigen::Matrix &,
- Eigen::Matrix&)>
+ Eigen::Matrix&,
+ Eigen::Matrix&)>
empty_fun;
- return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC);
+ return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J);
}
template <
@@ -37,6 +40,34 @@ template <
typename DerivedFB,
typename DerivedVC,
typename DerivedFC>
+IGL_INLINE void igl::mesh_boolean(
+ const Eigen::PlainObjectBase & VA,
+ const Eigen::PlainObjectBase & FA,
+ const Eigen::PlainObjectBase & VB,
+ const Eigen::PlainObjectBase & FB,
+ const MeshBooleanType & type,
+ Eigen::PlainObjectBase & VC,
+ Eigen::PlainObjectBase & FC)
+{
+ Eigen::Matrix J;
+ const std::function &,
+ const Eigen::Matrix&,
+ Eigen::Matrix &,
+ Eigen::Matrix&,
+ Eigen::Matrix&)>
+ empty_fun;
+ return mesh_boolean(VA,FA,VB,FB,type,empty_fun,VC,FC,J);
+}
+
+template <
+ typename DerivedVA,
+ typename DerivedFA,
+ typename DerivedVB,
+ typename DerivedFB,
+ typename DerivedVC,
+ typename DerivedFC,
+ typename DerivedJ>
IGL_INLINE void igl::mesh_boolean(
const Eigen::PlainObjectBase & VA,
const Eigen::PlainObjectBase & FA,
@@ -47,10 +78,12 @@ IGL_INLINE void igl::mesh_boolean(
const Eigen::Matrix&,
const Eigen::Matrix&,
Eigen::Matrix&,
- Eigen::Matrix&)>
+ Eigen::Matrix&,
+ Eigen::Matrix&)>
& resolve_fun,
Eigen::PlainObjectBase & VC,
- Eigen::PlainObjectBase & FC)
+ Eigen::PlainObjectBase & FC,
+ Eigen::PlainObjectBase & J)
{
using namespace Eigen;
using namespace std;
@@ -63,6 +96,7 @@ IGL_INLINE void igl::mesh_boolean(
typedef Matrix MatrixX3I;
typedef Matrix MatrixX2I;
typedef Matrix VectorXI;
+ typedef Matrix VectorXJ;
MatrixX3S V(VA.rows()+VB.rows(),3);
MatrixX3I F(FA.rows()+FB.rows(),3);
V.block(0,0,VA.rows(),VA.cols()) = VA;
@@ -89,14 +123,15 @@ IGL_INLINE void igl::mesh_boolean(
const MatrixX3S & V,
const MatrixX3I & F,
MatrixX3S & CV,
- MatrixX3I & CF)
+ MatrixX3I & CF,
+ VectorXJ & J)
{
MatrixX3S SV;
MatrixX3I SF;
MatrixX2I SIF;
- VectorXI SJ,SIM,UIM;
+ VectorXI SIM,UIM;
RemeshSelfIntersectionsParam params;
- remesh_self_intersections(V,F,params,SV,SF,SIF,SJ,SIM);
+ remesh_self_intersections(V,F,params,SV,SF,SIF,J,SIM);
for_each(SF.data(),SF.data()+SF.size(),[&SIM](int & a){a=SIM(a);});
{
remove_unreferenced(SV,SF,CV,CF,UIM);
@@ -105,18 +140,20 @@ IGL_INLINE void igl::mesh_boolean(
MatrixX3S CV;
MatrixX3I CF;
+ VectorXJ CJ;
if(resolve_fun)
{
- resolve_fun(V,F,CV,CF);
+ resolve_fun(V,F,CV,CF,CJ);
}else
{
- libigl_resolve(V,F,CV,CF);
+ libigl_resolve(V,F,CV,CF,CJ);
}
if(type == MESH_BOOLEAN_TYPE_RESOLVE)
{
FC = CF;
VC = CV;
+ J = CJ;
return;
}
@@ -152,7 +189,7 @@ IGL_INLINE void igl::mesh_boolean(
if((!odd(f) && !flip(f)) || (odd(f) && flip(f)))
{
vG.push_back(f);
- Gflip.push_back(false);
+ Gflip.push_back(type == MESH_BOOLEAN_TYPE_MINUS);
}
break;
default:
@@ -162,14 +199,23 @@ IGL_INLINE void igl::mesh_boolean(
}
const Index gm = vG.size();
MatrixX3I G(gm,3);
+ VectorXi GJ(gm,1);
for(Index g = 0;g, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
+template void igl::mesh_boolean, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
+template void igl::mesh_boolean, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
#endif
diff --git a/include/igl/boolean/mesh_boolean.h b/include/igl/boolean/mesh_boolean.h
index 096507bb3..464ab12b7 100644
--- a/include/igl/boolean/mesh_boolean.h
+++ b/include/igl/boolean/mesh_boolean.h
@@ -19,9 +19,27 @@ namespace igl
// Outputs:
// W #W by 3 list of vertex positions of boolean result mesh
// H #H by 3 list of triangle indices into W
+ // J #H list of indices into [FA;FB] revealing "birth" facet
//
// See also: self_intersect
//
+ template <
+ typename DerivedVA,
+ typename DerivedFA,
+ typename DerivedVB,
+ typename DerivedFB,
+ typename DerivedVC,
+ typename DerivedFC,
+ typename DerivedJ>
+ IGL_INLINE void mesh_boolean(
+ const Eigen::PlainObjectBase & VA,
+ const Eigen::PlainObjectBase & FA,
+ const Eigen::PlainObjectBase & VB,
+ const Eigen::PlainObjectBase & FB,
+ const MeshBooleanType & type,
+ Eigen::PlainObjectBase & VC,
+ Eigen::PlainObjectBase & FC,
+ Eigen::PlainObjectBase & J);
template <
typename DerivedVA,
typename DerivedFA,
@@ -46,7 +64,8 @@ namespace igl
typename DerivedVB,
typename DerivedFB,
typename DerivedVC,
- typename DerivedFC>
+ typename DerivedFC,
+ typename DerivedJ>
IGL_INLINE void mesh_boolean(
const Eigen::PlainObjectBase & VA,
const Eigen::PlainObjectBase & FA,
@@ -55,12 +74,14 @@ namespace igl
const MeshBooleanType & type,
const std::function &,
- const Eigen::Matrix &,
+ const Eigen::Matrix &,
Eigen::Matrix &,
- Eigen::Matrix &)>
+ Eigen::Matrix &,
+ Eigen::Matrix&)>
& resolve_fun,
Eigen::PlainObjectBase & VC,
- Eigen::PlainObjectBase & FC);
+ Eigen::PlainObjectBase & FC,
+ Eigen::PlainObjectBase & J);
}
#ifndef IGL_STATIC_LIBRARY
diff --git a/include/igl/boolean/mesh_boolean_cork.cpp b/include/igl/boolean/mesh_boolean_cork.cpp
index b82a1d7a9..65f2f7844 100644
--- a/include/igl/boolean/mesh_boolean_cork.cpp
+++ b/include/igl/boolean/mesh_boolean_cork.cpp
@@ -88,6 +88,7 @@ IGL_INLINE void igl::mesh_boolean_cork(
#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
template void igl::mesh_boolean_cork, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
+template void igl::mesh_boolean_cork, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
#endif
#endif
diff --git a/include/igl/boolean/to_cork_mesh.cpp b/include/igl/boolean/to_cork_mesh.cpp
index 7aba7f44c..c30997eb4 100644
--- a/include/igl/boolean/to_cork_mesh.cpp
+++ b/include/igl/boolean/to_cork_mesh.cpp
@@ -33,5 +33,6 @@ IGL_INLINE void igl::to_cork_mesh(
#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
template void igl::to_cork_mesh, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, CorkTriMesh&);
+template void igl::to_cork_mesh, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, CorkTriMesh&);
#endif
#endif
diff --git a/include/igl/cgal/remesh_self_intersections.cpp b/include/igl/cgal/remesh_self_intersections.cpp
index 80f6c5c37..57d9278f9 100644
--- a/include/igl/cgal/remesh_self_intersections.cpp
+++ b/include/igl/cgal/remesh_self_intersections.cpp
@@ -84,4 +84,5 @@ IGL_INLINE void igl::remesh_self_intersections(
// Explicit template specialization
template void igl::remesh_self_intersections, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
template void igl::remesh_self_intersections, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
+template void igl::remesh_self_intersections, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, igl::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&);
#endif
diff --git a/include/igl/matlab/mexStream.h b/include/igl/matlab/mexStream.h
index 242184f36..079fb5f61 100644
--- a/include/igl/matlab/mexStream.h
+++ b/include/igl/matlab/mexStream.h
@@ -32,6 +32,7 @@ namespace igl
}
// Implementation
+#include
inline std::streamsize igl::MexStream::xsputn(
const char *s,
std::streamsize n)
diff --git a/include/igl/matlab/prepare_lhs.cpp b/include/igl/matlab/prepare_lhs.cpp
index 2d46e423a..cfa455909 100644
--- a/include/igl/matlab/prepare_lhs.cpp
+++ b/include/igl/matlab/prepare_lhs.cpp
@@ -37,4 +37,5 @@ IGL_INLINE void igl::prepare_lhs_index(
template void igl::prepare_lhs_index >(Eigen::PlainObjectBase > const&, mxArray_tag**);
template void igl::prepare_lhs_index >(Eigen::PlainObjectBase > const&, mxArray_tag**);
template void igl::prepare_lhs_double >(Eigen::PlainObjectBase > const&, mxArray_tag**);
+template void igl::prepare_lhs_index >(Eigen::PlainObjectBase > const&, mxArray_tag**);
#endif
diff --git a/include/igl/triangle_triangle_adjacency.cpp b/include/igl/triangle_triangle_adjacency.cpp
index d4d6f4733..a0555ef35 100644
--- a/include/igl/triangle_triangle_adjacency.cpp
+++ b/include/igl/triangle_triangle_adjacency.cpp
@@ -137,7 +137,6 @@ template <
using namespace std;
assert(F.cols() == 3 && "Faces must be triangles");
// number of faces
- const int m = F.rows();
typedef typename DerivedF::Index Index;
typedef Matrix MatrixX2I;
typedef Matrix VectorXI;
@@ -166,7 +165,7 @@ template <
using namespace Eigen;
typedef typename DerivedE::Index Index;
const size_t m = E.rows()/3;
- assert(E.rows() == m*3 && "E should come from list of triangles.");
+ assert((size_t)E.rows() == m*3 && "E should come from list of triangles.");
// E2E[i] --> {j,k,...} means face edge i corresponds to other faces edges j
// and k
TT.resize (m,vector >(3));
@@ -177,20 +176,17 @@ template <
// No race conditions because TT*[f][c]'s are in bijection with e's
// Minimum number of iterms per openmp thread
- const size_t ne = E.rows();
+ //const size_t num_e = E.rows();
# ifndef IGL_OMP_MIN_VALUE
# define IGL_OMP_MIN_VALUE 1000
# endif
-# pragma omp parallel for if (ne>IGL_OMP_MIN_VALUE)
+# pragma omp parallel for if (m>IGL_OMP_MIN_VALUE)
// Slightly better memory access than loop over E
for(Index f = 0;f<(Index)m;f++)
{
for(Index c = 0;c<3;c++)
{
const Index e = f + m*c;
- const Index i = E(e,0);
- const Index j = E(e,1);
- //const Index f = e%m;
//const Index c = e/m;
const vector & N = uE2E[EMAP(e)];
for(const auto & ne : N)
diff --git a/include/igl/unique_edge_map.cpp b/include/igl/unique_edge_map.cpp
index 8ddbd5766..bf1a70901 100644
--- a/include/igl/unique_edge_map.cpp
+++ b/include/igl/unique_edge_map.cpp
@@ -29,7 +29,7 @@ IGL_INLINE void igl::unique_edge_map(
uE2E.resize(uE.rows());
// This does help a little
for_each(uE2E.begin(),uE2E.end(),[](vector & v){v.reserve(2);});
- assert(EMAP.size() == ne);
+ assert((size_t)EMAP.size() == ne);
for(uE2EType e = 0;e<(uE2EType)ne;e++)
{
uE2E[EMAP(e)].push_back(e);
diff --git a/include/igl/viewer/Viewer.cpp b/include/igl/viewer/Viewer.cpp
index 73810544b..4af70fdcd 100644
--- a/include/igl/viewer/Viewer.cpp
+++ b/include/igl/viewer/Viewer.cpp
@@ -911,7 +911,7 @@ namespace igl
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
- window = glfwCreateWindow(1280, 800, "IGL Viewer", NULL, NULL);
+ window = glfwCreateWindow(1280, 800, "libigl viewer", NULL, NULL);
if (!window)
{
glfwTerminate();
diff --git a/tutorial/609_Boolean/CMakeLists.txt b/tutorial/609_Boolean/CMakeLists.txt
new file mode 100644
index 000000000..a200c45a4
--- /dev/null
+++ b/tutorial/609_Boolean/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 2.6)
+project(609_Boolean)
+
+find_package(CGAL REQUIRED)
+include(${CGAL_USE_FILE})
+
+# for some reason must come after cgal include
+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} ${CGAL_LIBRARIES})
diff --git a/tutorial/609_Boolean/main.cpp b/tutorial/609_Boolean/main.cpp
new file mode 100755
index 000000000..170ba2eb6
--- /dev/null
+++ b/tutorial/609_Boolean/main.cpp
@@ -0,0 +1,94 @@
+#include
+#define IGL_NO_CORK
+#include
+#include
+
+#include
+#include
+
+Eigen::MatrixXd VA,VB,VC;
+Eigen::VectorXi J;
+Eigen::MatrixXi FA,FB,FC;
+igl::MeshBooleanType boolean_type(igl::MESH_BOOLEAN_TYPE_UNION);
+
+const char * MESH_BOOLEAN_TYPE_NAMES[] =
+{
+ "Union",
+ "Intersect",
+ "Minus",
+ "XOR",
+ "Resolve",
+};
+
+void update(igl::Viewer &viewer)
+{
+ igl::mesh_boolean(VA,FA,VB,FB,boolean_type,VC,FC,J);
+ Eigen::MatrixXd C(FC.rows(),3);
+ for(size_t f = 0;f(
+ (boolean_type+1)% igl::NUM_MESH_BOOLEAN_TYPES);
+ break;
+ case ',':
+ boolean_type =
+ static_cast(
+ (boolean_type+igl::NUM_MESH_BOOLEAN_TYPES-1)%
+ igl::NUM_MESH_BOOLEAN_TYPES);
+ break;
+ case '[':
+ viewer.core.camera_dnear -= 0.1;
+ return true;
+ case ']':
+ viewer.core.camera_dnear += 0.1;
+ return true;
+ }
+ std::cout<<"A "<
606 Baking ambient occlusion
607 Picking vertices and faces
608 Locally Injective Maps
+609 Boolean Operations on Meshes
Chapter 7: Outlook for continuing development
@@ -2422,6 +2423,78 @@ editing plus the anti-flipping constraints (right)." />
A mesh (left) deformed using Laplacian editing (middle) and with Laplacian
editing plus the anti-flipping constraints (right).
+Boolean operations on meshes
+
+Constructive solid geometry (CSG) is a technique to define a complex surface as
+the result of a number of set operations on solid regions of space: union,
+intersection, set difference, symmetric difference, complement. Typically, CSG
+libraries represent the inputs and outputs to these operations implicitly :
+the solid \(A\) is defined as the open set of points \(\mathbf{x}\) for which some
+function \(a(\mathbf{x})\) ``returns true’’. The surface of this shape is the
+closure of all points \(x\) in \(A\) .
+
+With this sort of representation, boolean
+operations are straightforward. For example, the union of solids \(A\) and \(B\)
+is simply
+
+\(A \cup B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ or } b(\mathbf{x})\},\)
+
+the intersection is
+
+\(A \cap B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ and } b(\mathbf{x})\},\)
+
+the difference \(A\) minus \(B\) is
+
+\(A \setminus B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ and _not_ } b(\mathbf{x})\},\)
+
+and the symmetric difference (XOR) is
+
+\(A \setminus B = \{\mathbf{x} \left.\right|
+ \text{either } a(\mathbf{x}) \text{ or } b(\mathbf{x}) \text{ but not both }\}.\)
+
+Stringing together many of these operations, one can design quite complex
+shapes. A typical CSG library might only keep explicit base-case
+representations of canonical shapes: half-spaces, quadrics, etc.
+
+In libigl, we do currently not have an implicit surface representation.
+Instead we expect our users to be working with explicit triangle mesh
+boundary representations of solid shapes. CSG operations are much hard to
+compute robustly with boundary representations, but are nonetheless useful.
+
+To compute a boolean operation on a triangle mesh with vertices VA and
+triangles FA and another mesh VB and FB, libigl first computes a unified
+mesh with vertices V and triangles F where all triangle-triangle
+intersections have been “resolved”. That is, edges and vertices are added
+exactly at the intersection lines, so the resulting non-manifold mesh (V,F)
+has no self-intersections.
+
+Then libigl peals the outer hull [#attene_14] off this mesh recursively,
+keeping track of the iteration parity and orientation flips for each layer.
+For any boolean operation, these two pieces of information determine for each
+triangle (1) if it should be included in the output, and (2) if its orientation
+should be reversed before added to the output.
+
+Calling libigl’s boolean operations is simple. To compute the union of
+(VA,FA) and (VB,FB) into a new mesh (VC,FC), use:
+
+igl::mesh_boolean(VA,FA,VB,FB,MESH_BOOLEAN_TYPE_UNION,VC,FC);
+
+
+
+
+The example Boolean conducts
+boolean operations on the Cheburashka (red) and Knight (green). From left
+to right: union, intersection, set minus, symmetric difference (XOR),
+``resolve’’. Bottom row reveals inner surfaces, darker color indicates
+back-facing triangles.
+
Outlook for continuing development
Libigl is in active development, and we plan to focus on the following features
@@ -2557,7 +2630,8 @@ Nicolas Ray, Bruno Vallet, Wan Chiu Li, Bruno Lévy TOG 2008
bommes_2009 Mixed-integer
-quadrangulation , David Bommes, Henrik Zimmer, Leif Kobbelt SIGGRAPH 2009
+quadrangulation,
+David Bommes, Henrik Zimmer, Leif Kobbelt SIGGRAPH 2009
knoppel_2013 Globally Optimal Direction
diff --git a/tutorial/tutorial.md b/tutorial/tutorial.md
index d0833fffe..b2cc83ba2 100644
--- a/tutorial/tutorial.md
+++ b/tutorial/tutorial.md
@@ -85,6 +85,7 @@ lecture notes links to a cross-platform example application.
* [606 Baking ambient occlusion](#606)
* [607 Picking vertices and faces](#607)
* [608 Locally Injective Maps](#608)
+ * [609 Boolean Operations on Meshes](#609)
* [Chapter 7: Outlook for continuing development](#future)
# Chapter 1 [100]
@@ -2198,6 +2199,75 @@ deformation energies. A simple deformation of a 2D grid is computed in [Example

+## Boolean operations on meshes [609]
+
+Constructive solid geometry (CSG) is a technique to define a complex surface as
+the result of a number of set operations on solid regions of space: union,
+intersection, set difference, symmetric difference, complement. Typically, CSG
+libraries represent the inputs and outputs to these operations _implicitly_:
+the solid $A$ is defined as the open set of points $\mathbf{x}$ for which some
+function $a(\mathbf{x})$ ``returns true''. The surface of this shape is the
+_closure_ of all points $x$ in $A$.
+
+With this sort of representation, boolean
+operations are straightforward. For example, the union of solids $A$ and $B$
+is simply
+
+$A \cup B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ or } b(\mathbf{x})\},$
+
+the intersection is
+
+$A \cap B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ and } b(\mathbf{x})\},$
+
+the difference $A$ _minus_ $B$ is
+
+$A \setminus B = \{\mathbf{x} \left.\right|
+ a(\mathbf{x}) \text{ and _not_ } b(\mathbf{x})\},$
+
+and the symmetric difference (XOR) is
+
+$A \setminus B = \{\mathbf{x} \left.\right|
+ \text{either } a(\mathbf{x}) \text{ or } b(\mathbf{x}) \text{ but not both }\}.$
+
+Stringing together many of these operations, one can design quite complex
+shapes. A typical CSG library might only keep explicit _base-case_
+representations of canonical shapes: half-spaces, quadrics, etc.
+
+In libigl, we do currently _not_ have an implicit surface representation.
+Instead we expect our users to be working with _explicit_ triangle mesh
+_boundary representations_ of solid shapes. CSG operations are much hard to
+compute robustly with boundary representations, but are nonetheless useful.
+
+To compute a boolean operation on a triangle mesh with vertices `VA` and
+triangles `FA` and another mesh `VB` and `FB`, libigl first computes a unified
+mesh with vertices `V` and triangles `F` where all triangle-triangle
+intersections have been "resolved". That is, edges and vertices are added
+exactly at the intersection lines, so the resulting _non-manifold_ mesh `(V,F)`
+has no self-intersections.
+
+Then libigl _peals_ the outer hull [#attene_14][] off this mesh recursively,
+keeping track of the iteration parity and orientation flips for each layer.
+For any boolean operation, these two pieces of information determine for each
+triangle (1) if it should be included in the output, and (2) if its orientation
+should be reversed before added to the output.
+
+Calling libigl's boolean operations is simple. To compute the union of
+`(VA,FA)` and `(VB,FB)` into a new mesh `(VC,FC)`, use:
+
+```cpp
+igl::mesh_boolean(VA,FA,VB,FB,MESH_BOOLEAN_TYPE_UNION,VC,FC);
+```
+
+ conducts
+boolean operations on the _Cheburashka_ (red) and _Knight_ (green). From left
+to right: union, intersection, set minus, symmetric difference (XOR),
+``resolve''. Bottom row reveals inner surfaces, darker color indicates
+back-facing triangles.](images/cheburashka-knight-boolean.jpg)
+
+
+
# Outlook for continuing development [future]
Libigl is in active development, and we plan to focus on the following features
@@ -2229,8 +2299,13 @@ repository](https://github.com/libigl/libigl).
+[#attene_2014]:["Direct repair of
+ self-intersecting
+ meshes"](https://www.google.com/search?q=Direct+repair+of+self-intersecting+meshes),
+ Marco Attene, 2014.
[#bommes_2009]:[Mixed-integer
-quadrangulation](http://www-sop.inria.fr/members/David.Bommes/publications/miq.pdf), David Bommes, Henrik Zimmer, Leif Kobbelt SIGGRAPH 2009
+quadrangulation](http://www-sop.inria.fr/members/David.Bommes/publications/miq.pdf),
+David Bommes, Henrik Zimmer, Leif Kobbelt SIGGRAPH 2009
[#botsch_2004]: Matrio Botsch and Leif Kobbelt. ["An Intuitive Framework for
Real-Time Freeform
Modeling,"](https://www.google.com/search?q=An+Intuitive+Framework+for+Real-Time+Freeform+Modeling)