From 284cdbb6cf5061e2cb17ea6ca9f277e94b2bb62f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 9 Feb 2023 21:55:32 -0500 Subject: [PATCH] Cleanup: Use lambdas in mesh mapping callback, remove unused arguments Using callback functions didn't scale well as more arguments are added. It got very confusing when to pass tehmarguments weren't always used. Instead use a `FunctionRef` with indices for arguments. Also remove unused edge arguments to topology mapping functions. --- source/blender/blenkernel/BKE_mesh_mapping.h | 5 +- .../blender/blenkernel/intern/mesh_mapping.cc | 251 +++++++----------- .../blender/blenkernel/intern/mesh_remap.cc | 1 - .../editors/sculpt_paint/sculpt_face_set.cc | 1 - .../editors/sculpt_paint/sculpt_geodesic.cc | 10 +- .../wavefront_obj/exporter/obj_export_mesh.cc | 3 +- source/blender/makesrna/intern/rna_mesh_api.c | 3 +- 7 files changed, 107 insertions(+), 167 deletions(-) diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index b0f29a838bd..40d3b95139c 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -170,7 +170,6 @@ void BKE_mesh_vert_edge_vert_map_create( */ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, - const struct MEdge *medge, int totedge, const struct MPoly *mpoly, int totpoly, @@ -183,7 +182,6 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, */ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, - const struct MEdge *medge, int totedge, const struct MPoly *mpoly, int totpoly, @@ -317,8 +315,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3], * starting at 1 (0 being used as 'invalid' flag). * Note it's callers's responsibility to MEM_freeN returned array. */ -int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge, - int totedge, +int *BKE_mesh_calc_smoothgroups(int totedge, const struct MPoly *mpoly, int totpoly, const struct MLoop *mloop, diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index 5e29565e02a..427f3a44ddf 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -15,6 +15,7 @@ #include "BLI_array.hh" #include "BLI_bitmap.h" #include "BLI_buffer.h" +#include "BLI_function_ref.hh" #include "BLI_math.h" #include "BLI_task.hh" #include "BLI_utildefines.h" @@ -385,7 +386,6 @@ void BKE_mesh_vert_edge_vert_map_create( void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, - const MEdge * /*medge*/, const int totedge, const MPoly *mpoly, const int totpoly, @@ -438,7 +438,6 @@ void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, - const MEdge * /*medge*/, const int totedge, const MPoly *mpoly, const int totpoly, @@ -645,27 +644,19 @@ Vector> build_edge_to_loop_map_resizable(const Span loops, co /** * Callback deciding whether the given poly/loop/edge define an island boundary or not. */ -using MeshRemap_CheckIslandBoundary = bool (*)(const MPoly *mpoly, - const MLoop *mloop, - const MEdge *medge, - const int edge_index, - const bool *sharp_edges, - const int edge_user_count, - const MPoly *mpoly_array, - const MeshElemMap *edge_poly_map, - void *user_data); +using MeshRemap_CheckIslandBoundary = + blender::FunctionRef; -static void poly_edge_loop_islands_calc(const MEdge *medge, - const int totedge, - const MPoly *mpoly, - const int totpoly, - const MLoop *mloop, - const int totloop, - const bool *sharp_edges, +static void poly_edge_loop_islands_calc(const int totedge, + const blender::Span polys, + const blender::Span loops, MeshElemMap *edge_poly_map, const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, - void *edge_boundary_check_data, int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, @@ -689,7 +680,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, /* map vars */ int *edge_poly_mem = nullptr; - if (totpoly == 0) { + if (polys.size() == 0) { *r_totgroup = 0; *r_poly_groups = nullptr; if (r_edge_borders) { @@ -705,12 +696,17 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, } if (!edge_poly_map) { - BKE_mesh_edge_poly_map_create( - &edge_poly_map, &edge_poly_mem, medge, totedge, mpoly, totpoly, mloop, totloop); + BKE_mesh_edge_poly_map_create(&edge_poly_map, + &edge_poly_mem, + totedge, + polys.data(), + int(polys.size()), + loops.data(), + int(loops.size())); } - poly_groups = static_cast(MEM_callocN(sizeof(int) * size_t(totpoly), __func__)); - poly_stack = static_cast(MEM_mallocN(sizeof(int) * size_t(totpoly), __func__)); + poly_groups = static_cast(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__)); + poly_stack = static_cast(MEM_mallocN(sizeof(int) * size_t(polys.size()), __func__)); while (true) { int poly; @@ -718,13 +714,13 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, int poly_group_id; int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */ - for (poly = poly_prev; poly < totpoly; poly++) { + for (poly = poly_prev; poly < int(polys.size()); poly++) { if (poly_groups[poly] == 0) { break; } } - if (poly == totpoly) { + if (poly == int(polys.size())) { /* all done */ break; } @@ -738,23 +734,16 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, poly_stack[ps_end_idx++] = poly; while (ps_curr_idx != ps_end_idx) { - const MPoly *mp; - const MLoop *ml; - int j; - poly = poly_stack[ps_curr_idx++]; BLI_assert(poly_groups[poly] == poly_group_id); - mp = &mpoly[poly]; - for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) { + for (const int64_t loop : blender::IndexRange(polys[poly].loopstart, polys[poly].totloop)) { + const int edge = int(loops[loop].e); /* loop over poly users */ - const int me_idx = int(ml->e); - const MEdge *me = &medge[me_idx]; - const MeshElemMap *map_ele = &edge_poly_map[me_idx]; - const int *p = map_ele->indices; - int i = map_ele->count; - if (!edge_boundary_check( - mp, ml, me, me_idx, sharp_edges, i, mpoly, map_ele, edge_boundary_check_data)) { + const MeshElemMap &map_ele = edge_poly_map[edge]; + const int *p = map_ele.indices; + int i = map_ele.count; + if (!edge_boundary_check(poly, int(loop), edge, i, map_ele)) { for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); @@ -766,8 +755,8 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, } } else { - if (edge_borders && !BLI_BITMAP_TEST(edge_borders, me_idx)) { - BLI_BITMAP_ENABLE(edge_borders, me_idx); + if (edge_borders && !BLI_BITMAP_TEST(edge_borders, edge)) { + BLI_BITMAP_ENABLE(edge_borders, edge); num_edgeborders++; } if (use_bitflags) { @@ -828,7 +817,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, } if (UNLIKELY(group_id_overflow)) { - int i = totpoly, *gid = poly_groups; + int i = int(polys.size()), *gid = poly_groups; for (; i--; gid++) { if (*gid == poly_group_id_overflowed) { *gid = 0; @@ -852,31 +841,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge, } } -static bool poly_is_island_boundary_smooth_cb(const MPoly *mp, - const MLoop * /*ml*/, - const MEdge * /*me*/, - const int edge_index, - const bool *sharp_edges, - const int edge_user_count, - const MPoly *mpoly_array, - const MeshElemMap *edge_poly_map, - void * /*user_data*/) -{ - /* Edge is sharp if one of its polys is flat, or edge itself is sharp, - * or edge is not used by exactly two polygons. */ - if ((mp->flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) && - (edge_user_count == 2)) { - /* In that case, edge appears to be smooth, but we need to check its other poly too. */ - const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ? - &mpoly_array[edge_poly_map->indices[1]] : - &mpoly_array[edge_poly_map->indices[0]]; - return (mp_other->flag & ME_SMOOTH) == 0; - } - return true; -} - -int *BKE_mesh_calc_smoothgroups(const MEdge *medge, - const int totedge, +int *BKE_mesh_calc_smoothgroups(const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, @@ -887,17 +852,30 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, { int *poly_groups = nullptr; - poly_edge_loop_islands_calc(medge, - totedge, - mpoly, - totpoly, - mloop, - totloop, - sharp_edges, + auto poly_is_island_boundary_smooth = [&](const int poly_index, + const int /*loop_index*/, + const int edge_index, + const int edge_user_count, + const MeshElemMap &edge_poly_map_elem) { + /* Edge is sharp if one of its polys is flat, or edge itself is sharp, + * or edge is not used by exactly two polygons. */ + if ((mpoly[poly_index].flag & ME_SMOOTH) && !(sharp_edges && sharp_edges[edge_index]) && + (edge_user_count == 2)) { + /* In that case, edge appears to be smooth, but we need to check its other poly too. */ + const int other_poly_index = (poly_index == edge_poly_map_elem.indices[0]) ? + edge_poly_map_elem.indices[1] : + edge_poly_map_elem.indices[0]; + return (mpoly[other_poly_index].flag & ME_SMOOTH) == 0; + } + return true; + }; + + poly_edge_loop_islands_calc(totedge, + {mpoly, totpoly}, + {mloop, totloop}, nullptr, use_bitflags, - poly_is_island_boundary_smooth_cb, - nullptr, + poly_is_island_boundary_smooth, &poly_groups, r_totgroup, nullptr, @@ -1021,64 +999,6 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store, sizeof(*innrcut->indices) * size_t(num_innercut_items)); } -/* TODO: I'm not sure edge seam flag is enough to define UV islands? - * Maybe we should also consider UV-maps values - * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?). - * Would make things much more complex though, - * and each UVMap would then need its own mesh mapping, not sure we want that at all! - */ -struct MeshCheckIslandBoundaryUv { - const MLoop *loops; - const float (*luvs)[2]; - const MeshElemMap *edge_loop_map; -}; - -static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/, - const MLoop *ml, - const MEdge *me, - const int /*edge_index*/, - const bool * /*sharp_edges*/, - const int /*edge_user_count*/, - const MPoly * /*mpoly_array*/, - const MeshElemMap * /*edge_poly_map*/, - void *user_data) -{ - if (user_data) { - const MeshCheckIslandBoundaryUv *data = static_cast( - user_data); - const MLoop *loops = data->loops; - const float(*luvs)[2] = data->luvs; - const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e]; - - BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0); - - const uint v1 = loops[edge_to_loops->indices[0]].v; - const uint v2 = loops[edge_to_loops->indices[1]].v; - const float *uvco_v1 = luvs[edge_to_loops->indices[0]]; - const float *uvco_v2 = luvs[edge_to_loops->indices[1]]; - for (int i = 2; i < edge_to_loops->count; i += 2) { - if (loops[edge_to_loops->indices[i]].v == v1) { - if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) || - !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]])) { - return true; - } - } - else { - BLI_assert(loops[edge_to_loops->indices[i]].v == v2); - UNUSED_VARS_NDEBUG(v2); - if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) || - !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]])) { - return true; - } - } - } - return false; - } - - /* Edge is UV boundary if tagged as seam. */ - return (me->flag & ME_SEAM) != 0; -} - static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, const int totedge, const MPoly *polys, @@ -1098,8 +1018,6 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, MeshElemMap *edge_loop_map; int *edge_loop_mem; - MeshCheckIslandBoundaryUv edge_boundary_check_data; - int *poly_indices; int *loop_indices; int num_pidx, num_lidx; @@ -1120,27 +1038,62 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges, r_island_store, MISLAND_TYPE_LOOP, totloop, MISLAND_TYPE_POLY, MISLAND_TYPE_EDGE); BKE_mesh_edge_poly_map_create( - &edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop); + &edge_poly_map, &edge_poly_mem, totedge, polys, totpoly, loops, totloop); if (luvs) { BKE_mesh_edge_loop_map_create( - &edge_loop_map, &edge_loop_mem, edges, totedge, polys, totpoly, loops, totloop); - edge_boundary_check_data.loops = loops; - edge_boundary_check_data.luvs = luvs; - edge_boundary_check_data.edge_loop_map = edge_loop_map; + &edge_loop_map, &edge_loop_mem, totedge, polys, totpoly, loops, totloop); } - poly_edge_loop_islands_calc(edges, - totedge, - polys, - totpoly, - loops, - totloop, - nullptr, + /* TODO: I'm not sure edge seam flag is enough to define UV islands? + * Maybe we should also consider UV-maps values + * themselves (i.e. different UV-edges for a same mesh-edge => boundary edge too?). + * Would make things much more complex though, + * and each UVMap would then need its own mesh mapping, not sure we want that at all! + */ + auto mesh_check_island_boundary_uv = [&](const int /*poly_index*/, + const int loop_index, + const int edge_index, + const int /*edge_user_count*/, + const MeshElemMap & /*edge_poly_map_elem*/) -> bool { + if (luvs) { + const MeshElemMap &edge_to_loops = edge_loop_map[loops[loop_index].e]; + + BLI_assert(edge_to_loops.count >= 2 && (edge_to_loops.count % 2) == 0); + + const uint v1 = loops[edge_to_loops.indices[0]].v; + const uint v2 = loops[edge_to_loops.indices[1]].v; + const float *uvco_v1 = luvs[edge_to_loops.indices[0]]; + const float *uvco_v2 = luvs[edge_to_loops.indices[1]]; + for (int i = 2; i < edge_to_loops.count; i += 2) { + if (loops[edge_to_loops.indices[i]].v == v1) { + if (!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i]]) || + !equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i + 1]])) { + return true; + } + } + else { + BLI_assert(loops[edge_to_loops.indices[i]].v == v2); + UNUSED_VARS_NDEBUG(v2); + if (!equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i]]) || + !equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i + 1]])) { + return true; + } + } + } + return false; + } + + /* Edge is UV boundary if tagged as seam. */ + return (edges[edge_index].flag & ME_SEAM) != 0; + }; + + poly_edge_loop_islands_calc(totedge, + {polys, totpoly}, + {loops, totloop}, edge_poly_map, false, mesh_check_island_boundary_uv, - luvs ? &edge_boundary_check_data : nullptr, &poly_groups, &num_poly_groups, &edge_borders, diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index c32a9c067ac..5f3961398fb 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -1424,7 +1424,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, /* Needed for islands (or plain mesh) to AStar graph conversion. */ BKE_mesh_edge_poly_map_create(&edge_to_poly_map_src, &edge_to_poly_map_src_buff, - edges_src, num_edges_src, polys_src, num_polys_src, diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index d3c9e411f9c..51ecaa168f3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -548,7 +548,6 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill if (!ss->epmap) { BKE_mesh_edge_poly_map_create(&ss->epmap, &ss->epmap_mem, - edges.data(), edges.size(), polys.data(), polys.size(), diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc index 526f9028e8b..84232a295dd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc @@ -95,14 +95,8 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, BLI_bitmap *edge_tag = BLI_BITMAP_NEW(totedge, "edge tag"); if (!ss->epmap) { - BKE_mesh_edge_poly_map_create(&ss->epmap, - &ss->epmap_mem, - edges, - mesh->totedge, - polys, - mesh->totpoly, - loops, - mesh->totloop); + BKE_mesh_edge_poly_map_create( + &ss->epmap, &ss->epmap_mem, mesh->totedge, polys, mesh->totpoly, loops, mesh->totloop); } if (!ss->vemap) { BKE_mesh_vert_edge_map_create(&ss->vemap, &ss->vemap_mem, edges, mesh->totvert, mesh->totedge); diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc index 0d664811d12..e2ad7de7291 100644 --- a/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc +++ b/source/blender/io/wavefront_obj/exporter/obj_export_mesh.cc @@ -194,8 +194,7 @@ void OBJMesh::calc_smooth_groups(const bool use_bitflags) { const bool *sharp_edges = static_cast( CustomData_get_layer_named(&export_mesh_->edata, CD_PROP_BOOL, "sharp_edge")); - poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.data(), - mesh_edges_.size(), + poly_smooth_groups_ = BKE_mesh_calc_smoothgroups(mesh_edges_.size(), mesh_polys_.data(), mesh_polys_.size(), mesh_loops_.data(), diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 12b9c805701..f1de3185956 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -93,8 +93,7 @@ static void rna_Mesh_calc_smooth_groups( *r_poly_group_len = mesh->totpoly; const bool *sharp_edges = (const bool *)CustomData_get_layer_named( &mesh->edata, CD_PROP_BOOL, "sharp_edge"); - *r_poly_group = BKE_mesh_calc_smoothgroups(BKE_mesh_edges(mesh), - mesh->totedge, + *r_poly_group = BKE_mesh_calc_smoothgroups(mesh->totedge, BKE_mesh_polys(mesh), mesh->totpoly, BKE_mesh_loops(mesh),