From 023788ef9a4e661c00c67505a466a3046b496048 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 2 Mar 2021 20:58:05 -0600 Subject: Cleanup: Use span and float matrix type in direct boolean code This commit includes a few simple improvements to the direct mesh boolean code added recently. - Passing the transforms and meshes to `direct_mesh_boolean` as spans makes the function easier to call from C++. - The definition of `TransMat`, was unecessary when we have the `float4x4` type already used elsewhere in C++ code. Differential Revision: https://developer.blender.org/D10592 --- .../blenkernel/intern/mesh_boolean_convert.cc | 71 ++++++++++------------ 1 file changed, 32 insertions(+), 39 deletions(-) (limited to 'source/blender/blenkernel/intern/mesh_boolean_convert.cc') diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 299b1ff1c71..d9564f91a04 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -32,6 +32,7 @@ #include "BLI_alloca.h" #include "BLI_float2.hh" +#include "BLI_float4x4.hh" #include "BLI_math.h" #include "BLI_mesh_boolean.hh" #include "BLI_mesh_intersect.hh" @@ -50,12 +51,12 @@ constexpr int estimated_max_facelen = 100; /* Used for initial size of some Vect * so this is a hack to clean up such matrices. * Would be better to change the transformation code itself. */ -static void clean_obmat(float cleaned[4][4], const float mat[4][4]) +static void clean_obmat(float4x4 &cleaned, const float4x4 &mat) { const float fuzz = 1e-6f; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - float f = mat[i][j]; + float f = mat.values[i][j]; if (fabsf(f) <= fuzz) { f = 0.0f; } @@ -65,17 +66,11 @@ static void clean_obmat(float cleaned[4][4], const float mat[4][4]) else if (fabsf(f + 1.0f) <= fuzz) { f = -1.0f; } - cleaned[i][j] = f; + cleaned.values[i][j] = f; } } } -/* Need to wrap this in a class to use it in an Array. */ -class TransMat { - public: - float mat[4][4]; -}; - /* `MeshesToIMeshInfo` keeps track of information used when combining a number * of `Mesh`es into a single `IMesh` for doing boolean on. * Mostly this means keeping track of the index offsets for various mesh elements. */ @@ -97,7 +92,7 @@ class MeshesToIMeshInfo { Array mesh_to_imesh_face; /* Transformation matrix to transform a coordinate in the corresponding * Mesh to the local space of the first Mesh. */ - Array to_obj0; + Array to_obj0; /* Total number of input mesh vertices. */ int tot_meshes_verts; /* Total number of input mesh edges. */ @@ -242,7 +237,7 @@ const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index, * All allocation of memory for the IMesh comes from `arena`. */ static IMesh meshes_to_imesh(Span meshes, - const float (*obmats[])[4][4], + Span obmats, IMeshArena &arena, MeshesToIMeshInfo *r_info) { @@ -271,7 +266,7 @@ static IMesh meshes_to_imesh(Span meshes, r_info->mesh_vert_offset = Array(nmeshes); r_info->mesh_edge_offset = Array(nmeshes); r_info->mesh_poly_offset = Array(nmeshes); - r_info->to_obj0 = Array(nmeshes); + r_info->to_obj0 = Array(nmeshes); int v = 0; int e = 0; int f = 0; @@ -286,15 +281,15 @@ static IMesh meshes_to_imesh(Span meshes, * of object 0, we multiply each object's `obmat` by the inverse of * object 0's `obmat`. Exact Boolean works better if these matrices * are 'cleaned' -- see the comment for the `clean_obmat` function, above. */ - float obj0_mat[4][4]; - float inv_obj0_mat[4][4]; + float4x4 obj0_mat; + float4x4 inv_obj0_mat; if (obmats[0] == nullptr) { - unit_m4(obj0_mat); - unit_m4(inv_obj0_mat); + unit_m4(obj0_mat.values); + unit_m4(inv_obj0_mat.values); } else { clean_obmat(obj0_mat, *obmats[0]); - invert_m4_m4(inv_obj0_mat, obj0_mat); + invert_m4_m4(inv_obj0_mat.values, obj0_mat.values); } /* For each input `Mesh`, make `Vert`s and `Face`s for the corresponding @@ -303,13 +298,13 @@ static IMesh meshes_to_imesh(Span meshes, * When making `Face`s, we also put in the original indices for `MEdge`s that * make up the `MPoly`s using the same scheme. */ for (int mi : meshes.index_range()) { - float objn_to_obj0_mat[4][4]; + float4x4 objn_to_obj0_mat; const Mesh *me = meshes[mi]; if (mi == 0) { r_info->mesh_vert_offset[mi] = 0; r_info->mesh_edge_offset[mi] = 0; r_info->mesh_poly_offset[mi] = 0; - unit_m4(r_info->to_obj0[0].mat); + unit_m4(r_info->to_obj0[0].values); } else { r_info->mesh_vert_offset[mi] = v; @@ -317,23 +312,22 @@ static IMesh meshes_to_imesh(Span meshes, r_info->mesh_poly_offset[mi] = f; /* Get matrix that transforms a coordinate in objects[mi]'s local space * to object[0]'s local space.*/ - float objn_mat[4][4]; + float4x4 objn_mat; if (obmats[mi] == nullptr) { - unit_m4(objn_mat); + unit_m4(objn_mat.values); } else { clean_obmat(objn_mat, *obmats[mi]); } - mul_m4_m4m4(objn_to_obj0_mat, inv_obj0_mat, objn_mat); - copy_m4_m4(r_info->to_obj0[mi].mat, objn_to_obj0_mat); + objn_to_obj0_mat = inv_obj0_mat * objn_mat; + r_info->to_obj0[mi] = objn_to_obj0_mat; } for (int vi = 0; vi < me->totvert; ++vi) { - float co[3]; - copy_v3_v3(co, me->mvert[vi].co); + float3 co = me->mvert[vi].co; if (mi > 0) { - mul_m4_v3(objn_to_obj0_mat, co); + co = objn_to_obj0_mat * co; } - r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co[0], co[1], co[2]), v); + r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(mpq3(co.x, co.y, co.z), v); ++v; } for (const MPoly &poly : Span(me->mpoly, me->totpoly)) { @@ -534,7 +528,7 @@ static int fill_orig_loops(const Face *f, static void get_poly2d_cos(const Mesh *me, const MPoly *mp, float (*cos_2d)[2], - const TransMat &trans_mat, + const float4x4 &trans_mat, float r_axis_mat[3][3]) { int n = mp->totloop; @@ -546,9 +540,8 @@ static void get_poly2d_cos(const Mesh *me, MLoop *ml = &me->mloop[mp->loopstart]; const MVert *mverts = me->mvert; for (int i = 0; i < n; ++i) { - float co[3]; - copy_v3_v3(co, mverts[ml->v].co); - mul_m4_v3(trans_mat.mat, co); + float3 co = mverts[ml->v].co; + co = trans_mat * co; mul_v2_m3v3(cos_2d[i], r_axis_mat, co); ++ml; } @@ -763,23 +756,23 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) * Do Exact Boolean directly, without a round trip through #BMesh. * The Mesh operands are in `meshes`, with corresponding transforms in in `obmats`. */ -static Mesh *direct_mesh_boolean(const Mesh **meshes, - const float (*obmats[])[4][4], - const int meshes_len, +static Mesh *direct_mesh_boolean(Span meshes, + Span obmats, const bool use_self, const BoolOpType boolean_mode) { const int dbg_level = 0; + BLI_assert(meshes.size() == obmats.size()); + const int meshes_len = meshes.size(); if (meshes_len <= 0) { return nullptr; } if (dbg_level > 0) { std::cout << "\nDIRECT_MESH_INTERSECT, nmeshes = " << meshes_len << "\n"; } - Span mesh_span(meshes, meshes_len); MeshesToIMeshInfo mim; IMeshArena arena; - IMesh m_in = meshes_to_imesh(mesh_span, obmats, arena, &mim); + IMesh m_in = meshes_to_imesh(meshes, obmats, arena, &mim); std::function shape_fn = [&mim](int f) { for (int mi = 0; mi < mim.mesh_poly_offset.size() - 1; ++mi) { if (f < mim.mesh_poly_offset[mi + 1]) { @@ -814,10 +807,10 @@ Mesh *BKE_mesh_boolean(const Mesh **meshes, const bool use_self, const int boolean_mode) { + const blender::float4x4 **transforms = (const blender::float4x4 **)obmats; return blender::meshintersect::direct_mesh_boolean( - meshes, - obmats, - meshes_len, + blender::Span(meshes, meshes_len), + blender::Span(transforms, meshes_len), use_self, static_cast(boolean_mode)); } -- cgit v1.2.3