Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoward Trickey <howard.trickey@gmail.com>2020-07-01 16:15:17 +0300
committerHoward Trickey <howard.trickey@gmail.com>2020-07-01 16:15:17 +0300
commit590ce6817d76b01d1eff0a54bf2f5240596ccefa (patch)
tree104aedae2a24822ddf352a7d765b8068eecb7cda
parenta62bca844ce10dec2e4835db804f3c84c3ff5d58 (diff)
Change bmesh_boolean.c into a C++ file and start using PolyMesh interface.
Also, use BLI_math_mpq.hh everywhere instead of gmpxx.h.
m---------release/scripts/addons0
-rw-r--r--source/blender/blenlib/BLI_boolean.h2
-rw-r--r--source/blender/blenlib/BLI_delaunay_2d.h3
-rw-r--r--source/blender/blenlib/BLI_math_mpq.hh15
-rw-r--r--source/blender/blenlib/BLI_mesh_intersect.hh3
-rw-r--r--source/blender/blenlib/BLI_mpq2.hh2
-rw-r--r--source/blender/blenlib/BLI_mpq3.hh1
-rw-r--r--source/blender/blenlib/intern/boolean.cc3
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc3
-rw-r--r--source/blender/blenlib/intern/math_vec.cc3
-rw-r--r--source/blender/bmesh/CMakeLists.txt14
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.c211
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.cc228
-rw-r--r--source/blender/bmesh/tools/bmesh_boolean.h8
-rw-r--r--tests/gtests/blenlib/BLI_boolean_test.cc2
-rw-r--r--tests/gtests/blenlib/BLI_delaunay_2d_test.cc3
-rw-r--r--tests/gtests/blenlib/BLI_mesh_intersect_test.cc3
17 files changed, 268 insertions, 236 deletions
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject aea05413b7689f1c72e04804b4faabc3694aec9
+Subproject c83bd8d7068b7bbf59b88c984d213592d1887e5
diff --git a/source/blender/blenlib/BLI_boolean.h b/source/blender/blenlib/BLI_boolean.h
index c28c71d3be6..55155afc1d4 100644
--- a/source/blender/blenlib/BLI_boolean.h
+++ b/source/blender/blenlib/BLI_boolean.h
@@ -57,9 +57,9 @@ void BLI_boolean_trimesh_free(Boolean_trimesh_output *output);
}
# include "BLI_array.hh"
+# include "BLI_math_mpq.hh"
# include "BLI_mesh_intersect.hh"
# include "BLI_mpq3.hh"
-# include "gmpxx.h"
namespace blender {
namespace meshintersect {
diff --git a/source/blender/blenlib/BLI_delaunay_2d.h b/source/blender/blenlib/BLI_delaunay_2d.h
index 34722982022..96501268cee 100644
--- a/source/blender/blenlib/BLI_delaunay_2d.h
+++ b/source/blender/blenlib/BLI_delaunay_2d.h
@@ -208,12 +208,11 @@ void BLI_delaunay_2d_cdt_free(CDT_result *result);
/* C++ Interface. */
-# include "gmpxx.h"
-
# include "BLI_array.hh"
# include "BLI_double2.hh"
# include "BLI_linklist.h"
# include "BLI_mempool.h"
+# include "BLI_math_mpq.hh"
# include "BLI_mpq2.hh"
# include "BLI_vector.hh"
diff --git a/source/blender/blenlib/BLI_math_mpq.hh b/source/blender/blenlib/BLI_math_mpq.hh
index ede30da29b8..06fa0a2e257 100644
--- a/source/blender/blenlib/BLI_math_mpq.hh
+++ b/source/blender/blenlib/BLI_math_mpq.hh
@@ -17,10 +17,15 @@
#ifndef __BLI_MATH_MPQ_HH__
#define __BLI_MATH_MPQ_HH__
+/* This file uses an external file header to define the multiprecision
+ * rational type, mpq_class.
+ * This class keeps separate multiprecision integer numerator and
+ * denominator, reduced to lowest terms after each arithmetic operation.
+ * It can be used where it is important to have exact arithmetic results.
+ *
+ * See gmplib.org for full documentation. In particular:
+ * https://gmplib.org/manual/C_002b_002b-Interface-Rationals
+ */
#include "gmpxx.h"
-namespace BLI {
-
-} // namespace BLI
-
-#endif /* __BLI_MATH_NPQ_HH__ */
+#endif /* __BLI_MATH_MPQ_HH__ */
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh
index dcdc93d8e6f..8ce26b6e533 100644
--- a/source/blender/blenlib/BLI_mesh_intersect.hh
+++ b/source/blender/blenlib/BLI_mesh_intersect.hh
@@ -25,9 +25,8 @@
#include <iostream>
-#include "gmpxx.h"
-
#include "BLI_array.hh"
+#include "BLI_math_mpq.hh"
#include "BLI_mpq3.hh"
#include "BLI_vector.hh"
diff --git a/source/blender/blenlib/BLI_mpq2.hh b/source/blender/blenlib/BLI_mpq2.hh
index b9a519404b4..6ad36e645f0 100644
--- a/source/blender/blenlib/BLI_mpq2.hh
+++ b/source/blender/blenlib/BLI_mpq2.hh
@@ -17,8 +17,6 @@
#ifndef __BLI_MPQ2_HH__
#define __BLI_MPQ2_HH__
-#include "gmpxx.h"
-
#include "BLI_math_mpq.hh"
#include "BLI_mpq3.hh"
diff --git a/source/blender/blenlib/BLI_mpq3.hh b/source/blender/blenlib/BLI_mpq3.hh
index 1efa8c9ad7b..82cae0bd26d 100644
--- a/source/blender/blenlib/BLI_mpq3.hh
+++ b/source/blender/blenlib/BLI_mpq3.hh
@@ -21,7 +21,6 @@
#include "BLI_math.h"
#include "BLI_math_mpq.hh"
-#include "gmpxx.h"
namespace blender {
diff --git a/source/blender/blenlib/intern/boolean.cc b/source/blender/blenlib/intern/boolean.cc
index 6f0b18f42d1..55f969c1b81 100644
--- a/source/blender/blenlib/intern/boolean.cc
+++ b/source/blender/blenlib/intern/boolean.cc
@@ -18,14 +18,13 @@
#include <fstream>
#include <iostream>
-#include "gmpxx.h"
-
#include "BLI_array.hh"
#include "BLI_assert.h"
#include "BLI_delaunay_2d.h"
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_math.h"
+#include "BLI_math_mpq.hh"
#include "BLI_mesh_intersect.hh"
#include "BLI_mpq3.hh"
#include "BLI_set.hh"
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index e7691317210..ac3868dc194 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -19,11 +19,10 @@
#include <iostream>
#include <sstream>
-#include "gmpxx.h"
-
#include "BLI_array.hh"
#include "BLI_double2.hh"
#include "BLI_linklist.h"
+#include "BLI_math_mpq.hh"
#include "BLI_mpq2.hh"
#include "BLI_vector.hh"
diff --git a/source/blender/blenlib/intern/math_vec.cc b/source/blender/blenlib/intern/math_vec.cc
index 793c4c78148..3261d5f5f69 100644
--- a/source/blender/blenlib/intern/math_vec.cc
+++ b/source/blender/blenlib/intern/math_vec.cc
@@ -18,13 +18,12 @@
* \ingroup bli
*/
-#include "gmpxx.h"
-
#include "BLI_double2.hh"
#include "BLI_double3.hh"
#include "BLI_float2.hh"
#include "BLI_float3.hh"
#include "BLI_hash.hh"
+#include "BLI_math_mpq.hh"
#include "BLI_mpq2.hh"
#include "BLI_mpq3.hh"
#include "BLI_utildefines.h"
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index cead636404b..5e2a689bc95 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -135,7 +135,7 @@ set(SRC
tools/bmesh_bevel.h
tools/bmesh_bisect_plane.c
tools/bmesh_bisect_plane.h
- tools/bmesh_boolean.c
+ tools/bmesh_boolean.cc
tools/bmesh_boolean.h
tools/bmesh_decimate.h
tools/bmesh_decimate_collapse.c
@@ -199,4 +199,16 @@ if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
+if(WITH_GMP)
+ add_definitions(-DWITH_GMP)
+
+ list(APPEND INC_SYS
+ ${GMP_INCLUDE_DIRS}
+ )
+
+ list(APPEND LIB
+ ${GMP_LIBRARIES}
+ )
+endif()
+
blender_add_lib(bf_bmesh "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/bmesh/tools/bmesh_boolean.c b/source/blender/bmesh/tools/bmesh_boolean.c
deleted file mode 100644
index 67bf834be3a..00000000000
--- a/source/blender/bmesh/tools/bmesh_boolean.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/** \file
- * \ingroup bmesh
- *
- * Main functions for boolean on a BMesh (used by the tool and modifier)
- */
-
-#include "MEM_guardedalloc.h"
-
-#include "BLI_boolean.h"
-#include "BLI_math.h"
-
-#include "bmesh.h"
-#include "bmesh_boolean.h"
-
-/* Make a a triangle mesh for input to the Boolean function.
- * We take only take triangles from faces f for which test_fn(f, user_data) returns 'side'.
- * Caller must call free_trimesh_input when done with the returned value. */
-static Boolean_trimesh_input *trimesh_input_from_bm(BMesh *bm,
- struct BMLoop *(*looptris)[3],
- const int looptris_tot,
- int (*(test_fn))(BMFace *f, void *user_data),
- void *user_data,
- int side)
-{
- int i, in_v_index, in_t_index, bmv_index, looptri_index, tot_in_vert, tot_in_tri;
- Boolean_trimesh_input *trimesh;
- int *bmv_to_v, *v_to_bmv, *t_to_looptri;
- BMFace *f;
-
- BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
- BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE);
- trimesh = MEM_mallocN(sizeof(*trimesh), __func__);
- bmv_to_v = MEM_malloc_arrayN(bm->totvert, sizeof(int), __func__);
- v_to_bmv = MEM_malloc_arrayN(bm->totvert, sizeof(int), __func__);
- t_to_looptri = MEM_malloc_arrayN(looptris_tot, sizeof(int), __func__);
- for (i = 0; i < bm->totvert; i++) {
- bmv_to_v[i] = -1;
- v_to_bmv[i] = -1;
- }
- in_v_index = 0;
- tot_in_tri = 0;
- for (looptri_index = 0; looptri_index < looptris_tot; looptri_index++) {
- f = looptris[looptri_index][0]->f;
- if (test_fn(f, user_data) == side) {
- t_to_looptri[tot_in_tri++] = looptri_index;
- for (i = 0; i < 3; i++) {
- bmv_index = BM_elem_index_get(looptris[looptri_index][i]->v);
- if (bmv_to_v[bmv_index] == -1) {
- v_to_bmv[in_v_index] = bmv_index;
- bmv_to_v[bmv_index] = in_v_index;
- in_v_index++;
- }
- }
- }
- }
- tot_in_vert = in_v_index;
- trimesh->vert_len = tot_in_vert;
- trimesh->tri_len = tot_in_tri;
- trimesh->vert_coord = MEM_malloc_arrayN(tot_in_vert, sizeof(trimesh->vert_coord[0]), __func__);
- trimesh->tri = MEM_malloc_arrayN(tot_in_tri, sizeof(trimesh->tri[0]), __func__);
- for (in_v_index = 0; in_v_index < tot_in_vert; in_v_index++) {
- bmv_index = v_to_bmv[in_v_index];
- BMVert *bmv = BM_vert_at_index(bm, bmv_index);
- copy_v3_v3(trimesh->vert_coord[in_v_index], bmv->co);
- }
- for (in_t_index = 0; in_t_index < tot_in_tri; in_t_index++) {
- looptri_index = t_to_looptri[in_t_index];
- for (i = 0; i < 3; i++) {
- bmv_index = BM_elem_index_get(looptris[looptri_index][i]->v);
- BLI_assert(bmv_to_v[bmv_index] != -1);
- trimesh->tri[in_t_index][i] = bmv_to_v[bmv_index];
- }
- }
- MEM_freeN(bmv_to_v);
- MEM_freeN(v_to_bmv);
- MEM_freeN(t_to_looptri);
-
- return trimesh;
-}
-
-static void free_trimesh_input(Boolean_trimesh_input *in)
-{
- MEM_freeN(in->vert_coord);
- MEM_freeN(in->tri);
- MEM_freeN(in);
-}
-
-static void apply_trimesh_output_to_bmesh(BMesh *bm, Boolean_trimesh_output *out)
-{
- /* For now, for testing, just create new BMesh elements for returned subdivided mesh and kill old
- * mesh. */
- int v, t;
- BMIter iter;
- BMVert *bmv, *bmv_next;
-
- BM_ITER_MESH_MUTABLE (bmv, bmv_next, &iter, bm, BM_VERTS_OF_MESH) {
- BM_vert_kill(bm, bmv);
- }
-
- if (out->vert_len > 0 && out->tri_len > 0) {
- BMVert **new_bmv = MEM_malloc_arrayN(out->vert_len, sizeof(BMVert *), __func__);
- for (v = 0; v < out->vert_len; v++) {
- new_bmv[v] = BM_vert_create(bm, out->vert_coord[v], NULL, BM_CREATE_NOP);
- }
- for (t = 0; t < out->tri_len; t++) {
- BMVert *v0 = new_bmv[out->tri[t][0]];
- BMVert *v1 = new_bmv[out->tri[t][1]];
- BMVert *v2 = new_bmv[out->tri[t][2]];
- BM_face_create_quad_tri(bm, v0, v1, v2, NULL, NULL, BM_CREATE_NOP);
- }
- MEM_freeN(new_bmv);
- }
-}
-
-/*
- * Perform the boolean operation specified by boolean_mode on the mesh bm.
- * The inputs to the boolean operation are either one submesh (if use_self is true),
- * or two submeshes. The submeshes are specified by providing a test_fn which takes
- * a face and the supplied user_data and says with 'side' of the boolean operation
- * that face is for: 0 for the first side (side A), 1 for the second side (side B),
- * and -1 if the face is to be ignored completely in the boolean operation.
- *
- * If use_self is true, all operations do the same: the submesh is self-intersected
- * and all pieces inside that result are removed.
- * Otherwise, the operations can be one of BMESH_ISECT_BOOLEAN_ISECT, BMESH_ISECT_BOOLEAN_UNION,
- * or BMESH_ISECT_BOOLEAN_DIFFERENCE.
- *
- * (The actual library function called to do the boolean is internally capable of handling
- * n-ary operands, so maybe in the future we can expose that functionality to users.)
- */
-bool BM_mesh_boolean(BMesh *bm,
- struct BMLoop *(*looptris)[3],
- const int looptris_tot,
- int (*test_fn)(BMFace *f, void *user_data),
- void *user_data,
- const bool use_self,
- const int boolean_mode)
-{
- Boolean_trimesh_input *in_a = trimesh_input_from_bm(
- bm, looptris, looptris_tot, test_fn, user_data, 0);
- Boolean_trimesh_input *in_b = NULL;
- if (!use_self) {
- in_b = trimesh_input_from_bm(bm, looptris, looptris_tot, test_fn, user_data, 1);
- /* The old boolean code does DIFFERENCE as b - a, which is weird, so adapt here
- * so the rest of the code is sensible.
- */
- SWAP(Boolean_trimesh_input *, in_a, in_b);
- }
- Boolean_trimesh_output *out = BLI_boolean_trimesh(in_a, in_b, boolean_mode);
- BLI_assert(out != NULL);
- bool intersections_found = out->tri_len != in_a->tri_len + (in_b ? in_b->tri_len : 0) ||
- out->vert_len != in_a->vert_len + (in_b ? in_b->vert_len : 0);
- apply_trimesh_output_to_bmesh(bm, out);
- free_trimesh_input(in_a);
- if (in_b) {
- free_trimesh_input(in_b);
- }
- BLI_boolean_trimesh_free(out);
- return intersections_found;
-}
-
-/*
- * Perform a Knife Intersection operation on the mesh bm.
- * There are either one or two operands, the same as described above for BM_mesh_boolean().
- * If use_separate_all is true, each edge that is created from the intersection should
- * be used to separate all its incident faces. TODO: implement that.
- * TODO: need to ensure that "selected/non-selected" flag of original faces gets propagated
- * to the intersection result faces.
- */
-bool BM_mesh_boolean_knife(BMesh *bm,
- struct BMLoop *(*looptris)[3],
- const int looptris_tot,
- int (*test_fn)(BMFace *f, void *user_data),
- void *user_data,
- const bool use_self,
- const bool UNUSED(use_separate_all))
-{
- Boolean_trimesh_input *in_a = trimesh_input_from_bm(
- bm, looptris, looptris_tot, test_fn, user_data, 0);
- Boolean_trimesh_input *in_b = NULL;
- if (!use_self) {
- in_b = trimesh_input_from_bm(bm, looptris, looptris_tot, test_fn, user_data, 1);
- }
- Boolean_trimesh_output *out = BLI_boolean_trimesh(in_a, in_b, BOOLEAN_NONE);
- BLI_assert(out != NULL);
- bool intersections_found = out->tri_len != in_a->tri_len + (in_b ? in_b->tri_len : 0) ||
- out->vert_len != in_a->vert_len + (in_b ? in_b->vert_len : 0);
- apply_trimesh_output_to_bmesh(bm, out);
- free_trimesh_input(in_a);
- if (in_b) {
- free_trimesh_input(in_b);
- }
- BLI_boolean_trimesh_free(out);
- return intersections_found;
-}
diff --git a/source/blender/bmesh/tools/bmesh_boolean.cc b/source/blender/bmesh/tools/bmesh_boolean.cc
new file mode 100644
index 00000000000..56385f741b5
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_boolean.cc
@@ -0,0 +1,228 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bmesh
+ *
+ * Main functions for boolean on a BMesh (used by the tool and modifier)
+ */
+
+#include "BLI_array.hh"
+#include "BLI_boolean.h"
+#include "BLI_math.h"
+#include "BLI_math_mpq.hh"
+#include "BLI_mesh_intersect.hh"
+
+#include "bmesh.h"
+#include "bmesh_boolean.h"
+
+namespace blender {
+namespace meshintersect {
+
+static PolyMesh polymesh_from_bm(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot)
+{
+ BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
+ BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE);
+ PolyMesh pm;
+ pm.vert = Array<mpq3>(bm->totvert);
+ for (int v = 0; v < bm->totvert; ++v) {
+ BMVert *bmv = BM_vert_at_index(bm, v);
+ pm.vert[v] = mpq3(mpq_class(bmv->co[0]),
+ mpq_class(bmv->co[1]),
+ mpq_class(bmv->co[2]));
+ }
+ pm.face = Array<Array<int>>(bm->totface);
+ pm.triangulation = Array<Array<IndexedTriangle>>(bm->totface);
+ for (int f = 0; f < bm->totface; ++f) {
+ BMFace *bmf = BM_face_at_index(bm, f);
+ int flen = bmf->len;
+ pm.face[f] = Array<int>(flen);
+ Array<int> &face = pm.face[f];
+ BMLoop *l = bmf->l_first;
+ for (int i = 0; i < flen; ++i) {
+ face[i] = BM_elem_index_get(l->v);
+ l = l->next;
+ }
+ /* A correct triangulation of a polygon with flen sides has flen-2 tris. */
+ pm.triangulation[f] = Array<IndexedTriangle>(flen - 2);
+ }
+ Array<int> triangulation_next_index(bm->totface, 0);
+ for (int i = 0; i < looptris_tot; ++i) {
+ BMFace *bmf = looptris[i][0]->f;
+ int f = BM_elem_index_get(bmf);
+ BLI_assert(triangulation_next_index[f] < bmf->len - 2);
+ if (triangulation_next_index[f] >= bmf->len - 2) {
+ continue;
+ }
+ int v0 = BM_elem_index_get(looptris[i][0]->v);
+ int v1 = BM_elem_index_get(looptris[i][1]->v);
+ int v2 = BM_elem_index_get(looptris[i][2]->v);
+ pm.triangulation[f][triangulation_next_index[f]++] = IndexedTriangle(v0, v1, v2, f);
+ }
+ return pm;
+}
+
+static void apply_polymesh_output_to_bmesh(BMesh *bm, const PolyMesh &pm_out)
+{
+ /* For now, just for testing, just kill the whole old mesh and create the new one.
+ * No attempt yet to use proper examples for the new elements so that they inherit the
+ * proper attributes.
+ * No attempt yet to leave the correct geometric elements selected.
+ */
+
+ /* The BM_ITER_... macros need attention to work in C++. For now, copy the old BMVerts. */
+ int totvert_orig = bm->totvert;
+ Array<BMVert *> orig_bmv(totvert_orig);
+ for (int v = 0; v < bm->totvert; ++v) {
+ orig_bmv[v] = BM_vert_at_index(bm, v);
+ }
+ for (int v = 0; v < totvert_orig; ++v) {
+ BM_vert_kill(bm, orig_bmv[v]);
+ }
+
+ if (pm_out.vert.size() > 0 && pm_out.face.size() > 0) {
+ Array<BMVert *> new_bmv(pm_out.vert.size());
+ for (int v = 0; v < static_cast<int>(pm_out.vert.size()); ++v) {
+ float co[3];
+ const mpq3 & mpq3_co = pm_out.vert[v];
+ for (int i = 0; i < 3; ++i) {
+ co[i] = static_cast<float>(mpq3_co[i].get_d());
+ }
+ new_bmv[v] = BM_vert_create(bm, co, NULL, BM_CREATE_NOP);
+ }
+ int maxflen = 0;
+ int new_totface = static_cast<int>(pm_out.face.size());
+ for (int f = 0; f < new_totface; ++f) {
+ maxflen = max_ii(maxflen, static_cast<int>(pm_out.face[f].size()));
+ }
+ Array<BMVert *> face_bmverts(maxflen);
+ for (int f = 0; f < new_totface; ++f) {
+ const Array<int> &face = pm_out.face[f];
+ int flen = static_cast<int>(face.size());
+ for (int i = 0; i < flen; ++i) {
+ BMVert *bmv = new_bmv[face[i]];
+ face_bmverts[i] = bmv;
+ }
+ BM_face_create_ngon_verts(bm, face_bmverts.begin(), flen, NULL, BM_CREATE_NOP, true, true);
+ }
+ }
+}
+
+static int bmesh_boolean(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data),
+ void *user_data,
+ const bool use_self,
+ const bool UNUSED(use_separate_all),
+ const int boolean_mode)
+{
+ PolyMesh pm_in = polymesh_from_bm(bm, looptris, looptris_tot);
+ std::function<int(int)> shape_fn;
+ int nshapes;
+ if (use_self) {
+ /* Unary boolean operation. Want every face where test_fn doesn't return -1. */
+ nshapes = 1;
+ shape_fn = [bm, test_fn, user_data](int f) {
+ BMFace *bmf = BM_face_at_index(bm, f);
+ if (test_fn(bmf, user_data) != -1) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ };
+ }
+ else {
+ /* Binary boolean operation.
+ * Because our boolean function's difference does shape 0 - shape 1,
+ * and Blender's convention is to do the opposite, reverse the shape
+ * assigment in this test.
+ */
+ nshapes = 2;
+ shape_fn = [bm, test_fn, user_data](int f) {
+ BMFace *bmf = BM_face_at_index(bm, f);
+ int test_val = test_fn(bmf, user_data);
+ if (test_val == 0) {
+ return 1;
+ }
+ else if (test_val == 1) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+ };
+ }
+ PolyMesh pm_out = boolean(pm_in, boolean_mode, nshapes, shape_fn);
+ apply_polymesh_output_to_bmesh(bm, pm_out);
+ return pm_in.vert.size() != pm_out.vert.size() || pm_in.face.size() != pm_out.face.size();
+}
+
+} // namespace meshintersect
+} // namespace blender
+
+extern "C" {
+/*
+ * Perform the boolean operation specified by boolean_mode on the mesh bm.
+ * The inputs to the boolean operation are either one submesh (if use_self is true),
+ * or two submeshes. The submeshes are specified by providing a test_fn which takes
+ * a face and the supplied user_data and says with 'side' of the boolean operation
+ * that face is for: 0 for the first side (side A), 1 for the second side (side B),
+ * and -1 if the face is to be ignored completely in the boolean operation.
+ *
+ * If use_self is true, all operations do the same: the submesh is self-intersected
+ * and all pieces inside that result are removed.
+ * Otherwise, the operations can be one of BMESH_ISECT_BOOLEAN_ISECT, BMESH_ISECT_BOOLEAN_UNION,
+ * or BMESH_ISECT_BOOLEAN_DIFFERENCE.
+ *
+ * (The actual library function called to do the boolean is internally capable of handling
+ * n-ary operands, so maybe in the future we can expose that functionality to users.)
+ */
+bool BM_mesh_boolean(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data),
+ void *user_data,
+ const bool use_self,
+ const int boolean_mode)
+{
+ return blender::meshintersect::bmesh_boolean(bm, looptris, looptris_tot, test_fn, user_data, use_self, false, boolean_mode);
+}
+
+/*
+ * Perform a Knife Intersection operation on the mesh bm.
+ * There are either one or two operands, the same as described above for BM_mesh_boolean().
+ * If use_separate_all is true, each edge that is created from the intersection should
+ * be used to separate all its incident faces. TODO: implement that.
+ * TODO: need to ensure that "selected/non-selected" flag of original faces gets propagated
+ * to the intersection result faces.
+ */
+bool BM_mesh_boolean_knife(BMesh *bm,
+ struct BMLoop *(*looptris)[3],
+ const int looptris_tot,
+ int (*test_fn)(BMFace *f, void *user_data),
+ void *user_data,
+ const bool use_self,
+ const bool use_separate_all)
+{
+ return blender::meshintersect::bmesh_boolean(bm, looptris, looptris_tot, test_fn, user_data, use_self, use_separate_all, BOOLEAN_NONE);
+}
+
+} /* extern "C" */
+
diff --git a/source/blender/bmesh/tools/bmesh_boolean.h b/source/blender/bmesh/tools/bmesh_boolean.h
index e246ac365b6..cb4ce2cd12d 100644
--- a/source/blender/bmesh/tools/bmesh_boolean.h
+++ b/source/blender/bmesh/tools/bmesh_boolean.h
@@ -21,6 +21,10 @@
* \ingroup bmesh
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool BM_mesh_boolean(BMesh *bm,
struct BMLoop *(*looptris)[3],
const int looptris_tot,
@@ -37,4 +41,8 @@ bool BM_mesh_boolean_knife(BMesh *bm,
const bool use_self,
const bool use_separate_all);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BMESH_BOOLEAN_H__ */
diff --git a/tests/gtests/blenlib/BLI_boolean_test.cc b/tests/gtests/blenlib/BLI_boolean_test.cc
index d4e9257c90c..6503d9ca946 100644
--- a/tests/gtests/blenlib/BLI_boolean_test.cc
+++ b/tests/gtests/blenlib/BLI_boolean_test.cc
@@ -7,10 +7,10 @@
#include <sstream>
#include "MEM_guardedalloc.h"
-#include "gmpxx.h"
#include "BLI_array.hh"
#include "BLI_boolean.h"
+#include "BLI_math_mpq.hh"
#include "BLI_mpq3.hh"
#include "BLI_vector.hh"
diff --git a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
index 3760ea46ab0..05ccc861136 100644
--- a/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
+++ b/tests/gtests/blenlib/BLI_delaunay_2d_test.cc
@@ -2,8 +2,6 @@
#include "testing/testing.h"
-#include "gmpxx.h"
-
#include "MEM_guardedalloc.h"
extern "C" {
@@ -23,6 +21,7 @@ extern "C" {
#include "BLI_array.hh"
#include "BLI_double2.hh"
+#include "BLI_math_mpq.hh"
#include "BLI_mpq2.hh"
#include "BLI_vector.hh"
diff --git a/tests/gtests/blenlib/BLI_mesh_intersect_test.cc b/tests/gtests/blenlib/BLI_mesh_intersect_test.cc
index 15e8b15f0f0..2d961473053 100644
--- a/tests/gtests/blenlib/BLI_mesh_intersect_test.cc
+++ b/tests/gtests/blenlib/BLI_mesh_intersect_test.cc
@@ -6,9 +6,8 @@
#include <fstream>
#include <iostream>
-#include "gmpxx.h"
-
#include "BLI_array.hh"
+#include "BLI_math_mpq.hh"
#include "BLI_mesh_intersect.hh"
#include "BLI_mpq3.hh"
#include "BLI_vector.hh"