diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 8b52ddcc3c3..f11d3895606 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -119,27 +119,6 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); #ifdef __cplusplus -/** - * Generates a map where the key is the vertex and the value - * is a list of polys that use that vertex as a corner. - * The lists are allocated from one memory pool. - */ -void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, - int **r_mem, - blender::OffsetIndices polys, - const int *corner_verts, - int totvert); -/** - * Generates a map where the key is the vertex and the value - * is a list of loops that use that vertex as a corner. - * The lists are allocated from one memory pool. - */ -void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, - int **r_mem, - blender::OffsetIndices polys, - const int *corner_verts, - int totvert); - /** * Generates a map where the key is the edge and the value * is a list of looptris that use that edge. @@ -152,42 +131,6 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, int totlooptri, const int *corner_verts, int totloop); -/** - * Generates a map where the key is the vertex and the value - * is a list of edges that use that vertex as an endpoint. - * The lists are allocated from one memory pool. - */ -void BKE_mesh_vert_edge_map_create( - MeshElemMap **r_map, int **r_mem, const blender::int2 *edges, int totvert, int totedge); -/** - * A version of #BKE_mesh_vert_edge_map_create that references connected vertices directly - * (not their edges). - */ -void BKE_mesh_vert_edge_vert_map_create( - MeshElemMap **r_map, int **r_mem, const blender::int2 *edges, int totvert, int totedge); - -/** - * Generates a map where the key is the edge and the value is a list of loops that use that edge. - * Loops indices of a same poly are contiguous and in winding order. - * The lists are allocated from one memory pool. - */ -void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, - int **r_mem, - int totedge, - blender::OffsetIndices polys, - const int *corner_edges, - int totloop); -/** - * Generates a map where the key is the edge and the value - * is a list of polygons that use that edge. - * The lists are allocated from one memory pool. - */ -void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, - int **r_mem, - int totedge, - blender::OffsetIndices polys, - const int *corner_edges, - int totloop); /** * This function creates a map so the source-data (vert/edge/loop/poly) * can loop over the destination data (using the destination arrays origindex). @@ -346,20 +289,36 @@ int *BKE_mesh_calc_smoothgroups(int totedge, #ifdef __cplusplus -namespace blender::bke::mesh_topology { +namespace blender::bke::mesh { Array build_loop_to_poly_map(OffsetIndices polys); -Array> build_vert_to_edge_map(Span edges, int verts_num); -Array> build_vert_to_poly_map(OffsetIndices polys, - Span corner_verts, - int verts_num); -Array> build_vert_to_loop_map(Span corner_verts, int verts_num); -Array> build_edge_to_loop_map(Span corner_edges, int edges_num); -Array> build_edge_to_poly_map(OffsetIndices polys, - Span corner_edges, - int edges_num); -Vector> build_edge_to_loop_map_resizable(Span corner_edges, int edges_num); +GroupedSpan build_vert_to_edge_map(Span edges, + int verts_num, + Array &r_offsets, + Array &r_indices); -} // namespace blender::bke::mesh_topology +GroupedSpan build_vert_to_poly_map(OffsetIndices polys, + Span corner_verts, + int verts_num, + Array &r_offsets, + Array &r_indices); + +GroupedSpan build_vert_to_loop_map(Span corner_verts, + int verts_num, + Array &r_offsets, + Array &r_indices); + +GroupedSpan build_edge_to_loop_map(Span corner_edges, + int edges_num, + Array &r_offsets, + Array &r_indices); + +GroupedSpan build_edge_to_poly_map(OffsetIndices polys, + Span corner_edges, + int edges_num, + Array &r_offsets, + Array &r_indices); + +} // namespace blender::bke::mesh #endif diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index cb674d3f744..a366fe0d991 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -9,6 +9,10 @@ #include "BLI_bitmap.h" #include "BLI_compiler_compat.h" +#ifdef __cplusplus +# include "BLI_array.hh" +# include "BLI_offset_indices.hh" +#endif #include "BLI_utildefines.h" #include "DNA_brush_enums.h" @@ -40,7 +44,6 @@ struct ListBase; struct MLoopTri; struct Main; struct Mesh; -struct MeshElemMap; struct Object; struct PBVH; struct Paint; @@ -273,12 +276,17 @@ void BKE_paint_blend_read_lib(struct BlendLibReader *reader, #define SCULPT_FACE_SET_NONE 0 /** Used for both vertex color and weight paint. */ +#ifdef __cplusplus struct SculptVertexPaintGeomMap { - int *vert_map_mem; - struct MeshElemMap *vert_to_loop; - int *poly_map_mem; - struct MeshElemMap *vert_to_poly; + blender::Array vert_to_loop_offsets; + blender::Array vert_to_loop_indices; + blender::GroupedSpan vert_to_loop; + + blender::Array vert_to_poly_offsets; + blender::Array vert_to_poly_indices; + blender::GroupedSpan vert_to_poly; }; +#endif /** Pose Brush IK Chain. */ typedef struct SculptPoseIKChainSegment { @@ -599,16 +607,19 @@ typedef struct SculptSession { /* Mesh connectivity maps. */ /* Vertices to adjacent polys. */ - struct MeshElemMap *pmap; - int *pmap_mem; + blender::Array vert_to_poly_offsets; + blender::Array vert_to_poly_indices; + blender::GroupedSpan pmap; /* Edges to adjacent polys. */ - struct MeshElemMap *epmap; - int *epmap_mem; + blender::Array edge_to_poly_offsets; + blender::Array edge_to_poly_indices; + blender::GroupedSpan epmap; /* Vertices to adjacent edges. */ - struct MeshElemMap *vemap; - int *vemap_mem; + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + blender::GroupedSpan vemap; /* Mesh Face Sets */ /* Total number of polys of the base mesh. */ @@ -706,7 +717,7 @@ typedef struct SculptSession { float prev_pivot_rot[4]; float prev_pivot_scale[3]; - union { + struct { struct { struct SculptVertexPaintGeomMap gmap; } vpaint; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 8e8b08f5d8a..fa82f1015ac 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -35,7 +35,6 @@ struct DMFlagMat; struct IsectRayPrecalc; struct MLoopTri; struct Mesh; -struct MeshElemMap; struct PBVH; struct PBVHBatches; struct PBVHNode; @@ -45,7 +44,6 @@ struct SubdivCCG; struct TaskParallelSettings; struct Image; struct ImageUser; -struct MeshElemMap; typedef struct PBVH PBVH; typedef struct PBVHNode PBVHNode; @@ -808,7 +806,6 @@ void BKE_pbvh_is_drawing_set(PBVH *pbvh, bool val); void BKE_pbvh_node_num_loops(PBVH *pbvh, PBVHNode *node, int *r_totloop); void BKE_pbvh_update_active_vcol(PBVH *pbvh, const struct Mesh *mesh); -void BKE_pbvh_pmap_set(PBVH *pbvh, const struct MeshElemMap *pmap); void BKE_pbvh_vertex_color_set(PBVH *pbvh, PBVHVertRef vertex, const float color[4]); void BKE_pbvh_vertex_color_get(const PBVH *pbvh, PBVHVertRef vertex, float r_color[4]); @@ -818,6 +815,7 @@ bool BKE_pbvh_draw_cache_invalid(const PBVH *pbvh); int BKE_pbvh_debug_draw_gen_get(PBVHNode *node); #ifdef __cplusplus +void BKE_pbvh_pmap_set(PBVH *pbvh, blender::GroupedSpan pmap); } namespace blender::bke::pbvh { diff --git a/source/blender/blenkernel/BKE_subdiv_mesh.hh b/source/blender/blenkernel/BKE_subdiv_mesh.hh index 1380aeeb1b7..b922b7b39bb 100644 --- a/source/blender/blenkernel/BKE_subdiv_mesh.hh +++ b/source/blender/blenkernel/BKE_subdiv_mesh.hh @@ -8,10 +8,10 @@ #pragma once #include "BLI_math_vector_types.hh" +#include "BLI_offset_indices.hh" #include "BLI_sys_types.h" struct Mesh; -struct MeshElemMap; struct Subdiv; struct SubdivToMeshSettings { @@ -36,7 +36,7 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, * interpolation will be done base on the edge vertices. */ void BKE_subdiv_mesh_interpolate_position_on_edge(const float (*coarse_positions)[3], const blender::int2 *coarse_edges, - const MeshElemMap *vert_to_edge_map, + blender::GroupedSpan vert_to_edge_map, int coarse_edge_index, bool is_simple, float u, diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index ecf88f5c797..e7c79bfcd09 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -66,9 +66,9 @@ class FairingContext { return totvert_; } - MeshElemMap *vertex_loop_map_get(const int v) + Span vertex_loop_map_get(const int v) { - return &vlmap_[v]; + return vlmap_[v]; } float *vertex_deformation_co_get(const int v) @@ -93,8 +93,7 @@ class FairingContext { int totvert_; int totloop_; - MeshElemMap *vlmap_; - int *vlmap_mem_; + blender::GroupedSpan vlmap_; private: void fair_setup_fairing(const int v, @@ -120,9 +119,9 @@ class FairingContext { float w_ij_sum = 0; const float w_i = vertex_weight->weight_at_index(v); - MeshElemMap *vlmap_elem = &vlmap_[v]; - for (int l = 0; l < vlmap_elem->count; l++) { - const int l_index = vlmap_elem->indices[l]; + const Span vlmap_elem = vlmap_[v]; + for (const int l : vlmap_elem.index_range()) { + const int l_index = vlmap_elem[l]; const int other_vert = other_vertex_index_from_loop(l_index, v); const float w_ij = loop_weight->weight_at_index(l_index); w_ij_sum += w_ij; @@ -202,8 +201,8 @@ class MeshFairingContext : public FairingContext { polys = mesh->polys(); corner_verts_ = mesh->corner_verts(); corner_edges_ = mesh->corner_edges(); - BKE_mesh_vert_loop_map_create( - &vlmap_, &vlmap_mem_, polys, corner_verts_.data(), mesh->totvert); + vlmap_ = blender::bke::mesh::build_vert_to_loop_map( + corner_verts_, positions.size(), vert_to_poly_offsets_, vert_to_poly_indices_); /* Deformation coords. */ co_.reserve(mesh->totvert); @@ -218,13 +217,7 @@ class MeshFairingContext : public FairingContext { } } - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys); - } - - ~MeshFairingContext() override - { - MEM_SAFE_FREE(vlmap_); - MEM_SAFE_FREE(vlmap_mem_); + loop_to_poly_map_ = blender::bke::mesh::build_loop_to_poly_map(polys); } void adjacents_coords_from_loop(const int loop, @@ -252,6 +245,8 @@ class MeshFairingContext : public FairingContext { blender::OffsetIndices polys; Span edges_; Array loop_to_poly_map_; + Array vert_to_poly_offsets_; + Array vert_to_poly_indices_; }; class BMeshFairingContext : public FairingContext { @@ -272,9 +267,9 @@ class BMeshFairingContext : public FairingContext { co_[i] = v->co; } - bmloop_.reserve(bm->totloop); - vlmap_ = (MeshElemMap *)MEM_calloc_arrayN(bm->totvert, sizeof(MeshElemMap), "bmesh loop map"); - vlmap_mem_ = (int *)MEM_malloc_arrayN(bm->totloop, sizeof(int), "bmesh loop map mempool"); + bmloop_.reinitialize(bm->totloop); + vert_to_loop_offsets_ = Array(bm->totvert, 0); + vert_to_loop_indices_.reinitialize(bm->totloop); BMVert *v; BMLoop *l; @@ -286,22 +281,16 @@ class BMeshFairingContext : public FairingContext { BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { int loop_count = 0; const int vert_index = BM_elem_index_get(v); - vlmap_[vert_index].indices = &vlmap_mem_[index_iter]; + vert_to_loop_offsets_[vert_index] = index_iter; BM_ITER_ELEM (l, &loop_iter, v, BM_LOOPS_OF_VERT) { const int loop_index = BM_elem_index_get(l); bmloop_[loop_index] = l; - vlmap_mem_[index_iter] = loop_index; + vert_to_loop_indices_[index_iter] = loop_index; index_iter++; loop_count++; } - vlmap_[vert_index].count = loop_count; } - } - - ~BMeshFairingContext() override - { - MEM_SAFE_FREE(vlmap_); - MEM_SAFE_FREE(vlmap_mem_); + vert_to_loop_offsets_.last() = index_iter; } void adjacents_coords_from_loop(const int loop, @@ -322,7 +311,9 @@ class BMeshFairingContext : public FairingContext { protected: BMesh *bm; - Vector bmloop_; + Array bmloop_; + Array vert_to_loop_offsets_; + Array vert_to_loop_indices_; }; class UniformVertexWeight : public VertexWeight { @@ -332,7 +323,7 @@ class UniformVertexWeight : public VertexWeight { const int totvert = fairing_context->vertex_count_get(); vertex_weights_.reserve(totvert); for (int i = 0; i < totvert; i++) { - const int tot_loop = fairing_context->vertex_loop_map_get(i)->count; + const int tot_loop = fairing_context->vertex_loop_map_get(i).size(); if (tot_loop != 0) { vertex_weights_[i] = 1.0f / tot_loop; } @@ -366,9 +357,9 @@ class VoronoiVertexWeight : public VertexWeight { copy_v3_v3(a, fairing_context->vertex_deformation_co_get(i)); const float acute_threshold = M_PI_2; - MeshElemMap *vlmap_elem = fairing_context->vertex_loop_map_get(i); - for (int l = 0; l < vlmap_elem->count; l++) { - const int l_index = vlmap_elem->indices[l]; + const Span vlmap_elem = fairing_context->vertex_loop_map_get(i); + for (const int l : vlmap_elem.index_range()) { + const int l_index = vlmap_elem[l]; float b[3], c[3], d[3]; fairing_context->adjacents_coords_from_loop(l_index, b, c); diff --git a/source/blender/blenkernel/intern/mesh_mapping.cc b/source/blender/blenkernel/intern/mesh_mapping.cc index 29655e7266c..4d2d7448d22 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.cc +++ b/source/blender/blenkernel/intern/mesh_mapping.cc @@ -183,74 +183,6 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap) } } -/** - * Generates a map where the key is the vertex and the value is a list - * of polys or loops that use that vertex as a corner. The lists are allocated - * from one memory pool. - * - * Wrapped by #BKE_mesh_vert_poly_map_create & BKE_mesh_vert_loop_map_create - */ -static void mesh_vert_poly_or_loop_map_create(MeshElemMap **r_map, - int **r_mem, - const blender::OffsetIndices polys, - const int *corner_verts, - int totvert, - const bool do_loops) -{ - MeshElemMap *map = MEM_cnew_array(size_t(totvert), __func__); - int *indices, *index_iter; - - indices = static_cast(MEM_mallocN(sizeof(int) * size_t(polys.total_size()), __func__)); - index_iter = indices; - - /* Count number of polys for each vertex */ - for (const int64_t i : polys.index_range()) { - for (const int64_t corner : polys[i]) { - map[corner_verts[corner]].count++; - } - } - - /* Assign indices mem */ - for (int64_t i = 0; i < totvert; i++) { - map[i].indices = index_iter; - index_iter += map[i].count; - - /* Reset 'count' for use as index in last loop */ - map[i].count = 0; - } - - /* Find the users */ - for (const int64_t i : polys.index_range()) { - for (const int64_t corner : polys[i]) { - const int v = corner_verts[corner]; - - map[v].indices[map[v].count] = do_loops ? int(corner) : int(i); - map[v].count++; - } - } - - *r_map = map; - *r_mem = indices; -} - -void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, - int **r_mem, - const blender::OffsetIndices polys, - const int *corner_verts, - int totvert) -{ - mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, corner_verts, totvert, false); -} - -void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, - int **r_mem, - const blender::OffsetIndices polys, - const int *corner_verts, - int totvert) -{ - mesh_vert_poly_or_loop_map_create(r_map, r_mem, polys, corner_verts, totvert, true); -} - void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, int **r_mem, const int totvert, @@ -294,166 +226,6 @@ void BKE_mesh_vert_looptri_map_create(MeshElemMap **r_map, *r_mem = indices; } -void BKE_mesh_vert_edge_map_create( - MeshElemMap **r_map, int **r_mem, const blender::int2 *edges, int totvert, int totedge) -{ - MeshElemMap *map = MEM_cnew_array(size_t(totvert), __func__); - int *indices = static_cast(MEM_mallocN(sizeof(int[2]) * size_t(totedge), __func__)); - int *i_pt = indices; - - int i; - - /* Count number of edges for each vertex */ - for (i = 0; i < totedge; i++) { - map[edges[i][0]].count++; - map[edges[i][1]].count++; - } - - /* Assign indices mem */ - for (i = 0; i < totvert; i++) { - map[i].indices = i_pt; - i_pt += map[i].count; - - /* Reset 'count' for use as index in last loop */ - map[i].count = 0; - } - - /* Find the users */ - for (i = 0; i < totedge; i++) { - const int v[2] = {edges[i][0], edges[i][1]}; - - map[v[0]].indices[map[v[0]].count] = i; - map[v[1]].indices[map[v[1]].count] = i; - - map[v[0]].count++; - map[v[1]].count++; - } - - *r_map = map; - *r_mem = indices; -} - -void BKE_mesh_vert_edge_vert_map_create( - MeshElemMap **r_map, int **r_mem, const blender::int2 *edges, int totvert, int totedge) -{ - MeshElemMap *map = MEM_cnew_array(size_t(totvert), __func__); - int *indices = static_cast(MEM_mallocN(sizeof(int[2]) * size_t(totedge), __func__)); - int *i_pt = indices; - - int i; - - /* Count number of edges for each vertex */ - for (i = 0; i < totedge; i++) { - map[edges[i][0]].count++; - map[edges[i][1]].count++; - } - - /* Assign indices mem */ - for (i = 0; i < totvert; i++) { - map[i].indices = i_pt; - i_pt += map[i].count; - - /* Reset 'count' for use as index in last loop */ - map[i].count = 0; - } - - /* Find the users */ - for (i = 0; i < totedge; i++) { - const int v[2] = {edges[i][0], edges[i][1]}; - - map[v[0]].indices[map[v[0]].count] = int(v[1]); - map[v[1]].indices[map[v[1]].count] = int(v[0]); - - map[v[0]].count++; - map[v[1]].count++; - } - - *r_map = map; - *r_mem = indices; -} - -void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, - int **r_mem, - const int totedge, - const blender::OffsetIndices polys, - const int *corner_edges, - const int totloop) -{ - using namespace blender; - MeshElemMap *map = MEM_cnew_array(size_t(totedge), __func__); - int *indices = static_cast(MEM_mallocN(sizeof(int) * size_t(totloop) * 2, __func__)); - int *index_step; - - /* count face users */ - for (const int64_t i : IndexRange(totloop)) { - map[corner_edges[i]].count += 2; - } - - /* create offsets */ - index_step = indices; - for (int i = 0; i < totedge; i++) { - map[i].indices = index_step; - index_step += map[i].count; - - /* re-count, using this as an index below */ - map[i].count = 0; - } - - /* assign loop-edge users */ - for (const int64_t i : polys.index_range()) { - MeshElemMap *map_ele; - for (const int64_t corner : polys[i]) { - map_ele = &map[corner_edges[corner]]; - map_ele->indices[map_ele->count++] = int(corner); - map_ele->indices[map_ele->count++] = int(corner) + 1; - } - /* last edge/loop of poly, must point back to first loop! */ - map_ele->indices[map_ele->count - 1] = int(polys[i].start()); - } - - *r_map = map; - *r_mem = indices; -} - -void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, - int **r_mem, - const int totedge, - const blender::OffsetIndices polys, - const int *corner_edges, - const int totloop) -{ - MeshElemMap *map = MEM_cnew_array(size_t(totedge), __func__); - int *indices = static_cast(MEM_mallocN(sizeof(int) * size_t(totloop), __func__)); - int *index_step; - - /* count face users */ - for (const int64_t i : blender::IndexRange(totloop)) { - map[corner_edges[i]].count++; - } - - /* create offsets */ - index_step = indices; - for (int i = 0; i < totedge; i++) { - map[i].indices = index_step; - index_step += map[i].count; - - /* re-count, using this as an index below */ - map[i].count = 0; - } - - /* assign poly-edge users */ - for (const int64_t i : polys.index_range()) { - for (const int64_t corner : polys[i]) { - const int edge_i = corner_edges[corner]; - MeshElemMap *map_ele = &map[edge_i]; - map_ele->indices[map_ele->count++] = int(i); - } - } - - *r_map = map; - *r_mem = indices; -} - void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, const int totsource, @@ -522,7 +294,17 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map, *r_mem = indices; } -namespace blender::bke::mesh_topology { +namespace blender::bke::mesh { + +static Array create_reverse_offsets(const Span indices, const int items_num) +{ + Array offsets(items_num + 1, 0); + for (const int i : indices) { + offsets[i]++; + } + offset_indices::accumulate_counts_to_offsets(offsets); + return offsets; +} Array build_loop_to_poly_map(const OffsetIndices polys) { @@ -531,72 +313,97 @@ Array build_loop_to_poly_map(const OffsetIndices polys) return map; } -Array> build_vert_to_edge_map(const Span edges, const int verts_num) +GroupedSpan build_vert_to_edge_map(const Span edges, + const int verts_num, + Array &r_offsets, + Array &r_indices) { - Array> map(verts_num); - for (const int64_t i : edges.index_range()) { - map[edges[i][0]].append(int(i)); - map[edges[i][1]].append(int(i)); - } - return map; -} + r_offsets = create_reverse_offsets(edges.cast(), verts_num); + r_indices.reinitialize(r_offsets.last()); + Array counts(verts_num, 0); -Array> build_vert_to_poly_map(const OffsetIndices polys, - const Span corner_verts, - int verts_num) -{ - Array> map(verts_num); - for (const int64_t i : polys.index_range()) { - for (const int64_t vert_i : corner_verts.slice(polys[i])) { - map[int(vert_i)].append(int(i)); + for (const int64_t edge_i : edges.index_range()) { + for (const int vert : {edges[edge_i][0], edges[edge_i][1]}) { + r_indices[r_offsets[vert] + counts[vert]] = int(edge_i); + counts[vert]++; } } - return map; + return {OffsetIndices(r_offsets), r_indices}; } -Array> build_vert_to_loop_map(const Span corner_verts, const int verts_num) +GroupedSpan build_vert_to_poly_map(const OffsetIndices polys, + const Span corner_verts, + const int verts_num, + Array &r_offsets, + Array &r_indices) { - Array> map(verts_num); - for (const int64_t i : corner_verts.index_range()) { - map[corner_verts[i]].append(int(i)); - } - return map; -} + r_offsets = create_reverse_offsets(corner_verts, verts_num); + r_indices.reinitialize(r_offsets.last()); + Array counts(verts_num, 0); -Array> build_edge_to_loop_map(const Span corner_edges, const int edges_num) -{ - Array> map(edges_num); - for (const int64_t i : corner_edges.index_range()) { - map[corner_edges[i]].append(int(i)); - } - return map; -} - -Array> build_edge_to_poly_map(const OffsetIndices polys, - const Span corner_edges, - const int edges_num) -{ - Array> map(edges_num); - for (const int64_t i : polys.index_range()) { - for (const int edge : corner_edges.slice(polys[i])) { - map[edge].append(int(i)); + for (const int64_t poly_i : polys.index_range()) { + for (const int vert : corner_verts.slice(polys[poly_i])) { + r_indices[r_offsets[vert] + counts[vert]] = int(poly_i); + counts[vert]++; } } - return map; + return {OffsetIndices(r_offsets), r_indices}; } -Vector> build_edge_to_loop_map_resizable(const Span corner_edges, - const int edges_num) - +GroupedSpan build_vert_to_loop_map(const Span corner_verts, + const int verts_num, + Array &r_offsets, + Array &r_indices) { - Vector> map(edges_num); - for (const int64_t i : corner_edges.index_range()) { - map[corner_edges[i]].append(int(i)); + r_offsets = create_reverse_offsets(corner_verts, verts_num); + r_indices.reinitialize(r_offsets.last()); + Array counts(verts_num, 0); + + for (const int64_t corner : corner_verts.index_range()) { + const int vert = corner_verts[corner]; + r_indices[r_offsets[vert] + counts[vert]] = int(corner); + counts[vert]++; } - return map; + return {OffsetIndices(r_offsets), r_indices}; } -} // namespace blender::bke::mesh_topology +GroupedSpan build_edge_to_loop_map(const Span corner_edges, + const int edges_num, + Array &r_offsets, + Array &r_indices) +{ + r_offsets = create_reverse_offsets(corner_edges, edges_num); + r_indices.reinitialize(r_offsets.last()); + Array counts(edges_num, 0); + + for (const int64_t corner : corner_edges.index_range()) { + const int edge = corner_edges[corner]; + r_indices[r_offsets[edge] + counts[edge]] = int(corner); + counts[edge]++; + } + return {OffsetIndices(r_offsets), r_indices}; +} + +GroupedSpan build_edge_to_poly_map(const OffsetIndices polys, + const Span corner_edges, + const int edges_num, + Array &r_offsets, + Array &r_indices) +{ + r_offsets = create_reverse_offsets(corner_edges, edges_num); + r_indices.reinitialize(r_offsets.last()); + Array counts(edges_num, 0); + + for (const int64_t poly_i : polys.index_range()) { + for (const int edge : corner_edges.slice(polys[poly_i])) { + r_indices[r_offsets[edge] + counts[edge]] = int(poly_i); + counts[edge]++; + } + } + return {OffsetIndices(r_offsets), r_indices}; +} + +} // namespace blender::bke::mesh /** \} */ @@ -613,12 +420,12 @@ using MeshRemap_CheckIslandBoundary = int loop_index, int edge_index, int edge_user_count, - const MeshElemMap &edge_poly_map_elem)>; + const blender::Span edge_poly_map_elem)>; static void poly_edge_loop_islands_calc(const int totedge, const blender::OffsetIndices polys, const blender::Span corner_edges, - MeshElemMap *edge_poly_map, + blender::GroupedSpan edge_poly_map, const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, int **r_poly_groups, @@ -641,9 +448,6 @@ static void poly_edge_loop_islands_calc(const int totedge, int tot_group = 0; bool group_id_overflow = false; - /* map vars */ - int *edge_poly_mem = nullptr; - if (polys.size() == 0) { *r_totgroup = 0; *r_poly_groups = nullptr; @@ -659,13 +463,11 @@ static void poly_edge_loop_islands_calc(const int totedge, *r_totedgeborder = 0; } - if (!edge_poly_map) { - BKE_mesh_edge_poly_map_create(&edge_poly_map, - &edge_poly_mem, - totedge, - polys, - corner_edges.data(), - int(corner_edges.size())); + blender::Array edge_to_poly_src_offsets; + blender::Array edge_to_poly_src_indices; + if (edge_poly_map.is_empty()) { + edge_poly_map = blender::bke::mesh::build_edge_to_poly_map( + polys, corner_edges, totedge, edge_to_poly_src_offsets, edge_to_poly_src_indices); } poly_groups = static_cast(MEM_callocN(sizeof(int) * size_t(polys.size()), __func__)); @@ -703,9 +505,9 @@ static void poly_edge_loop_islands_calc(const int totedge, for (const int64_t loop : polys[poly]) { const int edge = corner_edges[loop]; /* loop over poly users */ - const MeshElemMap &map_ele = edge_poly_map[edge]; - const int *p = map_ele.indices; - int i = map_ele.count; + const blender::Span map_ele = edge_poly_map[edge]; + const int *p = map_ele.data(); + int i = int(map_ele.size()); if (!edge_boundary_check(poly, int(loop), edge, i, map_ele)) { for (; i--; p++) { /* if we meet other non initialized its a bug */ @@ -790,10 +592,6 @@ static void poly_edge_loop_islands_calc(const int totedge, tot_group++; } - if (edge_poly_mem) { - MEM_freeN(edge_poly_map); - MEM_freeN(edge_poly_mem); - } MEM_freeN(poly_stack); *r_totgroup = tot_group; @@ -822,16 +620,15 @@ int *BKE_mesh_calc_smoothgroups(const int totedge, const int /*loop_index*/, const int edge_index, const int edge_user_count, - const MeshElemMap &edge_poly_map_elem) { + const blender::Span 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 (poly_is_smooth(poly_index) && !(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]; + const int other_poly_index = (poly_index == edge_poly_map_elem[0]) ? edge_poly_map_elem[1] : + edge_poly_map_elem[0]; return !poly_is_smooth(other_poly_index); } return true; @@ -840,7 +637,7 @@ int *BKE_mesh_calc_smoothgroups(const int totedge, poly_edge_loop_islands_calc(totedge, blender::Span(poly_offsets, totpoly + 1), {corner_edges, totloop}, - nullptr, + {}, use_bitflags, poly_is_island_boundary_smooth, &poly_groups, @@ -975,16 +772,10 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, const float (*luvs)[2], MeshIslandStore *r_island_store) { + using namespace blender; int *poly_groups = nullptr; int num_poly_groups; - /* map vars */ - MeshElemMap *edge_poly_map; - int *edge_poly_mem; - - MeshElemMap *edge_loop_map; - int *edge_loop_mem; - int *poly_indices; int *loop_indices; int num_pidx, num_lidx; @@ -1004,12 +795,17 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, BKE_mesh_loop_islands_init( 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, totedge, polys, corner_edges, totloop); + Array edge_to_poly_offsets; + Array edge_to_poly_indices; + const GroupedSpan edge_to_poly_map = bke::mesh::build_edge_to_poly_map( + polys, {corner_edges, totloop}, totedge, edge_to_poly_offsets, edge_to_poly_indices); + Array edge_to_loop_offsets; + Array edge_to_loop_indices; + GroupedSpan edge_to_loop_map; if (luvs) { - BKE_mesh_edge_loop_map_create( - &edge_loop_map, &edge_loop_mem, totedge, polys, corner_edges, totloop); + edge_to_loop_map = bke::mesh::build_edge_to_loop_map( + {corner_edges, totloop}, totedge, edge_to_loop_offsets, edge_to_loop_indices); } /* TODO: I'm not sure edge seam flag is enough to define UV islands? @@ -1022,29 +818,29 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, const int loop_index, const int edge_index, const int /*edge_user_count*/, - const MeshElemMap & /*edge_poly_map_elem*/) -> bool { + const Span /*edge_poly_map_elem*/) -> bool { if (luvs) { - const MeshElemMap &edge_to_loops = edge_loop_map[corner_edges[loop_index]]; + const Span edge_to_loops = edge_to_loop_map[corner_edges[loop_index]]; - BLI_assert(edge_to_loops.count >= 2 && (edge_to_loops.count % 2) == 0); + BLI_assert(edge_to_loops.size() >= 2 && (edge_to_loops.size() % 2) == 0); - const int v1 = corner_verts[edge_to_loops.indices[0]]; - const int v2 = corner_verts[edge_to_loops.indices[1]]; - 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 (corner_verts[edge_to_loops.indices[i]] == v1) { - if (!equals_v2v2(uvco_v1, luvs[edge_to_loops.indices[i]]) || - !equals_v2v2(uvco_v2, luvs[edge_to_loops.indices[i + 1]])) + const int v1 = corner_verts[edge_to_loops[0]]; + const int v2 = corner_verts[edge_to_loops[1]]; + const float *uvco_v1 = luvs[edge_to_loops[0]]; + const float *uvco_v2 = luvs[edge_to_loops[1]]; + for (int i = 2; i < edge_to_loops.size(); i += 2) { + if (corner_verts[edge_to_loops[i]] == v1) { + if (!equals_v2v2(uvco_v1, luvs[edge_to_loops[i]]) || + !equals_v2v2(uvco_v2, luvs[edge_to_loops[i + 1]])) { return true; } } else { - BLI_assert(corner_verts[edge_to_loops.indices[i]] == v2); + BLI_assert(corner_verts[edge_to_loops[i]] == 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]])) + if (!equals_v2v2(uvco_v2, luvs[edge_to_loops[i]]) || + !equals_v2v2(uvco_v1, luvs[edge_to_loops[i + 1]])) { return true; } @@ -1060,7 +856,7 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, poly_edge_loop_islands_calc(totedge, polys, {corner_edges, totloop}, - edge_poly_map, + edge_to_poly_map, false, mesh_check_island_boundary_uv, &poly_groups, @@ -1069,10 +865,6 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, &num_edge_borders); if (!num_poly_groups) { - /* Should never happen... */ - MEM_freeN(edge_poly_map); - MEM_freeN(edge_poly_mem); - if (edge_borders) { MEM_freeN(edge_borders); } @@ -1126,14 +918,6 @@ static bool mesh_calc_islands_loop_poly_uv(const int totedge, edge_innercut_indices); } - MEM_freeN(edge_poly_map); - MEM_freeN(edge_poly_mem); - - if (luvs) { - MEM_freeN(edge_loop_map); - MEM_freeN(edge_loop_mem); - } - MEM_freeN(poly_indices); MEM_freeN(loop_indices); MEM_freeN(poly_groups); diff --git a/source/blender/blenkernel/intern/mesh_merge_customdata.cc b/source/blender/blenkernel/intern/mesh_merge_customdata.cc index a135a7e7d55..45c82f2fff4 100644 --- a/source/blender/blenkernel/intern/mesh_merge_customdata.cc +++ b/source/blender/blenkernel/intern/mesh_merge_customdata.cc @@ -113,10 +113,10 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me) return; } - int *vert_map_mem; - struct MeshElemMap *vert_to_loop; - BKE_mesh_vert_loop_map_create( - &vert_to_loop, &vert_map_mem, me->polys(), me->corner_verts().data(), me->totvert); + Array vert_to_loop_offsets; + Array vert_to_loop_indices; + const GroupedSpan vert_to_loop = bke::mesh::build_vert_to_loop_map( + me->corner_verts(), me->totvert, vert_to_loop_offsets, vert_to_loop_indices); Vector mloopuv_layers; mloopuv_layers.reserve(mloopuv_layers_num); @@ -130,12 +130,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me) threading::parallel_for(IndexRange(me->totvert), 1024, [&](IndexRange range) { for (const int64_t v_index : range) { - MeshElemMap &loops_for_vert = vert_to_loop[v_index]; - Span loops_for_vert_span(loops_for_vert.indices, loops_for_vert.count); - merge_uvs_for_vertex(loops_for_vert_span, mloopuv_layers_as_span); + merge_uvs_for_vertex(vert_to_loop[v_index], mloopuv_layers_as_span); } }); - - MEM_freeN(vert_to_loop); - MEM_freeN(vert_map_mem); } diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc index 78efd3e2256..725d25e1fb2 100644 --- a/source/blender/blenkernel/intern/mesh_normals.cc +++ b/source/blender/blenkernel/intern/mesh_normals.cc @@ -819,7 +819,7 @@ void edges_sharp_from_angle_set(const OffsetIndices polys, Array edge_to_loops(sharp_edges.size(), int2(0)); /* Simple mapping from a loop to its polygon index. */ - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys); + const Array loop_to_poly = build_loop_to_poly_map(polys); mesh_edges_sharp_tag(polys, corner_verts, @@ -1318,7 +1318,7 @@ void normals_calc_loop(const Span vert_positions, Span loop_to_poly; Array local_loop_to_poly_map; if (loop_to_poly_map.is_empty()) { - local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map(polys); + local_loop_to_poly_map = build_loop_to_poly_map(polys); loop_to_poly = local_loop_to_poly_map; } else { @@ -1419,11 +1419,8 @@ static void reverse_index_array(const Span item_indices, Array &r_reverse_indices) { r_offsets = Array(items_num + 1, 0); - for (const int index : item_indices) { - r_offsets[index]++; - } + offset_indices::build_reverse_offsets(item_indices, r_offsets); - offset_indices::accumulate_counts_to_offsets(r_offsets); r_reverse_indices.reinitialize(r_offsets.last()); Array count_per_item(items_num, 0); @@ -1465,7 +1462,7 @@ static void mesh_normals_loop_custom_set(Span positions, CornerNormalSpaceArray lnors_spacearr; BitVector<> done_loops(corner_verts.size(), false); Array loop_normals(corner_verts.size()); - const Array loop_to_poly = mesh_topology::build_loop_to_poly_map(polys); + const Array loop_to_poly = build_loop_to_poly_map(polys); /* In this case we always consider split nors as ON, * and do not want to use angle to define smooth fans! */ const bool use_split_normals = true; diff --git a/source/blender/blenkernel/intern/mesh_remap.cc b/source/blender/blenkernel/intern/mesh_remap.cc index 207ea5bb327..f1134290817 100644 --- a/source/blender/blenkernel/intern/mesh_remap.cc +++ b/source/blender/blenkernel/intern/mesh_remap.cc @@ -693,6 +693,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, Mesh *me_dst, MeshPairRemap *r_map) { + using namespace blender; const float full_weight = 1.0f; const float max_dist_sq = max_dist * max_dist; int i; @@ -719,9 +720,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const blender::Span edges_src = me_src->edges(); const float(*positions_src)[3] = BKE_mesh_vert_positions(me_src); - MeshElemMap *vert_to_edge_src_map; - int *vert_to_edge_src_map_mem; - struct HitData { float hit_dist; int index; @@ -733,11 +731,10 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, v_dst_to_src_map[i].hit_dist = -1.0f; } - BKE_mesh_vert_edge_map_create(&vert_to_edge_src_map, - &vert_to_edge_src_map_mem, - edges_src.data(), - num_verts_src, - int(edges_src.size())); + Array vert_to_edge_src_offsets; + Array vert_to_edge_src_indices; + const GroupedSpan vert_to_edge_src_map = bke::mesh::build_vert_to_edge_map( + edges_src, num_verts_src, vert_to_edge_src_offsets, vert_to_edge_src_indices); BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_VERTS, 2); nearest.index = -1; @@ -778,14 +775,15 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, const int vidx_dst = j ? e_dst[0] : e_dst[1]; const float first_dist = v_dst_to_src_map[vidx_dst].hit_dist; const int vidx_src = v_dst_to_src_map[vidx_dst].index; - int *eidx_src, k; + const int *eidx_src; + int k; if (vidx_src < 0) { continue; } - eidx_src = vert_to_edge_src_map[vidx_src].indices; - k = vert_to_edge_src_map[vidx_src].count; + eidx_src = vert_to_edge_src_map[vidx_src].data(); + k = int(vert_to_edge_src_map[vidx_src].size()); for (; k--; eidx_src++) { const blender::int2 &edge_src = edges_src[*eidx_src]; @@ -838,8 +836,6 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, } MEM_freeN(v_dst_to_src_map); - MEM_freeN(vert_to_edge_src_map); - MEM_freeN(vert_to_edge_src_map_mem); } else if (mode == MREMAP_MODE_EDGE_NEAREST) { BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2); @@ -1036,25 +1032,26 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode, #define POLY_CENTER_INIT 1 #define POLY_COMPLETE 2 -static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, - const int island_index, - BLI_AStarGraph *as_graph, - const blender::Span positions, - const blender::OffsetIndices polys, - const blender::Span corner_verts, - const int edge_idx, - BLI_bitmap *done_edges, - MeshElemMap *edge_to_poly_map, - const bool is_edge_innercut, - const int *poly_island_index_map, - float (*poly_centers)[3], - uchar *poly_status) +static void mesh_island_to_astar_graph_edge_process( + MeshIslandStore *islands, + const int island_index, + BLI_AStarGraph *as_graph, + const blender::Span positions, + const blender::OffsetIndices polys, + const blender::Span corner_verts, + const int edge_idx, + BLI_bitmap *done_edges, + const blender::GroupedSpan edge_to_poly_map, + const bool is_edge_innercut, + const int *poly_island_index_map, + float (*poly_centers)[3], + uchar *poly_status) { - blender::Array poly_island_indices(edge_to_poly_map[edge_idx].count); + blender::Array poly_island_indices(edge_to_poly_map[edge_idx].size()); int i, j; - for (i = 0; i < edge_to_poly_map[edge_idx].count; i++) { - const int pidx = edge_to_poly_map[edge_idx].indices[i]; + for (i = 0; i < edge_to_poly_map[edge_idx].size(); i++) { + const int pidx = edge_to_poly_map[edge_idx][i]; const blender::IndexRange poly = polys[pidx]; const int pidx_isld = islands ? poly_island_index_map[pidx] : pidx; void *custom_data = is_edge_innercut ? POINTER_FROM_INT(edge_idx) : POINTER_FROM_INT(-1); @@ -1098,7 +1095,7 @@ static void mesh_island_to_astar_graph_edge_process(MeshIslandStore *islands, static void mesh_island_to_astar_graph(MeshIslandStore *islands, const int island_index, const blender::Span positions, - MeshElemMap *edge_to_poly_map, + const blender::GroupedSpan edge_to_poly_map, const int numedges, const blender::OffsetIndices polys, const blender::Span corner_verts, @@ -1242,6 +1239,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, const float islands_precision_src, MeshPairRemap *r_map) { + using namespace blender; const float full_weight = 1.0f; const float max_dist_sq = max_dist * max_dist; @@ -1285,12 +1283,18 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, blender::Array poly_cents_src; - MeshElemMap *vert_to_loop_map_src = nullptr; - int *vert_to_loop_map_src_buff = nullptr; - MeshElemMap *vert_to_poly_map_src = nullptr; - int *vert_to_poly_map_src_buff = nullptr; - MeshElemMap *edge_to_poly_map_src = nullptr; - int *edge_to_poly_map_src_buff = nullptr; + Array vert_to_loop_src_offsets; + Array vert_to_loop_src_indices; + GroupedSpan vert_to_loop_map_src; + + Array vert_to_poly_src_offsets; + Array vert_to_poly_src_indices; + GroupedSpan vert_to_poly_map_src; + + Array edge_to_poly_src_offsets; + Array edge_to_poly_src_indices; + GroupedSpan edge_to_poly_map_src; + MeshElemMap *poly_to_looptri_map_src = nullptr; int *poly_to_looptri_map_src_buff = nullptr; @@ -1386,29 +1390,27 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } if (use_from_vert) { - BKE_mesh_vert_loop_map_create(&vert_to_loop_map_src, - &vert_to_loop_map_src_buff, - polys_src, - corner_verts_src.data(), - num_verts_src); + vert_to_loop_map_src = bke::mesh::build_vert_to_loop_map( + corner_verts_src, num_verts_src, vert_to_loop_src_offsets, vert_to_loop_src_indices); + if (mode & MREMAP_USE_POLY) { - BKE_mesh_vert_poly_map_create(&vert_to_poly_map_src, - &vert_to_poly_map_src_buff, - polys_src, - corner_verts_src.data(), - num_verts_src); + vert_to_poly_map_src = bke::mesh::build_vert_to_poly_map(polys_src, + corner_verts_src, + num_verts_src, + vert_to_poly_src_offsets, + vert_to_poly_src_indices); } } /* 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, - int(edges_src.size()), - polys_src, - corner_edges_src.data(), - int(corner_edges_src.size())); + edge_to_poly_map_src = bke::mesh::build_edge_to_poly_map(polys_src, + corner_edges_src, + int(edges_src.size()), + edge_to_poly_src_offsets, + edge_to_poly_src_indices); + if (use_from_vert) { - loop_to_poly_map_src = blender::bke::mesh_topology::build_loop_to_poly_map(polys_src); + loop_to_poly_map_src = blender::bke::mesh::build_loop_to_poly_map(polys_src); poly_cents_src.reinitialize(polys_src.size()); for (const int64_t i : polys_src.index_range()) { poly_cents_src[i] = blender::bke::mesh::poly_center_calc( @@ -1583,7 +1585,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, for (plidx_dst = 0; plidx_dst < poly_dst.size(); plidx_dst++) { const int vert_dst = corner_verts_dst[poly_dst.start() + plidx_dst]; if (use_from_vert) { - MeshElemMap *vert_to_refelem_map_src = nullptr; + blender::Span vert_to_refelem_map_src; copy_v3_v3(tmp_co, vert_positions_dst[vert_dst]); nearest.index = -1; @@ -1608,16 +1610,15 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, } nor_dst = &tmp_no; nors_src = loop_normals_src; - vert_to_refelem_map_src = vert_to_loop_map_src; + vert_to_refelem_map_src = vert_to_loop_map_src[nearest.index]; } else { /* if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { */ nor_dst = &pnor_dst; nors_src = poly_normals_src; - vert_to_refelem_map_src = vert_to_poly_map_src; + vert_to_refelem_map_src = vert_to_poly_map_src[nearest.index]; } - for (int i = vert_to_refelem_map_src[nearest.index].count; i--;) { - const int index_src = vert_to_refelem_map_src[nearest.index].indices[i]; + for (const int index_src : vert_to_refelem_map_src) { BLI_assert(index_src != -1); const float dot = dot_v3v3(nors_src[index_src], *nor_dst); @@ -2084,24 +2085,6 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, BLI_astar_solution_free(&as_solution); } - if (vert_to_loop_map_src) { - MEM_freeN(vert_to_loop_map_src); - } - if (vert_to_loop_map_src_buff) { - MEM_freeN(vert_to_loop_map_src_buff); - } - if (vert_to_poly_map_src) { - MEM_freeN(vert_to_poly_map_src); - } - if (vert_to_poly_map_src_buff) { - MEM_freeN(vert_to_poly_map_src_buff); - } - if (edge_to_poly_map_src) { - MEM_freeN(edge_to_poly_map_src); - } - if (edge_to_poly_map_src_buff) { - MEM_freeN(edge_to_poly_map_src_buff); - } if (poly_to_looptri_map_src) { MEM_freeN(poly_to_looptri_map_src); } diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index b294de04a11..f0ad83e155c 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -365,10 +365,13 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) int i = 0; const CustomDataLayer *layer; - MeshElemMap *source_lmap = nullptr; - int *source_lmap_mem = nullptr; - MeshElemMap *target_lmap = nullptr; - int *target_lmap_mem = nullptr; + Array source_vert_to_loop_offsets; + Array source_vert_to_loop_indices; + blender::GroupedSpan source_lmap; + + Array target_vert_to_loop_offsets; + Array target_vert_to_loop_indices; + blender::GroupedSpan target_lmap; while ((layer = BKE_id_attribute_from_index( const_cast(&source->id), i++, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL))) @@ -412,18 +415,15 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) } else { /* Lazily init vertex -> loop maps. */ - if (!source_lmap) { - BKE_mesh_vert_loop_map_create(&source_lmap, - &source_lmap_mem, - source->polys(), - source->corner_verts().data(), - source->totvert); - - BKE_mesh_vert_loop_map_create(&target_lmap, - &target_lmap_mem, - target->polys(), - target->corner_verts().data(), - target->totvert); + if (source_lmap.is_empty()) { + source_lmap = blender::bke::mesh::build_vert_to_loop_map(source->corner_verts(), + source->totvert, + source_vert_to_loop_offsets, + source_vert_to_loop_indices); + target_lmap = blender::bke::mesh::build_vert_to_loop_map(target->corner_verts(), + target->totvert, + target_vert_to_loop_offsets, + target_vert_to_loop_indices); } blender::threading::parallel_for( @@ -439,10 +439,10 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) continue; } - MeshElemMap *source_loops = source_lmap + nearest.index; - MeshElemMap *target_loops = target_lmap + i; + const Span source_loops = source_lmap[nearest.index]; + const Span target_loops = target_lmap[i]; - if (target_loops->count == 0 || source_loops->count == 0) { + if (target_loops.size() == 0 || source_loops.size() == 0) { continue; } @@ -453,18 +453,17 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) CustomData_interp(source_cdata, target_cdata, - source_loops->indices, + source_loops.data(), nullptr, nullptr, - source_loops->count, - target_loops->indices[0]); + source_loops.size(), + target_loops[0]); - void *elem = POINTER_OFFSET(target_data, - size_t(target_loops->indices[0]) * data_size); + void *elem = POINTER_OFFSET(target_data, size_t(target_loops[0]) * data_size); /* Copy to rest of target loops. */ - for (int j = 1; j < target_loops->count; j++) { - memcpy(POINTER_OFFSET(target_data, size_t(target_loops->indices[j]) * data_size), + for (int j = 1; j < target_loops.size(); j++) { + memcpy(POINTER_OFFSET(target_data, size_t(target_loops[j]) * data_size), elem, data_size); } @@ -483,10 +482,6 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) target->default_color_attribute = BLI_strdup(source->default_color_attribute); } - MEM_SAFE_FREE(source_lmap); - MEM_SAFE_FREE(source_lmap_mem); - MEM_SAFE_FREE(target_lmap); - MEM_SAFE_FREE(target_lmap_mem); free_bvhtree_from_mesh(&bvhtree); } diff --git a/source/blender/blenkernel/intern/multires.cc b/source/blender/blenkernel/intern/multires.cc index 078ad9604ee..07ab12259e4 100644 --- a/source/blender/blenkernel/intern/multires.cc +++ b/source/blender/blenkernel/intern/multires.cc @@ -471,9 +471,9 @@ void multires_force_sculpt_rebuild(Object *object) object->sculpt->pbvh = nullptr; } - MEM_SAFE_FREE(ss->pmap); - - MEM_SAFE_FREE(ss->pmap_mem); + ss->vert_to_poly_indices = {}; + ss->vert_to_poly_offsets = {}; + ss->pmap = {}; } void multires_force_external_reload(Object *object) diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc index 359e271b44b..f3d5bfe82ed 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.cc +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.cc @@ -70,13 +70,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape float(*base_positions)[3] = BKE_mesh_vert_positions_for_write(base_mesh); /* Update the context in case the vertices were duplicated. */ reshape_context->base_positions = base_positions; - MeshElemMap *pmap; - int *pmap_mem; - BKE_mesh_vert_poly_map_create(&pmap, - &pmap_mem, - reshape_context->base_polys, - reshape_context->base_corner_verts.data(), - base_mesh->totvert); + blender::Array vert_to_poly_offsets; + blender::Array vert_to_poly_indices; + const blender::GroupedSpan pmap = blender::bke::mesh::build_vert_to_poly_map( + reshape_context->base_polys, + reshape_context->base_corner_verts, + base_mesh->totvert, + vert_to_poly_offsets, + vert_to_poly_indices); float(*origco)[3] = static_cast( MEM_calloc_arrayN(base_mesh->totvert, sizeof(float[3]), __func__)); @@ -88,14 +89,14 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape float avg_no[3] = {0, 0, 0}, center[3] = {0, 0, 0}, push[3]; /* Don't adjust vertices not used by at least one poly. */ - if (!pmap[i].count) { + if (!pmap[i].size()) { continue; } /* Find center. */ int tot = 0; - for (int j = 0; j < pmap[i].count; j++) { - const blender::IndexRange poly = reshape_context->base_polys[pmap[i].indices[j]]; + for (int j = 0; j < pmap[i].size(); j++) { + const blender::IndexRange poly = reshape_context->base_polys[pmap[i][j]]; /* This double counts, not sure if that's bad or good. */ for (const int corner : poly) { @@ -109,8 +110,8 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape mul_v3_fl(center, 1.0f / tot); /* Find normal. */ - for (int j = 0; j < pmap[i].count; j++) { - const blender::IndexRange poly = reshape_context->base_polys[pmap[i].indices[j]]; + for (int j = 0; j < pmap[i].size(); j++) { + const blender::IndexRange poly = reshape_context->base_polys[pmap[i][j]]; /* Set up poly, loops, and coords in order to call #bke::mesh::poly_normal_calc(). */ blender::Array poly_verts(poly.size()); @@ -142,8 +143,6 @@ void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape } MEM_freeN(origco); - MEM_freeN(pmap); - MEM_freeN(pmap_mem); /* Vertices were moved around, need to update normals after all the vertices are updated * Probably this is possible to do in the loop above, but this is rather tricky because diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.cc b/source/blender/blenkernel/intern/multires_unsubdivide.cc index 6b2cb748ad0..c843313912e 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.cc +++ b/source/blender/blenkernel/intern/multires_unsubdivide.cc @@ -950,7 +950,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract( BM_elem_flag_set(v, BM_ELEM_TAG, true); } - context->loop_to_face_map = blender::bke::mesh_topology::build_loop_to_poly_map(original_polys); + context->loop_to_face_map = blender::bke::mesh::build_loop_to_poly_map(original_polys); } /** diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index ea55efca7aa..02e331e2cf7 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1388,10 +1388,12 @@ void BKE_sculptsession_free_vwpaint_data(SculptSession *ss) else { return; } - MEM_SAFE_FREE(gmap->vert_to_loop); - MEM_SAFE_FREE(gmap->vert_map_mem); - MEM_SAFE_FREE(gmap->vert_to_poly); - MEM_SAFE_FREE(gmap->poly_map_mem); + gmap->vert_to_loop_offsets = {}; + gmap->vert_to_loop_indices = {}; + gmap->vert_to_loop = {}; + gmap->vert_to_poly_offsets = {}; + gmap->vert_to_poly_indices = {}; + gmap->vert_to_poly = {}; } /** @@ -1442,15 +1444,6 @@ static void sculptsession_free_pbvh(Object *object) ss->pbvh = nullptr; } - MEM_SAFE_FREE(ss->pmap); - MEM_SAFE_FREE(ss->pmap_mem); - - MEM_SAFE_FREE(ss->epmap); - MEM_SAFE_FREE(ss->epmap_mem); - - MEM_SAFE_FREE(ss->vemap); - MEM_SAFE_FREE(ss->vemap_mem); - MEM_SAFE_FREE(ss->preview_vert_list); ss->preview_vert_count = 0; @@ -1495,15 +1488,6 @@ void BKE_sculptsession_free(Object *ob) sculptsession_free_pbvh(ob); - MEM_SAFE_FREE(ss->pmap); - MEM_SAFE_FREE(ss->pmap_mem); - - MEM_SAFE_FREE(ss->epmap); - MEM_SAFE_FREE(ss->epmap_mem); - - MEM_SAFE_FREE(ss->vemap); - MEM_SAFE_FREE(ss->vemap_mem); - if (ss->bm_log) { BM_log_free(ss->bm_log); } @@ -1536,7 +1520,7 @@ void BKE_sculptsession_free(Object *ob) MEM_SAFE_FREE(ss->last_paint_canvas_key); - MEM_freeN(ss); + MEM_delete(ss); ob->sculpt = nullptr; } @@ -1766,9 +1750,12 @@ static void sculpt_update_object( sculpt_attribute_update_refs(ob); sculpt_update_persistent_base(ob); - if (ob->type == OB_MESH && !ss->pmap) { - BKE_mesh_vert_poly_map_create( - &ss->pmap, &ss->pmap_mem, me->polys(), me->corner_verts().data(), me->totvert); + if (ob->type == OB_MESH && ss->pmap.is_empty()) { + ss->pmap = blender::bke::mesh::build_vert_to_poly_map(me->polys(), + me->corner_verts(), + me->totvert, + ss->vert_to_poly_offsets, + ss->vert_to_poly_indices); } if (ss->pbvh) { diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index d4ce777027e..e7f8ecd1cf2 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -1396,7 +1396,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span nodes) for (const PBVHNode *node : nodes) { for (const int vert : Span(node->vert_indices, node->uniq_verts)) { if (update_tags[vert]) { - polys_to_update.add_multiple({pbvh->pmap[vert].indices, pbvh->pmap[vert].count}); + polys_to_update.add_multiple(pbvh->pmap[vert]); } } } @@ -1435,7 +1435,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span nodes) threading::parallel_for(verts_to_update.index_range(), 1024, [&](const IndexRange range) { for (const int vert : verts_to_update.as_span().slice(range)) { float3 normal(0.0f); - for (const int poly : Span(pbvh->pmap[vert].indices, pbvh->pmap[vert].count)) { + for (const int poly : pbvh->pmap[vert]) { normal += poly_normals[poly]; } vert_normals[vert] = math::normalize(normal); @@ -3449,7 +3449,7 @@ void BKE_pbvh_update_active_vcol(PBVH *pbvh, const Mesh *mesh) BKE_pbvh_get_color_layer(mesh, &pbvh->color_layer, &pbvh->color_domain); } -void BKE_pbvh_pmap_set(PBVH *pbvh, const MeshElemMap *pmap) +void BKE_pbvh_pmap_set(PBVH *pbvh, const blender::GroupedSpan pmap) { pbvh->pmap = pmap; } diff --git a/source/blender/blenkernel/intern/pbvh_colors.cc b/source/blender/blenkernel/intern/pbvh_colors.cc index 8ac45e9863f..faa1e20283b 100644 --- a/source/blender/blenkernel/intern/pbvh_colors.cc +++ b/source/blender/blenkernel/intern/pbvh_colors.cc @@ -89,11 +89,9 @@ static void pbvh_vertex_color_get(const PBVH &pbvh, PBVHVertRef vertex, float r_ int index = vertex.i; if (pbvh.color_domain == ATTR_DOMAIN_CORNER) { - const MeshElemMap &melem = pbvh.pmap[index]; - int count = 0; zero_v4(r_color); - for (const int i_poly : Span(melem.indices, melem.count)) { + for (const int i_poly : pbvh.pmap[index]) { const IndexRange poly = pbvh.polys[i_poly]; Span colors{static_cast(pbvh.color_layer->data) + poly.start(), poly.size()}; Span poly_verts{pbvh.corner_verts + poly.start(), poly.size()}; @@ -124,9 +122,7 @@ static void pbvh_vertex_color_set(PBVH &pbvh, PBVHVertRef vertex, const float co int index = vertex.i; if (pbvh.color_domain == ATTR_DOMAIN_CORNER) { - const MeshElemMap &melem = pbvh.pmap[index]; - - for (const int i_poly : Span(melem.indices, melem.count)) { + for (const int i_poly : pbvh.pmap[index]) { const IndexRange poly = pbvh.polys[i_poly]; MutableSpan colors{static_cast(pbvh.color_layer->data) + poly.start(), poly.size()}; Span poly_verts{pbvh.corner_verts + poly.start(), poly.size()}; diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index 9fcd02a6c5d..ecc940b54a2 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -12,7 +12,6 @@ struct PBVHGPUFormat; struct MLoopTri; -struct MeshElemMap; /* Axis-aligned bounding box */ struct BB { @@ -206,7 +205,7 @@ struct PBVH { BMLog *bm_log; SubdivCCG *subdiv_ccg; - const MeshElemMap *pmap; + blender::GroupedSpan pmap; CustomDataLayer *color_layer; eAttrDomain color_domain; diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index afe85ff3e19..7738175c62d 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -79,8 +79,9 @@ struct SubdivMeshContext { /* Lazily initialize a map from vertices to connected edges. */ std::mutex vert_to_edge_map_mutex; - int *vert_to_edge_buffer; - MeshElemMap *vert_to_edge_map; + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + blender::GroupedSpan vert_to_edge_map; }; static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx) @@ -132,8 +133,6 @@ static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vert static void subdiv_mesh_context_free(SubdivMeshContext *ctx) { MEM_SAFE_FREE(ctx->accumulated_counters); - MEM_SAFE_FREE(ctx->vert_to_edge_buffer); - MEM_SAFE_FREE(ctx->vert_to_edge_map); } /** \} */ @@ -951,7 +950,7 @@ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context * - neighbors[0] is an edge adjacent to edge->v1. * - neighbors[1] is an edge adjacent to edge->v2. */ static void find_edge_neighbors(const int2 *coarse_edges, - const MeshElemMap *vert_to_edge_map, + const blender::GroupedSpan vert_to_edge_map, const int edge_index, const int2 *neighbors[2]) { @@ -959,7 +958,7 @@ static void find_edge_neighbors(const int2 *coarse_edges, neighbors[0] = nullptr; neighbors[1] = nullptr; int neighbor_counters[2] = {0, 0}; - for (const int i : Span(vert_to_edge_map[edge[0]].indices, vert_to_edge_map[edge[0]].count)) { + for (const int i : vert_to_edge_map[edge[0]]) { if (i == edge_index) { continue; } @@ -968,7 +967,7 @@ static void find_edge_neighbors(const int2 *coarse_edges, ++neighbor_counters[0]; } } - for (const int i : Span(vert_to_edge_map[edge[1]].indices, vert_to_edge_map[edge[1]].count)) { + for (const int i : vert_to_edge_map[edge[1]]) { if (i == edge_index) { continue; } @@ -1026,7 +1025,7 @@ static void points_for_loose_edges_interpolation_get(const float (*coarse_positi void BKE_subdiv_mesh_interpolate_position_on_edge(const float (*coarse_positions)[3], const blender::int2 *coarse_edges, - const MeshElemMap *vert_to_edge_map, + const blender::GroupedSpan vert_to_edge_map, const int coarse_edge_index, const bool is_simple, const float u, @@ -1085,14 +1084,14 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach /* Lazily initialize a vertex to edge map to avoid quadratic runtime when subdividing loose * edges. Do this here to avoid the cost in common cases when there are no loose edges at all. */ - if (ctx->vert_to_edge_map == nullptr) { + if (ctx->vert_to_edge_map.is_empty()) { std::lock_guard lock{ctx->vert_to_edge_map_mutex}; - if (ctx->vert_to_edge_map == nullptr) { - BKE_mesh_vert_edge_map_create(&ctx->vert_to_edge_map, - &ctx->vert_to_edge_buffer, - ctx->coarse_edges.data(), - coarse_mesh->totvert, - ctx->coarse_mesh->totedge); + if (ctx->vert_to_edge_map.is_empty()) { + ctx->vert_to_edge_map = blender::bke::mesh::build_vert_to_edge_map( + ctx->coarse_edges, + coarse_mesh->totvert, + ctx->vert_to_edge_offsets, + ctx->vert_to_edge_indices); } } diff --git a/source/blender/blenlib/BLI_offset_indices.hh b/source/blender/blenlib/BLI_offset_indices.hh index 3fa8ce9dd2a..e867ab9a35e 100644 --- a/source/blender/blenlib/BLI_offset_indices.hh +++ b/source/blender/blenlib/BLI_offset_indices.hh @@ -92,10 +92,50 @@ template class OffsetIndices { } }; +/** + * References many separate spans in a larger contiguous array. This gives a more efficient way to + * store many grouped arrays, without requiring many small allocations, giving the general benefits + * of using contiguous memory. + * + * \note If the offsets are shared between many #GroupedSpan objects, it will still + * be more efficient to retrieve the #IndexRange only once and slice each span. + */ +template struct GroupedSpan { + OffsetIndices offsets; + Span data; + + GroupedSpan() = default; + GroupedSpan(OffsetIndices offsets, Span data) : offsets(offsets), data(data) + { + BLI_assert(this->offsets.total_size() == this->data.size()); + } + + Span operator[](const int64_t index) const + { + return this->data.slice(this->offsets[index]); + } + + int64_t size() const + { + return this->offsets.size(); + } + + IndexRange index_range() const + { + return this->offsets.index_range(); + } + + bool is_empty() const + { + return this->data.size() == 0; + } +}; + /** * Turn an array of sizes into the offset at each index including all previous sizes. */ -void accumulate_counts_to_offsets(MutableSpan counts_to_offsets, int start_offset = 0); +OffsetIndices accumulate_counts_to_offsets(MutableSpan counts_to_offsets, + int start_offset = 0); /** * Create a map from indexed elements to the source indices, in other words from the larger array @@ -103,8 +143,14 @@ void accumulate_counts_to_offsets(MutableSpan counts_to_offsets, int start_ */ void build_reverse_map(OffsetIndices offsets, MutableSpan r_map); +/** + * Build offsets to group the elements of \a indices pointing to the same index. + */ +void build_reverse_offsets(Span indices, MutableSpan r_map); + } // namespace blender::offset_indices namespace blender { +using offset_indices::GroupedSpan; using offset_indices::OffsetIndices; -} +} // namespace blender diff --git a/source/blender/blenlib/intern/offset_indices.cc b/source/blender/blenlib/intern/offset_indices.cc index 8b38d630b05..904e71c0a43 100644 --- a/source/blender/blenlib/intern/offset_indices.cc +++ b/source/blender/blenlib/intern/offset_indices.cc @@ -5,7 +5,7 @@ namespace blender::offset_indices { -void accumulate_counts_to_offsets(MutableSpan counts_to_offsets, const int start_offset) +OffsetIndices accumulate_counts_to_offsets(MutableSpan counts_to_offsets, const int start_offset) { int offset = start_offset; for (const int i : counts_to_offsets.index_range().drop_back(1)) { @@ -15,6 +15,7 @@ void accumulate_counts_to_offsets(MutableSpan counts_to_offsets, const int offset += count; } counts_to_offsets.last() = offset; + return OffsetIndices(counts_to_offsets); } void build_reverse_map(OffsetIndices offsets, MutableSpan r_map) @@ -26,4 +27,13 @@ void build_reverse_map(OffsetIndices offsets, MutableSpan r_map) }); } +void build_reverse_offsets(const Span indices, MutableSpan offsets) +{ + BLI_assert(std::all_of(offsets.begin(), offsets.end(), [](int value) { return value == 0; })); + for (const int i : indices) { + offsets[i]++; + } + offset_indices::accumulate_counts_to_offsets(offsets); +} + } // namespace blender::offset_indices diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index d20058ad317..fe87877b016 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -2230,13 +2230,10 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac const Span coarse_positions = coarse_mesh->vert_positions(); const Span coarse_edges = coarse_mesh->edges(); - int *vert_to_edge_buffer; - MeshElemMap *vert_to_edge_map; - BKE_mesh_vert_edge_map_create(&vert_to_edge_map, - &vert_to_edge_buffer, - coarse_edges.data(), - coarse_mesh->totvert, - coarse_edges.size()); + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + const blender::GroupedSpan vert_to_edge_map = blender::bke::mesh::build_vert_to_edge_map( + coarse_edges, coarse_mesh->totvert, vert_to_edge_offsets, vert_to_edge_indices); for (int i = 0; i < coarse_loose_edge_len; i++) { const int coarse_edge_index = cache->loose_geom.edges[i]; @@ -2279,9 +2276,6 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac } } - MEM_freeN(vert_to_edge_buffer); - MEM_freeN(vert_to_edge_map); - /* Copy the remaining loose_verts. */ for (int i = 0; i < coarse_loose_vert_len; i++) { const int coarse_vertex_index = cache->loose_geom.verts[i]; diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc index 9baf7982026..24c9a21c6f5 100644 --- a/source/blender/editors/mesh/editface.cc +++ b/source/blender/editors/mesh/editface.cc @@ -795,10 +795,12 @@ void paintvert_select_more(Mesh *mesh, const bool face_step) const Span corner_verts = mesh->corner_verts(); const Span edges = mesh->edges(); - Array> edge_to_face_map; + Array edge_to_face_offsets; + Array edge_to_face_indices; + GroupedSpan edge_to_face_map; if (face_step) { - edge_to_face_map = bke::mesh_topology::build_edge_to_poly_map( - polys, corner_edges, mesh->totedge); + edge_to_face_map = bke::mesh::build_edge_to_poly_map( + polys, corner_edges, mesh->totedge, edge_to_face_offsets, edge_to_face_indices); } /* Need a copy of the selected verts that we can read from and is not modified. */ @@ -851,15 +853,12 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) const Span corner_verts = mesh->corner_verts(); const Span edges = mesh->edges(); - MeshElemMap *edge_poly_map; - int *edge_poly_mem = nullptr; + GroupedSpan edge_to_poly_map; + Array edge_to_poly_offsets; + Array edge_to_poly_indices; if (face_step) { - BKE_mesh_edge_poly_map_create(&edge_poly_map, - &edge_poly_mem, - edges.size(), - polys, - corner_edges.data(), - corner_edges.size()); + edge_to_poly_map = bke::mesh::build_edge_to_poly_map( + polys, corner_edges, edges.size(), edge_to_poly_offsets, edge_to_poly_indices); } /* Need a copy of the selected verts that we can read from and is not modified. */ @@ -879,8 +878,7 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) if (!face_step) { continue; } - const Span neighbor_polys(edge_poly_map[i].indices, edge_poly_map[i].count); - for (const int poly_i : neighbor_polys) { + for (const int poly_i : edge_to_poly_map[i]) { if (hide_poly[poly_i]) { continue; } @@ -890,10 +888,6 @@ void paintvert_select_less(Mesh *mesh, const bool face_step) } } } - if (edge_poly_mem) { - MEM_freeN(edge_poly_map); - MEM_freeN(edge_poly_mem); - } select_vert.finish(); } diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index e7032857e28..4bfca674e77 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -2900,12 +2900,12 @@ static void skin_armature_bone_create(Object *skin_ob, const blender::int2 *edges, bArmature *arm, BLI_bitmap *edges_visited, - const MeshElemMap *emap, + const blender::GroupedSpan emap, EditBone *parent_bone, int parent_v) { - for (int i = 0; i < emap[parent_v].count; i++) { - int endx = emap[parent_v].indices[i]; + for (int i = 0; i < emap[parent_v].size(); i++) { + int endx = emap[parent_v][i]; const blender::int2 &edge = edges[endx]; /* ignore edge if already visited */ @@ -2967,9 +2967,11 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, MVertSkin *mvert_skin = static_cast( CustomData_get_layer_for_write(&me->vdata, CD_MVERT_SKIN, me->totvert)); - int *emap_mem; - MeshElemMap *emap; - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me_edges.data(), me->totvert, me->totedge); + + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + const blender::GroupedSpan emap = blender::bke::mesh::build_vert_to_edge_map( + me_edges, me->totvert, vert_to_edge_offsets, vert_to_edge_indices); BLI_bitmap *edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); @@ -2982,7 +2984,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, /* Unless the skin root has just one adjacent edge, create * a fake root bone (have it going off in the Y direction * (arbitrary) */ - if (emap[v].count > 1) { + if (emap[v].size() > 1) { bone = ED_armature_ebone_add(arm, "Bone"); copy_v3_v3(bone->head, me_positions[v]); @@ -2992,7 +2994,7 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, bone->rad_head = bone->rad_tail = 0.25; } - if (emap[v].count >= 1) { + if (emap[v].size() >= 1) { skin_armature_bone_create( skin_ob, positions_eval, me_edges.data(), arm, edges_visited, emap, bone, v); } @@ -3000,8 +3002,6 @@ static Object *modifier_skin_armature_create(Depsgraph *depsgraph, Main *bmain, } MEM_freeN(edges_visited); - MEM_freeN(emap); - MEM_freeN(emap_mem); ED_armature_from_edit(bmain, arm); ED_armature_edit_free(arm); diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index dc6c5ca0886..57f6412112d 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -1569,9 +1569,6 @@ static void vgroup_smooth_subset(Object *ob, BMesh *bm = em ? em->bm : nullptr; Mesh *me = em ? nullptr : static_cast(ob->data); - MeshElemMap *emap; - int *emap_mem; - float *weight_accum_prev; float *weight_accum_curr; @@ -1585,15 +1582,16 @@ static void vgroup_smooth_subset(Object *ob, ED_vgroup_parray_alloc(static_cast(ob->data), &dvert_array, &dvert_tot, false); vgroup_subset_weights.fill(0.0f); + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + blender::GroupedSpan emap; if (bm) { BM_mesh_elem_table_ensure(bm, BM_VERT); BM_mesh_elem_index_ensure(bm, BM_VERT); - - emap = nullptr; - emap_mem = nullptr; } else { - BKE_mesh_vert_edge_map_create(&emap, &emap_mem, me->edges().data(), me->totvert, me->totedge); + emap = blender::bke::mesh::build_vert_to_edge_map( + me->edges(), me->totvert, vert_to_edge_offsets, vert_to_edge_indices); } weight_accum_prev = static_cast( @@ -1639,8 +1637,8 @@ static void vgroup_smooth_subset(Object *ob, const blender::Span edges = me->edges(); for (int i = 0; i < dvert_tot; i++) { if (IS_ME_VERT_WRITE(i)) { - for (int j = 0; j < emap[i].count; j++) { - const int2 &edge = edges[emap[i].indices[j]]; + for (int j = 0; j < emap[i].size(); j++) { + const int2 &edge = edges[emap[i][j]]; const int i_other = (edge[0] == i) ? edge[1] : edge[0]; if (IS_ME_VERT_READ(i_other)) { STACK_PUSH(verts_used, i); @@ -1718,8 +1716,8 @@ static void vgroup_smooth_subset(Object *ob, /* checked already */ BLI_assert(IS_ME_VERT_WRITE(i)); - for (j = 0; j < emap[i].count; j++) { - const int2 &edge = edges[emap[i].indices[j]]; + for (j = 0; j < emap[i].size(); j++) { + const int2 &edge = edges[emap[i][j]]; const int i_other = (edge[0] == i ? edge[1] : edge[0]); if (IS_ME_VERT_READ(i_other)) { WEIGHT_ACCUMULATE; @@ -1754,14 +1752,6 @@ static void vgroup_smooth_subset(Object *ob, MEM_freeN(weight_accum_prev); MEM_freeN(verts_used); - if (bm) { - /* pass */ - } - else { - MEM_freeN(emap); - MEM_freeN(emap_mem); - } - if (dvert_array) { MEM_freeN(dvert_array); } diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index de01debacf9..f811879a762 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -1246,15 +1246,11 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) const blender::OffsetIndices polys = me->polys(); const Span corner_verts = me->corner_verts(); - if (gmap->vert_to_loop == nullptr) { - gmap->vert_map_mem = nullptr; - gmap->vert_to_loop = nullptr; - gmap->poly_map_mem = nullptr; - gmap->vert_to_poly = nullptr; - BKE_mesh_vert_loop_map_create( - &gmap->vert_to_loop, &gmap->vert_map_mem, polys, corner_verts.data(), me->totvert); - BKE_mesh_vert_poly_map_create( - &gmap->vert_to_poly, &gmap->poly_map_mem, polys, corner_verts.data(), me->totvert); + if (gmap->vert_to_loop_indices.is_empty()) { + gmap->vert_to_loop = blender::bke::mesh::build_vert_to_loop_map( + corner_verts, me->totvert, gmap->vert_to_loop_offsets, gmap->vert_to_loop_indices); + gmap->vert_to_poly = blender::bke::mesh::build_vert_to_poly_map( + polys, corner_verts, me->totvert, gmap->vert_to_poly_offsets, gmap->vert_to_poly_indices); } /* Create average brush arrays */ @@ -1975,8 +1971,7 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata, /* Get the average poly weight */ int total_hit_loops = 0; float weight_final = 0.0f; - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; + for (const int p_index : gmap->vert_to_poly[v_index]) { const blender::IndexRange poly = ss->polys[p_index]; total_hit_loops += poly.size(); @@ -2089,8 +2084,7 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata, /* Get the color of the loop in the opposite direction of the brush movement * (this callback is specifically for smear.) */ float weight_final = 0.0; - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; + for (const int p_index : gmap->vert_to_poly[v_index]) { for (const int v_other_index : ss->corner_verts.slice(ss->polys[p_index])) { if (v_other_index != v_index) { const float3 &mv_other = ss->vert_positions[v_other_index]; @@ -3022,8 +3016,7 @@ static void do_vpaint_brush_blur_loops(bContext *C, int total_hit_loops = 0; Blend blend[4] = {0}; - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - int p_index = gmap->vert_to_poly[v_index].indices[j]; + for (const int p_index : gmap->vert_to_poly[v_index]) { if (!use_face_sel || select_poly[p_index]) { const blender::IndexRange poly = ss->polys[p_index]; total_hit_loops += poly.size(); @@ -3054,9 +3047,9 @@ static void do_vpaint_brush_blur_loops(bContext *C, /* For each poly owning this vert, * paint each loop belonging to this vert. */ - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const int l_index = gmap->vert_to_loop[v_index].indices[j]; + for (const int j : gmap->vert_to_poly[v_index].index_range()) { + const int p_index = gmap->vert_to_poly[v_index][j]; + const int l_index = gmap->vert_to_loop[v_index][j]; BLI_assert(ss->corner_verts[l_index] == v_index); if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3166,8 +3159,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, int total_hit_loops = 0; Blend blend[4] = {0}; - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - int p_index = gmap->vert_to_poly[v_index].indices[j]; + for (const int p_index : gmap->vert_to_poly[v_index]) { if (!use_face_sel || select_poly[p_index]) { const blender::IndexRange poly = ss->polys[p_index]; total_hit_loops += poly.size(); @@ -3198,11 +3190,7 @@ static void do_vpaint_brush_blur_verts(bContext *C, /* For each poly owning this vert, * paint each loop belonging to this vert. */ - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; - - BLI_assert(ss->corner_verts[gmap->vert_to_loop[v_index].indices[j]] == v_index); - + for (const int p_index : gmap->vert_to_poly[v_index]) { if (!use_face_sel || select_poly[p_index]) { Color color_orig(0, 0, 0, 0); /* unused when array is nullptr */ @@ -3323,9 +3311,9 @@ static void do_vpaint_brush_smear(bContext *C, * direction of the brush movement */ Color color_final(0, 0, 0, 0); - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const int l_index = gmap->vert_to_loop[v_index].indices[j]; + for (const int j : gmap->vert_to_poly[v_index].index_range()) { + const int p_index = gmap->vert_to_poly[v_index][j]; + const int l_index = gmap->vert_to_loop[v_index][j]; BLI_assert(ss->corner_verts[l_index] == v_index); UNUSED_VARS_NDEBUG(l_index); if (!use_face_sel || select_poly[p_index]) { @@ -3368,15 +3356,15 @@ static void do_vpaint_brush_smear(bContext *C, /* For each poly owning this vert, * paint each loop belonging to this vert. */ - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; + for (const int j : gmap->vert_to_poly[v_index].index_range()) { + const int p_index = gmap->vert_to_poly[v_index][j]; int elem_index; if constexpr (domain == ATTR_DOMAIN_POINT) { elem_index = v_index; } else { - const int l_index = gmap->vert_to_loop[v_index].indices[j]; + const int l_index = gmap->vert_to_loop[v_index][j]; elem_index = l_index; BLI_assert(ss->corner_verts[l_index] == v_index); } @@ -3460,13 +3448,13 @@ static void calculate_average_color(VPaintData *vpd, if (BKE_brush_curve_strength(brush, 0.0, cache->radius) > 0.0) { /* If the vertex is selected for painting. */ if (!use_vert_sel || select_vert[v_index]) { - accum2->len += gmap->vert_to_loop[v_index].count; + accum2->len += gmap->vert_to_poly[v_index].size(); /* if a vertex is within the brush region, then add its color to the blend. */ - for (int j = 0; j < gmap->vert_to_loop[v_index].count; j++) { + for (int j = 0; j < gmap->vert_to_poly[v_index].size(); j++) { int elem_index; if constexpr (domain == ATTR_DOMAIN_CORNER) { - elem_index = gmap->vert_to_loop[v_index].indices[j]; + elem_index = gmap->vert_to_loop[v_index][j]; } else { elem_index = v_index; @@ -3632,9 +3620,9 @@ static void vpaint_do_draw(bContext *C, } else { /* For each poly owning this vert, paint each loop belonging to this vert. */ - for (int j = 0; j < gmap->vert_to_poly[v_index].count; j++) { - const int p_index = gmap->vert_to_poly[v_index].indices[j]; - const int l_index = gmap->vert_to_loop[v_index].indices[j]; + for (const int j : gmap->vert_to_poly[v_index].index_range()) { + const int p_index = gmap->vert_to_poly[v_index][j]; + const int l_index = gmap->vert_to_loop[v_index][j]; BLI_assert(ss->corner_verts[l_index] == v_index); if (!use_face_sel || select_poly[p_index]) { Color color_orig = Color(0, 0, 0, 0); /* unused when array is nullptr */ diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 1583cabd98e..25b8da1a96b 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -483,9 +483,8 @@ bool SCULPT_vertex_any_face_visible_get(SculptSession *ss, PBVHVertRef vertex) if (!ss->hide_poly) { return true; } - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; - for (int j = 0; j < ss->pmap[vertex.i].count; j++) { - if (!ss->hide_poly[vert_map->indices[j]]) { + for (const int poly : ss->pmap[vertex.i]) { + if (!ss->hide_poly[poly]) { return true; } } @@ -506,9 +505,8 @@ bool SCULPT_vertex_all_faces_visible_get(const SculptSession *ss, PBVHVertRef ve if (!ss->hide_poly) { return true; } - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; - for (int j = 0; j < vert_map->count; j++) { - if (ss->hide_poly[vert_map->indices[j]]) { + for (const int poly : ss->pmap[vertex.i]) { + if (ss->hide_poly[poly]) { return false; } } @@ -556,9 +554,7 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_ switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { BLI_assert(ss->face_sets != nullptr); - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; - for (int j = 0; j < vert_map->count; j++) { - const int poly_index = vert_map->indices[j]; + for (const int poly_index : ss->pmap[vertex.i]) { if (ss->hide_poly && ss->hide_poly[poly_index]) { /* Skip hidden faces connected to the vertex. */ continue; @@ -591,11 +587,10 @@ int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex) if (!ss->face_sets) { return SCULPT_FACE_SET_NONE; } - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; int face_set = 0; - for (int i = 0; i < vert_map->count; i++) { - if (ss->face_sets[vert_map->indices[i]] > face_set) { - face_set = abs(ss->face_sets[vert_map->indices[i]]); + for (const int poly_index : ss->pmap[vertex.i]) { + if (ss->face_sets[poly_index] > face_set) { + face_set = abs(ss->face_sets[poly_index]); } } return face_set; @@ -622,9 +617,8 @@ bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_ if (!ss->face_sets) { return face_set == SCULPT_FACE_SET_NONE; } - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; - for (int i = 0; i < vert_map->count; i++) { - if (ss->face_sets[vert_map->indices[i]] == face_set) { + for (const int poly_index : ss->pmap[vertex.i]) { + if (ss->face_sets[poly_index] == face_set) { return true; } } @@ -702,14 +696,13 @@ static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int ind if (!ss->face_sets) { return true; } - const MeshElemMap *vert_map = &ss->pmap[index]; int face_set = -1; - for (int i = 0; i < vert_map->count; i++) { + for (const int poly_index : ss->pmap[index]) { if (face_set == -1) { - face_set = ss->face_sets[vert_map->indices[i]]; + face_set = ss->face_sets[poly_index]; } else { - if (ss->face_sets[vert_map->indices[i]] != face_set) { + if (ss->face_sets[poly_index] != face_set) { return false; } } @@ -723,19 +716,19 @@ static bool sculpt_check_unique_face_set_in_base_mesh(SculptSession *ss, int ind */ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(SculptSession *ss, int v1, int v2) { - const MeshElemMap *vert_map = &ss->pmap[v1]; + const Span vert_map = ss->pmap[v1]; int p1 = -1, p2 = -1; - for (int i = 0; i < vert_map->count; i++) { - const int poly_i = vert_map->indices[i]; + for (int i = 0; i < vert_map.size(); i++) { + const int poly_i = vert_map[i]; for (const int corner : ss->polys[poly_i]) { if (ss->corner_verts[corner] == v2) { if (p1 == -1) { - p1 = vert_map->indices[i]; + p1 = vert_map[i]; break; } if (p2 == -1) { - p2 = vert_map->indices[i]; + p2 = vert_map[i]; break; } } @@ -876,19 +869,18 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, PBVHVertRef vertex, SculptVertexNeighborIter *iter) { - const MeshElemMap *vert_map = &ss->pmap[vertex.i]; iter->size = 0; iter->num_duplicates = 0; iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; iter->neighbor_indices = iter->neighbor_indices_fixed; - for (int i = 0; i < vert_map->count; i++) { - if (ss->hide_poly && ss->hide_poly[vert_map->indices[i]]) { + for (const int poly_i : ss->pmap[vertex.i]) { + if (ss->hide_poly && ss->hide_poly[poly_i]) { /* Skip connectivity from hidden faces. */ continue; } - const blender::IndexRange poly = ss->polys[vert_map->indices[i]]; + const blender::IndexRange poly = ss->polys[poly_i]; const blender::int2 f_adj_v = blender::bke::mesh::poly_find_adjecent_verts( poly, ss->corner_verts, vertex.i); for (int j = 0; j < 2; j++) { diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index 7a6d19cfbcf..722a8318a74 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -639,11 +639,6 @@ static void SCULPT_topology_automasking_init(Sculpt *sd, Object *ob) SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert_unreachable(); - return; - } - const int totvert = SCULPT_vertex_count_get(ss); for (int i : IndexRange(totvert)) { PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i); @@ -678,11 +673,6 @@ static void sculpt_face_sets_automasking_init(Sculpt *sd, Object *ob) return; } - if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && !ss->pmap) { - BLI_assert_msg(0, "Face Sets automasking: pmap missing"); - return; - } - int tot_vert = SCULPT_vertex_count_get(ss); int active_face_set = SCULPT_active_face_set_get(ss); for (int i : IndexRange(tot_vert)) { @@ -702,11 +692,6 @@ static void SCULPT_boundary_automasking_init(Object *ob, { SculptSession *ss = ob->sculpt; - if (!ss->pmap) { - BLI_assert_msg(0, "Boundary Edges masking: pmap missing"); - return; - } - const int totvert = SCULPT_vertex_count_get(ss); int *edge_distance = (int *)MEM_callocN(sizeof(int) * totvert, "automask_factor"); diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc index bc7ce94fd18..bc07ef117d2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.cc @@ -70,10 +70,6 @@ void SCULPT_pbvh_clear(Object *ob) ss->pbvh = nullptr; } - MEM_SAFE_FREE(ss->pmap); - - MEM_SAFE_FREE(ss->pmap_mem); - BKE_object_free_derived_caches(ob); /* Tag to rebuild PBVH in depsgraph. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index c9962bb04e4..003356dcd16 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -727,8 +727,8 @@ static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertR int v_next_i = BKE_pbvh_vertex_to_index(ss->pbvh, v_next); - for (int j = 0; j < ss->pmap[v_next_i].count; j++) { - for (const int vert : ss->corner_verts.slice(ss->polys[ss->pmap[v_next_i].indices[j]])) { + for (const int poly : ss->pmap[v_next_i]) { + for (const int vert : ss->corner_verts.slice(ss->polys[poly])) { const PBVHVertRef neighbor_v = BKE_pbvh_make_vref(vert); if (BLI_BITMAP_TEST(visited_verts, neighbor_v.i)) { continue; @@ -1985,7 +1985,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, const int delete_id) { const int totface = ss->totfaces; - MeshElemMap *pmap = ss->pmap; + const blender::GroupedSpan pmap = ss->pmap; const blender::OffsetIndices polys = mesh->polys(); const blender::Span corner_verts = mesh->corner_verts(); @@ -2023,10 +2023,7 @@ static void sculpt_expand_delete_face_set_id(int *r_face_sets, const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue)); int other_id = delete_id; for (const int vert : corner_verts.slice(polys[f_index])) { - const MeshElemMap *vert_map = &pmap[vert]; - for (int i = 0; i < vert_map->count; i++) { - - const int neighbor_face_index = vert_map->indices[i]; + for (const int neighbor_face_index : pmap[vert]) { if (expand_cache->original_face_sets[neighbor_face_index] <= 0) { /* Skip picking IDs from hidden Face Sets. */ continue; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 566e7e57386..da6e6416d02 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -140,9 +140,8 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, SCULPT_automasking_node_update(ss, &automask_data, &vd); if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { - MeshElemMap *vert_map = &ss->pmap[vd.index]; - for (int j = 0; j < ss->pmap[vd.index].count; j++) { - const blender::IndexRange poly = ss->polys[vert_map->indices[j]]; + for (const int poly_i : ss->pmap[vd.index]) { + const blender::IndexRange poly = ss->polys[poly_i]; const float3 poly_center = bke::mesh::poly_center_calc(positions, ss->corner_verts.slice(poly)); @@ -150,7 +149,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, if (!sculpt_brush_test_sq_fn(&test, poly_center)) { continue; } - const bool face_hidden = ss->hide_poly && ss->hide_poly[vert_map->indices[j]]; + const bool face_hidden = ss->hide_poly && ss->hide_poly[poly_i]; if (face_hidden) { continue; } @@ -166,7 +165,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, &automask_data); if (fade > 0.05f) { - ss->face_sets[vert_map->indices[j]] = ss->cache->paint_face_set; + ss->face_sets[poly_i] = ss->cache->paint_face_set; changed = true; } } @@ -552,9 +551,9 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill const OffsetIndices polys = mesh->polys(); const Span corner_edges = mesh->corner_edges(); - if (!ss->epmap) { - BKE_mesh_edge_poly_map_create( - &ss->epmap, &ss->epmap_mem, edges.size(), polys, corner_edges.data(), corner_edges.size()); + if (ss->epmap.is_empty()) { + ss->epmap = bke::mesh::build_edge_to_poly_map( + polys, corner_edges, edges.size(), ss->edge_to_poly_offsets, ss->edge_to_poly_indices); } int next_face_set = 1; @@ -574,8 +573,7 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, const FaceSetsFloodFill queue.pop(); for (const int edge_i : corner_edges.slice(polys[poly_i])) { - const Span neighbor_polys(ss->epmap[edge_i].indices, ss->epmap[edge_i].count); - for (const int neighbor_i : neighbor_polys) { + for (const int neighbor_i : ss->epmap[edge_i]) { if (neighbor_i == poly_i) { continue; } @@ -1084,9 +1082,7 @@ static void sculpt_face_set_grow(Object *ob, continue; } for (const int vert : corner_verts.slice(polys[p])) { - const MeshElemMap *vert_map = &ss->pmap[vert]; - for (int i = 0; i < vert_map->count; i++) { - const int neighbor_face_index = vert_map->indices[i]; + for (const int neighbor_face_index : ss->pmap[vert]) { if (neighbor_face_index == p) { continue; } @@ -1114,9 +1110,7 @@ static void sculpt_face_set_shrink(Object *ob, } if (abs(prev_face_sets[p]) == active_face_set_id) { for (const int vert_i : corner_verts.slice(polys[p])) { - const MeshElemMap *vert_map = &ss->pmap[vert_i]; - for (int i = 0; i < vert_map->count; i++) { - const int neighbor_face_index = vert_map->indices[i]; + for (const int neighbor_face_index : ss->pmap[vert_i]) { if (neighbor_face_index == p) { continue; } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc index 78428d13239..2bb0a655233 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc @@ -359,7 +359,6 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - const PBVHType pbvh_type_prev = BKE_pbvh_type(ss->pbvh); SCULPT_undo_push_begin(ob, op); BKE_sculpt_color_layer_create_if_needed(ob); @@ -367,9 +366,6 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op) * earlier steps modifying the data. */ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, true); - if (pbvh_type_prev == PBVH_FACES && !ob->sculpt->pmap) { - return OPERATOR_CANCELLED; - } SCULPT_filter_cache_init(C, ob, diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index e1949d8c063..3b61040e913 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -174,10 +174,6 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) SCULPT_vertex_random_access_ensure(ss); - if (!ob->sculpt->pmap) { - return OPERATOR_CANCELLED; - } - int num_verts = SCULPT_vertex_count_get(ss); Vector nodes = blender::bke::pbvh::search_gather(pbvh, nullptr, nullptr); diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc index 7345f9afcfa..7e4d4e23b68 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc @@ -95,13 +95,13 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, float *dists = static_cast(MEM_malloc_arrayN(totvert, sizeof(float), __func__)); 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.size(), polys, corner_edges.data(), corner_edges.size()); + if (ss->epmap.is_empty()) { + ss->epmap = blender::bke::mesh::build_edge_to_poly_map( + polys, corner_edges, edges.size(), ss->edge_to_poly_offsets, ss->edge_to_poly_indices); } - if (!ss->vemap) { - BKE_mesh_vert_edge_map_create( - &ss->vemap, &ss->vemap_mem, edges.data(), mesh->totvert, edges.size()); + if (ss->vemap.is_empty()) { + ss->vemap = blender::bke::mesh::build_vert_to_edge_map( + edges, mesh->totvert, ss->vert_to_edge_offsets, ss->vert_to_edge_indices); } /* Both contain edge indices encoded as *void. */ @@ -171,9 +171,9 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, vert_positions, v2, v1, SCULPT_GEODESIC_VERTEX_NONE, dists, initial_verts); } - if (ss->epmap[e].count != 0) { - for (int poly_map_index = 0; poly_map_index < ss->epmap[e].count; poly_map_index++) { - const int poly = ss->epmap[e].indices[poly_map_index]; + if (ss->epmap[e].size() != 0) { + for (int poly_map_index = 0; poly_map_index < ss->epmap[e].size(); poly_map_index++) { + const int poly = ss->epmap[e][poly_map_index]; if (ss->hide_poly && ss->hide_poly[poly]) { continue; } @@ -183,9 +183,9 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, } if (sculpt_geodesic_mesh_test_dist_add( vert_positions, v_other, v1, v2, dists, initial_verts)) { - for (int edge_map_index = 0; edge_map_index < ss->vemap[v_other].count; + for (int edge_map_index = 0; edge_map_index < ss->vemap[v_other].size(); edge_map_index++) { - const int e_other = ss->vemap[v_other].indices[edge_map_index]; + const int e_other = ss->vemap[v_other][edge_map_index]; int ev_other; if (edges[e_other][0] == v_other) { ev_other = edges[e_other][1]; @@ -195,7 +195,7 @@ static float *SCULPT_geodesic_mesh_create(Object *ob, } if (e_other != e && !BLI_BITMAP_TEST(edge_tag, e_other) && - (ss->epmap[e_other].count == 0 || dists[ev_other] != FLT_MAX)) + (ss->epmap[e_other].size() == 0 || dists[ev_other] != FLT_MAX)) { if (BLI_BITMAP_TEST(affected_vertex, v_other) || BLI_BITMAP_TEST(affected_vertex, ev_other)) { diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index ad88e6a62ad..46a9a43c54f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -577,10 +577,6 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false); - if (!ss->pmap) { - return; - } - float brush_co[3]; copy_v3_v3(brush_co, SCULPT_active_vertex_co_get(ss)); diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index 8a84fda1d27..c4860717525 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -331,7 +331,6 @@ void SCULPT_smooth( const int max_iterations = 4; const float fract = 1.0f / max_iterations; - PBVHType type = BKE_pbvh_type(ss->pbvh); int iteration, count; float last; @@ -340,11 +339,6 @@ void SCULPT_smooth( count = int(bstrength * max_iterations); last = max_iterations * (bstrength - count * fract); - if (type == PBVH_FACES && !ss->pmap) { - BLI_assert_msg(0, "sculpt smooth: pmap missing"); - return; - } - SCULPT_vertex_random_access_ensure(ss); SCULPT_boundary_info_ensure(ob); diff --git a/source/blender/geometry/intern/mesh_split_edges.cc b/source/blender/geometry/intern/mesh_split_edges.cc index 1811191fb20..dfa539e3006 100644 --- a/source/blender/geometry/intern/mesh_split_edges.cc +++ b/source/blender/geometry/intern/mesh_split_edges.cc @@ -372,11 +372,18 @@ void split_edges(Mesh &mesh, } /* Precalculate topology info. */ - Array> vert_to_edge_map = bke::mesh_topology::build_vert_to_edge_map(edges, - mesh.totvert); - Vector> edge_to_loop_map = bke::mesh_topology::build_edge_to_loop_map_resizable( - mesh.corner_edges(), mesh.totedge); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(mesh.polys()); + Array> vert_to_edge_map(mesh.totvert); + for (const int i : edges.index_range()) { + vert_to_edge_map[edges[i][0]].append(i); + vert_to_edge_map[edges[i][1]].append(i); + } + + Array orig_edge_to_loop_offsets; + Array orig_edge_to_loop_indices; + const GroupedSpan orig_edge_to_loop_map = bke::mesh::build_edge_to_loop_map( + mesh.corner_edges(), mesh.totedge, orig_edge_to_loop_offsets, orig_edge_to_loop_indices); + + Array loop_to_poly_map = bke::mesh::build_loop_to_poly_map(mesh.polys()); /* Store offsets, so we can split edges in parallel. */ Array edge_offsets(edges.size()); @@ -385,7 +392,7 @@ void split_edges(Mesh &mesh, for (const int edge : mask) { edge_offsets[edge] = new_edges_size; /* We add duplicates of the edge for each poly (except the first). */ - const int num_connected_loops = edge_to_loop_map[edge].size(); + const int num_connected_loops = orig_edge_to_loop_map[edge].size(); const int num_duplicates = std::max(0, num_connected_loops - 1); new_edges_size += num_duplicates; num_edge_duplicates[edge] = num_duplicates; @@ -398,7 +405,12 @@ void split_edges(Mesh &mesh, Vector new_edges(new_edges_size); new_edges.as_mutable_span().take_front(edges.size()).copy_from(edges); - edge_to_loop_map.resize(new_edges_size); + Vector> edge_to_loop_map(new_edges_size); + threading::parallel_for(edges.index_range(), 512, [&](const IndexRange range) { + for (const int i : range) { + edge_to_loop_map[i].extend(orig_edge_to_loop_map[i]); + } + }); /* Used for transferring attributes. */ Vector new_to_old_edges_map(IndexRange(new_edges.size()).as_span()); diff --git a/source/blender/modifiers/intern/MOD_skin.cc b/source/blender/modifiers/intern/MOD_skin.cc index f02dd705295..ecd74987196 100644 --- a/source/blender/modifiers/intern/MOD_skin.cc +++ b/source/blender/modifiers/intern/MOD_skin.cc @@ -453,7 +453,7 @@ static void merge_frame_corners(Frame **frames, int totframe) static Frame **collect_hull_frames(int v, SkinNode *frames, - const MeshElemMap *emap, + blender::GroupedSpan emap, const blender::Span edges, int *tothullframe) { @@ -461,11 +461,11 @@ static Frame **collect_hull_frames(int v, Frame **hull_frames; int hull_frames_num, i; - (*tothullframe) = emap[v].count; + (*tothullframe) = emap[v].size(); hull_frames = MEM_cnew_array(*tothullframe, __func__); hull_frames_num = 0; - for (i = 0; i < emap[v].count; i++) { - const blender::int2 &edge = edges[emap[v].indices[i]]; + for (i = 0; i < emap[v].size(); i++) { + const blender::int2 &edge = edges[emap[v][i]]; f = &frames[blender::bke::mesh::edge_other_vert(edge, v)]; /* Can't have adjacent branch nodes yet */ if (f->totframe) { @@ -530,13 +530,13 @@ static void end_node_frames(int v, SkinNode *skin_nodes, const float (*vert_positions)[3], const MVertSkin *nodes, - const MeshElemMap *emap, + blender::GroupedSpan emap, EMat *emat) { const float *rad = nodes[v].radius; float mat[3][3]; - if (emap[v].count == 0) { + if (emap[v].size() == 0) { float avg = half_v2(rad); /* For solitary nodes, just build a box (two frames) */ @@ -557,8 +557,8 @@ static void end_node_frames(int v, skin_nodes[v].flag |= CAP_START; /* Use incoming edge for orientation */ - copy_m3_m3(mat, emat[emap[v].indices[0]].mat); - if (emat[emap[v].indices[0]].origin != v) { + copy_m3_m3(mat, emat[emap[v][0]].mat); + if (emat[emap[v][0]].origin != v) { negate_v3(mat[0]); } @@ -578,13 +578,13 @@ static void end_node_frames(int v, } /* Returns 1 for seam, 0 otherwise */ -static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, EMat *emat) +static int connection_node_mat(float mat[3][3], int v, blender::GroupedSpan emap, EMat *emat) { float axis[3], angle, ine[3][3], oute[3][3]; EMat *e1, *e2; - e1 = &emat[emap[v].indices[0]]; - e2 = &emat[emap[v].indices[1]]; + e1 = &emat[emap[v][0]]; + e2 = &emat[emap[v][1]]; if (e1->origin != v && e2->origin == v) { copy_m3_m3(ine, e1->mat); @@ -615,7 +615,7 @@ static void connection_node_frames(int v, SkinNode *skin_nodes, const float (*vert_positions)[3], const MVertSkin *nodes, - const MeshElemMap *emap, + blender::GroupedSpan emap, EMat *emat) { const float *rad = nodes[v].radius; @@ -626,8 +626,8 @@ static void connection_node_frames(int v, float avg = half_v2(rad); /* Get edges */ - e1 = &emat[emap[v].indices[0]]; - e2 = &emat[emap[v].indices[1]]; + e1 = &emat[emap[v][0]]; + e2 = &emat[emap[v][1]]; /* Handle seam separately to avoid twisting */ /* Create two frames, will be hulled to neighbors later */ @@ -639,14 +639,14 @@ static void connection_node_frames(int v, negate_v3(mat[0]); } create_frame(&skin_nodes[v].frames[0], vert_positions[v], rad, mat, avg); - skin_nodes[v].seam_edges[0] = emap[v].indices[0]; + skin_nodes[v].seam_edges[0] = emap[v][0]; copy_m3_m3(mat, e2->mat); if (e2->origin != v) { negate_v3(mat[0]); } create_frame(&skin_nodes[v].frames[1], vert_positions[v], rad, mat, avg); - skin_nodes[v].seam_edges[1] = emap[v].indices[1]; + skin_nodes[v].seam_edges[1] = emap[v][1]; return; } @@ -659,7 +659,7 @@ static void connection_node_frames(int v, static SkinNode *build_frames(const float (*vert_positions)[3], int verts_num, const MVertSkin *nodes, - const MeshElemMap *emap, + blender::GroupedSpan emap, EMat *emat) { int v; @@ -667,10 +667,10 @@ static SkinNode *build_frames(const float (*vert_positions)[3], SkinNode *skin_nodes = MEM_cnew_array(verts_num, __func__); for (v = 0; v < verts_num; v++) { - if (emap[v].count <= 1) { + if (emap[v].size() <= 1) { end_node_frames(v, skin_nodes, vert_positions, nodes, emap, emat); } - else if (emap[v].count == 2) { + else if (emap[v].size() == 2) { connection_node_frames(v, skin_nodes, vert_positions, nodes, emap, emat); } else { @@ -721,7 +721,7 @@ struct EdgeStackElem { static void build_emats_stack(BLI_Stack *stack, BLI_bitmap *visited_e, EMat *emat, - const MeshElemMap *emap, + blender::GroupedSpan emap, const blender::Span edges, const MVertSkin *vs, const float (*vert_positions)[3]) @@ -744,7 +744,7 @@ static void build_emats_stack(BLI_Stack *stack, /* Process edge */ - parent_is_branch = ((emap[parent_v].count > 2) || (vs[parent_v].flag & MVERT_SKIN_ROOT)); + parent_is_branch = ((emap[parent_v].size() > 2) || (vs[parent_v].flag & MVERT_SKIN_ROOT)); v = blender::bke::mesh::edge_other_vert(edges[e], parent_v); emat[e].origin = parent_v; @@ -765,10 +765,10 @@ static void build_emats_stack(BLI_Stack *stack, } /* Add neighbors to stack */ - for (i = 0; i < emap[v].count; i++) { + for (i = 0; i < emap[v].size(); i++) { /* Add neighbors to stack */ copy_m3_m3(stack_elem.mat, emat[e].mat); - stack_elem.e = emap[v].indices[i]; + stack_elem.e = emap[v][i]; stack_elem.parent_v = v; BLI_stack_push(stack, &stack_elem); } @@ -778,7 +778,7 @@ static EMat *build_edge_mats(const MVertSkin *vs, const float (*vert_positions)[3], const int verts_num, const blender::Span edges, - const MeshElemMap *emap, + blender::GroupedSpan emap, bool *has_valid_root) { BLI_Stack *stack; @@ -796,16 +796,16 @@ static EMat *build_edge_mats(const MVertSkin *vs, * children to the stack */ for (v = 0; v < verts_num; v++) { if (vs[v].flag & MVERT_SKIN_ROOT) { - if (emap[v].count >= 1) { - const blender::int2 &edge = edges[emap[v].indices[0]]; + if (emap[v].size() >= 1) { + const blender::int2 &edge = edges[emap[v][0]]; calc_edge_mat(stack_elem.mat, vert_positions[v], vert_positions[blender::bke::mesh::edge_other_vert(edge, v)]); stack_elem.parent_v = v; /* Add adjacent edges to stack */ - for (i = 0; i < emap[v].count; i++) { - stack_elem.e = emap[v].indices[i]; + for (i = 0; i < emap[v].size(); i++) { + stack_elem.e = emap[v][i]; BLI_stack_push(stack, &stack_elem); } @@ -1568,7 +1568,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) static void skin_merge_close_frame_verts(SkinNode *skin_nodes, int verts_num, - const MeshElemMap *emap, + blender::GroupedSpan emap, const blender::Span edges) { Frame **hull_frames; @@ -1790,7 +1790,7 @@ static void skin_smooth_hulls(BMesh *bm, static bool skin_output_branch_hulls(SkinOutput *so, SkinNode *skin_nodes, int verts_num, - const MeshElemMap *emap, + blender::GroupedSpan emap, const blender::Span edges) { bool result = true; @@ -1824,7 +1824,7 @@ ENUM_OPERATORS(eSkinErrorFlag, SKIN_ERROR_HULL); static BMesh *build_skin(SkinNode *skin_nodes, int verts_num, - const MeshElemMap *emap, + blender::GroupedSpan emap, const blender::Span edges, const MDeformVert *input_dvert, SkinModifierData *smd, @@ -1913,8 +1913,6 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ BMesh *bm; EMat *emat; SkinNode *skin_nodes; - MeshElemMap *emap; - int *emapmem; const MDeformVert *dvert; bool has_valid_root = false; @@ -1926,18 +1924,19 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd, eSkinErrorFlag *r_ dvert = BKE_mesh_deform_verts(origmesh); const int verts_num = origmesh->totvert; - BKE_mesh_vert_edge_map_create(&emap, &emapmem, edges.data(), verts_num, edges.size()); + blender::Array vert_to_edge_offsets; + blender::Array vert_to_edge_indices; + const blender::GroupedSpan vert_to_edge = blender::bke::mesh::build_vert_to_edge_map( + edges, verts_num, vert_to_edge_offsets, vert_to_edge_indices); - emat = build_edge_mats(nodes, vert_positions, verts_num, edges, emap, &has_valid_root); - skin_nodes = build_frames(vert_positions, verts_num, nodes, emap, emat); + emat = build_edge_mats(nodes, vert_positions, verts_num, edges, vert_to_edge, &has_valid_root); + skin_nodes = build_frames(vert_positions, verts_num, nodes, vert_to_edge, emat); MEM_freeN(emat); emat = nullptr; - bm = build_skin(skin_nodes, verts_num, emap, edges, dvert, smd, r_error); + bm = build_skin(skin_nodes, verts_num, vert_to_edge, edges, dvert, smd, r_error); MEM_freeN(skin_nodes); - MEM_freeN(emap); - MEM_freeN(emapmem); if (!has_valid_root) { *r_error |= SKIN_ERROR_NO_VALID_ROOT; diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc index d20ecbaf473..447d6d5d102 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.cc +++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc @@ -538,7 +538,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * int defgrp_index; MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index); - const Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(result->polys()); + const Array loop_to_poly_map = bke::mesh::build_loop_to_poly_map(result->polys()); bke::MutableAttributeAccessor attributes = result->attributes_for_write(); bke::SpanAttributeWriter sharp_edges = attributes.lookup_or_add_for_write_span( diff --git a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc index 0c64781d539..cda23543272 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_blur_attribute.cc @@ -131,119 +131,128 @@ static void node_update(bNodeTree *ntree, bNode *node) bke::nodeSetSocketAvailability(ntree, out_socket_value_color4f, data_type == CD_PROP_COLOR); } -static Array> build_vert_to_vert_by_edge_map(const Span edges, - const int verts_num) +static void build_vert_to_vert_by_edge_map(const Span edges, + const int verts_num, + Array &r_offsets, + Array &r_indices) { - Array> map(verts_num); - for (const int2 &edge : edges) { - map[edge[0]].append(edge[1]); - map[edge[1]].append(edge[0]); - } - return map; -} - -static Array> build_edge_to_edge_by_vert_map(const Span edges, - const int verts_num, - const IndexMask edge_mask) -{ - Array> map(edges.size()); - Array> vert_to_edge_map = bke::mesh_topology::build_vert_to_edge_map(edges, - verts_num); - - threading::parallel_for(edge_mask.index_range(), 1024, [&](IndexRange range) { - for (const int edge_i : edge_mask.slice(range)) { - - Vector &self_edges = map[edge_i]; - const Span vert_1_edges = vert_to_edge_map[edges[edge_i][0]]; - const Span vert_2_edges = vert_to_edge_map[edges[edge_i][1]]; - - self_edges.reserve(vert_1_edges.size() - 1 + vert_2_edges.size() - 1); - - for (const int i : vert_1_edges) { - if (i != edge_i) { - self_edges.append(i); - } - } - for (const int i : vert_2_edges) { - if (i != edge_i) { - self_edges.append(i); - } + bke::mesh::build_vert_to_edge_map(edges, verts_num, r_offsets, r_indices); + const OffsetIndices offsets(r_offsets); + threading::parallel_for(IndexRange(verts_num), 2048, [&](const IndexRange range) { + for (const int vert : range) { + MutableSpan neighbors = r_indices.as_mutable_span().slice(offsets[vert]); + for (const int i : neighbors.index_range()) { + neighbors[i] = bke::mesh::edge_other_vert(edges[neighbors[i]], vert); } } }); - return map; } -static Array> build_face_to_edge_by_loop_map(const OffsetIndices polys, - const Span corner_edges, - const int edges_num) +static void build_edge_to_edge_by_vert_map(const Span edges, + const int verts_num, + Array &r_offsets, + Array &r_indices) { - Array> map(edges_num); - for (const int i : polys.index_range()) { - for (const int edge : corner_edges.slice(polys[i])) { - map[edge].append(i); + Array vert_to_edge_offset_data; + Array vert_to_edge_indices; + const GroupedSpan vert_to_edge = bke::mesh::build_vert_to_edge_map( + edges, verts_num, vert_to_edge_offset_data, vert_to_edge_indices); + const OffsetIndices vert_to_edge_offsets(vert_to_edge_offset_data); + + r_offsets = Array(edges.size() + 1, 0); + threading::parallel_for(edges.index_range(), 1024, [&](const IndexRange range) { + for (const int edge_i : range) { + const int2 edge = edges[edge_i]; + r_offsets[edge_i] = vert_to_edge_offsets[edge[0]].size() - 1 + + vert_to_edge_offsets[edge[1]].size() - 1; } - } - return map; -} + }); + const OffsetIndices offsets = offset_indices::accumulate_counts_to_offsets(r_offsets); + r_indices.reinitialize(offsets.total_size()); -static Array> build_face_to_face_by_edge_map(const OffsetIndices polys, - const Span corner_edges, - const int edges_num, - const IndexMask poly_mask) -{ - Array> map(polys.size()); - Array> faces_by_edge = build_face_to_edge_by_loop_map( - polys, corner_edges, edges_num); - - threading::parallel_for(poly_mask.index_range(), 1024, [&](IndexRange range) { - for (const int poly_i : poly_mask.slice(range)) { - for (const int edge : corner_edges.slice(polys[poly_i])) { - if (faces_by_edge[edge].size() > 1) { - for (const int neighbor : faces_by_edge[edge]) { - if (neighbor != poly_i) { - map[poly_i].append(neighbor); - } + threading::parallel_for(edges.index_range(), 1024, [&](const IndexRange range) { + for (const int edge_i : range) { + const int2 edge = edges[edge_i]; + MutableSpan neighbors = r_indices.as_mutable_span().slice(offsets[edge_i]); + int count = 0; + for (const Span neighbor_edges : {vert_to_edge[edge[0]], vert_to_edge[edge[1]]}) { + for (const int neighbor_edge : neighbor_edges) { + if (neighbor_edge != edge_i) { + neighbors[count] = neighbor_edge; + count++; } } } } }); - return map; } -static Array> create_mesh_map(const Mesh &mesh, - const eAttrDomain domain, - const IndexMask mask) +static void build_face_to_face_by_edge_map(const OffsetIndices polys, + const Span corner_edges, + const int edges_num, + Array &r_offsets, + Array &r_indices) +{ + Array edge_to_poly_offsets; + Array edge_to_poly_indices; + const GroupedSpan edge_to_poly_map = bke::mesh::build_edge_to_poly_map( + polys, corner_edges, edges_num, edge_to_poly_offsets, edge_to_poly_indices); + + r_offsets = Array(polys.size() + 1, 0); + for (const int poly_i : polys.index_range()) { + for (const int edge : corner_edges.slice(polys[poly_i])) { + for (const int neighbor : edge_to_poly_map[edge]) { + if (neighbor != poly_i) { + r_offsets[poly_i]++; + } + } + } + } + const OffsetIndices offsets = offset_indices::accumulate_counts_to_offsets(r_offsets); + r_indices.reinitialize(offsets.total_size()); + + threading::parallel_for(polys.index_range(), 1024, [&](IndexRange range) { + for (const int poly_i : range) { + MutableSpan neighbors = r_indices.as_mutable_span().slice(offsets[poly_i]); + int count = 0; + for (const int edge : corner_edges.slice(polys[poly_i])) { + for (const int neighbor : edge_to_poly_map[edge]) { + if (neighbor != poly_i) { + neighbors[count] = neighbor; + count++; + } + } + } + } + }); +} + +static GroupedSpan create_mesh_map(const Mesh &mesh, + const eAttrDomain domain, + Array &r_offsets, + Array &r_indices) { switch (domain) { - case ATTR_DOMAIN_POINT: { - const Span edges = mesh.edges(); - const int verts_num = mesh.totvert; - return build_vert_to_vert_by_edge_map(edges, verts_num); - } - case ATTR_DOMAIN_EDGE: { - const Span edges = mesh.edges(); - const int verts_num = mesh.totvert; - return build_edge_to_edge_by_vert_map(edges, verts_num, mask); - } - case ATTR_DOMAIN_FACE: { - const OffsetIndices polys = mesh.polys(); - const int edges_num = mesh.totedge; - return build_face_to_face_by_edge_map(polys, mesh.corner_edges(), edges_num, mask); - } - case ATTR_DOMAIN_CORNER: { - return {}; - } + case ATTR_DOMAIN_POINT: + build_vert_to_vert_by_edge_map(mesh.edges(), mesh.totvert, r_offsets, r_indices); + break; + case ATTR_DOMAIN_EDGE: + build_edge_to_edge_by_vert_map(mesh.edges(), mesh.totvert, r_offsets, r_indices); + break; + case ATTR_DOMAIN_FACE: + build_face_to_face_by_edge_map( + mesh.polys(), mesh.corner_edges(), mesh.totedge, r_offsets, r_indices); + break; default: BLI_assert_unreachable(); - return {}; + break; } + return {OffsetIndices(r_offsets), r_indices}; } template static Span blur_on_mesh_exec(const Span neighbor_weights, - const Span> neighbors_map, + const GroupedSpan neighbors_map, const int iterations, const MutableSpan buffer_a, const MutableSpan buffer_b) @@ -279,10 +288,11 @@ static GSpan blur_on_mesh(const Mesh &mesh, const GMutableSpan buffer_a, const GMutableSpan buffer_b) { - Array> neighbors_map = create_mesh_map(mesh, domain, neighbor_weights.index_range()); - if (neighbors_map.is_empty()) { - return buffer_a; - } + Array neighbor_offsets; + Array neighbor_indices; + const GroupedSpan neighbors_map = create_mesh_map( + mesh, domain, neighbor_offsets, neighbor_indices); + GSpan result_buffer; bke::attribute_math::convert_to_static_type(buffer_a.type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc index ccf7521badb..d439d72f33c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc @@ -534,7 +534,7 @@ static bool vertex_needs_dissolving(const int vertex, const int first_poly_index, const int second_poly_index, const Span vertex_types, - const Span> vert_to_poly_map) + const GroupedSpan vert_to_poly_map) { /* Order is guaranteed to be the same because 2poly verts that are not on the boundary are * ignored in `sort_vertex_polys`. */ @@ -553,7 +553,7 @@ static bool vertex_needs_dissolving(const int vertex, static void dissolve_redundant_verts(const Span edges, const OffsetIndices polys, const Span corner_edges, - const Span> vert_to_poly_map, + const GroupedSpan vert_to_poly_map, MutableSpan vertex_types, MutableSpan old_to_new_edges_map, Vector &new_edges, @@ -628,11 +628,19 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, /* Stores the indices of the polygons connected to the vertex. Because the polygons are looped * over in order of their indices, the polygon's indices will be sorted in ascending order. * (This can change once they are sorted using `sort_vertex_polys`). */ - Array> vert_to_poly_map = bke::mesh_topology::build_vert_to_poly_map( - src_polys, src_corner_verts, src_positions.size()); + Array vert_to_poly_offset_data; + Array vert_to_poly_indices; + const GroupedSpan vert_to_poly_map = bke::mesh::build_vert_to_poly_map( + src_polys, + src_corner_verts, + src_positions.size(), + vert_to_poly_offset_data, + vert_to_poly_indices); + const OffsetIndices vert_to_poly_offsets(vert_to_poly_offset_data); + Array> vertex_shared_edges(src_mesh.totvert); Array> vertex_corners(src_mesh.totvert); - threading::parallel_for(vert_to_poly_map.index_range(), 512, [&](IndexRange range) { + threading::parallel_for(src_positions.index_range(), 512, [&](IndexRange range) { for (const int i : range) { if (vertex_types[i] == VertexType::Loose || vertex_types[i] >= VertexType::NonManifold || (!keep_boundaries && vertex_types[i] == VertexType::Boundary)) @@ -640,7 +648,8 @@ static Mesh *calc_dual_mesh(const Mesh &src_mesh, /* Bad vertex that we can't work with. */ continue; } - MutableSpan loop_indices = vert_to_poly_map[i]; + MutableSpan loop_indices = vert_to_poly_indices.as_mutable_span().slice( + vert_to_poly_offsets[i]); Array sorted_corners(loop_indices.size()); bool vertex_ok = true; if (vertex_types[i] == VertexType::Normal) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc index 0399d8620c9..cd17886ccf7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_edges_to_face_groups.cc @@ -54,8 +54,10 @@ class FaceSetFromBoundariesInput final : public bke::MeshFieldInput { const OffsetIndices polys = mesh.polys(); - const Array> edge_to_face_map = bke::mesh_topology::build_edge_to_poly_map( - polys, mesh.corner_edges(), mesh.totedge); + Array edge_to_face_offsets; + Array edge_to_face_indices; + const GroupedSpan edge_to_face_map = bke::mesh::build_edge_to_poly_map( + polys, mesh.corner_edges(), mesh.totedge, edge_to_face_offsets, edge_to_face_indices); AtomicDisjointSet islands(polys.size()); for (const int edge : non_boundary_edges) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 13e64e7f857..802bfb901d2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -441,8 +441,10 @@ static void extrude_mesh_edges(Mesh &mesh, return; } - const Array> edge_to_poly_map = bke::mesh_topology::build_edge_to_poly_map( - orig_polys, mesh.corner_edges(), mesh.totedge); + Array edge_to_poly_offsets; + Array edge_to_poly_indices; + const GroupedSpan edge_to_poly_map = bke::mesh::build_edge_to_poly_map( + orig_polys, mesh.corner_edges(), mesh.totedge, edge_to_poly_offsets, edge_to_poly_indices); /* Find the offsets on the vertex domain for translation. This must be done before the mesh's * custom data layers are reallocated, in case the virtual array references one of them. */ @@ -579,7 +581,7 @@ static void extrude_mesh_edges(Mesh &mesh, * original edge. */ copy_with_mixing( attribute.span, - [&](const int i) { return edge_to_poly_map[edge_selection[i]].as_span(); }, + [&](const int i) { return edge_to_poly_map[edge_selection[i]]; }, attribute.span.slice(new_poly_range)); break; } @@ -749,8 +751,10 @@ static void extrude_mesh_face_regions(Mesh &mesh, } /* All of the faces (selected and deselected) connected to each edge. */ - const Array> edge_to_poly_map = bke::mesh_topology::build_edge_to_poly_map( - orig_polys, mesh.corner_edges(), orig_edges.size()); + Array edge_to_poly_offsets; + Array edge_to_poly_indices; + const GroupedSpan edge_to_poly_map = bke::mesh::build_edge_to_poly_map( + orig_polys, mesh.corner_edges(), mesh.totedge, edge_to_poly_offsets, edge_to_poly_indices); /* All vertices that are connected to the selected polygons. * Start the size at one vert per poly to reduce unnecessary reallocation. */ diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc index b5ff2f3a7dc..f99efcbd5b2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_corners_of_vertex.cc @@ -54,9 +54,10 @@ class CornersOfVertInput final : public bke::MeshFieldInput { const IndexMask mask) const final { const IndexRange vert_range(mesh.totvert); - const Span corner_verts = mesh.corner_verts(); - Array> vert_to_loop_map = bke::mesh_topology::build_vert_to_loop_map(corner_verts, - mesh.totvert); + Array map_offsets; + Array map_indices; + const GroupedSpan vert_to_loop_map = bke::mesh::build_vert_to_loop_map( + mesh.corner_verts(), mesh.totvert, map_offsets, map_indices); const bke::MeshFieldContext context{mesh, domain}; fn::FieldEvaluator evaluator{context, &mask}; @@ -67,7 +68,7 @@ class CornersOfVertInput final : public bke::MeshFieldInput { const VArray indices_in_sort = evaluator.get_evaluated(1); const bke::MeshFieldContext corner_context{mesh, ATTR_DOMAIN_CORNER}; - fn::FieldEvaluator corner_evaluator{corner_context, corner_verts.size()}; + fn::FieldEvaluator corner_evaluator{corner_context, mesh.totloop}; corner_evaluator.add(sort_weight_); corner_evaluator.evaluate(); const VArray all_sort_weights = corner_evaluator.get_evaluated(0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc index 2bd74c25838..f601464dde7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_corner.cc @@ -76,7 +76,7 @@ class CornerPreviousEdgeFieldInput final : public bke::MeshFieldInput { } const OffsetIndices polys = mesh.polys(); const Span corner_edges = mesh.corner_edges(); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); + Array loop_to_poly_map = bke::mesh::build_loop_to_poly_map(polys); return VArray::ForFunc( mesh.totloop, [polys, corner_edges, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc index c44771657e0..c1fad4ea87d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_edges_of_vertex.cc @@ -55,8 +55,10 @@ class EdgesOfVertInput final : public bke::MeshFieldInput { { const IndexRange vert_range(mesh.totvert); const Span edges = mesh.edges(); - const Array> vert_to_edge_map = bke::mesh_topology::build_vert_to_edge_map( - edges, mesh.totvert); + Array map_offsets; + Array map_indices; + const GroupedSpan vert_to_edge_map = bke::mesh::build_vert_to_edge_map( + edges, mesh.totvert, map_offsets, map_indices); const bke::MeshFieldContext context{mesh, domain}; fn::FieldEvaluator evaluator{context, &mask}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc index efe7d3835ac..c9eefa8cef2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_face_of_corner.cc @@ -34,7 +34,7 @@ class CornerFaceIndexInput final : public bke::MeshFieldInput { if (domain != ATTR_DOMAIN_CORNER) { return {}; } - return VArray::ForContainer(bke::mesh_topology::build_loop_to_poly_map(mesh.polys())); + return VArray::ForContainer(bke::mesh::build_loop_to_poly_map(mesh.polys())); } uint64_t hash() const final @@ -63,7 +63,7 @@ class CornerIndexInFaceInput final : public bke::MeshFieldInput { return {}; } const OffsetIndices polys = mesh.polys(); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); + Array loop_to_poly_map = bke::mesh::build_loop_to_poly_map(polys); return VArray::ForFunc( mesh.totloop, [polys, loop_to_poly_map = std::move(loop_to_poly_map)](const int corner_i) { const int poly_i = loop_to_poly_map[corner_i]; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc index 8b22769e59a..162faefa2f9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_topology_offset_corner_in_face.cc @@ -50,7 +50,7 @@ class OffsetCornerInFaceFieldInput final : public bke::MeshFieldInput { const VArray corner_indices = evaluator.get_evaluated(0); const VArray offsets = evaluator.get_evaluated(1); - Array loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(polys); + Array loop_to_poly_map = bke::mesh::build_loop_to_poly_map(polys); Array offset_corners(mask.min_array_size()); threading::parallel_for(mask.index_range(), 2048, [&](const IndexRange range) { diff --git a/source/blender/render/intern/texture_margin.cc b/source/blender/render/intern/texture_margin.cc index da8e9ef1cce..c151b749cd7 100644 --- a/source/blender/render/intern/texture_margin.cc +++ b/source/blender/render/intern/texture_margin.cc @@ -282,7 +282,7 @@ class TextureMarginMap { void build_tables() { - loop_to_poly_map_ = blender::bke::mesh_topology::build_loop_to_poly_map(polys_); + loop_to_poly_map_ = blender::bke::mesh::build_loop_to_poly_map(polys_); loop_adjacency_map_.resize(corner_edges_.size(), -1);