diff options
Diffstat (limited to 'source/blender/blenkernel/intern/mesh_boolean_convert.cc')
-rw-r--r-- | source/blender/blenkernel/intern/mesh_boolean_convert.cc | 133 |
1 files changed, 76 insertions, 57 deletions
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index a1ef2d2e6b5..360c7da2ae2 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -9,6 +9,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "BKE_attribute.hh" #include "BKE_customdata.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -23,6 +24,7 @@ #include "BLI_mesh_intersect.hh" #include "BLI_span.hh" #include "BLI_task.hh" +#include "BLI_virtual_array.hh" namespace blender::meshintersect { @@ -112,7 +114,7 @@ class MeshesToIMeshInfo { * input `Mesh` that contained the `MVert` that it came from. */ int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const { - int n = static_cast<int>(mesh_vert_offset.size()); + int n = int(mesh_vert_offset.size()); for (int i = 0; i < n - 1; ++i) { if (imesh_v < mesh_vert_offset[i + 1]) { return i; @@ -125,7 +127,7 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const * return the index of the input `Mesh` that contained the `MVert` that it came from. */ int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const { - int n = static_cast<int>(mesh_edge_offset.size()); + int n = int(mesh_edge_offset.size()); for (int i = 0; i < n - 1; ++i) { if (imesh_e < mesh_edge_offset[i + 1]) { return i; @@ -138,7 +140,7 @@ int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const * input `Mesh` that contained the `MPoly` that it came from. */ int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const { - int n = static_cast<int>(mesh_poly_offset.size()); + int n = int(mesh_poly_offset.size()); for (int i = 0; i < n - 1; ++i) { if (imesh_f < mesh_poly_offset[i + 1]) { return i; @@ -160,9 +162,10 @@ const MPoly *MeshesToIMeshInfo::input_mpoly_for_orig_index(int orig_index, int orig_mesh_index = input_mesh_for_imesh_face(orig_index); BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size()); const Mesh *me = meshes[orig_mesh_index]; + const Span<MPoly> polys = me->polys(); int index_in_mesh = orig_index - mesh_poly_offset[orig_mesh_index]; BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totpoly); - const MPoly *mp = &me->mpoly[index_in_mesh]; + const MPoly *mp = &polys[index_in_mesh]; if (r_orig_mesh) { *r_orig_mesh = me; } @@ -186,9 +189,10 @@ const MVert *MeshesToIMeshInfo::input_mvert_for_orig_index(int orig_index, int orig_mesh_index = input_mesh_for_imesh_vert(orig_index); BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size()); const Mesh *me = meshes[orig_mesh_index]; + const Span<MVert> verts = me->verts(); int index_in_mesh = orig_index - mesh_vert_offset[orig_mesh_index]; BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totvert); - const MVert *mv = &me->mvert[index_in_mesh]; + const MVert *mv = &verts[index_in_mesh]; if (r_orig_mesh) { *r_orig_mesh = me; } @@ -206,9 +210,10 @@ const MEdge *MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index, int orig_mesh_index = input_mesh_for_imesh_edge(orig_index); BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size()); const Mesh *me = meshes[orig_mesh_index]; + const Span<MEdge> edges = me->edges(); int index_in_mesh = orig_index - mesh_edge_offset[orig_mesh_index]; BLI_assert(0 <= index_in_mesh && index_in_mesh < me->totedge); - const MEdge *medge = &me->medge[index_in_mesh]; + const MEdge *medge = &edges[index_in_mesh]; if (r_orig_mesh) { *r_orig_mesh = me; } @@ -304,17 +309,19 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, bool need_face_flip = r_info->has_negative_transform[mi] != r_info->has_negative_transform[0]; Vector<Vert *> verts(me->totvert); - Span<MVert> mverts = Span(me->mvert, me->totvert); + const Span<MVert> mesh_verts = me->verts(); + const Span<MPoly> polys = me->polys(); + const Span<MLoop> loops = me->loops(); /* Allocate verts * 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). */ if (obmats[mi] == nullptr) { - threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) { + threading::parallel_for(mesh_verts.index_range(), 2048, [&](IndexRange range) { float3 co; for (int i : range) { - co = float3(mverts[i].co); + co = float3(mesh_verts[i].co); mpq3 mco = mpq3(co.x, co.y, co.z); double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); verts[i] = new Vert(mco, dco, NO_INDEX, i); @@ -322,26 +329,26 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, }); } else { - threading::parallel_for(mverts.index_range(), 2048, [&](IndexRange range) { + threading::parallel_for(mesh_verts.index_range(), 2048, [&](IndexRange range) { float3 co; for (int i : range) { - co = r_info->to_target_transform[mi] * float3(mverts[i].co); + co = r_info->to_target_transform[mi] * float3(mesh_verts[i].co); mpq3 mco = mpq3(co.x, co.y, co.z); double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d()); verts[i] = new Vert(mco, dco, NO_INDEX, i); } }); } - for (int i : mverts.index_range()) { + for (int i : mesh_verts.index_range()) { r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(verts[i]); ++v; } - for (const MPoly &poly : Span(me->mpoly, me->totpoly)) { + for (const MPoly &poly : polys) { int flen = poly.totloop; face_vert.resize(flen); face_edge_orig.resize(flen); - const MLoop *l = &me->mloop[poly.loopstart]; + const MLoop *l = &loops[poly.loopstart]; for (int i = 0; i < flen; ++i) { int mverti = r_info->mesh_vert_offset[mi] + l->v; const Vert *fv = r_info->mesh_to_imesh_vert[mverti]; @@ -368,15 +375,10 @@ static IMesh meshes_to_imesh(Span<const Mesh *> meshes, * `mv` is in `dest_mesh` with index `mv_index`. * The `orig_mv` vertex came from Mesh `orig_me` and had index `index_in_orig_me` there. */ static void copy_vert_attributes(Mesh *dest_mesh, - MVert *mv, - const MVert *orig_mv, const Mesh *orig_me, int mv_index, int index_in_orig_me) { - mv->bweight = orig_mv->bweight; - mv->flag = orig_mv->flag; - /* For all layers in the orig mesh, copy the layer information. */ CustomData *target_cd = &dest_mesh->vdata; const CustomData *source_cd = &orig_me->vdata; @@ -405,13 +407,17 @@ static void copy_poly_attributes(Mesh *dest_mesh, const Mesh *orig_me, int mp_index, int index_in_orig_me, - Span<short> material_remap) + Span<short> material_remap, + MutableSpan<int> dst_material_indices) { - if (material_remap.size() > 0 && material_remap.index_range().contains(orig_mp->mat_nr)) { - mp->mat_nr = material_remap[orig_mp->mat_nr]; + const VArray<int> src_material_indices = orig_me->attributes().lookup_or_default<int>( + "material_index", ATTR_DOMAIN_FACE, 0); + const int src_index = src_material_indices[index_in_orig_me]; + if (material_remap.size() > 0 && material_remap.index_range().contains(src_index)) { + dst_material_indices[mp_index] = material_remap[src_index]; } else { - mp->mat_nr = orig_mp->mat_nr; + dst_material_indices[mp_index] = src_index; } mp->flag = orig_mp->flag; @@ -439,8 +445,6 @@ static void copy_edge_attributes(Mesh *dest_mesh, int medge_index, int index_in_orig_me) { - medge->bweight = orig_medge->bweight; - medge->crease = orig_medge->crease; medge->flag = orig_medge->flag; CustomData *target_cd = &dest_mesh->edata; const CustomData *source_cd = &orig_me->edata; @@ -473,14 +477,16 @@ static int fill_orig_loops(const Face *f, const Mesh *orig_me, int orig_me_index, MeshesToIMeshInfo &mim, - Array<int> &orig_loops) + MutableSpan<int> r_orig_loops) { - orig_loops.fill(-1); + r_orig_loops.fill(-1); + const Span<MLoop> orig_loops = orig_me->loops(); + int orig_mplen = orig_mp->totloop; if (f->size() != orig_mplen) { return 0; } - BLI_assert(orig_loops.size() == orig_mplen); + BLI_assert(r_orig_loops.size() == orig_mplen); /* We'll look for the case where the first vertex in f has an original vertex * that is the same as one in orig_me (after correcting for offset in mim meshes). * Then see that loop and any subsequent ones have the same start and end vertex. @@ -502,7 +508,7 @@ static int fill_orig_loops(const Face *f, int offset = -1; for (int i = 0; i < orig_mplen; ++i) { int loop_i = i + orig_mp->loopstart; - if (orig_me->mloop[loop_i].v == first_orig_v_in_orig_me) { + if (orig_loops[loop_i].v == first_orig_v_in_orig_me) { offset = i; break; } @@ -513,7 +519,7 @@ static int fill_orig_loops(const Face *f, int num_orig_loops_found = 0; for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) { int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen; - MLoop *l = &orig_me->mloop[orig_mp->loopstart + orig_mp_loop_index]; + const MLoop *l = &orig_loops[orig_mp->loopstart + orig_mp_loop_index]; int fv_orig = f->vert[mp_loop_index]->orig; if (fv_orig != NO_INDEX) { fv_orig -= orig_me_vert_offset; @@ -522,7 +528,8 @@ static int fill_orig_loops(const Face *f, } } if (l->v == fv_orig) { - MLoop *lnext = &orig_me->mloop[orig_mp->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)]; + const MLoop *lnext = + &orig_loops[orig_mp->loopstart + ((orig_mp_loop_index + 1) % orig_mplen)]; int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig; if (fvnext_orig != NO_INDEX) { fvnext_orig -= orig_me_vert_offset; @@ -531,7 +538,7 @@ static int fill_orig_loops(const Face *f, } } if (lnext->v == fvnext_orig) { - orig_loops[mp_loop_index] = orig_mp->loopstart + orig_mp_loop_index; + r_orig_loops[mp_loop_index] = orig_mp->loopstart + orig_mp_loop_index; ++num_orig_loops_found; } } @@ -549,19 +556,18 @@ static void get_poly2d_cos(const Mesh *me, const float4x4 &trans_mat, float r_axis_mat[3][3]) { - int n = mp->totloop; + const Span<MVert> verts = me->verts(); + const Span<MLoop> loops = me->loops(); + const Span<MLoop> poly_loops = loops.slice(mp->loopstart, mp->totloop); /* Project coordinates to 2d in cos_2d, using normal as projection axis. */ float axis_dominant[3]; - BKE_mesh_calc_poly_normal(mp, &me->mloop[mp->loopstart], me->mvert, axis_dominant); + BKE_mesh_calc_poly_normal(mp, &loops[mp->loopstart], verts.data(), axis_dominant); axis_dominant_v3_to_m3(r_axis_mat, axis_dominant); - MLoop *ml = &me->mloop[mp->loopstart]; - const MVert *mverts = me->mvert; - for (int i = 0; i < n; ++i) { - float3 co = mverts[ml->v].co; + for (const int i : poly_loops.index_range()) { + float3 co = verts[poly_loops[i].v].co; co = trans_mat * co; mul_v2_m3v3(cos_2d[i], r_axis_mat, co); - ++ml; } } @@ -596,6 +602,8 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, get_poly2d_cos(orig_me, orig_mp, cos_2d, mim.to_target_transform[orig_me_index], axis_mat); } CustomData *target_cd = &dest_mesh->ldata; + const Span<MVert> dst_verts = dest_mesh->verts(); + const Span<MLoop> dst_loops = dest_mesh->loops(); for (int i = 0; i < mp->totloop; ++i) { int loop_index = mp->loopstart + i; int orig_loop_index = norig > 0 ? orig_loops[i] : -1; @@ -605,7 +613,7 @@ static void copy_or_interp_loop_attributes(Mesh *dest_mesh, * The coordinate needs to be projected into 2d, just like the interpolating polygon's * coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */ float co[2]; - mul_v2_m3v3(co, axis_mat, dest_mesh->mvert[dest_mesh->mloop[loop_index].v].co); + mul_v2_m3v3(co, axis_mat, dst_verts[dst_loops[loop_index].v].co); interp_weights_poly_v2(weights.data(), cos_2d, orig_mp->totloop, co); } for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) { @@ -663,15 +671,15 @@ static void merge_vertex_loop_poly_customdata_layers(Mesh *target, MeshesToIMesh const Mesh *me = mim.meshes[mesh_index]; if (me->totvert) { CustomData_merge( - &me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_DEFAULT, target->totvert); + &me->vdata, &target->vdata, CD_MASK_MESH.vmask, CD_SET_DEFAULT, target->totvert); } if (me->totloop) { CustomData_merge( - &me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_DEFAULT, target->totloop); + &me->ldata, &target->ldata, CD_MASK_MESH.lmask, CD_SET_DEFAULT, target->totloop); } if (me->totpoly) { CustomData_merge( - &me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_DEFAULT, target->totpoly); + &me->pdata, &target->pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, target->totpoly); } } } @@ -682,7 +690,7 @@ static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim) const Mesh *me = mim.meshes[mesh_index]; if (me->totedge) { CustomData_merge( - &me->edata, &target->edata, CD_MASK_MESH.emask, CD_DEFAULT, target->totedge); + &me->edata, &target->edata, CD_MASK_MESH.emask, CD_SET_DEFAULT, target->totedge); } } } @@ -708,22 +716,28 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) merge_vertex_loop_poly_customdata_layers(result, mim); /* Set the vertex coordinate values and other data. */ + MutableSpan<MVert> verts = result->verts_for_write(); for (int vi : im->vert_index_range()) { const Vert *v = im->vert(vi); - MVert *mv = &result->mvert[vi]; - copy_v3fl_v3db(mv->co, v->co); if (v->orig != NO_INDEX) { const Mesh *orig_me; int index_in_orig_me; - const MVert *orig_mv = mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me); - copy_vert_attributes(result, mv, orig_mv, orig_me, vi, index_in_orig_me); + mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me); + copy_vert_attributes(result, orig_me, vi, index_in_orig_me); } + MVert *mv = &verts[vi]; + copy_v3fl_v3db(mv->co, v->co); } /* Set the loopstart and totloop for each output poly, * and set the vertices in the appropriate loops. */ + bke::SpanAttributeWriter<int> dst_material_indices = + result->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index", + ATTR_DOMAIN_FACE); int cur_loop_index = 0; - MLoop *l = result->mloop; + MutableSpan<MLoop> dst_loops = result->loops_for_write(); + MutableSpan<MPoly> dst_polys = result->polys_for_write(); + MLoop *l = dst_loops.data(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); const Mesh *orig_me; @@ -731,7 +745,7 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) int orig_me_index; const MPoly *orig_mp = mim.input_mpoly_for_orig_index( f->orig, &orig_me, &orig_me_index, &index_in_orig_me); - MPoly *mp = &result->mpoly[fi]; + MPoly *mp = &dst_polys[fi]; mp->totloop = f->size(); mp->loopstart = cur_loop_index; for (int j : f->index_range()) { @@ -750,9 +764,11 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) index_in_orig_me, (mim.material_remaps.size() > 0) ? mim.material_remaps[orig_me_index].as_span() : - Span<short>()); + Span<short>(), + dst_material_indices.span); copy_or_interp_loop_attributes(result, f, mp, orig_mp, orig_me, orig_me_index, mim); } + dst_material_indices.finish(); /* BKE_mesh_calc_edges will calculate and populate all the * MEdges from the MPolys. */ @@ -761,17 +777,18 @@ static Mesh *imesh_to_mesh(IMesh *im, MeshesToIMeshInfo &mim) /* Now that the MEdges are populated, we can copy over the required attributes and custom layers. */ + MutableSpan<MEdge> edges = result->edges_for_write(); for (int fi : im->face_index_range()) { const Face *f = im->face(fi); - MPoly *mp = &result->mpoly[fi]; + const MPoly *mp = &dst_polys[fi]; for (int j : f->index_range()) { if (f->edge_orig[j] != NO_INDEX) { const Mesh *orig_me; int index_in_orig_me; const MEdge *orig_medge = mim.input_medge_for_orig_index( f->edge_orig[j], &orig_me, &index_in_orig_me); - int e_index = result->mloop[mp->loopstart + j].e; - MEdge *medge = &result->medge[e_index]; + int e_index = dst_loops[mp->loopstart + j].e; + MEdge *medge = &edges[e_index]; copy_edge_attributes(result, medge, orig_medge, orig_me, e_index, index_in_orig_me); } } @@ -814,7 +831,7 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, return mi; } } - return static_cast<int>(mim.mesh_poly_offset.size()) - 1; + return int(mim.mesh_poly_offset.size()) - 1; }; IMesh m_out = boolean_mesh(m_in, static_cast<BoolOpType>(boolean_mode), @@ -833,12 +850,14 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, /* Store intersecting edge indices. */ if (r_intersecting_edges != nullptr) { + const Span<MPoly> polys = result->polys(); + const Span<MLoop> loops = result->loops(); for (int fi : m_out.face_index_range()) { const Face &face = *m_out.face(fi); - const MPoly &poly = result->mpoly[fi]; + const MPoly &poly = polys[fi]; for (int corner_i : face.index_range()) { if (face.is_intersect[corner_i]) { - int e_index = result->mloop[poly.loopstart + corner_i].e; + int e_index = loops[poly.loopstart + corner_i].e; r_intersecting_edges->append(e_index); } } |