diff options
m--------- | release/scripts/addons | 0 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_boolean.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_delaunay_2d.h | 3 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_mpq.hh | 15 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_mesh_intersect.hh | 3 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_mpq2.hh | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_mpq3.hh | 1 | ||||
-rw-r--r-- | source/blender/blenlib/intern/boolean.cc | 3 | ||||
-rw-r--r-- | source/blender/blenlib/intern/delaunay_2d.cc | 3 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_vec.cc | 3 | ||||
-rw-r--r-- | source/blender/bmesh/CMakeLists.txt | 14 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_boolean.c | 211 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_boolean.cc | 228 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_boolean.h | 8 | ||||
-rw-r--r-- | tests/gtests/blenlib/BLI_boolean_test.cc | 2 | ||||
-rw-r--r-- | tests/gtests/blenlib/BLI_delaunay_2d_test.cc | 3 | ||||
-rw-r--r-- | tests/gtests/blenlib/BLI_mesh_intersect_test.cc | 3 |
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" |