From a0e1080428abb991c443a40b29d2ae3948eb4a56 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 2 Apr 2021 00:16:01 -0500 Subject: [PATCH] Cleanup: Remove unecessary C API for direct mesh boolean The main goal here is to remove the need for a C API to the code in `mesh_boolean_convert.cc`. This is achieved by moving `MOD_boolean.c` to C++ and making the necessary changes for it to compile. On top of that there are some other slight simplifications possible to the direct mesh boolean code: it doesn't need to copy the material remaps, and the modifier code can use some other C++ types directly. --- ..._convert.h => BKE_mesh_boolean_convert.hh} | 30 +- source/blender/blenkernel/CMakeLists.txt | 2 +- .../blenkernel/intern/mesh_boolean_convert.cc | 106 ++---- source/blender/bmesh/tools/bmesh_intersect.h | 8 + source/blender/modifiers/CMakeLists.txt | 2 +- .../intern/{MOD_boolean.c => MOD_boolean.cc} | 303 +++++++----------- .../nodes/geometry/nodes/node_geo_boolean.cc | 2 +- 7 files changed, 166 insertions(+), 287 deletions(-) rename source/blender/blenkernel/{BKE_mesh_boolean_convert.h => BKE_mesh_boolean_convert.hh} (66%) rename source/blender/modifiers/intern/{MOD_boolean.c => MOD_boolean.cc} (70%) diff --git a/source/blender/blenkernel/BKE_mesh_boolean_convert.h b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh similarity index 66% rename from source/blender/blenkernel/BKE_mesh_boolean_convert.h rename to source/blender/blenkernel/BKE_mesh_boolean_convert.hh index 7e285d3676e..59f6e75183e 100644 --- a/source/blender/blenkernel/BKE_mesh_boolean_convert.h +++ b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh @@ -23,39 +23,21 @@ * \ingroup bke */ -#ifdef __cplusplus -extern "C" { -#endif +#include "BLI_array.hh" +#include "BLI_float4x4.hh" +#include "BLI_mesh_boolean.hh" +#include "BLI_span.hh" -Mesh *BKE_mesh_boolean(const Mesh **meshes, - const float (*obmats[])[4][4], - const float (*target_transform)[4][4], - const short **material_remaps, - const int meshes_len, - const bool use_self, - const bool hole_tolerant, - const int boolean_mode); - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -# include "BLI_float4x4.hh" -# include "BLI_mesh_boolean.hh" -# include "BLI_span.hh" +struct Mesh; namespace blender::meshintersect { Mesh *direct_mesh_boolean(blender::Span meshes, blender::Span obmats, const float4x4 &target_transform, - blender::Span material_remaps, + blender::Span> material_remaps, const bool use_self, const bool hole_tolerant, const int boolean_mode); } // namespace blender::meshintersect - -#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f1f08b3ad3a..59e2c74ead1 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -371,7 +371,7 @@ set(SRC BKE_mball.h BKE_mball_tessellate.h BKE_mesh.h - BKE_mesh_boolean_convert.h + BKE_mesh_boolean_convert.hh BKE_mesh_fair.h BKE_mesh_iterators.h BKE_mesh_mapping.h diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index de9ad00ebde..ecf70c779e5 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -28,9 +28,10 @@ #include "BKE_customdata.h" #include "BKE_material.h" #include "BKE_mesh.h" -#include "BKE_mesh_boolean_convert.h" +#include "BKE_mesh_boolean_convert.hh" #include "BLI_alloca.h" +#include "BLI_array.hh" #include "BLI_float2.hh" #include "BLI_float4x4.hh" #include "BLI_math.h" @@ -97,7 +98,7 @@ class MeshesToIMeshInfo { Array to_target_transform; /* For each input mesh, how to remap the material slot numbers to * the material slots in the first mesh. */ - Array material_remaps; + Span> material_remaps; /* Total number of input mesh vertices. */ int tot_meshes_verts; /* Total number of input mesh edges. */ @@ -243,7 +244,7 @@ const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index, */ static IMesh meshes_to_imesh(Span meshes, Span obmats, - Span material_remaps, + Span> material_remaps, const float4x4 &target_transform, IMeshArena &arena, MeshesToIMeshInfo *r_info) @@ -274,7 +275,7 @@ static IMesh meshes_to_imesh(Span meshes, r_info->mesh_edge_offset = Array(nmeshes); r_info->mesh_poly_offset = Array(nmeshes); r_info->to_target_transform = Array(nmeshes); - r_info->material_remaps = Array(nmeshes); + r_info->material_remaps = material_remaps; int v = 0; int e = 0; int f = 0; @@ -307,13 +308,6 @@ static IMesh meshes_to_imesh(Span meshes, clean_obmat(*obmats[mi]); r_info->to_target_transform[mi] = inv_target_mat * objn_mat; - if (mi < material_remaps.size() && mi != 0) { - r_info->material_remaps[mi] = material_remaps[mi]; - } - else { - r_info->material_remaps[mi] = nullptr; - } - /* Skip the matrix multiplication for each point when there is no transform for a mesh, * for example when the first mesh is already in the target space. (Note the logic directly * above, which uses an identity matrix with a null input transform). */ @@ -393,14 +387,14 @@ static void copy_poly_attributes(Mesh *dest_mesh, const Mesh *orig_me, int mp_index, int index_in_orig_me, - const short *material_remap) + Span material_remap) { mp->mat_nr = orig_mp->mat_nr; if (mp->mat_nr >= dest_mesh->totcol) { mp->mat_nr = 0; } else { - if (material_remap) { + if (material_remap.size() > 0) { short mat_nr = material_remap[orig_mp->mat_nr]; if (mat_nr >= 0 && mat_nr < dest_mesh->totcol) { mp->mat_nr = mat_nr; @@ -733,8 +727,15 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) ++cur_loop_index; } - copy_poly_attributes( - result, mp, orig_mp, orig_me, fi, index_in_orig_me, mim.material_remaps[orig_me_index]); + copy_poly_attributes(result, + mp, + orig_mp, + orig_me, + fi, + index_in_orig_me, + (mim.material_remaps.size() > 0) ? + mim.material_remaps[orig_me_index].as_span() : + Span()); copy_or_interp_loop_attributes(result, f, mp, orig_mp, orig_me, orig_me_index, mim); } @@ -771,26 +772,33 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) #endif // WITH_GMP /** - * Do Exact Boolean directly, without a round trip through #BMesh. - * The Mesh operands are in `meshes`, with corresponding transforms in in `obmats`. + * Do a mesh boolean operation directly on meshes (without going back and forth to BMesh). + * \param meshes: An array of of Mesh pointers. + * \param obmats: An array of pointers to the obmat matrices that transform local + * coordinates to global ones. It is allowed for the pointers to be null, meaning the + * transformation is the identity. + * \param material_remaps: An array of pointers to arrays of maps from material slot numbers in the + * corresponding mesh to the material slot in the first mesh. It is OK for material_remaps or any + * of its constituent arrays to be empty. */ Mesh *direct_mesh_boolean(Span meshes, Span obmats, const float4x4 &target_transform, - Span material_remaps, + Span> material_remaps, const bool use_self, const bool hole_tolerant, const int boolean_mode) { #ifdef WITH_GMP - const int dbg_level = 0; BLI_assert(meshes.size() == obmats.size()); - const int meshes_len = meshes.size(); - if (meshes_len <= 0) { + BLI_assert(material_remaps.size() == 0 || material_remaps.size() == meshes.size()); + if (meshes.size() <= 0) { return nullptr; } + + const int dbg_level = 0; if (dbg_level > 0) { - std::cout << "\nDIRECT_MESH_INTERSECT, nmeshes = " << meshes_len << "\n"; + std::cout << "\nDIRECT_MESH_INTERSECT, nmeshes = " << meshes.size() << "\n"; } MeshesToIMeshInfo mim; IMeshArena arena; @@ -805,13 +813,13 @@ Mesh *direct_mesh_boolean(Span meshes, }; IMesh m_out = boolean_mesh(m_in, static_cast(boolean_mode), - meshes_len, + meshes.size(), shape_fn, use_self, hole_tolerant, nullptr, &arena); - if (dbg_level > 1) { + if (dbg_level > 0) { std::cout << m_out; write_obj_mesh(m_out, "m_out"); } @@ -825,53 +833,3 @@ Mesh *direct_mesh_boolean(Span meshes, } } // namespace blender::meshintersect - -extern "C" { - -#ifdef WITH_GMP -/* Do a mesh boolean directly on meshes (without going back and forth to BMesh). - * The \a meshes argument is an array of \a meshes_len of Mesh pointers. - * The \a obmats argument is an array of \a meshes_len of pointers to the obmat - * The \a material_remaps is an array of pointers to arrays of maps from material - * slot numbers in the corresponding mesh to the material slot in the first mesh. - * It is OK for material_remaps or any of its constituent arrays to be NULL. - * matrices that transform local coordinates to global ones. It is allowed - * for the pointers to be nullptr, meaning the transformation is the identity. */ -Mesh *BKE_mesh_boolean(const Mesh **meshes, - const float (*obmats[])[4][4], - const float (*target_transform)[4][4], - const short **material_remaps, - const int meshes_len, - const bool use_self, - const bool hole_tolerant, - const int boolean_mode) -{ - const blender::float4x4 **transforms = (const blender::float4x4 **)obmats; - const blender::float4x4 &target_float4x4 = *(const blender::float4x4 *)target_transform; - return blender::meshintersect::direct_mesh_boolean( - blender::Span(meshes, meshes_len), - blender::Span(transforms, meshes_len), - target_float4x4, - blender::Span(material_remaps, material_remaps ? meshes_len : 0), - use_self, - hole_tolerant, - boolean_mode); -} - -#else -Mesh *BKE_mesh_boolean(const Mesh **UNUSED(meshes), - const float (*obmats[])[4][4], - const float (*target_transform)[4][4], - const short **UNUSED(material_remaps), - const int UNUSED(meshes_len), - const bool UNUSED(use_self), - const bool UNUSED(hole_tolerant), - const int UNUSED(boolean_mode)) -{ - UNUSED_VARS(obmats, target_transform); - return NULL; -} - -#endif - -} // extern "C" diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h index adb88f2fd76..d09ea67a3bb 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.h +++ b/source/blender/bmesh/tools/bmesh_intersect.h @@ -20,6 +20,10 @@ * \ingroup bmesh */ +#ifdef __cplusplus +extern "C" { +#endif + bool BM_mesh_intersect(BMesh *bm, struct BMLoop *(*looptris)[3], const int looptris_tot, @@ -41,3 +45,7 @@ enum { BMESH_ISECT_BOOLEAN_UNION = 1, BMESH_ISECT_BOOLEAN_DIFFERENCE = 2, }; + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index c19782df44b..5fc88846527 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -50,7 +50,7 @@ set(SRC intern/MOD_armature.c intern/MOD_array.c intern/MOD_bevel.c - intern/MOD_boolean.c + intern/MOD_boolean.cc intern/MOD_build.c intern/MOD_cast.c intern/MOD_cloth.c diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.cc similarity index 70% rename from source/blender/modifiers/intern/MOD_boolean.c rename to source/blender/modifiers/intern/MOD_boolean.cc index d92f0d4219e..c49bcce2dd3 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.cc @@ -21,16 +21,15 @@ * \ingroup modifiers */ -// #define DEBUG_TIME - -#include +#include #include "BLI_utildefines.h" -#include "BLI_alloca.h" -#include "BLI_array.h" +#include "BLI_array.hh" +#include "BLI_float4x4.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" +#include "BLI_vector.hh" #include "BLT_translation.h" @@ -49,10 +48,9 @@ #include "BKE_lib_query.h" #include "BKE_material.h" #include "BKE_mesh.h" -#include "BKE_mesh_boolean_convert.h" +#include "BKE_mesh_boolean_convert.hh" #include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" -#include "BKE_screen.h" #include "UI_interface.h" #include "UI_resources.h" @@ -71,11 +69,16 @@ #include "tools/bmesh_boolean.h" #include "tools/bmesh_intersect.h" +// #define DEBUG_TIME + #ifdef DEBUG_TIME -# include "PIL_time.h" -# include "PIL_time_utildefines.h" +# include "BLI_timeit.hh" #endif +using blender::Array; +using blender::float4x4; +using blender::Vector; + static void initData(ModifierData *md) { BooleanModifierData *bmd = (BooleanModifierData *)md; @@ -113,14 +116,14 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { BooleanModifierData *bmd = (BooleanModifierData *)md; - if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object != NULL) { + if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object != nullptr) { DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); DEG_add_object_relation(ctx->node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); } Collection *col = bmd->collection; - if ((bmd->flag & eBooleanModifierFlag_Collection) && col != NULL) { + if ((bmd->flag & eBooleanModifierFlag_Collection) && col != nullptr) { FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (col, operand_ob) { if (operand_ob->type == OB_MESH && operand_ob != ctx->object) { DEG_add_object_relation(ctx->node, operand_ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); @@ -136,7 +139,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte static Mesh *get_quick_mesh( Object *ob_self, Mesh *mesh_self, Object *ob_operand_ob, Mesh *mesh_operand_ob, int operation) { - Mesh *result = NULL; + Mesh *result = nullptr; if (mesh_self->totpoly == 0 || mesh_operand_ob->totpoly == 0) { switch (operation) { @@ -149,11 +152,11 @@ static Mesh *get_quick_mesh( result = mesh_self; } else { - result = (Mesh *)BKE_id_copy_ex(NULL, &mesh_operand_ob->id, NULL, LIB_ID_COPY_LOCALIZE); + result = (Mesh *)BKE_id_copy_ex( + nullptr, &mesh_operand_ob->id, nullptr, LIB_ID_COPY_LOCALIZE); float imat[4][4]; float omat[4][4]; - invert_m4_m4(imat, ob_self->obmat); mul_m4_m4m4(omat, imat, ob_operand_ob->obmat); @@ -189,9 +192,10 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; } -static bool BMD_error_messages(const Object *ob, ModifierData *md, Collection *col) +static bool BMD_error_messages(const Object *ob, ModifierData *md) { BooleanModifierData *bmd = (BooleanModifierData *)md; + Collection *col = bmd->collection; bool error_returns_result = false; @@ -239,22 +243,20 @@ static bool BMD_error_messages(const Object *ob, ModifierData *md, Collection *c static BMesh *BMD_mesh_bm_create( Mesh *mesh, Object *object, Mesh *mesh_operand_ob, Object *operand_ob, bool *r_is_flip) { - BMesh *bm; +#ifdef DEBUG_TIME + SCOPED_TIMER(__func__) +#endif *r_is_flip = (is_negative_m4(object->obmat) != is_negative_m4(operand_ob->obmat)); const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh, mesh_operand_ob); - bm = BM_mesh_create(&allocsize, - &((struct BMeshCreateParams){ - .use_toolflags = false, - })); + BMeshCreateParams bmcp = {false}; + BMesh *bm = BM_mesh_create(&allocsize, &bmcp); - BM_mesh_bm_from_me(bm, - mesh_operand_ob, - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - })); + BMeshFromMeshParams params{}; + params.calc_face_normal = true; + BM_mesh_bm_from_me(bm, mesh_operand_ob, ¶ms); if (UNLIKELY(*r_is_flip)) { const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); @@ -265,11 +267,7 @@ static BMesh *BMD_mesh_bm_create( } } - BM_mesh_bm_from_me(bm, - mesh, - &((struct BMeshFromMeshParams){ - .calc_face_normal = true, - })); + BM_mesh_bm_from_me(bm, mesh, ¶ms); return bm; } @@ -282,13 +280,18 @@ static void BMD_mesh_intersection(BMesh *bm, Object *operand_ob, bool is_flip) { +#ifdef DEBUG_TIME + SCOPED_TIMER(__func__) +#endif + BooleanModifierData *bmd = (BooleanModifierData *)md; /* main bmesh intersection setup */ /* create tessface & intersect */ const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); int tottri; - BMLoop *(*looptris)[3] = MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); + BMLoop *(*looptris)[3] = (BMLoop * (*)[3]) + MEM_malloc_arrayN(looptris_tot, sizeof(*looptris), __func__); BM_mesh_calc_tessellation_beauty(bm, looptris, &tottri); @@ -324,12 +327,11 @@ static void BMD_mesh_intersection(BMesh *bm, negate_m3(nmat); } - const short ob_src_totcol = operand_ob->totcol; - short *material_remap = BLI_array_alloca(material_remap, ob_src_totcol ? ob_src_totcol : 1); + Array material_remap(operand_ob->totcol ? operand_ob->totcol : 1); /* Using original (not evaluated) object here since we are writing to it. */ /* XXX Pretty sure comment above is fully wrong now with CoW & co ? */ - BKE_object_material_remap_calc(ctx->object, operand_ob, material_remap); + BKE_object_material_remap_calc(ctx->object, operand_ob, material_remap.data()); BMFace *efa; i = 0; @@ -341,7 +343,7 @@ static void BMD_mesh_intersection(BMesh *bm, BM_elem_flag_enable(efa, BM_FACE_TAG); /* remap material */ - if (LIKELY(efa->mat_nr < ob_src_totcol)) { + if (LIKELY(efa->mat_nr < operand_ob->totcol)) { efa->mat_nr = material_remap[efa->mat_nr]; } @@ -370,7 +372,7 @@ static void BMD_mesh_intersection(BMesh *bm, looptris, tottri, bm_face_isect_pair, - NULL, + nullptr, false, use_separate, use_dissolve, @@ -388,59 +390,50 @@ static void BMD_mesh_intersection(BMesh *bm, /* Get a mapping from material slot numbers in the src_ob to slot numbers in the dst_ob. * If a material doesn't exist in the dst_ob, the mapping just goes to the same slot * or to zero if there aren't enough slots in the destination. - * Caller must MEM_freeN the returned array. */ -static short *get_material_remap(Object *dest_ob, Object *src_ob) + * Caller owns the returned array. */ +static Array get_material_remap(Object *dest_ob, Object *src_ob) { - short *remap; int n = dest_ob->totcol; if (n <= 0) { n = 1; } - remap = MEM_mallocN(n * sizeof(short), __func__); - BKE_object_material_remap_calc(dest_ob, src_ob, remap); + Array remap(n); + BKE_object_material_remap_calc(dest_ob, src_ob, remap.data()); return remap; } -/* New method: bypass trip through BMesh. */ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, const ModifierEvalContext *ctx, Mesh *mesh) { - Mesh *result; - Mesh *mesh_operand; - short *remap; - Mesh **meshes = NULL; - const float(**obmats)[4][4] = NULL; - short **material_remaps = NULL; - BLI_array_declare(meshes); - BLI_array_declare(obmats); - BLI_array_declare(material_remaps); + Vector meshes; + Vector obmats; + Vector> material_remaps; # ifdef DEBUG_TIME - TIMEIT_START(boolean_bmesh); + SCOPED_TIMER(__func__) # endif - if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object == NULL) { + if ((bmd->flag & eBooleanModifierFlag_Object) && bmd->object == nullptr) { return mesh; } - BLI_array_append(meshes, mesh); - BLI_array_append(obmats, &ctx->object->obmat); - BLI_array_append(material_remaps, NULL); + meshes.append(mesh); + obmats.append((float4x4 *)&ctx->object->obmat); + material_remaps.append({}); if (bmd->flag & eBooleanModifierFlag_Object) { - mesh_operand = BKE_modifier_get_evaluated_mesh_from_evaluated_object(bmd->object, false); + Mesh *mesh_operand = BKE_modifier_get_evaluated_mesh_from_evaluated_object(bmd->object, false); if (!mesh_operand) { return mesh; } BKE_mesh_wrapper_ensure_mdata(mesh_operand); - BLI_array_append(meshes, mesh_operand); - BLI_array_append(obmats, &bmd->object->obmat); - remap = get_material_remap(ctx->object, bmd->object); - BLI_array_append(material_remaps, remap); + meshes.append(mesh_operand); + obmats.append((float4x4 *)&bmd->object->obmat); + material_remaps.append(get_material_remap(ctx->object, bmd->object)); } else if (bmd->flag & eBooleanModifierFlag_Collection) { Collection *collection = bmd->collection; - /* Allow collection to be empty: then target mesh will just removed self-intersections. */ + /* Allow collection to be empty; then target mesh will just removed self-intersections. */ if (collection) { FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) { if (ob->type == OB_MESH && ob != ctx->object) { @@ -449,10 +442,9 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, continue; } BKE_mesh_wrapper_ensure_mdata(collection_mesh); - BLI_array_append(meshes, collection_mesh); - BLI_array_append(obmats, &ob->obmat); - remap = get_material_remap(ctx->object, ob); - BLI_array_append(material_remaps, remap); + meshes.append(collection_mesh); + obmats.append((float4x4 *)&ob->obmat); + material_remaps.append(get_material_remap(ctx->object, ob)); } } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; @@ -461,30 +453,13 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd, const bool use_self = (bmd->flag & eBooleanModifierFlag_Self) != 0; const bool hole_tolerant = (bmd->flag & eBooleanModifierFlag_HoleTolerant) != 0; - result = BKE_mesh_boolean((const Mesh **)meshes, - (const float(**)[4][4])obmats, - &ctx->object->obmat, - (const short **)material_remaps, - BLI_array_len(meshes), - use_self, - hole_tolerant, - bmd->operation); - - BLI_array_free(meshes); - BLI_array_free(obmats); - for (int i = 0; i < BLI_array_len(material_remaps); i++) { - remap = material_remaps[i]; - if (remap) { - MEM_freeN(remap); - } - } - BLI_array_free(material_remaps); - -# ifdef DEBUG_TIME - TIMEIT_END(boolean_bmesh); -# endif - - return result; + return blender::meshintersect::direct_mesh_boolean(meshes, + obmats, + *(float4x4 *)&ctx->object->obmat, + material_remaps, + use_self, + hole_tolerant, + bmd->operation); } #endif @@ -493,12 +468,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * BooleanModifierData *bmd = (BooleanModifierData *)md; Object *object = ctx->object; Mesh *result = mesh; - Mesh *mesh_operand_ob; - BMesh *bm; Collection *collection = bmd->collection; - bool is_flip = false; - const bool confirm_return = true; + /* Return result for certain errors. */ + if (BMD_error_messages(ctx->object, md)) { + return result; + } + #ifdef WITH_GMP if (bmd->solver == eBooleanModifierSolver_Exact) { return exact_boolean_mesh(bmd, ctx, mesh); @@ -506,27 +482,18 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif #ifdef DEBUG_TIME - TIMEIT_START(boolean_bmesh); + SCOPED_TIMER(__func__) #endif if (bmd->flag & eBooleanModifierFlag_Object) { - if (bmd->object == NULL) { + if (bmd->object == nullptr) { return result; } - BMD_error_messages(ctx->object, md, NULL); - Object *operand_ob = bmd->object; -#ifdef DEBUG_TIME - TIMEIT_BLOCK_INIT(operand_get_evaluated_mesh); - TIMEIT_BLOCK_START(operand_get_evaluated_mesh); -#endif - mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false); -#ifdef DEBUG_TIME - TIMEIT_BLOCK_END(operand_get_evaluated_mesh); - TIMEIT_BLOCK_STATS(operand_get_evaluated_mesh); -#endif + Mesh *mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, + false); if (mesh_operand_ob) { /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! @@ -537,80 +504,49 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * Returning mesh is depended on modifiers operation (sergey) */ result = get_quick_mesh(object, mesh, operand_ob, mesh_operand_ob, bmd->operation); - if (result == NULL) { -#ifdef DEBUG_TIME - TIMEIT_BLOCK_INIT(object_BMD_mesh_bm_create); - TIMEIT_BLOCK_START(object_BMD_mesh_bm_create); -#endif - bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); -#ifdef DEBUG_TIME - TIMEIT_BLOCK_END(object_BMD_mesh_bm_create); - TIMEIT_BLOCK_STATS(object_BMD_mesh_bm_create); -#endif + if (result == nullptr) { + bool is_flip; + BMesh *bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); -#ifdef DEBUG_TIME - TIMEIT_BLOCK_INIT(BMD_mesh_intersection); - TIMEIT_BLOCK_START(BMD_mesh_intersection); -#endif BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip); -#ifdef DEBUG_TIME - TIMEIT_BLOCK_END(BMD_mesh_intersection); - TIMEIT_BLOCK_STATS(BMD_mesh_intersection); -#endif -#ifdef DEBUG_TIME - TIMEIT_BLOCK_INIT(BKE_mesh_from_bmesh_for_eval_nomain); - TIMEIT_BLOCK_START(BKE_mesh_from_bmesh_for_eval_nomain); -#endif - result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); -#ifdef DEBUG_TIME - TIMEIT_BLOCK_END(BKE_mesh_from_bmesh_for_eval_nomain); - TIMEIT_BLOCK_STATS(BKE_mesh_from_bmesh_for_eval_nomain); -#endif + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh); + BM_mesh_free(bm); result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } - /* if new mesh returned, return it; otherwise there was - * an error, so delete the modifier object */ - if (result == NULL) { + if (result == nullptr) { BKE_modifier_set_error(object, md, "Cannot execute boolean operation"); } } } else { - if (collection == NULL) { - return result; - } - - /* Return result for certain errors. */ - if (BMD_error_messages(ctx->object, md, collection) == confirm_return) { + if (collection == nullptr) { return result; } FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, operand_ob) { if (operand_ob->type == OB_MESH && operand_ob != ctx->object) { - - mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, false); + Mesh *mesh_operand_ob = BKE_modifier_get_evaluated_mesh_from_evaluated_object(operand_ob, + false); if (mesh_operand_ob) { /* XXX This is utterly non-optimal, we may go from a bmesh to a mesh back to a bmesh! * But for 2.90 better not try to be smart here. */ BKE_mesh_wrapper_ensure_mdata(mesh_operand_ob); - bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); + bool is_flip; + BMesh *bm = BMD_mesh_bm_create(mesh, object, mesh_operand_ob, operand_ob, &is_flip); BMD_mesh_intersection(bm, md, ctx, mesh_operand_ob, object, operand_ob, is_flip); /* Needed for multiple objects to work. */ - BM_mesh_bm_to_me(NULL, - bm, - mesh, - (&(struct BMeshToMeshParams){ - .calc_object_remap = false, - })); + BMeshToMeshParams params{}; + params.calc_object_remap = false; + BM_mesh_bm_to_me(nullptr, bm, mesh, ¶ms); - result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh); + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh); BM_mesh_free(bm); result->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } @@ -619,10 +555,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } -#ifdef DEBUG_TIME - TIMEIT_END(boolean_bmesh); -#endif - return result; } @@ -638,22 +570,21 @@ static void requiredDataMask(Object *UNUSED(ob), static void panel_draw(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL); - - uiItemR(layout, ptr, "operation", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "operation", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiLayoutSetPropSep(layout, true); - uiItemR(layout, ptr, "operand_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "operand_type", 0, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object) { - uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "object", 0, nullptr, ICON_NONE); } else { - uiItemR(layout, ptr, "collection", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "collection", 0, nullptr, ICON_NONE); } - uiItemR(layout, ptr, "solver", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "solver", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); modifier_panel_end(layout, ptr); } @@ -661,8 +592,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) static void solver_options_panel_draw(const bContext *UNUSED(C), Panel *panel) { uiLayout *layout = panel->layout; - - PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL); + PointerRNA *ptr = modifier_panel_get_property_pointers(panel, nullptr); const bool use_exact = RNA_enum_get(ptr, "solver") == eBooleanModifierSolver_Exact; @@ -672,16 +602,16 @@ static void solver_options_panel_draw(const bContext *UNUSED(C), Panel *panel) if (use_exact) { /* When operand is collection, we always use_self. */ if (RNA_enum_get(ptr, "operand_type") == eBooleanModifierFlag_Object) { - uiItemR(col, ptr, "use_self", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_self", 0, nullptr, ICON_NONE); } - uiItemR(col, ptr, "use_hole_tolerant", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_hole_tolerant", 0, nullptr, ICON_NONE); } else { - uiItemR(col, ptr, "double_threshold", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "double_threshold", 0, nullptr, ICON_NONE); } if (G.debug) { - uiItemR(col, ptr, "debug_options", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "debug_options", 0, nullptr, ICON_NONE); } } @@ -689,7 +619,7 @@ static void panelRegister(ARegionType *region_type) { PanelType *panel = modifier_panel_register(region_type, eModifierType_Boolean, panel_draw); modifier_subpanel_register( - region_type, "solver_options", "Solver Options", NULL, solver_options_panel_draw, panel); + region_type, "solver_options", "Solver Options", nullptr, solver_options_panel_draw, panel); } ModifierTypeInfo modifierType_Boolean = { @@ -698,31 +628,32 @@ ModifierTypeInfo modifierType_Boolean = { /* structSize */ sizeof(BooleanModifierData), /* srna */ &RNA_BooleanModifier, /* type */ eModifierTypeType_Nonconstructive, - /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, + /* flags */ + (ModifierTypeFlag)(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode), /* icon */ ICON_MOD_BOOLEAN, /* copyData */ BKE_modifier_copydata_generic, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, + /* deformVerts */ nullptr, + /* deformMatrices */ nullptr, + /* deformVertsEM */ nullptr, + /* deformMatricesEM */ nullptr, /* modifyMesh */ modifyMesh, - /* modifyHair */ NULL, - /* modifyGeometrySet */ NULL, - /* modifyVolume */ NULL, + /* modifyHair */ nullptr, + /* modifyGeometrySet */ nullptr, + /* modifyVolume */ nullptr, /* initData */ initData, /* requiredDataMask */ requiredDataMask, - /* freeData */ NULL, + /* freeData */ nullptr, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* dependsOnTime */ nullptr, + /* dependsOnNormals */ nullptr, /* foreachIDLink */ foreachIDLink, - /* foreachTexLink */ NULL, - /* freeRuntimeData */ NULL, + /* foreachTexLink */ nullptr, + /* freeRuntimeData */ nullptr, /* panelRegister */ panelRegister, - /* blendWrite */ NULL, - /* blendRead */ NULL, + /* blendWrite */ nullptr, + /* blendRead */ nullptr, }; diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index c3017dc2610..6be5bc4f8b4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -17,7 +17,7 @@ #include "DNA_mesh_types.h" #include "BKE_mesh.h" -#include "BKE_mesh_boolean_convert.h" +#include "BKE_mesh_boolean_convert.hh" #include "UI_interface.h" #include "UI_resources.h"