diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 5c33d20863e..902bbffcdd2 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -1003,25 +1003,25 @@ void SCULPT_tag_update_overlays(bContext *C) namespace blender::ed::sculpt_paint::flood_fill { -void init_fill(SculptSession *ss, SculptFloodFill *flood) +void init_fill(SculptSession *ss, FillData *flood) { SCULPT_vertex_random_access_ensure(ss); flood->visited_verts.resize(SCULPT_vertex_count_get(ss)); } -void add_initial(SculptFloodFill *flood, PBVHVertRef vertex) +void add_initial(FillData *flood, PBVHVertRef vertex) { flood->queue.push(vertex); } -void add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex) +void add_and_skip_initial(FillData *flood, PBVHVertRef vertex) { flood->queue.push(vertex); flood->visited_verts[vertex.i].set(vertex.i); } void add_initial_with_symmetry( - Object *ob, SculptSession *ss, SculptFloodFill *flood, PBVHVertRef vertex, float radius) + Object *ob, SculptSession *ss, FillData *flood, PBVHVertRef vertex, float radius) { /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); @@ -1047,7 +1047,7 @@ void add_initial_with_symmetry( } } -void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius) +void add_active(Object *ob, SculptSession *ss, FillData *flood, float radius) { /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); @@ -1073,14 +1073,11 @@ void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float rad } } -void execute(SculptSession *ss, - SculptFloodFill *flood, - bool (*func)(SculptSession *ss, - PBVHVertRef from_v, - PBVHVertRef to_v, - bool is_duplicate, - void *userdata), - void *userdata) +void execute( + SculptSession *ss, + FillData *flood, + FunctionRef + func) { while (!flood->queue.empty()) { PBVHVertRef from_v = flood->queue.front(); @@ -1101,7 +1098,7 @@ void execute(SculptSession *ss, flood->visited_verts[BKE_pbvh_vertex_to_index(ss->pbvh, to_v)].set(); - if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { + if (func(ss, from_v, to_v, ni.is_duplicate)) { flood->queue.push(to_v); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index 78b2598c8cc..4d074f1b5ba 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -600,11 +600,11 @@ struct AutomaskFloodFillData { char symm; }; -static bool floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/, void *userdata) +static bool floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + AutomaskFloodFillData *data) { - AutomaskFloodFillData *data = (AutomaskFloodFillData *)userdata; - *(float *)SCULPT_vertex_attr_get(to_v, ss->attrs.automasking_factor) = 1.0f; *(float *)SCULPT_vertex_attr_get(from_v, ss->attrs.automasking_factor) = 1.0f; return (!data->use_radius || @@ -626,7 +626,7 @@ static void topology_automasking_init(const Sculpt *sd, Object *ob) /* Flood fill automask to connected vertices. Limited to vertices inside * the brush radius if the tool requires it. */ - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); const float radius = ss->cache ? ss->cache->radius : FLT_MAX; flood_fill::add_active(ob, ss, &flood, radius); @@ -638,7 +638,12 @@ static void topology_automasking_init(const Sculpt *sd, Object *ob) fdata.symm = SCULPT_mesh_symmetry_xyz_get(ob); copy_v3_v3(fdata.location, SCULPT_active_vertex_co_get(ss)); - flood_fill::execute(ss, &flood, floodfill_cb, &fdata); + flood_fill::execute( + ss, + &flood, + [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/) { + return floodfill_cb(ss, from_v, to_v, &fdata); + }); } static void init_face_sets_masking(const Sculpt *sd, Object *ob) diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.cc b/source/blender/editors/sculpt_paint/sculpt_boundary.cc index 25fce361da1..786cbccd730 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.cc +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.cc @@ -43,12 +43,12 @@ struct BoundaryInitialVertexFloodFillData { float radius_sq; }; -static bool boundary_initial_vertex_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + BoundaryInitialVertexFloodFillData *data) { - BoundaryInitialVertexFloodFillData *data = static_cast( - userdata); - int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); @@ -87,7 +87,7 @@ static PBVHVertRef sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss return initial_vertex; } - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial(&flood, initial_vertex); @@ -99,7 +99,10 @@ static PBVHVertRef sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss fdata.floodfill_steps = MEM_cnew_array(SCULPT_vertex_count_get(ss), __func__); - flood_fill::execute(ss, &flood, boundary_initial_vertex_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return boundary_initial_vertex_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); MEM_freeN(fdata.floodfill_steps); return fdata.boundary_initial_vertex; @@ -201,13 +204,15 @@ struct BoundaryFloodFillData { PBVHVertRef last_visited_vertex; }; -static bool boundary_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool boundary_floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + BoundaryFloodFillData *data) { int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - BoundaryFloodFillData *data = static_cast(userdata); SculptBoundary *boundary = data->boundary; if (!SCULPT_vertex_is_boundary(ss, to_v)) { return false; @@ -242,7 +247,7 @@ static void sculpt_boundary_indices_init(SculptSession *ss, MEM_malloc_arrayN(BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), __func__)); GSet *included_verts = BLI_gset_int_new_ex("included verts", BOUNDARY_INDICES_BLOCK_SIZE); - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); int initial_boundary_index = BKE_pbvh_vertex_to_index(ss->pbvh, initial_boundary_vertex); @@ -261,7 +266,10 @@ static void sculpt_boundary_indices_init(SculptSession *ss, fdata.included_verts = included_verts; fdata.last_visited_vertex = {BOUNDARY_VERTEX_NONE}; - flood_fill::execute(ss, &flood, boundary_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return boundary_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); /* Check if the boundary loops into itself and add the extra preview edge to close the loop. */ if (fdata.last_visited_vertex.i != BOUNDARY_VERTEX_NONE && diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index d86bd417ff7..45d703602ea 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -452,7 +452,7 @@ static PBVHVertRef sculpt_expand_get_vertex_index_for_symmetry_pass( * Geodesic: Initializes the falloff with geodesic distances from the given active vertex, taking * symmetry into account. */ -static float *sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRef v) +static Array sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRef v) { return geodesic::distances_create_from_vert_and_symm(ob, v, FLT_MAX); } @@ -464,41 +464,43 @@ static float *sculpt_expand_geodesic_falloff_create(Object *ob, const PBVHVertRe struct ExpandFloodFillData { float original_normal[3]; float edge_sensitivity; - float *dists; - float *edge_factor; + MutableSpan dists; + MutableSpan edge_factor; }; -static bool expand_topology_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool expand_topology_floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + MutableSpan dists) { int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - ExpandFloodFillData *data = static_cast(userdata); if (!is_duplicate) { - const float to_it = data->dists[from_v_i] + 1.0f; - data->dists[to_v_i] = to_it; + const float to_it = dists[from_v_i] + 1.0f; + dists[to_v_i] = to_it; } else { - data->dists[to_v_i] = data->dists[from_v_i]; + dists[to_v_i] = dists[from_v_i]; } return true; } -static float *sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRef v) +static Array sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRef v) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_calloc_arrayN(totvert, sizeof(float), __func__)); + Array dists(totvert, 0.0f); - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial_with_symmetry(ob, ss, &flood, v, FLT_MAX); - ExpandFloodFillData fdata; - fdata.dists = dists; - - flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return expand_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, dists); + }); return dists; } @@ -508,13 +510,15 @@ static float *sculpt_expand_topology_falloff_create(Object *ob, const PBVHVertRe * each vertex and the previous one. * This creates falloff patterns that follow and snap to the hard edges of the object. */ -static bool mask_expand_normal_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool mask_expand_normal_floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + ExpandFloodFillData *data) { int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - ExpandFloodFillData *data = static_cast(userdata); if (!is_duplicate) { float current_normal[3], prev_normal[3]; SCULPT_vertex_normal_get(ss, to_v, current_normal); @@ -534,20 +538,17 @@ static bool mask_expand_normal_floodfill_cb( return true; } -static float *sculpt_expand_normal_falloff_create(Object *ob, - const PBVHVertRef v, - const float edge_sensitivity, - const int blur_steps) +static Array sculpt_expand_normal_falloff_create(Object *ob, + const PBVHVertRef v, + const float edge_sensitivity, + const int blur_steps) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_calloc_arrayN(totvert, sizeof(float), __func__)); - float *edge_factor = static_cast(MEM_callocN(sizeof(float) * totvert, __func__)); - for (int i = 0; i < totvert; i++) { - edge_factor[i] = 1.0f; - } + Array dists(totvert, 0.0f); + Array edge_factor(totvert, 1.0f); - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial_with_symmetry(ob, ss, &flood, v, FLT_MAX); @@ -557,7 +558,10 @@ static float *sculpt_expand_normal_falloff_create(Object *ob, fdata.edge_sensitivity = edge_sensitivity; SCULPT_vertex_normal_get(ss, v, fdata.original_normal); - flood_fill::execute(ss, &flood, mask_expand_normal_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return mask_expand_normal_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); for (int repeat = 0; repeat < blur_steps; repeat++) { for (int i = 0; i < totvert; i++) { @@ -580,8 +584,6 @@ static float *sculpt_expand_normal_falloff_create(Object *ob, dists[i] = 1.0 - dists[i]; } - MEM_SAFE_FREE(edge_factor); - return dists; } @@ -589,15 +591,12 @@ static float *sculpt_expand_normal_falloff_create(Object *ob, * Spherical: Initializes the falloff based on the distance from a vertex, taking symmetry into * account. */ -static float *sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertRef v) +static Array sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertRef v) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_malloc_arrayN(totvert, sizeof(float), __func__)); - for (int i = 0; i < totvert; i++) { - dists[i] = FLT_MAX; - } + Array dists(totvert, FLT_MAX); const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char symm_it = 0; symm_it <= symm; symm_it++) { @@ -624,11 +623,11 @@ static float *sculpt_expand_spherical_falloff_create(Object *ob, const PBVHVertR * boundary to a falloff value of 0. Then, it propagates that falloff to the rest of the mesh so it * stays parallel to the boundary, increasing the falloff value by 1 on each step. */ -static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const PBVHVertRef v) +static Array sculpt_expand_boundary_topology_falloff_create(Object *ob, const PBVHVertRef v) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_calloc_arrayN(totvert, sizeof(float), __func__)); + Array dists(totvert, 0.0f); BitVector<> visited_verts(totvert); std::queue queue; @@ -686,11 +685,11 @@ static float *sculpt_expand_boundary_topology_falloff_create(Object *ob, const P * the base mesh faces when checking a vertex neighbor. For this reason, this is not implement * using the general flood-fill and sculpt neighbors accessors. */ -static float *sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertRef v) +static Array sculpt_expand_diagonals_falloff_create(Object *ob, const PBVHVertRef v) { SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_calloc_arrayN(totvert, sizeof(float), __func__)); + Array dists(totvert, 0.0f); /* This algorithm uses mesh data (faces and loops), so this falloff type can't be initialized for * Multires. It also does not make sense to implement it for dyntopo as the result will be the @@ -838,7 +837,7 @@ static void sculpt_expand_mesh_face_falloff_from_vertex_falloff(SculptSession *s Mesh *mesh, Cache *expand_cache) { - BLI_assert(expand_cache->vert_falloff != nullptr); + BLI_assert(!expand_cache->vert_falloff.is_empty()); if (!expand_cache->face_falloff) { expand_cache->face_falloff = static_cast( @@ -870,21 +869,19 @@ static void sculpt_expand_geodesics_from_state_boundary(Object *ob, SculptSession *ss = ob->sculpt; BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES); - GSet *initial_verts = BLI_gset_int_new("initial_verts"); + Set initial_verts; const BitVector<> boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false); const int totvert = SCULPT_vertex_count_get(ss); for (int i = 0; i < totvert; i++) { if (!boundary_verts[i]) { continue; } - BLI_gset_add(initial_verts, POINTER_FROM_INT(i)); + initial_verts.add(i); } - MEM_SAFE_FREE(expand_cache->vert_falloff); MEM_SAFE_FREE(expand_cache->face_falloff); expand_cache->vert_falloff = geodesic::distances_create(ob, initial_verts, FLT_MAX); - BLI_gset_free(initial_verts, nullptr); } /** @@ -895,16 +892,16 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob, Cache *expand_cache, const BitSpan enabled_verts) { - MEM_SAFE_FREE(expand_cache->vert_falloff); MEM_SAFE_FREE(expand_cache->face_falloff); SculptSession *ss = ob->sculpt; const int totvert = SCULPT_vertex_count_get(ss); - float *dists = static_cast(MEM_calloc_arrayN(totvert, sizeof(float), __func__)); + expand_cache->vert_falloff.reinitialize(totvert); + expand_cache->vert_falloff.fill(0); const BitVector<> boundary_verts = sculpt_expand_boundary_from_enabled(ss, enabled_verts, false); - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); for (int i = 0; i < totvert; i++) { if (!boundary_verts[i]) { @@ -915,11 +912,11 @@ static void sculpt_expand_topology_from_state_boundary(Object *ob, flood_fill::add_and_skip_initial(&flood, vertex); } - ExpandFloodFillData fdata; - fdata.dists = dists; - flood_fill::execute(ss, &flood, expand_topology_floodfill_cb, &fdata); - - expand_cache->vert_falloff = dists; + MutableSpan dists = expand_cache->vert_falloff; + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return expand_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, dists); + }); } /** @@ -1033,7 +1030,6 @@ static void sculpt_expand_initialize_from_face_set_boundary(Object *ob, static void sculpt_expand_falloff_factors_from_vertex_and_symm_create( Cache *expand_cache, Object *ob, const PBVHVertRef v, eSculptExpandFalloffType falloff_type) { - MEM_SAFE_FREE(expand_cache->vert_falloff); expand_cache->falloff_type = falloff_type; SculptSession *ss = ob->sculpt; @@ -1131,7 +1127,6 @@ static void sculpt_expand_snap_initialize_from_enabled(SculptSession *ss, Cache */ static void sculpt_expand_cache_data_free(Cache *expand_cache) { - MEM_SAFE_FREE(expand_cache->vert_falloff); MEM_SAFE_FREE(expand_cache->face_falloff); MEM_SAFE_FREE(expand_cache->original_colors); MEM_delete(expand_cache); diff --git a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc index d932aec92f6..6b5a22eeccb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_geodesic.cc +++ b/source/blender/editors/sculpt_paint/sculpt_geodesic.cc @@ -42,10 +42,10 @@ static bool sculpt_geodesic_mesh_test_dist_add(Span vert_positions, const int v0, const int v1, const int v2, - float *dists, - GSet *initial_verts) + MutableSpan dists, + const Set &initial_verts) { - if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(v0))) { + if (initial_verts.contains(v0)) { return false; } @@ -77,7 +77,9 @@ static bool sculpt_geodesic_mesh_test_dist_add(Span vert_positions, return false; } -static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float limit_radius) +static Array geodesic_mesh_create(Object *ob, + const Set &initial_verts, + const float limit_radius) { SculptSession *ss = ob->sculpt; Mesh *mesh = BKE_object_get_original_mesh(ob); @@ -95,7 +97,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float const bke::AttributeAccessor attributes = mesh->attributes(); const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); - float *dists = static_cast(MEM_malloc_arrayN(totvert, sizeof(float), __func__)); + Array dists(totvert); BitVector<> edge_tag(totedge); if (ss->edge_to_face_map.is_empty()) { @@ -115,7 +117,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float BLI_LINKSTACK_INIT(queue_next); for (int i = 0; i < totvert; i++) { - if (BLI_gset_haskey(initial_verts, POINTER_FROM_INT(i))) { + if (initial_verts.contains(i)) { dists[i] = 0.0f; } else { @@ -126,7 +128,6 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float /* Masks vertices that are further than limit radius from an initial vertex. As there is no need * to define a distance to them the algorithm can stop earlier by skipping them. */ BitVector<> affected_vert(totvert); - GSetIterator gs_iter; if (limit_radius == FLT_MAX) { /* In this case, no need to loop through all initial vertices to check distances as they are @@ -137,8 +138,7 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float /* This is an O(n^2) loop used to limit the geodesic distance calculation to a radius. When * this optimization is needed, it is expected for the tool to request the distance to a low * number of vertices (usually just 1 or 2). */ - GSET_ITER (gs_iter, initial_verts) { - const int v = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter)); + for (const int v : initial_verts) { const float *v_co = vert_positions[v]; for (int i = 0; i < totvert; i++) { if (len_squared_v3v3(v_co, vert_positions[i]) <= limit_radius_sq) { @@ -226,23 +226,15 @@ static float *geodesic_mesh_create(Object *ob, GSet *initial_verts, const float /* For sculpt mesh data that does not support a geodesic distances algorithm, fallback to the * distance to each vertex. In this case, only one of the initial vertices will be used to * calculate the distance. */ -static float *geodesic_fallback_create(Object *ob, GSet *initial_verts) +static Array geodesic_fallback_create(Object *ob, const Set &initial_verts) { SculptSession *ss = ob->sculpt; Mesh *mesh = BKE_object_get_original_mesh(ob); const int totvert = mesh->verts_num; - float *dists = static_cast(MEM_malloc_arrayN(totvert, sizeof(float), __func__)); - int first_affected = SCULPT_GEODESIC_VERTEX_NONE; - GSetIterator gs_iter; - GSET_ITER (gs_iter, initial_verts) { - first_affected = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter)); - break; - } - + Array dists(totvert, 0.0f); + const int first_affected = *initial_verts.begin(); if (first_affected == SCULPT_GEODESIC_VERTEX_NONE) { - for (int i = 0; i < totvert; i++) { - dists[i] = FLT_MAX; - } + dists.fill(FLT_MAX); return dists; } @@ -257,7 +249,7 @@ static float *geodesic_fallback_create(Object *ob, GSet *initial_verts) return dists; } -float *distances_create(Object *ob, GSet *initial_verts, const float limit_radius) +Array distances_create(Object *ob, const Set &initial_verts, const float limit_radius) { SculptSession *ss = ob->sculpt; switch (BKE_pbvh_type(ss->pbvh)) { @@ -268,15 +260,15 @@ float *distances_create(Object *ob, GSet *initial_verts, const float limit_radiu return geodesic_fallback_create(ob, initial_verts); } BLI_assert_unreachable(); - return nullptr; + return {}; } -float *distances_create_from_vert_and_symm(Object *ob, - const PBVHVertRef vertex, - const float limit_radius) +Array distances_create_from_vert_and_symm(Object *ob, + const PBVHVertRef vertex, + const float limit_radius) { SculptSession *ss = ob->sculpt; - GSet *initial_verts = BLI_gset_int_new("initial_verts"); + Set initial_verts; const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { @@ -292,14 +284,12 @@ float *distances_create_from_vert_and_symm(Object *ob, v = SCULPT_nearest_vertex_get(ob, location, FLT_MAX, false); } if (v.i != PBVH_REF_NONE) { - BLI_gset_add(initial_verts, POINTER_FROM_INT(BKE_pbvh_vertex_to_index(ss->pbvh, v))); + initial_verts.add(BKE_pbvh_vertex_to_index(ss->pbvh, v)); } } } - float *dists = distances_create(ob, initial_verts, limit_radius); - BLI_gset_free(initial_verts, nullptr); - return dists; + return distances_create(ob, initial_verts, limit_radius); } } // namespace blender::ed::sculpt_paint::geodesic diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 9d06a5190bf..73bdfc3ce79 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -121,12 +121,6 @@ struct SculptOrigFaceData { int face_set; }; -/* Flood Fill. */ -struct SculptFloodFill { - std::queue queue; - blender::BitVector<> visited_verts; -}; - enum eBoundaryAutomaskMode { AUTOMASK_INIT_BOUNDARY_EDGES = 1, AUTOMASK_INIT_BOUNDARY_FACE_SETS = 2, @@ -578,7 +572,7 @@ struct Cache { /* Indexed by vertex index, precalculated falloff value of that vertex (without any falloff * editing modification applied). */ - float *vert_falloff; + Array vert_falloff; /* Max falloff value in *vert_falloff. */ float max_vert_falloff; @@ -1175,20 +1169,22 @@ void SCULPT_tilt_effective_normal_get(const SculptSession *ss, const Brush *brus namespace blender::ed::sculpt_paint::flood_fill { -void init_fill(SculptSession *ss, SculptFloodFill *flood); -void add_active(Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius); +struct FillData { + std::queue queue; + blender::BitVector<> visited_verts; +}; + +void init_fill(SculptSession *ss, FillData *flood); +void add_active(Object *ob, SculptSession *ss, FillData *flood, float radius); void add_initial_with_symmetry( - Object *ob, SculptSession *ss, SculptFloodFill *flood, PBVHVertRef vertex, float radius); -void add_initial(SculptFloodFill *flood, PBVHVertRef vertex); -void add_and_skip_initial(SculptFloodFill *flood, PBVHVertRef vertex); -void execute(SculptSession *ss, - SculptFloodFill *flood, - bool (*func)(SculptSession *ss, - PBVHVertRef from_v, - PBVHVertRef to_v, - bool is_duplicate, - void *userdata), - void *userdata); + Object *ob, SculptSession *ss, FillData *flood, PBVHVertRef vertex, float radius); +void add_initial(FillData *flood, PBVHVertRef vertex); +void add_and_skip_initial(FillData *flood, PBVHVertRef vertex); +void execute( + SculptSession *ss, + FillData *flood, + FunctionRef + func); } @@ -1362,8 +1358,10 @@ namespace blender::ed::sculpt_paint::geodesic { * Geodesic distances will only work when used with PBVH_FACES, for other types of PBVH it will * fallback to euclidean distances to one of the initial vertices in the set. */ -float *distances_create(Object *ob, GSet *initial_verts, float limit_radius); -float *distances_create_from_vert_and_symm(Object *ob, PBVHVertRef vertex, float limit_radius); +Array distances_create(Object *ob, const Set &initial_verts, float limit_radius); +Array distances_create_from_vert_and_symm(Object *ob, + PBVHVertRef vertex, + float limit_radius); } diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 6f190c0f19e..6c1c9fff2f8 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -781,14 +781,15 @@ static void do_mask_by_color_contiguous_update_node(Object *ob, } } -static bool sculpt_mask_by_color_contiguous_floodfill( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool sculpt_mask_by_color_contiguous_floodfill(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + MaskByColorContiguousFloodFillData *data) { int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - MaskByColorContiguousFloodFillData *data = static_cast( - userdata); float current_color[4]; SCULPT_vertex_color_get(ss, to_v, current_color); @@ -825,7 +826,7 @@ static void sculpt_mask_by_color_contiguous(Object *object, } } - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial(&flood, vertex); @@ -839,7 +840,10 @@ static void sculpt_mask_by_color_contiguous(Object *object, copy_v3_v3(ffd.initial_color, color); - flood_fill::execute(ss, &flood, sculpt_mask_by_color_contiguous_floodfill, &ffd); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return sculpt_mask_by_color_contiguous_floodfill(ss, from_v, to_v, is_duplicate, &ffd); + }); Vector nodes = blender::bke::pbvh::search_gather(ss->pbvh, {}); const SculptMaskWriteInfo mask_write = SCULPT_mask_get_for_write(ss); diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index 3a4383f976e..213aa04b1d5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -379,12 +379,14 @@ struct PoseFloodFillData { int target_face_set; }; -static bool pose_topology_floodfill_cb( - SculptSession *ss, PBVHVertRef /*from_v*/, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool pose_topology_floodfill_cb(SculptSession *ss, + PBVHVertRef /*from_v*/, + PBVHVertRef to_v, + bool is_duplicate, + PoseFloodFillData *data) { int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); - PoseFloodFillData *data = static_cast(userdata); const float *co = SCULPT_vertex_co_get(ss, to_v); if (data->pose_factor) { @@ -412,11 +414,12 @@ static bool pose_topology_floodfill_cb( return false; } -static bool pose_face_sets_floodfill_cb( - SculptSession *ss, PBVHVertRef /*from_v*/, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool pose_face_sets_floodfill_cb(SculptSession *ss, + PBVHVertRef /*from_v*/, + PBVHVertRef to_v, + bool is_duplicate, + PoseFloodFillData *data) { - PoseFloodFillData *data = static_cast(userdata); - const int index = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); const PBVHVertRef vertex = to_v; bool visit_next = false; @@ -524,7 +527,7 @@ void calc_pose_data(Object *ob, SCULPT_vertex_random_access_ensure(ss); /* Calculate the pose rotation point based on the boundaries of the brush factor. */ - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_active(ob, ss, &flood, (r_pose_factor) ? radius : 0.0f); @@ -537,7 +540,10 @@ void calc_pose_data(Object *ob, zero_v3(fdata.pose_origin); copy_v3_v3(fdata.pose_initial_co, initial_location); copy_v3_v3(fdata.fallback_floodfill_origin, initial_location); - flood_fill::execute(ss, &flood, pose_topology_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return pose_topology_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); if (fdata.tot_co > 0) { mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co)); @@ -728,7 +734,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob, for (int s = 0; s < ik_chain->tot_segments; s++) { - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial_with_symmetry(ob, ss, &flood, current_vertex, FLT_MAX); @@ -750,7 +756,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob, zero_v3(fdata.pose_origin); zero_v3(fdata.fallback_origin); copy_v3_v3(fdata.pose_initial_co, SCULPT_vertex_co_get(ss, current_vertex)); - flood_fill::execute(ss, &flood, pose_face_sets_floodfill_cb, &fdata); + flood_fill::execute( + ss, + &flood, + [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return pose_face_sets_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); if (fdata.tot_co > 0) { mul_v3_fl(fdata.pose_origin, 1.0f / float(fdata.tot_co)); @@ -776,11 +787,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(Object *ob, return ik_chain; } -static bool pose_face_sets_fk_find_masked_floodfill_cb( - SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate, void *userdata) +static bool pose_face_sets_fk_find_masked_floodfill_cb(SculptSession *ss, + PBVHVertRef from_v, + PBVHVertRef to_v, + bool is_duplicate, + PoseFloodFillData *data) { - PoseFloodFillData *data = static_cast(userdata); - int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v); int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); @@ -817,11 +829,8 @@ static bool pose_face_sets_fk_find_masked_floodfill_cb( static bool pose_face_sets_fk_set_weights_floodfill_cb(SculptSession *ss, PBVHVertRef /*from_v*/, PBVHVertRef to_v, - bool /*is_duplicate*/, - void *userdata) + PoseFloodFillData *data) { - PoseFloodFillData *data = static_cast(userdata); - int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v); data->fk_weights[to_v_i] = 1.0f; @@ -842,7 +851,7 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob, const int active_face_set = face_set::active_face_set_get(ss); - SculptFloodFill flood; + flood_fill::FillData flood; flood_fill::init_fill(ss, &flood); flood_fill::add_initial(&flood, active_vertex); PoseFloodFillData fdata; @@ -853,7 +862,10 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob, fdata.target_face_set = SCULPT_FACE_SET_NONE; fdata.masked_face_set_it = 0; fdata.visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", 3); - flood_fill::execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata); + flood_fill::execute( + ss, &flood, [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate) { + return pose_face_sets_fk_find_masked_floodfill_cb(ss, from_v, to_v, is_duplicate, &fdata); + }); BLI_gset_free(fdata.visited_face_sets, nullptr); int origin_count = 0; @@ -908,7 +920,12 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(Object *ob, flood_fill::init_fill(ss, &flood); flood_fill::add_active(ob, ss, &flood, radius); fdata.fk_weights = ik_chain->segments[0].weights; - flood_fill::execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata); + flood_fill::execute( + ss, + &flood, + [&](SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/) { + return pose_face_sets_fk_set_weights_floodfill_cb(ss, from_v, to_v, &fdata); + }); pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head); return ik_chain;