From 347ec1acd7bd5c96ce507583ca196d1aadccc7df Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 29 Aug 2024 19:34:22 +0200 Subject: [PATCH] Refactor: Sculpt: Switch to new API for BVH node selection & data access Use `IndexMask` for a selection of nodes, and remove the temporarily added type-agnostic functions for PBVH node data access. This change results in a lot of boilerplate change since all iteration over nodes is affected, and the proper types for nodes need to be used to access their data. Until leaf and inner nodes are split, the `all_leaf_nodes` function has an unfortunate signature now since it needs to return an `IndexMask` as well. That should be simplified in the future. Pull Request: https://projects.blender.org/blender/blender/pulls/126944 --- source/blender/blenkernel/BKE_pbvh_api.hh | 33 +- source/blender/blenkernel/intern/paint.cc | 21 +- source/blender/blenkernel/intern/pbvh.cc | 16 +- source/blender/blenlib/BLI_index_mask_fwd.hh | 2 + .../brushes/bmesh_topology_rake.cc | 13 +- .../editors/sculpt_paint/brushes/clay.cc | 46 +- .../sculpt_paint/brushes/clay_strips.cc | 49 +- .../sculpt_paint/brushes/clay_thumb.cc | 47 +- .../editors/sculpt_paint/brushes/crease.cc | 51 +- .../editors/sculpt_paint/brushes/draw.cc | 56 +- .../sculpt_paint/brushes/draw_face_sets.cc | 71 +- .../sculpt_paint/brushes/draw_sharp.cc | 55 +- .../brushes/draw_vector_displacement.cc | 44 +- .../sculpt_paint/brushes/elastic_deform.cc | 44 +- .../sculpt_paint/brushes/enhance_details.cc | 87 +- .../editors/sculpt_paint/brushes/fill.cc | 45 +- .../editors/sculpt_paint/brushes/flatten.cc | 45 +- .../editors/sculpt_paint/brushes/grab.cc | 43 +- .../editors/sculpt_paint/brushes/inflate.cc | 41 +- .../editors/sculpt_paint/brushes/layer.cc | 35 +- .../editors/sculpt_paint/brushes/mask.cc | 33 +- .../sculpt_paint/brushes/multiplane_scrape.cc | 81 +- .../brushes/multires_displacement_eraser.cc | 12 +- .../brushes/multires_displacement_smear.cc | 23 +- .../editors/sculpt_paint/brushes/pinch.cc | 45 +- .../editors/sculpt_paint/brushes/relax.cc | 255 +++--- .../editors/sculpt_paint/brushes/rotate.cc | 41 +- .../editors/sculpt_paint/brushes/scrape.cc | 45 +- .../editors/sculpt_paint/brushes/smooth.cc | 50 +- .../sculpt_paint/brushes/smooth_mask.cc | 49 +- .../sculpt_paint/brushes/snake_hook.cc | 43 +- .../sculpt_paint/brushes/surface_smooth.cc | 124 +-- .../editors/sculpt_paint/brushes/thumb.cc | 50 +- .../sculpt_paint/brushes/topology_slide.cc | 41 +- .../editors/sculpt_paint/brushes/types.hh | 73 +- .../editors/sculpt_paint/mesh_brush_common.hh | 26 +- .../editors/sculpt_paint/paint_hide.cc | 431 +++++----- .../editors/sculpt_paint/paint_hide.hh | 5 +- .../editors/sculpt_paint/paint_intern.hh | 10 +- .../editors/sculpt_paint/paint_mask.cc | 334 ++++---- .../editors/sculpt_paint/paint_mask.hh | 5 +- .../editors/sculpt_paint/paint_vertex.cc | 108 +-- .../sculpt_paint/paint_vertex_color_ops.cc | 10 +- .../editors/sculpt_paint/paint_weight.cc | 86 +- source/blender/editors/sculpt_paint/sculpt.cc | 749 ++++++++++-------- .../sculpt_paint/sculpt_automasking.cc | 8 +- .../editors/sculpt_paint/sculpt_boundary.cc | 236 +++--- .../editors/sculpt_paint/sculpt_cloth.cc | 369 +++++---- .../editors/sculpt_paint/sculpt_cloth.hh | 14 +- .../editors/sculpt_paint/sculpt_color.hh | 6 +- .../editors/sculpt_paint/sculpt_detail.cc | 14 +- .../editors/sculpt_paint/sculpt_expand.cc | 117 +-- .../editors/sculpt_paint/sculpt_expand.hh | 4 +- .../editors/sculpt_paint/sculpt_face_set.cc | 448 +++++++---- .../editors/sculpt_paint/sculpt_filter.hh | 4 +- .../sculpt_paint/sculpt_filter_color.cc | 37 +- .../sculpt_paint/sculpt_filter_mask.cc | 283 ++++--- .../sculpt_paint/sculpt_filter_mesh.cc | 591 +++++++------- .../editors/sculpt_paint/sculpt_gesture.cc | 42 +- .../editors/sculpt_paint/sculpt_gesture.hh | 4 +- .../editors/sculpt_paint/sculpt_hide.cc | 2 +- .../editors/sculpt_paint/sculpt_hide.hh | 4 +- .../editors/sculpt_paint/sculpt_intern.hh | 14 +- .../editors/sculpt_paint/sculpt_mask_init.cc | 89 +-- .../editors/sculpt_paint/sculpt_ops.cc | 59 +- .../sculpt_paint/sculpt_paint_color.cc | 76 +- .../sculpt_paint/sculpt_paint_image.cc | 43 +- .../editors/sculpt_paint/sculpt_pose.cc | 77 +- .../editors/sculpt_paint/sculpt_pose.hh | 2 +- .../editors/sculpt_paint/sculpt_project.cc | 47 +- .../editors/sculpt_paint/sculpt_smooth.cc | 32 +- .../editors/sculpt_paint/sculpt_transform.cc | 150 ++-- .../editors/sculpt_paint/sculpt_undo.cc | 191 +++-- .../editors/sculpt_paint/sculpt_undo.hh | 3 +- 74 files changed, 3557 insertions(+), 2982 deletions(-) diff --git a/source/blender/blenkernel/BKE_pbvh_api.hh b/source/blender/blenkernel/BKE_pbvh_api.hh index f6b5566c64d..423332335e0 100644 --- a/source/blender/blenkernel/BKE_pbvh_api.hh +++ b/source/blender/blenkernel/BKE_pbvh_api.hh @@ -527,7 +527,7 @@ int BKE_pbvh_debug_draw_gen_get(blender::bke::pbvh::Node &node); namespace blender::bke::pbvh { /** Return pointers to all the leaf nodes in the BVH tree. */ -Vector all_leaf_nodes(Tree &pbvh); +IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory); /** Create a selection of nodes that match the filter function. */ IndexMask search_nodes(const Tree &pbvh, @@ -551,34 +551,3 @@ void update_node_bounds_grids(const CCGKey &key, Span grids, GridsNod void update_node_bounds_bmesh(BMeshNode &node); } // namespace blender::bke::pbvh - -/* TODO: Temporary inline definitions with generic #Node type signature. To be removed as - * refactoring changes code to use explicit node types. */ -namespace blender::bke::pbvh { -inline Span node_grid_indices(const Node &node) -{ - return node_grid_indices(static_cast(node)); -} -inline Span node_verts(const Node &node) -{ - return node_verts(static_cast(node)); -} -inline Span node_unique_verts(const Node &node) -{ - return node_unique_verts(static_cast(node)); -} -} // namespace blender::bke::pbvh -inline const blender::Set &BKE_pbvh_bmesh_node_unique_verts( - blender::bke::pbvh::Node *node) -{ - return BKE_pbvh_bmesh_node_unique_verts(static_cast(node)); -} -inline const blender::Set &BKE_pbvh_bmesh_node_other_verts( - blender::bke::pbvh::Node *node) -{ - return BKE_pbvh_bmesh_node_other_verts(static_cast(node)); -} -inline const blender::Set &BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::Node *node) -{ - return BKE_pbvh_bmesh_node_faces(static_cast(node)); -} diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index b6a9f01f14f..9565da791dc 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -2095,6 +2095,7 @@ static void sculpt_update_object(Depsgraph *depsgraph, void BKE_sculpt_update_object_before_eval(Object *ob_eval) { + using namespace blender; /* Update before mesh evaluation in the dependency graph. */ SculptSession *ss = ob_eval->sculpt; @@ -2120,8 +2121,24 @@ void BKE_sculpt_update_object_before_eval(Object *ob_eval) BKE_sculptsession_free_vwpaint_data(ob_eval->sculpt); } else if (ss->pbvh) { - for (blender::bke::pbvh::Node *node : blender::bke::pbvh::all_leaf_nodes(*ss->pbvh)) { - BKE_pbvh_node_mark_update(*node); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss->pbvh, memory); + switch (ss->pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss->pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss->pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss->pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); }); + break; + } } } } diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index f7205c5e315..fd3c7cac6a9 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -3055,18 +3055,14 @@ void BKE_pbvh_sync_visibility_from_verts(Object &object) namespace blender::bke::pbvh { -Vector all_leaf_nodes(Tree &pbvh) +IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory) { - Vector leaf_nodes; return std::visit( - [&](auto &nodes) { - leaf_nodes.reserve(nodes.size()); - for (Node &node : nodes) { - if (node.flag_ & PBVH_Leaf) { - leaf_nodes.append(&node); - } - } - return leaf_nodes; + [&](const auto &nodes) { + return IndexMask::from_predicate( + nodes.index_range(), GrainSize(1024), memory, [&](const int i) { + return (nodes[i].flag_ & PBVH_Leaf) != 0; + }); }, pbvh.nodes_); } diff --git a/source/blender/blenlib/BLI_index_mask_fwd.hh b/source/blender/blenlib/BLI_index_mask_fwd.hh index 5bfbf4ccc7f..88f1844e20c 100644 --- a/source/blender/blenlib/BLI_index_mask_fwd.hh +++ b/source/blender/blenlib/BLI_index_mask_fwd.hh @@ -7,11 +7,13 @@ namespace blender::index_mask { class IndexMask; +class IndexMaskMemory; } // namespace blender::index_mask namespace blender { using index_mask::IndexMask; +using index_mask::IndexMaskMemory; } // namespace blender diff --git a/source/blender/editors/sculpt_paint/brushes/bmesh_topology_rake.cc b/source/blender/editors/sculpt_paint/brushes/bmesh_topology_rake.cc index 9d8c6faa4ad..2fe0ef990ae 100644 --- a/source/blender/editors/sculpt_paint/brushes/bmesh_topology_rake.cc +++ b/source/blender/editors/sculpt_paint/brushes/bmesh_topology_rake.cc @@ -49,7 +49,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float3 &direction, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -93,7 +93,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes, + const IndexMask &node_mask, const float input_strength) { const SculptSession &ss = *object.sculpt; @@ -120,12 +120,13 @@ void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; for ([[maybe_unused]] const int i : IndexRange(count)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_bmesh( - depsgraph, sd, object, brush, direction, factor * ss.cache->pressure, *nodes[i], tls); - } + depsgraph, sd, object, brush, direction, factor * ss.cache->pressure, nodes[i], tls); + }); }); } } diff --git a/source/blender/editors/sculpt_paint/brushes/clay.cc b/source/blender/editors/sculpt_paint/brushes/clay.cc index 1501ba218c1..f354e7540d7 100644 --- a/source/blender/editors/sculpt_paint/brushes/clay.cc +++ b/source/blender/editors/sculpt_paint/brushes/clay.cc @@ -61,7 +61,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -106,7 +106,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float4 &test_plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -150,7 +150,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float4 &test_plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -191,14 +191,14 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_clay_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); float3 area_no; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co); const float initial_radius = fabsf(ss.cache->initial_radius); const float offset = SCULPT_brush_plane_offset_get(sd, ss); @@ -227,9 +227,10 @@ void do_clay_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -237,31 +238,36 @@ void do_clay_brush(const Depsgraph &depsgraph, bstrength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, test_plane, bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, test_plane, bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls); + }); }); break; + } } } + } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/brushes/clay_strips.cc b/source/blender/editors/sculpt_paint/brushes/clay_strips.cc index 0f7be1cd98e..f994e29f1ce 100644 --- a/source/blender/editors/sculpt_paint/brushes/clay_strips.cc +++ b/source/blender/editors/sculpt_paint/brushes/clay_strips.cc @@ -47,7 +47,7 @@ static void calc_faces(const Depsgraph &depsgraph, const bool flip, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -103,7 +103,7 @@ static void calc_grids(const Depsgraph &depsgraph, const float4 &plane, const float strength, const bool flip, - bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -159,7 +159,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const float4 &plane, const float strength, const bool flip, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -211,7 +211,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_clay_strips_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; if (math::is_zero(ss.cache->grab_delta_symmetry)) { @@ -226,13 +226,13 @@ void do_clay_strips_brush(const Depsgraph &depsgraph, float3 area_position; float3 plane_normal; - calc_brush_plane(depsgraph, brush, object, nodes, plane_normal, area_position); + calc_brush_plane(depsgraph, brush, object, node_mask, plane_normal, area_position); SCULPT_tilt_apply_to_normal(plane_normal, ss.cache, brush.tilt_strength_factor); area_position += plane_normal * ss.cache->scale * displace; float3 area_normal; if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) { - area_normal = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0)); + area_normal = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0)); } else { area_normal = plane_normal; @@ -274,15 +274,16 @@ void do_clay_strips_brush(const Depsgraph &depsgraph, const float strength = std::abs(ss.cache->bstrength); threading::EnumerableThreadSpecific all_tls; - switch (object.sculpt->pbvh->type()) { + switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -292,31 +293,35 @@ void do_clay_strips_brush(const Depsgraph &depsgraph, flip, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/clay_thumb.cc b/source/blender/editors/sculpt_paint/brushes/clay_thumb.cc index 9ab1a3c37c1..57bae854a0d 100644 --- a/source/blender/editors/sculpt_paint/brushes/clay_thumb.cc +++ b/source/blender/editors/sculpt_paint/brushes/clay_thumb.cc @@ -47,7 +47,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -95,7 +95,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane_tilt, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, LocalData &tls) { @@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const float4 &plane_tilt, const float strength, Object &object, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -188,7 +188,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_clay_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -201,10 +201,10 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph, float4x4 tmat; - calc_brush_plane(depsgraph, brush, object, nodes, area_no_sp, area_co_tmp); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no_sp, area_co_tmp); if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) { - area_no = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0)); + area_no = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0)); } else { area_no = area_no_sp; @@ -257,13 +257,14 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (object.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -271,31 +272,35 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph, clay_strength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, brush, plane_tilt, clay_strength, *nodes[i], object, tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, brush, plane_tilt, clay_strength, nodes[i], object, tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, brush, plane_tilt, clay_strength, object, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, brush, plane_tilt, clay_strength, object, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/crease.cc b/source/blender/editors/sculpt_paint/brushes/crease.cc index ed722c18116..a40889ecd81 100644 --- a/source/blender/editors/sculpt_paint/brushes/crease.cc +++ b/source/blender/editors/sculpt_paint/brushes/crease.cc @@ -73,7 +73,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -130,7 +130,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float3 &offset, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -184,7 +184,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float3 &offset, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -236,7 +236,7 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph, const Sculpt &sd, const bool invert_strength, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const StrokeCache &cache = *ss.cache; @@ -264,9 +264,10 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -274,31 +275,35 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph, strength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, offset, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, offset, strength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, offset, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, offset, strength, nodes[i], tls); + }); }); break; + } } } @@ -308,18 +313,18 @@ void do_crease_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { - do_crease_or_blob_brush(depsgraph, scene, sd, false, object, nodes); + do_crease_or_blob_brush(depsgraph, scene, sd, false, object, node_mask); } void do_blob_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { - do_crease_or_blob_brush(depsgraph, scene, sd, true, object, nodes); + do_crease_or_blob_brush(depsgraph, scene, sd, true, object, node_mask); } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/brushes/draw.cc b/source/blender/editors/sculpt_paint/brushes/draw.cc index 5267c9f8a05..1f74b73b9c3 100644 --- a/source/blender/editors/sculpt_paint/brushes/draw.cc +++ b/source/blender/editors/sculpt_paint/brushes/draw.cc @@ -42,7 +42,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float3 &offset, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -85,7 +85,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -127,7 +127,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -169,58 +169,62 @@ static void offset_positions(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const float3 &offset, - Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); threading::EnumerableThreadSpecific all_tls; - switch (object.sculpt->pbvh->type()) { + switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, offset, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; + } } } void do_draw_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -231,13 +235,13 @@ void do_draw_brush(const Depsgraph &depsgraph, const float3 offset = effective_normal * ss.cache->radius * ss.cache->scale * ss.cache->bstrength; - offset_positions(depsgraph, sd, object, offset, nodes); + offset_positions(depsgraph, sd, object, offset, node_mask); } void do_nudge_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; @@ -245,20 +249,20 @@ void do_nudge_brush(const Depsgraph &depsgraph, math::cross(ss.cache->sculpt_normal_symm, ss.cache->grab_delta_symmetry), ss.cache->sculpt_normal_symm); - offset_positions(depsgraph, sd, object, offset * ss.cache->bstrength, nodes); + offset_positions(depsgraph, sd, object, offset * ss.cache->bstrength, node_mask); } void do_gravity_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const float3 offset = ss.cache->gravity_direction * -ss.cache->radius_squared * ss.cache->scale * sd.gravity_factor; - offset_positions(depsgraph, sd, object, offset, nodes); + offset_positions(depsgraph, sd, object, offset, node_mask); } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc b/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc index 22fc63369d3..d44c20b60b5 100644 --- a/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc +++ b/source/blender/editors/sculpt_paint/brushes/draw_face_sets.cc @@ -117,7 +117,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const int face_set_id, Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, const Span face_indices, MeshLocalData &tls, const MutableSpan face_sets) @@ -169,7 +169,7 @@ static void calc_faces(const Depsgraph &depsgraph, static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, - const Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); @@ -181,13 +181,14 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, MutableSpan face_sets = attribute.span; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { MeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { const Span face_indices = bke::pbvh::node_face_indices_calc_mesh( - corner_tris, static_cast(*nodes[i]), tls.face_indices); + corner_tris, nodes[i], tls.face_indices); - undo::push_node(depsgraph, object, nodes[i], undo::Type::FaceSet); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); calc_faces(depsgraph, object, @@ -195,11 +196,11 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph, ss.cache->bstrength, ss.cache->paint_face_set, positions_eval, - *nodes[i], + nodes[i], face_indices, tls, face_sets); - } + }); }); attribute.finish(); @@ -232,7 +233,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float strength, const int face_set_id, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, GridLocalData &tls, const MutableSpan face_sets) { @@ -273,7 +274,7 @@ static void calc_grids(const Depsgraph &depsgraph, static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; @@ -281,22 +282,21 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph, MutableSpan face_sets = attribute.span; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - for (const int i : range) { - undo::push_node(depsgraph, object, node, undo::Type::FaceSet); + node_mask.slice(range).foreach_index([&](const int i) { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); - calc_grids(depsgraph, - object, - brush, - ss.cache->bstrength, - ss.cache->paint_face_set, - *nodes[i], - tls, - face_sets); - } - } + calc_grids(depsgraph, + object, + brush, + ss.cache->bstrength, + ss.cache->paint_face_set, + nodes[i], + tls, + face_sets); + }); }); attribute.finish(); } @@ -370,7 +370,7 @@ static void calc_bmesh(Object &object, const Brush &brush, const float strength, const int face_set_id, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, BMeshLocalData &tls, const int cd_offset) { @@ -406,19 +406,20 @@ static void calc_bmesh(Object &object, static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const int cd_offset = face_set::ensure_face_sets_bmesh(object); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); - for (const int i : range) { - undo::push_node(depsgraph, object, nodes[i], undo::Type::FaceSet); + node_mask.slice(range).foreach_index([&](const int i) { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); calc_bmesh( - object, brush, ss.cache->bstrength, ss.cache->paint_face_set, *nodes[i], tls, cd_offset); - } + object, brush, ss.cache->bstrength, ss.cache->paint_face_set, nodes[i], tls, cd_offset); + }); }); } @@ -427,20 +428,20 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph, void do_draw_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: - do_draw_face_sets_brush_mesh(depsgraph, object, brush, nodes); + do_draw_face_sets_brush_mesh(depsgraph, object, brush, node_mask); break; case bke::pbvh::Type::Grids: - do_draw_face_sets_brush_grids(depsgraph, object, brush, nodes); + do_draw_face_sets_brush_grids(depsgraph, object, brush, node_mask); break; case bke::pbvh::Type::BMesh: - do_draw_face_sets_brush_bmesh(depsgraph, object, brush, nodes); + do_draw_face_sets_brush_bmesh(depsgraph, object, brush, node_mask); break; } } diff --git a/source/blender/editors/sculpt_paint/brushes/draw_sharp.cc b/source/blender/editors/sculpt_paint/brushes/draw_sharp.cc index 0aa0f1487fe..5386cf0fa2d 100644 --- a/source/blender/editors/sculpt_paint/brushes/draw_sharp.cc +++ b/source/blender/editors/sculpt_paint/brushes/draw_sharp.cc @@ -40,7 +40,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const float3 &offset, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -84,7 +84,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -129,7 +129,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -174,8 +174,9 @@ static void offset_positions(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const float3 &offset, - Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); threading::EnumerableThreadSpecific all_tls; @@ -184,46 +185,42 @@ static void offset_positions(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_faces(depsgraph, - sd, - brush, - offset, - positions_eval, - *nodes[i], - object, - tls, - positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_faces( + depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; + } } } void do_draw_sharp_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -234,7 +231,7 @@ void do_draw_sharp_brush(const Depsgraph &depsgraph, const float3 offset = effective_normal * ss.cache->radius * ss.cache->scale * ss.cache->bstrength; - offset_positions(depsgraph, sd, object, offset, nodes); + offset_positions(depsgraph, sd, object, offset, node_mask); } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/brushes/draw_vector_displacement.cc b/source/blender/editors/sculpt_paint/brushes/draw_vector_displacement.cc index bdc073af14d..4b913223f61 100644 --- a/source/blender/editors/sculpt_paint/brushes/draw_vector_displacement.cc +++ b/source/blender/editors/sculpt_paint/brushes/draw_vector_displacement.cc @@ -83,7 +83,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, MutableSpan positions_orig) @@ -129,7 +129,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -174,7 +174,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -219,50 +219,54 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_draw_vector_displacement_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); threading::EnumerableThreadSpecific all_tls; - switch (object.sculpt->pbvh->type()) { + switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, nodes[i], tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/elastic_deform.cc b/source/blender/editors/sculpt_paint/brushes/elastic_deform.cc index f033d8f2e14..49651e4926e 100644 --- a/source/blender/editors/sculpt_paint/brushes/elastic_deform.cc +++ b/source/blender/editors/sculpt_paint/brushes/elastic_deform.cc @@ -90,7 +90,7 @@ static void calc_faces(const Depsgraph &depsgraph, const KelvinletParams &kelvinet_params, const float3 &offset, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -125,7 +125,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const KelvinletParams &kelvinet_params, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -161,7 +161,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const KelvinletParams &kelvinet_params, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -196,7 +196,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_elastic_deform_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -233,40 +233,44 @@ void do_elastic_deform_brush(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, params, grab_delta, positions_eval, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, params, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls); + }); }); - break; + } break; } } diff --git a/source/blender/editors/sculpt_paint/brushes/enhance_details.cc b/source/blender/editors/sculpt_paint/brushes/enhance_details.cc index 9c7fa0bb28d..1a201289354 100644 --- a/source/blender/editors/sculpt_paint/brushes/enhance_details.cc +++ b/source/blender/editors/sculpt_paint/brushes/enhance_details.cc @@ -42,7 +42,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Span vert_normals, const Span all_translations, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -89,7 +89,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const Span all_translations, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -134,7 +134,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const Span all_translations, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -176,7 +176,7 @@ static void calc_translations_faces(const Span vert_positions, const OffsetIndices faces, const Span corner_verts, const GroupedSpan vert_to_face_map, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalData &tls, const MutableSpan all_translations) { @@ -197,7 +197,7 @@ static void calc_translations_faces(const Span vert_positions, } static void calc_translations_grids(const SubdivCCG &subdiv_ccg, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls, const MutableSpan all_translations) { @@ -214,11 +214,12 @@ static void calc_translations_grids(const SubdivCCG &subdiv_ccg, scatter_data_grids(subdiv_ccg, translations.as_span(), grids, all_translations); } -static void calc_translations_bmesh(bke::pbvh::Node &node, +static void calc_translations_bmesh(const bke::pbvh::BMeshNode &node, LocalData &tls, const MutableSpan all_translations) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); + const Set &verts = BKE_pbvh_bmesh_node_unique_verts( + const_cast(&node)); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); tls.new_positions.resize(verts.size()); @@ -241,7 +242,7 @@ static void calc_translations_bmesh(bke::pbvh::Node &node, */ void calc_smooth_translations(const Depsgraph &depsgraph, const Object &object, - const Span nodes, + const IndexMask &node_mask, const MutableSpan translations) { const SculptSession &ss = *object.sculpt; @@ -254,38 +255,40 @@ void calc_smooth_translations(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_translations_faces(positions_eval, faces, corner_verts, ss.vert_to_face_map, - *nodes[i], + nodes[i], tls, translations); - } + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_translations_grids(subdiv_ccg, *nodes[i], tls, translations); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_translations_grids(subdiv_ccg, nodes[i], tls, translations); + }); }); break; } case bke::pbvh::Type::BMesh: BM_mesh_elem_index_ensure(ss.bm, BM_VERT); BM_mesh_elem_table_ensure(ss.bm, BM_VERT); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_translations_bmesh(*nodes[i], tls, translations); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_translations_bmesh(nodes[i], tls, translations); }); }); break; } @@ -294,7 +297,7 @@ void calc_smooth_translations(const Depsgraph &depsgraph, void do_enhance_details_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -302,8 +305,11 @@ void do_enhance_details_brush(const Depsgraph &depsgraph, if (SCULPT_stroke_is_first_brush_step(*ss.cache)) { ss.cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object)); - Vector effective_nodes = bke::pbvh::search_gather( - pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); }); + IndexMaskMemory memory; + const IndexMask effective_nodes = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { + return !node_fully_masked_or_hidden(node); + }); calc_smooth_translations(depsgraph, object, effective_nodes, ss.cache->detail_directions); } @@ -317,9 +323,10 @@ void do_enhance_details_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -327,31 +334,35 @@ void do_enhance_details_brush(const Depsgraph &depsgraph, vert_normals, translations, strength, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, translations, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, translations, strength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, translations, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, translations, strength, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/fill.cc b/source/blender/editors/sculpt_paint/brushes/fill.cc index c3d086f3b7d..e658b976737 100644 --- a/source/blender/editors/sculpt_paint/brushes/fill.cc +++ b/source/blender/editors/sculpt_paint/brushes/fill.cc @@ -44,7 +44,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -94,7 +94,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -190,14 +190,14 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_fill_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); float3 area_no; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co); SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor); const float offset = SCULPT_brush_plane_offset_get(sd, ss); @@ -214,9 +214,10 @@ void do_fill_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -224,31 +225,35 @@ void do_fill_brush(const Depsgraph &depsgraph, ss.cache->bstrength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/flatten.cc b/source/blender/editors/sculpt_paint/brushes/flatten.cc index 9fa11c8b227..678aaceaf7f 100644 --- a/source/blender/editors/sculpt_paint/brushes/flatten.cc +++ b/source/blender/editors/sculpt_paint/brushes/flatten.cc @@ -43,7 +43,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -91,7 +91,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -138,7 +138,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -183,14 +183,14 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_flatten_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); float3 area_no; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co); SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor); const float offset = SCULPT_brush_plane_offset_get(sd, ss); @@ -207,9 +207,10 @@ void do_flatten_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -217,31 +218,35 @@ void do_flatten_brush(const Depsgraph &depsgraph, ss.cache->bstrength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/grab.cc b/source/blender/editors/sculpt_paint/brushes/grab.cc index fbc4046f8bd..e4380e2b669 100644 --- a/source/blender/editors/sculpt_paint/brushes/grab.cc +++ b/source/blender/editors/sculpt_paint/brushes/grab.cc @@ -54,7 +54,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const float3 &offset, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -102,7 +102,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -151,7 +151,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -199,7 +199,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -218,39 +218,44 @@ void do_grab_brush(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, grab_delta, positions_eval, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, grab_delta, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, grab_delta, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/inflate.cc b/source/blender/editors/sculpt_paint/brushes/inflate.cc index cf7a09dcfbf..57dcb0fb6c7 100644 --- a/source/blender/editors/sculpt_paint/brushes/inflate.cc +++ b/source/blender/editors/sculpt_paint/brushes/inflate.cc @@ -49,7 +49,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float3 &scale, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -92,7 +92,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &scale, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -136,7 +136,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &scale, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -179,7 +179,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_inflate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -193,40 +193,43 @@ void do_inflate_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, scale, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, scale, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, scale, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, scale, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, scale, nodes[i], tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/layer.cc b/source/blender/editors/sculpt_paint/brushes/layer.cc index 1ac2514f21e..9227c003c87 100644 --- a/source/blender/editors/sculpt_paint/brushes/layer.cc +++ b/source/blender/editors/sculpt_paint/brushes/layer.cc @@ -124,7 +124,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Span persistent_base_positions, const Span persistent_base_normals, Object &object, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, LocalData &tls, MutableSpan layer_displacement_factor, MutableSpan positions_orig) @@ -218,7 +218,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls, MutableSpan layer_displacement_factor) { @@ -284,7 +284,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls, MutableSpan layer_displacement_factor) { @@ -349,7 +349,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_layer_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -391,9 +391,10 @@ void do_layer_brush(const Depsgraph &depsgraph, displacement = ss.cache->layer_displacement_factor; } - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -404,11 +405,11 @@ void do_layer_brush(const Depsgraph &depsgraph, persistent_position, persistent_normal, object, - *nodes[i], + nodes[i], tls, displacement, positions_orig); - } + }); }); persistent_disp_attr.finish(); break; @@ -418,11 +419,12 @@ void do_layer_brush(const Depsgraph &depsgraph, ss.cache->layer_displacement_factor = Array(SCULPT_vertex_count_get(object), 0.0f); } const MutableSpan displacement = ss.cache->layer_displacement_factor; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, brush, object, *nodes[i], tls, displacement); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, brush, object, nodes[i], tls, displacement); + }); }); break; } @@ -431,11 +433,12 @@ void do_layer_brush(const Depsgraph &depsgraph, ss.cache->layer_displacement_factor = Array(SCULPT_vertex_count_get(object), 0.0f); } const MutableSpan displacement = ss.cache->layer_displacement_factor; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, brush, object, *nodes[i], tls, displacement); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, brush, object, nodes[i], tls, displacement); + }); }); break; } diff --git a/source/blender/editors/sculpt_paint/brushes/mask.cc b/source/blender/editors/sculpt_paint/brushes/mask.cc index 4ecb03d7296..2e9940ea939 100644 --- a/source/blender/editors/sculpt_paint/brushes/mask.cc +++ b/source/blender/editors/sculpt_paint/brushes/mask.cc @@ -65,7 +65,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, Mesh &mesh, LocalData &tls, @@ -114,7 +114,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -162,7 +162,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -211,7 +211,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -220,6 +220,7 @@ void do_mask_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (ss.pbvh->type()) { case blender::bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const Span positions = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); @@ -229,39 +230,39 @@ void do_mask_brush(const Depsgraph &depsgraph, bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span( ".sculpt_mask", bke::AttrDomain::Point); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, brush, bstrength, positions, vert_normals, - *nodes[i], + nodes[i], object, mesh, tls, mask.span); - } + }); }); mask.finish(); break; } case blender::bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, object, brush, bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, object, brush, bstrength, nodes[i], tls); }); }); break; } case blender::bke::pbvh::Type::BMesh: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, object, brush, bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, object, brush, bstrength, nodes[i], tls); }); }); break; } diff --git a/source/blender/editors/sculpt_paint/brushes/multiplane_scrape.cc b/source/blender/editors/sculpt_paint/brushes/multiplane_scrape.cc index 3f863bf8696..906b7fa8733 100644 --- a/source/blender/editors/sculpt_paint/brushes/multiplane_scrape.cc +++ b/source/blender/editors/sculpt_paint/brushes/multiplane_scrape.cc @@ -131,7 +131,7 @@ static void sample_node_surface_mesh(const Depsgraph &depsgraph, const float4x4 &mat, const Span vert_positions, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, ScrapeSampleData &sample, LocalData &tls) { @@ -174,7 +174,7 @@ static void sample_node_surface_grids(const Depsgraph &depsgraph, const Object &object, const Brush &brush, const float4x4 &mat, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, ScrapeSampleData &sample, LocalData &tls) { @@ -219,14 +219,15 @@ static void sample_node_surface_bmesh(const Depsgraph &depsgraph, const Object &object, const Brush &brush, const float4x4 &mat, - bke::pbvh::Node &node, + const bke::pbvh::BMeshNode &node, ScrapeSampleData &sample, LocalData &tls) { const SculptSession &ss = *object.sculpt; const StrokeCache &cache = *ss.cache; - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); + const Set &verts = BKE_pbvh_bmesh_node_unique_verts( + const_cast(&node)); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); @@ -264,62 +265,65 @@ static ScrapeSampleData sample_surface(const Depsgraph &depsgraph, const Object &object, const Brush &brush, const float4x4 &mat, - const Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const bke::pbvh::Tree &pbvh = *ss.pbvh; threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + const Span nodes = pbvh.nodes(); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); return threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, ScrapeSampleData{}, [&](const IndexRange range, ScrapeSampleData sample) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { sample_node_surface_mesh(depsgraph, object, brush, mat, positions_eval, vert_normals, - *nodes[i], + nodes[i], sample, tls); - } + }); return sample; }, join_samples); break; } case bke::pbvh::Type::Grids: { + const Span nodes = pbvh.nodes(); return threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, ScrapeSampleData{}, [&](const IndexRange range, ScrapeSampleData sample) { LocalData &tls = all_tls.local(); - for (const int i : range) { - sample_node_surface_grids(depsgraph, object, brush, mat, *nodes[i], sample, tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + sample_node_surface_grids(depsgraph, object, brush, mat, nodes[i], sample, tls); + }); return sample; }, join_samples); break; } case bke::pbvh::Type::BMesh: { + const Span nodes = pbvh.nodes(); return threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, ScrapeSampleData{}, [&](const IndexRange range, ScrapeSampleData sample) { LocalData &tls = all_tls.local(); - for (const int i : range) { - sample_node_surface_bmesh(depsgraph, object, brush, mat, *nodes[i], sample, tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + sample_node_surface_bmesh(depsgraph, object, brush, mat, nodes[i], sample, tls); + }); return sample; }, join_samples); @@ -339,7 +343,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -398,7 +402,7 @@ static void calc_grids(const Depsgraph &depsgraph, const std::array &scrape_planes, const float angle, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, LocalData &tls) { @@ -457,7 +461,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const std::array &scrape_planes, const float angle, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, LocalData &tls) { @@ -511,7 +515,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_multiplane_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -523,11 +527,11 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, float3 area_no_sp; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no_sp, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no_sp, area_co); float3 area_no; if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA || (brush.flag & BRUSH_ORIGINAL_NORMAL)) { - area_no = calc_area_normal(depsgraph, brush, object, nodes).value_or(float3(0)); + area_no = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0)); } else { area_no = area_no_sp; @@ -564,7 +568,7 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, if (brush.flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) { /* Sample the individual normal and area center of the areas at both sides of the cursor. */ - const ScrapeSampleData sample = sample_surface(depsgraph, object, brush, mat, nodes); + const ScrapeSampleData sample = sample_surface(depsgraph, object, brush, mat, node_mask); /* Use the plane centers to check if we are sculpting along a concave or convex edge. */ const std::array sampled_plane_co{ @@ -637,6 +641,7 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (object.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); @@ -653,19 +658,20 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, strength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); + BKE_pbvh_node_mark_positions_update(nodes[i]); } }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_grids(depsgraph, sd, brush, @@ -673,16 +679,18 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, multiplane_scrape_planes, ss.cache->multiplane_scrape_angle, strength, - *nodes[i], + nodes[i], object, tls); - } + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_bmesh(depsgraph, sd, brush, @@ -690,12 +698,13 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph, multiplane_scrape_planes, ss.cache->multiplane_scrape_angle, strength, - *nodes[i], + nodes[i], object, tls); - } + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/multires_displacement_eraser.cc b/source/blender/editors/sculpt_paint/brushes/multires_displacement_eraser.cc index 1aee9d6b00f..7e753a9a5ad 100644 --- a/source/blender/editors/sculpt_paint/brushes/multires_displacement_eraser.cc +++ b/source/blender/editors/sculpt_paint/brushes/multires_displacement_eraser.cc @@ -50,7 +50,7 @@ static void calc_node(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -97,18 +97,18 @@ static void calc_node(const Depsgraph &depsgraph, void do_displacement_eraser_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); const float strength = std::min(ss.cache->bstrength, 1.0f); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_node(depsgraph, sd, object, brush, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_node(depsgraph, sd, object, brush, strength, nodes[i], tls); }); }); } diff --git a/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc b/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc index 822e6a325c6..59c2874ed95 100644 --- a/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc +++ b/source/blender/editors/sculpt_paint/brushes/multires_displacement_smear.cc @@ -37,7 +37,7 @@ static void calc_node(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -157,7 +157,7 @@ BLI_NOINLINE static void eval_all_limit_positions(const SubdivCCG &subdiv_ccg, BLI_NOINLINE static void store_node_prev_displacement(const Span limit_positions, const Span elems, const CCGKey &key, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, const MutableSpan prev_displacement) { for (const int grid : bke::pbvh::node_grid_indices(node)) { @@ -174,10 +174,12 @@ BLI_NOINLINE static void store_node_prev_displacement(const Span limit_p void do_displacement_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const Span elems = subdiv_ccg.grids; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -189,24 +191,23 @@ void do_displacement_smear_brush(const Depsgraph &depsgraph, eval_all_limit_positions(subdiv_ccg, ss.cache->displacement_smear.limit_surface_co); } - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + node_mask.slice(range).foreach_index([&](const int i) { store_node_prev_displacement(ss.cache->displacement_smear.limit_surface_co, elems, key, - *nodes[i], + nodes[i], ss.cache->displacement_smear.prev_displacement); - } + }); }); const float strength = std::clamp(ss.cache->bstrength, 0.0f, 1.0f); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_node(depsgraph, ob, brush, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_node(depsgraph, ob, brush, strength, nodes[i], tls); }); }); } diff --git a/source/blender/editors/sculpt_paint/brushes/pinch.cc b/source/blender/editors/sculpt_paint/brushes/pinch.cc index 74301407541..06c61896289 100644 --- a/source/blender/editors/sculpt_paint/brushes/pinch.cc +++ b/source/blender/editors/sculpt_paint/brushes/pinch.cc @@ -67,7 +67,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -118,7 +118,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const std::array &stroke_xz, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -168,7 +168,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const std::array &stroke_xz, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -217,14 +217,14 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_pinch_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); float3 area_no; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co); /* delay the first daub because grab delta is not setup */ if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(*ss.cache)) { @@ -253,9 +253,10 @@ void do_pinch_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -263,31 +264,35 @@ void do_pinch_brush(const Depsgraph &depsgraph, ss.cache->bstrength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/relax.cc b/source/blender/editors/sculpt_paint/brushes/relax.cc index 1a4b46433ba..23d99fc7055 100644 --- a/source/blender/editors/sculpt_paint/brushes/relax.cc +++ b/source/blender/editors/sculpt_paint/brushes/relax.cc @@ -106,7 +106,7 @@ BLI_NOINLINE static void calc_factors_faces(const Depsgraph &depsgraph, const float strength, const bool relax_face_sets, const Object &object, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, MeshLocalData &tls, const MutableSpan factors) { @@ -144,11 +144,12 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength, const bool relax_face_sets) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -160,15 +161,16 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); Array node_offset_data; - const OffsetIndices node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data); + const OffsetIndices node_vert_offsets = create_node_vert_offsets( + nodes, node_mask, node_offset_data); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { MeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_factors_faces(depsgraph, brush, positions_eval, @@ -176,15 +178,15 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph, strength, relax_face_sets, object, - *nodes[i], + nodes[i], tls, factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { MeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_faces( positions_eval, vert_normals, @@ -195,23 +197,21 @@ static void do_relax_face_sets_brush_mesh(const Depsgraph &depsgraph, ss.face_sets, hide_poly, relax_face_sets, - bke::pbvh::node_unique_verts(*nodes[i]), + bke::pbvh::node_unique_verts(nodes[i]), factors.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_faces(depsgraph, - sd, - positions_eval, - bke::pbvh::node_unique_verts(*nodes[i]), - object, - translations.as_mutable_span().slice(node_vert_offsets[i]), - positions_orig); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_faces(depsgraph, + sd, + positions_eval, + bke::pbvh::node_unique_verts(nodes[i]), + object, + translations.as_mutable_span().slice(node_vert_offsets[i]), + positions_orig); }); } @@ -219,7 +219,7 @@ BLI_NOINLINE static void calc_factors_grids(const Depsgraph &depsgraph, const Brush &brush, const Span corner_verts, const OffsetIndices faces, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, const float strength, const bool relax_face_sets, Object &object, @@ -270,11 +270,12 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength, const bool relax_face_sets) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -286,33 +287,33 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph, Array node_offset_data; const OffsetIndices node_vert_offsets = create_node_vert_offsets( - nodes, key, node_offset_data); + key, nodes, node_mask, node_offset_data); Array current_positions(node_vert_offsets.total_size()); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_factors_grids(depsgraph, brush, corner_verts, faces, - *nodes[i], + nodes[i], strength, relax_face_sets, object, tls, current_positions.as_mutable_span().slice(node_vert_offsets[i]), factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_grids( subdiv_ccg, faces, @@ -320,30 +321,28 @@ static void do_relax_face_sets_brush_grids(const Depsgraph &depsgraph, ss.face_sets, ss.vert_to_face_map, ss.vertex_info.boundary, - bke::pbvh::node_grid_indices(*nodes[i]), + bke::pbvh::node_grid_indices(nodes[i]), relax_face_sets, factors.as_span().slice(node_vert_offsets[i]), current_positions.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_grids(sd, - bke::pbvh::node_grid_indices(*nodes[i]), - object, - current_positions.as_mutable_span().slice(node_vert_offsets[i]), - translations.as_mutable_span().slice(node_vert_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_grids(sd, + bke::pbvh::node_grid_indices(nodes[i]), + object, + current_positions.as_mutable_span().slice(node_vert_offsets[i]), + translations.as_mutable_span().slice(node_vert_offsets[i])); }); } static void calc_factors_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, const float strength, const bool relax_face_sets, BMeshLocalData &tls, @@ -382,55 +381,55 @@ static void do_relax_face_sets_brush_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength, const bool relax_face_sets) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Array node_offset_data; - const OffsetIndices node_vert_offsets = create_node_vert_offsets_bmesh(nodes, - node_offset_data); + const OffsetIndices node_vert_offsets = create_node_vert_offsets_bmesh( + nodes, node_mask, node_offset_data); Array current_positions(node_vert_offsets.total_size()); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_factors_bmesh(depsgraph, object, brush, - *nodes[i], + nodes[i], strength, relax_face_sets, tls, current_positions.as_mutable_span().slice(node_vert_offsets[i]), factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_bmesh( - BKE_pbvh_bmesh_node_unique_verts(nodes[i]), + BKE_pbvh_bmesh_node_unique_verts(&nodes[i]), current_positions.as_mutable_span().slice(node_vert_offsets[i]), relax_face_sets, factors.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_bmesh(sd, - BKE_pbvh_bmesh_node_unique_verts(nodes[i]), - object, - translations.as_mutable_span().slice(node_vert_offsets[i]), - current_positions.as_span().slice(node_vert_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_bmesh(sd, + BKE_pbvh_bmesh_node_unique_verts(&nodes[i]), + object, + translations.as_mutable_span().slice(node_vert_offsets[i]), + current_positions.as_span().slice(node_vert_offsets[i])); }); } @@ -443,7 +442,7 @@ BLI_NOINLINE static void calc_topology_relax_factors_faces(const Depsgraph &deps const Brush &brush, const float strength, const Object &object, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, MeshLocalData &tls, const MutableSpan factors) { @@ -479,10 +478,11 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -494,28 +494,29 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); Array node_offset_data; - const OffsetIndices node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data); + const OffsetIndices node_vert_offsets = create_node_vert_offsets( + nodes, node_mask, node_offset_data); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { MeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_topology_relax_factors_faces(depsgraph, brush, strength, object, - *nodes[i], + nodes[i], tls, factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { MeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_faces( positions_eval, vert_normals, @@ -526,23 +527,21 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph, ss.face_sets, hide_poly, false, - bke::pbvh::node_unique_verts(*nodes[i]), + bke::pbvh::node_unique_verts(nodes[i]), factors.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_faces(depsgraph, - sd, - positions_eval, - bke::pbvh::node_unique_verts(*nodes[i]), - object, - translations.as_mutable_span().slice(node_vert_offsets[i]), - positions_orig); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_faces(depsgraph, + sd, + positions_eval, + bke::pbvh::node_unique_verts(nodes[i]), + object, + translations.as_mutable_span().slice(node_vert_offsets[i]), + positions_orig); }); } @@ -550,7 +549,7 @@ BLI_NOINLINE static void calc_topology_relax_factors_grids(const Depsgraph &deps const Brush &brush, const float strength, const Object &object, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, GridLocalData &tls, const MutableSpan positions, const MutableSpan factors) @@ -591,10 +590,11 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -606,31 +606,31 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph, Array node_offset_data; const OffsetIndices node_vert_offsets = create_node_vert_offsets( - nodes, key, node_offset_data); + key, nodes, node_mask, node_offset_data); Array current_positions(node_vert_offsets.total_size()); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_topology_relax_factors_grids( depsgraph, brush, strength, object, - *nodes[i], + nodes[i], tls, current_positions.as_mutable_span().slice(node_vert_offsets[i]), factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { GridLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_grids( subdiv_ccg, faces, @@ -638,30 +638,28 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph, ss.face_sets, ss.vert_to_face_map, ss.vertex_info.boundary, - bke::pbvh::node_grid_indices(*nodes[i]), + bke::pbvh::node_grid_indices(nodes[i]), false, factors.as_span().slice(node_vert_offsets[i]), current_positions.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_grids(sd, - bke::pbvh::node_grid_indices(*nodes[i]), - object, - current_positions.as_mutable_span().slice(node_vert_offsets[i]), - translations.as_mutable_span().slice(node_vert_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_grids(sd, + bke::pbvh::node_grid_indices(nodes[i]), + object, + current_positions.as_mutable_span().slice(node_vert_offsets[i]), + translations.as_mutable_span().slice(node_vert_offsets[i])); }); } static void calc_topology_relax_factors_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, const float strength, BMeshLocalData &tls, MutableSpan positions, @@ -702,54 +700,55 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - const Span nodes, + const IndexMask &node_mask, const float strength) { + const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + Array node_offset_data; - const OffsetIndices node_vert_offsets = create_node_vert_offsets_bmesh(nodes, - node_offset_data); + const OffsetIndices node_vert_offsets = create_node_vert_offsets_bmesh( + nodes, node_mask, node_offset_data); Array current_positions(node_vert_offsets.total_size()); Array translations(node_vert_offsets.total_size()); Array factors(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_topology_relax_factors_bmesh( depsgraph, object, brush, - *nodes[i], + nodes[i], strength, tls, current_positions.as_mutable_span().slice(node_vert_offsets[i]), factors.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BMeshLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth::calc_relaxed_translations_bmesh( - BKE_pbvh_bmesh_node_unique_verts(nodes[i]), + BKE_pbvh_bmesh_node_unique_verts(&nodes[i]), current_positions.as_mutable_span().slice(node_vert_offsets[i]), false, factors.as_span().slice(node_vert_offsets[i]), tls.vert_neighbors, translations.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - apply_positions_bmesh(sd, - BKE_pbvh_bmesh_node_unique_verts(nodes[i]), - object, - translations.as_mutable_span().slice(node_vert_offsets[i]), - current_positions.as_span().slice(node_vert_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + apply_positions_bmesh(sd, + BKE_pbvh_bmesh_node_unique_verts(&nodes[i]), + object, + translations.as_mutable_span().slice(node_vert_offsets[i]), + current_positions.as_span().slice(node_vert_offsets[i])); }); } /** \} */ @@ -759,7 +758,7 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph, void do_relax_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -776,15 +775,15 @@ void do_relax_face_sets_brush(const Depsgraph &depsgraph, switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: do_relax_face_sets_brush_mesh( - depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets); + depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets); break; case bke::pbvh::Type::Grids: do_relax_face_sets_brush_grids( - depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets); + depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets); break; case bke::pbvh::Type::BMesh: do_relax_face_sets_brush_bmesh( - depsgraph, sd, brush, object, nodes, strength * strength, relax_face_sets); + depsgraph, sd, brush, object, node_mask, strength * strength, relax_face_sets); break; } } @@ -793,7 +792,7 @@ void do_relax_face_sets_brush(const Depsgraph &depsgraph, void do_topology_relax_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); const SculptSession &ss = *object.sculpt; @@ -809,13 +808,13 @@ void do_topology_relax_brush(const Depsgraph &depsgraph, for (int i = 0; i < 4; i++) { switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: - do_topology_relax_brush_mesh(depsgraph, sd, brush, object, nodes, strength); + do_topology_relax_brush_mesh(depsgraph, sd, brush, object, node_mask, strength); break; case bke::pbvh::Type::Grids: - do_topology_relax_brush_grids(depsgraph, sd, brush, object, nodes, strength); + do_topology_relax_brush_grids(depsgraph, sd, brush, object, node_mask, strength); break; case bke::pbvh::Type::BMesh: - do_topology_relax_brush_bmesh(depsgraph, sd, brush, object, nodes, strength); + do_topology_relax_brush_bmesh(depsgraph, sd, brush, object, node_mask, strength); break; } } diff --git a/source/blender/editors/sculpt_paint/brushes/rotate.cc b/source/blender/editors/sculpt_paint/brushes/rotate.cc index be04d8e6f99..dea8394438d 100644 --- a/source/blender/editors/sculpt_paint/brushes/rotate.cc +++ b/source/blender/editors/sculpt_paint/brushes/rotate.cc @@ -58,7 +58,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const float angle, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -105,7 +105,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float angle, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -154,7 +154,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float angle, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -201,7 +201,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_rotate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -215,32 +215,35 @@ void do_rotate_brush(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces( - depsgraph, sd, brush, angle, positions_eval, *nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + depsgraph, sd, brush, angle, positions_eval, nodes[i], object, tls, positions_orig); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, angle, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, angle, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, angle, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, angle, nodes[i], tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/scrape.cc b/source/blender/editors/sculpt_paint/brushes/scrape.cc index 5bf35aba811..78ac2895379 100644 --- a/source/blender/editors/sculpt_paint/brushes/scrape.cc +++ b/source/blender/editors/sculpt_paint/brushes/scrape.cc @@ -44,7 +44,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float strength, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -94,7 +94,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -143,7 +143,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, const float4 &plane, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -191,14 +191,14 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); float3 area_no; float3 area_co; - calc_brush_plane(depsgraph, brush, object, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co); SCULPT_tilt_apply_to_normal(area_no, ss.cache, brush.tilt_strength_factor); const float offset = SCULPT_brush_plane_offset_get(sd, ss); @@ -215,9 +215,10 @@ void do_scrape_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -225,31 +226,35 @@ void do_scrape_brush(const Depsgraph &depsgraph, ss.cache->bstrength, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/smooth.cc b/source/blender/editors/sculpt_paint/brushes/smooth.cc index 0a6ef98f3cb..5b2e7447ef6 100644 --- a/source/blender/editors/sculpt_paint/brushes/smooth.cc +++ b/source/blender/editors/sculpt_paint/brushes/smooth.cc @@ -59,7 +59,7 @@ BLI_NOINLINE static void apply_positions_faces(const Depsgraph &depsgraph, const Brush &brush, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, const float strength, Object &object, LocalData &tls, @@ -106,10 +106,11 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, Object &object, - Span nodes, + const IndexMask &node_mask, const float brush_strength) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -121,7 +122,8 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); Array node_offset_data; - const OffsetIndices node_vert_offsets = create_node_vert_offsets(nodes, node_offset_data); + const OffsetIndices node_vert_offsets = create_node_vert_offsets( + nodes, node_mask, node_offset_data); Array new_positions(node_vert_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; @@ -130,10 +132,10 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph, * are updated in parallel. Without this there would be non-threadsafe access to changing * positions in other bke::pbvh::Tree nodes. */ for (const float strength : iteration_strengths(brush_strength)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.vert_neighbors.resize(verts.size()); calc_vert_neighbors_interior(faces, corner_verts, @@ -147,24 +149,24 @@ BLI_NOINLINE static void do_smooth_brush_mesh(const Depsgraph &depsgraph, verts, tls.vert_neighbors, new_positions.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_positions_faces(depsgraph, sd, brush, positions_eval, vert_normals, - *nodes[i], + nodes[i], strength, object, tls, new_positions.as_span().slice(node_vert_offsets[i]), positions_orig); - } + }); }); } } @@ -177,7 +179,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -227,7 +229,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -275,7 +277,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const float brush_strength) { SculptSession &ss = *object.sculpt; @@ -285,7 +287,7 @@ void do_smooth_brush(const Depsgraph &depsgraph, switch (object.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: - do_smooth_brush_mesh(depsgraph, sd, brush, object, nodes, brush_strength); + do_smooth_brush_mesh(depsgraph, sd, brush, object, node_mask, brush_strength); break; case bke::pbvh::Type::Grids: { const Mesh &base_mesh = *static_cast(object.data); @@ -294,9 +296,10 @@ void do_smooth_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; for (const float strength : iteration_strengths(brush_strength)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_grids(depsgraph, sd, faces, @@ -305,9 +308,9 @@ void do_smooth_brush(const Depsgraph &depsgraph, object, brush, strength, - *nodes[i], + nodes[i], tls); - } + }); }); } break; @@ -317,11 +320,12 @@ void do_smooth_brush(const Depsgraph &depsgraph, BM_mesh_elem_table_ensure(ss.bm, BM_VERT); threading::EnumerableThreadSpecific all_tls; for (const float strength : iteration_strengths(brush_strength)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, strength, nodes[i], tls); + }); }); } break; diff --git a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc index 08430192a1c..e3bf8e3e6dd 100644 --- a/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc +++ b/source/blender/editors/sculpt_paint/brushes/smooth_mask.cc @@ -70,7 +70,7 @@ static void apply_masks_faces(const Depsgraph &depsgraph, const Brush &brush, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, const float strength, Object &object, LocalData &tls, @@ -119,10 +119,11 @@ static void apply_masks_faces(const Depsgraph &depsgraph, static void do_smooth_brush_mesh(const Depsgraph &depsgraph, const Brush &brush, Object &object, - Span nodes, + const IndexMask &node_mask, const float brush_strength) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -133,7 +134,8 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph, const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); Array node_vert_offset_data; - OffsetIndices node_vert_offsets = create_node_vert_offsets(nodes, node_vert_offset_data); + OffsetIndices node_vert_offsets = create_node_vert_offsets( + nodes, node_mask, node_vert_offset_data); Array new_masks(node_vert_offsets.total_size()); bke::MutableAttributeAccessor write_attributes = mesh.attributes_for_write(); @@ -145,34 +147,34 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph, for (const float strength : iteration_strengths(brush_strength)) { /* Calculate new masks into a separate array to avoid non-threadsafe access of values from * neighboring nodes. */ - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_smooth_masks_faces(faces, corner_verts, ss.vert_to_face_map, hide_poly, - bke::pbvh::node_unique_verts(*nodes[i]), + bke::pbvh::node_unique_verts(nodes[i]), mask.span.as_span(), tls, new_masks.as_mutable_span().slice(node_vert_offsets[i])); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_masks_faces(depsgraph, brush, positions_eval, vert_normals, - *nodes[i], + nodes[i], strength, object, tls, new_masks.as_span().slice(node_vert_offsets[i]), mask.span); - } + }); }); } mask.finish(); @@ -182,7 +184,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -235,7 +237,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const int mask_offset, const Brush &brush, const float strength, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -287,7 +289,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_smooth_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes, + const IndexMask &node_mask, float brush_strength) { SculptSession &ss = *object.sculpt; @@ -295,17 +297,17 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph, boundary::ensure_boundary_info(object); switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { - do_smooth_brush_mesh(depsgraph, brush, object, nodes, brush_strength); + do_smooth_brush_mesh(depsgraph, brush, object, node_mask, brush_strength); break; } case bke::pbvh::Type::Grids: { threading::EnumerableThreadSpecific all_tls; for (const float strength : iteration_strengths(brush_strength)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, object, brush, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, object, brush, strength, nodes[i], tls); }); }); } break; @@ -317,11 +319,12 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph, const int mask_offset = CustomData_get_offset_named( &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); for (const float strength : iteration_strengths(brush_strength)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, object, mask_offset, brush, strength, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, object, mask_offset, brush, strength, nodes[i], tls); + }); }); } break; diff --git a/source/blender/editors/sculpt_paint/brushes/snake_hook.cc b/source/blender/editors/sculpt_paint/brushes/snake_hook.cc index be5e28dc0e5..becf007760e 100644 --- a/source/blender/editors/sculpt_paint/brushes/snake_hook.cc +++ b/source/blender/editors/sculpt_paint/brushes/snake_hook.cc @@ -163,7 +163,7 @@ static void calc_faces(const Depsgraph &depsgraph, const float3 &grab_delta, const Span positions_eval, const Span vert_normals, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, LocalData &tls, const MutableSpan positions_orig) { @@ -225,7 +225,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Brush &brush, SculptProjectVector *spvc, const float3 &grab_delta, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -289,7 +289,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Brush &brush, SculptProjectVector *spvc, const float3 &grab_delta, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -349,7 +349,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_snake_hook_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -379,9 +379,10 @@ void do_snake_hook_brush(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, object, @@ -390,30 +391,34 @@ void do_snake_hook_brush(const Depsgraph &depsgraph, grab_delta, positions_eval, vert_normals, - *nodes[i], + nodes[i], tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, &spvc, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_grids(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, &spvc, grab_delta, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_bmesh(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls); + }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc b/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc index c86cc6fa92a..1c953495a1c 100644 --- a/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc +++ b/source/blender/editors/sculpt_paint/brushes/surface_smooth.cc @@ -48,7 +48,7 @@ BLI_NOINLINE static void clamp_factors(const MutableSpan factors) BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, - const Span nodes, + const IndexMask &node_mask, Object &object, const MutableSpan all_laplacian_disp) { @@ -56,6 +56,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph const StrokeCache &cache = *ss.cache; const float alpha = brush.surface_smooth_shape_preservation; const float beta = brush.surface_smooth_current_vertex; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); @@ -68,16 +69,16 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph MutableSpan positions_orig = mesh.vert_positions_for_write(); Array node_offset_data; - const OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_offset_data); + const OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_mask, node_offset_data); Array all_factors(node_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); - const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[i]); + const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[pos]); fill_factor_from_hide_and_mask(mesh, verts, factors); filter_region_clip_factors(ss, positions_eval, verts, factors); if (brush.flag & BRUSH_FRONTFACE) { @@ -93,23 +94,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph calc_brush_strength_factors(cache, brush, distances, factors); auto_mask::calc_vert_factors( - depsgraph, object, cache.automasking.get(), *nodes[i], verts, factors); + depsgraph, object, cache.automasking.get(), nodes[i], verts, factors); calc_brush_texture_factors(ss, brush, positions_eval, verts, factors); scale_factors(factors, cache.bstrength); clamp_factors(factors); - } + }); }); for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const MutableSpan positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); tls.vert_neighbors.resize(verts.size()); calc_vert_neighbors( @@ -135,14 +136,14 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); const MutableSpan laplacian_disp = gather_data_mesh( all_laplacian_disp.as_span(), verts, tls.laplacian_disp); @@ -164,7 +165,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_mesh(const Depsgraph &depsgraph write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - } + }); }); } } @@ -173,7 +174,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, - const Span nodes, + const IndexMask &node_mask, Object &object, const MutableSpan all_laplacian_disp) { @@ -181,22 +182,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( const StrokeCache &cache = *ss.cache; const float alpha = brush.surface_smooth_shape_preservation; const float beta = brush.surface_smooth_current_vertex; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Array node_offset_data; const OffsetIndices node_offsets = create_node_vert_offsets( - nodes, BKE_subdiv_ccg_key_top_level(subdiv_ccg), node_offset_data); + BKE_subdiv_ccg_key_top_level(subdiv_ccg), nodes, node_mask, node_offset_data); Array all_factors(node_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[i]); + const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[pos]); fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); filter_region_clip_factors(ss, positions, factors); if (brush.flag & BRUSH_FRONTFACE) { @@ -211,23 +213,23 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( calc_brush_strength_factors(cache, brush, distances, factors); auto_mask::calc_grids_factors( - depsgraph, object, cache.automasking.get(), *nodes[i], grids, factors); + depsgraph, object, cache.automasking.get(), nodes[i], grids, factors); calc_brush_texture_factors(ss, brush, positions, factors); scale_factors(factors, cache.bstrength); clamp_factors(factors); - } + }); }); for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); tls.average_positions.resize(positions.size()); const MutableSpan average_positions = tls.average_positions; @@ -249,15 +251,15 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, grids, subdiv_ccg); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); const MutableSpan laplacian_disp = gather_data_grids( subdiv_ccg, all_laplacian_disp.as_span(), grids, tls.laplacian_disp); @@ -275,7 +277,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_grids( clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, grids, subdiv_ccg); - } + }); }); } } @@ -284,7 +286,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, - const Span nodes, + const IndexMask &node_mask, Object &object, const MutableSpan all_laplacian_disp) { @@ -292,19 +294,21 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( const StrokeCache &cache = *ss.cache; const float alpha = brush.surface_smooth_shape_preservation; const float beta = brush.surface_smooth_current_vertex; + MutableSpan nodes = ss.pbvh->nodes(); Array node_offset_data; - const OffsetIndices node_offsets = create_node_vert_offsets_bmesh(nodes, node_offset_data); + const OffsetIndices node_offsets = create_node_vert_offsets_bmesh( + nodes, node_mask, node_offset_data); Array all_factors(node_offsets.total_size()); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); - const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[i]); + const MutableSpan factors = all_factors.as_mutable_span().slice(node_offsets[pos]); fill_factor_from_hide_and_mask(*ss.bm, verts, factors); filter_region_clip_factors(ss, positions, factors); if (brush.flag & BRUSH_FRONTFACE) { @@ -319,25 +323,25 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( calc_brush_strength_factors(cache, brush, distances, factors); auto_mask::calc_vert_factors( - depsgraph, object, cache.automasking.get(), *nodes[i], verts, factors); + depsgraph, object, cache.automasking.get(), nodes[i], verts, factors); calc_brush_texture_factors(ss, brush, positions, factors); scale_factors(factors, cache.bstrength); clamp_factors(factors); - } + }); }); for ([[maybe_unused]] const int iteration : IndexRange(brush.surface_smooth_iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); Array orig_normals(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); tls.average_positions.resize(positions.size()); const MutableSpan average_positions = tls.average_positions; @@ -355,15 +359,15 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, verts); - } + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i, const int pos) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); - const Span factors = all_factors.as_span().slice(node_offsets[i]); + const Span factors = all_factors.as_span().slice(node_offsets[pos]); const MutableSpan laplacian_disp = gather_data_vert_bmesh( all_laplacian_disp.as_span(), verts, tls.laplacian_disp); @@ -380,7 +384,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, verts); - } + }); }); } } @@ -390,7 +394,7 @@ BLI_NOINLINE static void do_surface_smooth_brush_bmesh( void do_surface_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -398,17 +402,17 @@ void do_surface_smooth_brush(const Depsgraph &depsgraph, switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: do_surface_smooth_brush_mesh( - depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp); + depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp); break; case bke::pbvh::Type::Grids: { do_surface_smooth_brush_grids( - depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp); + depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp); break; } case bke::pbvh::Type::BMesh: { BM_mesh_elem_index_ensure(ss.bm, BM_VERT); do_surface_smooth_brush_bmesh( - depsgraph, sd, brush, nodes, object, ss.cache->surface_smooth_laplacian_disp); + depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp); break; } } diff --git a/source/blender/editors/sculpt_paint/brushes/thumb.cc b/source/blender/editors/sculpt_paint/brushes/thumb.cc index 3bb82f4767c..b146fedd427 100644 --- a/source/blender/editors/sculpt_paint/brushes/thumb.cc +++ b/source/blender/editors/sculpt_paint/brushes/thumb.cc @@ -40,7 +40,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Brush &brush, const float3 &offset, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -85,7 +85,7 @@ static void calc_grids(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -131,7 +131,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float3 &offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -176,7 +176,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -191,39 +191,35 @@ void do_thumb_brush(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_faces(depsgraph, - sd, - brush, - offset, - positions_eval, - *nodes[i], - object, - tls, - positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_faces( + depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, offset, nodes[i], tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/topology_slide.cc b/source/blender/editors/sculpt_paint/brushes/topology_slide.cc index 49037877e8a..62e3daa7c66 100644 --- a/source/blender/editors/sculpt_paint/brushes/topology_slide.cc +++ b/source/blender/editors/sculpt_paint/brushes/topology_slide.cc @@ -160,7 +160,7 @@ static void calc_faces(const Depsgraph &depsgraph, const Span corner_verts, const GroupedSpan vert_to_face_map, const Span hide_poly, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -212,7 +212,7 @@ static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -259,7 +259,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -308,7 +308,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, void do_topology_slide_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes) + const IndexMask &node_mask) { const SculptSession &ss = *object.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -327,9 +327,10 @@ void do_topology_slide_brush(const Depsgraph &depsgraph, const Span corner_verts = mesh.corner_verts(); const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_faces(depsgraph, sd, brush, @@ -338,31 +339,33 @@ void do_topology_slide_brush(const Depsgraph &depsgraph, corner_verts, ss.vert_to_face_map, hide_poly, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, object, brush, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, object, brush, nodes[i], tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, object, brush, *nodes[i], tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, object, brush, nodes[i], tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/brushes/types.hh b/source/blender/editors/sculpt_paint/brushes/types.hh index 908d5c26015..5052634512c 100644 --- a/source/blender/editors/sculpt_paint/brushes/types.hh +++ b/source/blender/editors/sculpt_paint/brushes/types.hh @@ -4,6 +4,7 @@ #pragma once +#include "BLI_index_mask_fwd.hh" #include "BLI_span.hh" struct Depsgraph; @@ -19,162 +20,162 @@ namespace blender::ed::sculpt_paint { void do_clay_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_clay_strips_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_clay_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_crease_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_blob_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes, + const IndexMask &node_mask, float strength); void do_displacement_eraser_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_displacement_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_draw_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); /** A simple normal-direction displacement. */ void do_draw_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); /** A simple normal-direction displacement based on image texture RGB/XYZ values. */ void do_draw_vector_displacement_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_draw_sharp_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_elastic_deform_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_enhance_details_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_fill_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_flatten_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_gravity_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_inflate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); void do_layer_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); /** A brush that modifies mask values instead of position. */ void do_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_multiplane_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_pinch_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_nudge_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_relax_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_rotate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); /** Smooth positions with neighboring vertices. */ void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes, + const IndexMask &node_mask, float brush_strength); /** Smooth mask values with neighboring vertices. */ void do_smooth_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes, + const IndexMask &node_mask, float brush_strength); void do_snake_hook_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_surface_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_topology_slide_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); void do_topology_relax_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); namespace boundary { void do_boundary_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); } namespace cloth { void do_cloth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - Span nodes); + const IndexMask &node_mask); } } // namespace blender::ed::sculpt_paint diff --git a/source/blender/editors/sculpt_paint/mesh_brush_common.hh b/source/blender/editors/sculpt_paint/mesh_brush_common.hh index 633896d6c67..0e97e0c7b1d 100644 --- a/source/blender/editors/sculpt_paint/mesh_brush_common.hh +++ b/source/blender/editors/sculpt_paint/mesh_brush_common.hh @@ -304,13 +304,13 @@ namespace auto_mask { void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Span verts, MutableSpan factors); inline void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache *cache, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Span verts, MutableSpan factors) { @@ -322,13 +322,13 @@ inline void calc_vert_factors(const Depsgraph &depsgraph, void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Span grids, MutableSpan factors); inline void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache *cache, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Span grids, MutableSpan factors) { @@ -340,13 +340,13 @@ inline void calc_grids_factors(const Depsgraph &depsgraph, void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::BMeshNode &node, const Set &verts, MutableSpan factors); inline void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache *cache, - const bke::pbvh::Node &node, + const bke::pbvh::BMeshNode &node, const Set &verts, MutableSpan factors) { @@ -364,7 +364,7 @@ void calc_face_factors(const Depsgraph &depsgraph, OffsetIndices faces, Span corner_verts, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Span face_indices, MutableSpan factors); @@ -447,11 +447,15 @@ void write_translations(const Depsgraph &depsgraph, * Creates OffsetIndices based on each node's unique vertex count, allowing for easy slicing of a * new array. */ -OffsetIndices create_node_vert_offsets(Span nodes, Array &node_data); -OffsetIndices create_node_vert_offsets(Span nodes, - const CCGKey &key, +OffsetIndices create_node_vert_offsets(const Span nodes, + const IndexMask &nodes_mask, Array &node_data); -OffsetIndices create_node_vert_offsets_bmesh(Span nodes, +OffsetIndices create_node_vert_offsets(const CCGKey &key, + const Span nodes, + const IndexMask &nodes_mask, + Array &node_data); +OffsetIndices create_node_vert_offsets_bmesh(const Span nodes, + const IndexMask &nodes_mask, Array &node_data); /** diff --git a/source/blender/editors/sculpt_paint/paint_hide.cc b/source/blender/editors/sculpt_paint/paint_hide.cc index c1b5b1a4d7c..771f168cdfd 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.cc +++ b/source/blender/editors/sculpt_paint/paint_hide.cc @@ -122,57 +122,55 @@ void tag_update_visibility(const bContext &C) } } -void mesh_show_all(const Depsgraph &depsgraph, Object &object, const Span nodes) +void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); if (const VArray attribute = *attributes.lookup(".hide_vert", bke::AttrDomain::Point)) { const VArraySpan hide_vert(attribute); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = bke::pbvh::node_unique_verts(*node); - if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) { - undo::push_node(depsgraph, object, node, undo::Type::HideVert); - BKE_pbvh_node_mark_rebuild_draw(*node); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); + BKE_pbvh_node_mark_rebuild_draw(nodes[i]); } }); } - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_fully_hidden_set(*node, false); - } + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); + attributes.remove(".hide_vert"); bke::mesh_hide_vert_flush(mesh); } -void grids_show_all(Depsgraph &depsgraph, Object &object, const Span nodes) +void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; bool any_changed = false; if (!grid_hidden.is_empty()) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span grids = bke::pbvh::node_grid_indices(*node); - if (std::any_of(grids.begin(), grids.end(), [&](const int i) { - return bits::any_bit_set(grid_hidden[i]); - })) - { - any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::HideVert); - BKE_pbvh_node_mark_rebuild_draw(*node); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); + if (std::any_of(grids.begin(), grids.end(), [&](const int i) { + return bits::any_bit_set(grid_hidden[i]); + })) + { + any_changed = true; + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); + BKE_pbvh_node_mark_rebuild_draw(nodes[i]); } }); } if (!any_changed) { return; } - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_fully_hidden_set(*node, false); - } + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); }); + BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg); BKE_pbvh_sync_visibility_from_verts(object); multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED); @@ -211,7 +209,8 @@ static void calc_face_hide(const Span node_faces, /* Updates a node's face's visibility based on the updated vertex visibility. */ static void flush_face_changes_node(Mesh &mesh, - const Span nodes, + MutableSpan nodes, + const IndexMask &node_mask, const Span hide_vert) { bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); @@ -228,11 +227,11 @@ static void flush_face_changes_node(Mesh &mesh, Vector new_hide; }; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TLS &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { + node_mask.slice(range).foreach_index([&](const int i) { const Span node_faces = bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), tls.face_indices); + tri_faces, nodes[i], tls.face_indices); tls.new_hide.resize(node_faces.size()); gather_data_mesh(hide_poly.span.as_span(), node_faces, tls.new_hide.as_mutable_span()); @@ -240,13 +239,13 @@ static void flush_face_changes_node(Mesh &mesh, calc_face_hide(node_faces, faces, corner_verts, hide_vert, tls.new_hide.as_mutable_span()); if (array_utils::indexed_data_equal(hide_poly.span, node_faces, tls.new_hide)) { - continue; + return; } scatter_data_mesh(tls.new_hide.as_span(), node_faces, hide_poly.span); - BKE_pbvh_node_mark_update_visibility(*node); - bke::pbvh::node_update_visibility_mesh(hide_vert, static_cast(*node)); - } + BKE_pbvh_node_mark_update_visibility(nodes[i]); + bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]); + }); }); hide_poly.finish(); } @@ -276,9 +275,12 @@ static void flush_edge_changes(Mesh &mesh, const Span hide_vert) static void vert_hide_update(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const FunctionRef, MutableSpan)> calc_hide) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); bke::SpanAttributeWriter hide_vert = attributes.lookup_or_add_for_write_span( @@ -286,22 +288,22 @@ static void vert_hide_update(const Depsgraph &depsgraph, bool any_changed = false; threading::EnumerableThreadSpecific> all_new_hide; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &new_hide = all_new_hide.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = bke::pbvh::node_unique_verts(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); new_hide.resize(verts.size()); gather_data_mesh(hide_vert.span.as_span(), verts, new_hide.as_mutable_span()); calc_hide(verts, new_hide); if (array_utils::indexed_data_equal(hide_vert.span, verts, new_hide)) { - continue; + return; } any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::HideVert); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); scatter_data_mesh(new_hide.as_span(), verts, hide_vert.span); - } + }); }); hide_vert.finish(); @@ -309,23 +311,26 @@ static void vert_hide_update(const Depsgraph &depsgraph, /* We handle flushing ourselves at the node level instead of delegating to * bke::mesh_hide_vert_flush because we need to tag node visibility changes as well in cases * where the vertices hidden are on a node boundary.*/ - flush_face_changes_node(mesh, nodes, hide_vert.span); + flush_face_changes_node(mesh, nodes, node_mask, hide_vert.span); flush_edge_changes(mesh, hide_vert.span); } } static void grid_hide_update(Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const FunctionRef calc_hide) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg); bool any_changed = false; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span grids = bke::pbvh::node_grid_indices(*node); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); BitGroupVector<> new_hide(grids.size(), grid_hidden.group_size()); for (const int i : grids.index_range()) { new_hide[i].copy_from(grid_hidden[grids[i]].as_span()); @@ -339,20 +344,19 @@ static void grid_hide_update(Depsgraph &depsgraph, return bits::spans_equal(grid_hidden[grids[i]], new_hide[i]); })) { - continue; + return; } any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::HideVert); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); for (const int i : grids.index_range()) { grid_hidden[grids[i]].copy_from(new_hide[i].as_span()); } - BKE_pbvh_node_mark_update_visibility(*node); - bke::pbvh::node_update_visibility_grids(grid_hidden, - static_cast(*node)); - } + BKE_pbvh_node_mark_update_visibility(nodes[i]); + bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]); + }); }); if (any_changed) { @@ -398,30 +402,39 @@ static void partialvis_update_bmesh_faces(const Set &faces) static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph, Object &ob, - const Span nodes, + const IndexMask &node_mask, const VisAction action, const FunctionRef vert_test_fn) { - for (bke::pbvh::Node *node : nodes) { + SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + + node_mask.foreach_index([&](const int i) { bool any_changed = false; bool any_visible = false; - undo::push_node(depsgraph, ob, node, undo::Type::HideVert); + undo::push_node(depsgraph, ob, &nodes[i], undo::Type::HideVert); - partialvis_update_bmesh_verts( - BKE_pbvh_bmesh_node_unique_verts(node), action, vert_test_fn, &any_changed, &any_visible); + partialvis_update_bmesh_verts(BKE_pbvh_bmesh_node_unique_verts(&nodes[i]), + action, + vert_test_fn, + &any_changed, + &any_visible); - partialvis_update_bmesh_verts( - BKE_pbvh_bmesh_node_other_verts(node), action, vert_test_fn, &any_changed, &any_visible); + partialvis_update_bmesh_verts(BKE_pbvh_bmesh_node_other_verts(&nodes[i]), + action, + vert_test_fn, + &any_changed, + &any_visible); /* Finally loop over node faces and tag the ones that are fully hidden. */ - partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(node)); + partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(&nodes[i])); if (any_changed) { - BKE_pbvh_node_mark_rebuild_draw(*node); - BKE_pbvh_node_fully_hidden_set(*node, !any_visible); + BKE_pbvh_node_mark_rebuild_draw(nodes[i]); + BKE_pbvh_node_fully_hidden_set(nodes[i], !any_visible); } - } + }); } /** \} */ @@ -434,7 +447,7 @@ static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph, static void partialvis_all_update_mesh(const Depsgraph &depsgraph, Object &object, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); @@ -446,12 +459,12 @@ static void partialvis_all_update_mesh(const Depsgraph &depsgraph, switch (action) { case VisAction::Hide: vert_hide_update( - depsgraph, object, nodes, [&](const Span /*verts*/, MutableSpan hide) { + depsgraph, object, node_mask, [&](const Span /*verts*/, MutableSpan hide) { hide.fill(true); }); break; case VisAction::Show: - mesh_show_all(depsgraph, object, nodes); + mesh_show_all(depsgraph, object, node_mask); break; } } @@ -459,17 +472,17 @@ static void partialvis_all_update_mesh(const Depsgraph &depsgraph, static void partialvis_all_update_grids(Depsgraph &depsgraph, Object &object, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { switch (action) { case VisAction::Hide: grid_hide_update(depsgraph, object, - nodes, + node_mask, [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); }); break; case VisAction::Show: - grids_show_all(depsgraph, object, nodes); + grids_show_all(depsgraph, object, node_mask); break; } } @@ -477,10 +490,10 @@ static void partialvis_all_update_grids(Depsgraph &depsgraph, static void partialvis_all_update_bmesh(const Depsgraph &depsgraph, Object &ob, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { partialvis_update_bmesh_nodes( - depsgraph, ob, nodes, action, [](const BMVert * /*vert*/) { return true; }); + depsgraph, ob, node_mask, action, [](const BMVert * /*vert*/) { return true; }); } static int hide_show_all_exec(bContext *C, wmOperator *op) @@ -503,17 +516,18 @@ static int hide_show_all_exec(bContext *C, wmOperator *op) break; } - Vector nodes = bke::pbvh::all_leaf_nodes(*pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory); switch (pbvh->type()) { case bke::pbvh::Type::Mesh: - partialvis_all_update_mesh(*depsgraph, ob, action, nodes); + partialvis_all_update_mesh(*depsgraph, ob, action, node_mask); break; case bke::pbvh::Type::Grids: - partialvis_all_update_grids(*depsgraph, ob, action, nodes); + partialvis_all_update_grids(*depsgraph, ob, action, node_mask); break; case bke::pbvh::Type::BMesh: - partialvis_all_update_bmesh(*depsgraph, ob, action, nodes); + partialvis_all_update_bmesh(*depsgraph, ob, action, node_mask); break; } @@ -529,7 +543,7 @@ static int hide_show_all_exec(bContext *C, wmOperator *op) static void partialvis_masked_update_mesh(const Depsgraph &depsgraph, Object &object, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); @@ -541,23 +555,24 @@ static void partialvis_masked_update_mesh(const Depsgraph &depsgraph, const bool value = action_to_hide(action); const VArraySpan mask = *attributes.lookup(".sculpt_mask", bke::AttrDomain::Point); if (action == VisAction::Show && mask.is_empty()) { - mesh_show_all(depsgraph, object, nodes); + mesh_show_all(depsgraph, object, node_mask); } else if (!mask.is_empty()) { - vert_hide_update(depsgraph, object, nodes, [&](const Span verts, MutableSpan hide) { - for (const int i : verts.index_range()) { - if (mask[verts[i]] > 0.5f) { - hide[i] = value; - } - } - }); + vert_hide_update( + depsgraph, object, node_mask, [&](const Span verts, MutableSpan hide) { + for (const int i : verts.index_range()) { + if (mask[verts[i]] > 0.5f) { + hide[i] = value; + } + } + }); } } static void partialvis_masked_update_grids(Depsgraph &depsgraph, Object &object, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; @@ -567,12 +582,12 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph, if (!key.has_mask) { grid_hide_update(depsgraph, object, - nodes, + node_mask, [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); }); } else { grid_hide_update( - depsgraph, object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) { + depsgraph, object, node_mask, [&](const int grid_index, MutableBoundedBitSpan hide) { CCGElem *grid = grids[grid_index]; for (const int y : IndexRange(key.grid_size)) { for (const int x : IndexRange(key.grid_size)) { @@ -589,7 +604,7 @@ static void partialvis_masked_update_grids(Depsgraph &depsgraph, static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph, Object &ob, const VisAction action, - const Span nodes) + const IndexMask &node_mask) { BMesh *bm = ob.sculpt->bm; const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); @@ -598,7 +613,7 @@ static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph, return vmask > 0.5f; }; - partialvis_update_bmesh_nodes(depsgraph, ob, nodes, action, mask_test_fn); + partialvis_update_bmesh_nodes(depsgraph, ob, node_mask, action, mask_test_fn); } static int hide_show_masked_exec(bContext *C, wmOperator *op) @@ -621,17 +636,18 @@ static int hide_show_masked_exec(bContext *C, wmOperator *op) break; } - Vector nodes = bke::pbvh::all_leaf_nodes(*pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory); switch (pbvh->type()) { case bke::pbvh::Type::Mesh: - partialvis_masked_update_mesh(*depsgraph, ob, action, nodes); + partialvis_masked_update_mesh(*depsgraph, ob, action, node_mask); break; case bke::pbvh::Type::Grids: - partialvis_masked_update_grids(*depsgraph, ob, action, nodes); + partialvis_masked_update_grids(*depsgraph, ob, action, node_mask); break; case bke::pbvh::Type::BMesh: - partialvis_masked_update_bmesh(*depsgraph, ob, action, nodes); + partialvis_masked_update_bmesh(*depsgraph, ob, action, node_mask); break; } @@ -692,27 +708,29 @@ void PAINT_OT_hide_show_all(wmOperatorType *ot) static void invert_visibility_mesh(const Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + Mesh &mesh = *static_cast(object.data); const Span tri_faces = mesh.corner_tri_faces(); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); bke::SpanAttributeWriter hide_poly = attributes.lookup_or_add_for_write_span( ".hide_poly", bke::AttrDomain::Face); - undo::push_nodes(depsgraph, object, nodes, undo::Type::HideFace); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideFace); threading::EnumerableThreadSpecific> all_index_data; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &faces = all_index_data.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), faces); + node_mask.slice(range).foreach_index([&](const int i) { + bke::pbvh::node_face_indices_calc_mesh(tri_faces, nodes[i], faces); for (const int face : faces) { hide_poly.span[face] = !hide_poly.span[face]; } - BKE_pbvh_node_mark_update_visibility(*node); - } + BKE_pbvh_node_mark_update_visibility(nodes[i]); + }); }); hide_poly.finish(); @@ -722,22 +740,21 @@ static void invert_visibility_mesh(const Depsgraph &depsgraph, static void invert_visibility_grids(Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; - undo::push_nodes(depsgraph, object, nodes, undo::Type::HideVert); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideVert); BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - for (const int i : bke::pbvh::node_grid_indices(*node)) { - bits::invert(grid_hidden[i]); - } - BKE_pbvh_node_mark_update_visibility(*node); - bke::pbvh::node_update_visibility_grids(grid_hidden, - static_cast(*node)); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int i : bke::pbvh::node_grid_indices(nodes[i])) { + bits::invert(grid_hidden[i]); } + BKE_pbvh_node_mark_update_visibility(nodes[i]); + bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]); }); multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED); @@ -746,25 +763,23 @@ static void invert_visibility_grids(Depsgraph &depsgraph, static void invert_visibility_bmesh(const Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { - undo::push_nodes(depsgraph, object, nodes, undo::Type::HideVert); + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::HideVert); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - bool fully_hidden = true; - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { - BM_elem_flag_toggle(vert, BM_ELEM_HIDDEN); - fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN); - } - BKE_pbvh_node_fully_hidden_set(*node, fully_hidden); - BKE_pbvh_node_mark_rebuild_draw(*node); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + bool fully_hidden = true; + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { + BM_elem_flag_toggle(vert, BM_ELEM_HIDDEN); + fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN); } + BKE_pbvh_node_fully_hidden_set(nodes[i], fully_hidden); + BKE_pbvh_node_mark_rebuild_draw(nodes[i]); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(node)); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + partialvis_update_bmesh_faces(BKE_pbvh_bmesh_node_faces(&nodes[i])); }); } @@ -776,17 +791,18 @@ static int visibility_invert_exec(bContext *C, wmOperator *op) bke::pbvh::Tree *pbvh = BKE_sculpt_object_pbvh_ensure(&depsgraph, &object); BLI_assert(BKE_object_sculpt_pbvh_get(&object) == pbvh); - Vector nodes = bke::pbvh::all_leaf_nodes(*pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*pbvh, memory); undo::push_begin(object, op); switch (pbvh->type()) { case bke::pbvh::Type::Mesh: - invert_visibility_mesh(depsgraph, object, nodes); + invert_visibility_mesh(depsgraph, object, node_mask); break; case bke::pbvh::Type::Grids: - invert_visibility_grids(depsgraph, object, nodes); + invert_visibility_grids(depsgraph, object, node_mask); break; case bke::pbvh::Type::BMesh: - invert_visibility_bmesh(depsgraph, object, nodes); + invert_visibility_bmesh(depsgraph, object, node_mask); break; } @@ -885,35 +901,38 @@ static void propagate_vertex_visibility(Mesh &mesh, static void update_undo_state(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const Span old_hide_vert, const Span new_hide_vert) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - for (const int vert : bke::pbvh::node_unique_verts(*node)) { - if (old_hide_vert[vert] != new_hide_vert[vert]) { - undo::push_node(depsgraph, object, node, undo::Type::HideVert); - break; - } + const SculptSession &ss = *object.sculpt; + const Span nodes = ss.pbvh->nodes(); + + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) { + if (old_hide_vert[vert] != new_hide_vert[vert]) { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert); + break; } } }); } -static void update_node_visibility_from_face_changes(const Span nodes, +static void update_node_visibility_from_face_changes(MutableSpan nodes, + const IndexMask &node_mask, const Span tri_faces, const Span orig_hide_poly, const Span new_hide_poly, const Span hide_vert) { + threading::EnumerableThreadSpecific> all_face_indices; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &face_indices = all_face_indices.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { + node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; const Span indices = bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), face_indices); + tri_faces, nodes[i], face_indices); for (const int face_index : indices) { if (orig_hide_poly[face_index] != new_hide_poly[face_index]) { any_changed = true; @@ -922,17 +941,16 @@ static void update_node_visibility_from_face_changes(const Span(*node)); + BKE_pbvh_node_mark_update_visibility(nodes[i]); + bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]); } - } + }); }); } static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const VisAction action, const int iterations) { @@ -959,14 +977,18 @@ static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph, const Span last_buffer = buffers.write_buffer(iterations - 1); - update_undo_state(depsgraph, object, nodes, hide_vert.span, last_buffer); + update_undo_state(depsgraph, object, node_mask, hide_vert.span, last_buffer); /* We can wait until after all iterations are done to flush edge changes as they are * not used for coarse filtering while iterating.*/ flush_edge_changes(mesh, last_buffer); - update_node_visibility_from_face_changes( - nodes, mesh.corner_tri_faces(), orig_hide_poly, hide_poly, last_buffer); + update_node_visibility_from_face_changes(object.sculpt->pbvh->nodes(), + node_mask, + mesh.corner_tri_faces(), + orig_hide_poly, + hide_poly, + last_buffer); array_utils::copy(last_buffer, hide_vert.span); hide_vert.finish(); } @@ -988,11 +1010,14 @@ struct DualBitBuffer { static void grow_shrink_visibility_grid(Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const VisAction action, const int iterations) { - SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + + SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg); @@ -1009,62 +1034,48 @@ static void grow_shrink_visibility_grid(Depsgraph &depsgraph, BitGroupVector<> &read_buffer = buffers.read_buffer(i); BitGroupVector<> &write_buffer = buffers.write_buffer(i); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int node_index : range) { - bke::pbvh::Node *node = nodes[node_index]; - const Span grids = bke::pbvh::node_grid_indices(*node); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) { + for (const int y : IndexRange(key.grid_size)) { + for (const int x : IndexRange(key.grid_size)) { + const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y); + if (read_buffer[grid][grid_elem_idx] != desired_state) { + continue; + } - for (const int grid_index : grids) { - for (const int y : IndexRange(key.grid_size)) { - for (const int x : IndexRange(key.grid_size)) { - const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y); - if (read_buffer[grid_index][grid_elem_idx] != desired_state) { - continue; - } + SubdivCCGCoord coord{}; + coord.grid_index = grid; + coord.x = x; + coord.y = y; - SubdivCCGCoord coord{}; - coord.grid_index = grid_index; - coord.x = x; - coord.y = y; + SubdivCCGNeighbors neighbors; + BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors); - SubdivCCGNeighbors neighbors; - BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors); + for (const SubdivCCGCoord neighbor : neighbors.coords) { + const int neighbor_grid_elem_idx = CCG_grid_xy_to_index( + key.grid_size, neighbor.x, neighbor.y); - for (const SubdivCCGCoord neighbor : neighbors.coords) { - const int neighbor_grid_elem_idx = CCG_grid_xy_to_index( - key.grid_size, neighbor.x, neighbor.y); - - write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state); - } + write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state); } } } - - node_changed[node_index] = true; } + + node_changed[i] = true; }); } IndexMaskMemory memory; - IndexMask mask = IndexMask::from_bools(node_changed, memory); - mask.foreach_index(GrainSize(1), [&](const int64_t index) { - undo::push_node(depsgraph, object, nodes[index], undo::Type::HideVert); - }); + const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory); + + undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert); BitGroupVector<> &last_buffer = buffers.write_buffer(iterations - 1); grid_hidden = std::move(last_buffer); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int node_index : range) { - if (!node_changed[node_index]) { - continue; - } - bke::pbvh::Node *node = nodes[node_index]; - - BKE_pbvh_node_mark_update_visibility(*node); - bke::pbvh::node_update_visibility_grids(grid_hidden, - static_cast(*node)); - } + changed_nodes.foreach_index(GrainSize(1), [&](const int i) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); + bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]); }); multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED); @@ -1085,14 +1096,14 @@ static Array duplicate_visibility_bmesh(const Object &object) static void grow_shrink_visibility_bmesh(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const VisAction action, const int iterations) { for (const int i : IndexRange(iterations)) { UNUSED_VARS(i); const Array prev_visibility = duplicate_visibility_bmesh(object); - partialvis_update_bmesh_nodes(depsgraph, object, nodes, action, [&](BMVert *vert) { + partialvis_update_bmesh_nodes(depsgraph, object, node_mask, action, [&](BMVert *vert) { Vector neighbors; for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) { if (prev_visibility[BM_elem_index_get(neighbor)] == action_to_hide(action)) { @@ -1114,7 +1125,8 @@ static int visibility_filter_exec(bContext *C, wmOperator *op) const VisAction mode = VisAction(RNA_enum_get(op->ptr, "action")); - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); int num_verts = SCULPT_vertex_count_get(object); @@ -1129,13 +1141,13 @@ static int visibility_filter_exec(bContext *C, wmOperator *op) undo::push_begin(object, op); switch (pbvh.type()) { case bke::pbvh::Type::Mesh: - grow_shrink_visibility_mesh(depsgraph, object, nodes, mode, iterations); + grow_shrink_visibility_mesh(depsgraph, object, node_mask, mode, iterations); break; case bke::pbvh::Type::Grids: - grow_shrink_visibility_grid(depsgraph, object, nodes, mode, iterations); + grow_shrink_visibility_grid(depsgraph, object, node_mask, mode, iterations); break; case bke::pbvh::Type::BMesh: - grow_shrink_visibility_bmesh(depsgraph, object, nodes, mode, iterations); + grow_shrink_visibility_bmesh(depsgraph, object, node_mask, mode, iterations); break; } undo::push_end(object); @@ -1209,7 +1221,7 @@ static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data) Object *object = gesture_data.vc.obact; const Depsgraph &depsgraph = *gesture_data.vc.depsgraph; const VisAction action = operation->action; - const Span nodes = gesture_data.nodes; + const IndexMask &node_mask = gesture_data.node_mask; Mesh *mesh = static_cast(object->data); bke::MutableAttributeAccessor attributes = mesh->attributes_for_write(); @@ -1221,13 +1233,14 @@ static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data) const bool value = action_to_hide(action); const Span positions = bke::pbvh::vert_positions_eval(depsgraph, *object); const Span normals = bke::pbvh::vert_normals_eval(depsgraph, *object); - vert_hide_update(depsgraph, *object, nodes, [&](const Span verts, MutableSpan hide) { - for (const int i : verts.index_range()) { - if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) { - hide[i] = value; - } - } - }); + vert_hide_update( + depsgraph, *object, node_mask, [&](const Span verts, MutableSpan hide) { + for (const int i : verts.index_range()) { + if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) { + hide[i] = value; + } + } + }); } static void partialvis_gesture_update_grids(Depsgraph &depsgraph, @@ -1236,7 +1249,7 @@ static void partialvis_gesture_update_grids(Depsgraph &depsgraph, HideShowOperation *operation = reinterpret_cast(gesture_data.operation); Object *object = gesture_data.vc.obact; const VisAction action = operation->action; - const Span nodes = gesture_data.nodes; + const IndexMask &node_mask = gesture_data.node_mask; SubdivCCG &subdiv_ccg = *object->sculpt->subdiv_ccg; @@ -1244,7 +1257,7 @@ static void partialvis_gesture_update_grids(Depsgraph &depsgraph, const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = subdiv_ccg.grids; grid_hide_update( - depsgraph, *object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) { + depsgraph, *object, node_mask, [&](const int grid_index, MutableBoundedBitSpan hide) { CCGElem *grid = grids[grid_index]; for (const int y : IndexRange(key.grid_size)) { for (const int x : IndexRange(key.grid_size)) { @@ -1268,7 +1281,7 @@ static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data) partialvis_update_bmesh_nodes(*gesture_data.vc.depsgraph, *gesture_data.vc.obact, - gesture_data.nodes, + gesture_data.node_mask, operation->action, selection_test_fn); } diff --git a/source/blender/editors/sculpt_paint/paint_hide.hh b/source/blender/editors/sculpt_paint/paint_hide.hh index 3e09e1fd554..35ed322834f 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.hh +++ b/source/blender/editors/sculpt_paint/paint_hide.hh @@ -8,6 +8,7 @@ #pragma once +#include "BLI_index_mask_fwd.hh" #include "BLI_span.hh" struct bContext; @@ -20,8 +21,8 @@ class Node; namespace blender::ed::sculpt_paint::hide { void sync_all_from_faces(Object &object); -void mesh_show_all(const Depsgraph &depsgraph, Object &object, Span nodes); -void grids_show_all(Depsgraph &depsgraph, Object &object, Span nodes); +void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask); +void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask); void tag_update_visibility(const bContext &C); void PAINT_OT_hide_show_masked(wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/paint_intern.hh b/source/blender/editors/sculpt_paint/paint_intern.hh index f3f54ba52c2..b0f78f251ec 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.hh +++ b/source/blender/editors/sculpt_paint/paint_intern.hh @@ -11,6 +11,7 @@ #include "BLI_array.hh" #include "BLI_compiler_compat.h" #include "BLI_function_ref.hh" +#include "BLI_index_mask_fwd.hh" #include "BLI_math_vector_types.hh" #include "BLI_set.hh" #include "BLI_span.hh" @@ -550,10 +551,11 @@ void init_session_data(const ToolSettings &ts, Object &ob); void init_session( Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob, eObjectMode object_mode); -Vector pbvh_gather_generic(const Depsgraph &depsgraph, - Object &ob, - const VPaint &wp, - const Brush &brush); +IndexMask pbvh_gather_generic(const Depsgraph &depsgraph, + const Object &ob, + const VPaint &wp, + const Brush &brush, + IndexMaskMemory &memory); void mode_enter_generic( Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob, eObjectMode mode_flag); diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index 6cd37b489f8..150ee93b5c6 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -41,6 +41,7 @@ #include "bmesh.hh" +#include "mesh_brush_common.hh" #include "paint_intern.hh" #include "sculpt_gesture.hh" #include "sculpt_hide.hh" @@ -251,9 +252,12 @@ void average_neighbor_mask_bmesh(const int mask_offset, void update_mask_mesh(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, FunctionRef, Span)> update_fn) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); @@ -269,22 +273,20 @@ void update_mask_mesh(const Depsgraph &depsgraph, }; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - threading::isolate_task([&]() { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = hide::node_visible_verts(*node, hide_vert, tls.visible_verts); - tls.mask.resize(verts.size()); - array_utils::gather(mask.span, verts, tls.mask); - update_fn(tls.mask, verts); - if (array_utils::indexed_data_equal(mask.span, verts, tls.mask)) { - continue; - } - undo::push_node(depsgraph, object, node, undo::Type::Mask); - array_utils::scatter(tls.mask, verts, mask.span); - bke::pbvh::node_update_mask_mesh(mask.span, static_cast(*node)); - BKE_pbvh_node_mark_redraw(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = hide::node_visible_verts(nodes[i], hide_vert, tls.visible_verts); + tls.mask.resize(verts.size()); + gather_data_mesh(mask.span.as_span(), verts, tls.mask.as_mutable_span()); + update_fn(tls.mask, verts); + if (array_utils::indexed_data_equal(mask.span, verts, tls.mask)) { + return; } + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + scatter_data_mesh(tls.mask.as_span(), verts, mask.span); + bke::pbvh::node_update_mask_mesh(mask.span, static_cast(nodes[i])); + BKE_pbvh_node_mark_redraw(nodes[i]); }); }); @@ -363,7 +365,7 @@ static const EnumPropertyItem mode_items[] = { {int(FloodFillMode::InverseMeshValue), "INVERT", 0, "Invert", "Invert the mask"}, {0}}; -static Span get_hidden_verts(const bke::pbvh::Node &node, +static Span get_hidden_verts(const bke::pbvh::MeshNode &node, const Span hide_vert, Vector &indices) { @@ -384,8 +386,10 @@ static Span get_hidden_verts(const bke::pbvh::Node &node, static bool try_remove_mask_mesh(const Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); const VArraySpan mask = *attributes.lookup(".sculpt_mask", bke::AttrDomain::Point); @@ -399,21 +403,25 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph, const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); threading::EnumerableThreadSpecific> all_index_data; const bool hidden_masked_verts = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, false, - [&](const IndexRange range, bool init) { - if (init) { - return init; + [&](const IndexRange range, bool value) { + if (value) { + return value; } Vector &index_data = all_index_data.local(); - for (const bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = get_hidden_verts(*node, hide_vert, index_data); - if (std::any_of(verts.begin(), verts.end(), [&](int i) { return mask[i] > 0.0f; })) { - return true; + node_mask.slice(range).foreach_index([&](const int i) { + if (value) { + return; } - } - return false; + const Span verts = get_hidden_verts(nodes[i], hide_vert, index_data); + if (std::any_of(verts.begin(), verts.end(), [&](int i) { return mask[i] > 0.0f; })) { + value = true; + return; + } + }); + return value; }, std::logical_or()); if (hidden_masked_verts) { @@ -421,31 +429,37 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph, } /* Store undo data for nodes with changed mask. */ - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = bke::pbvh::node_unique_verts(*node); - if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) { - continue; - } - undo::push_node(depsgraph, object, node, undo::Type::Mask); - BKE_pbvh_node_mark_redraw(*node); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) { + return; } + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + BKE_pbvh_node_mark_redraw(nodes[i]); }); attributes.remove(".sculpt_mask"); + /* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */ + node_mask.foreach_index([&](const int i) { + BKE_pbvh_node_fully_masked_set(nodes[i], false); + BKE_pbvh_node_fully_unmasked_set(nodes[i], true); + }); return true; } static void fill_mask_mesh(const Depsgraph &depsgraph, Object &object, const float value, - const Span nodes) + const IndexMask &node_mask) { + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); if (value == 0.0f) { - if (try_remove_mask_mesh(depsgraph, object, nodes)) { + if (try_remove_mask_mesh(depsgraph, object, node_mask)) { return; } } @@ -454,20 +468,25 @@ static void fill_mask_mesh(const Depsgraph &depsgraph, ".sculpt_mask", bke::AttrDomain::Point); threading::EnumerableThreadSpecific> all_index_data; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &index_data = all_index_data.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span verts = hide::node_visible_verts(*node, hide_vert, index_data); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = hide::node_visible_verts(nodes[i], hide_vert, index_data); if (std::all_of(verts.begin(), verts.end(), [&](int i) { return mask.span[i] == value; })) { - continue; + return; } - undo::push_node(depsgraph, object, node, undo::Type::Mask); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); mask.span.fill_indices(verts, value); - BKE_pbvh_node_mark_redraw(*node); - } + BKE_pbvh_node_mark_redraw(nodes[i]); + }); }); mask.finish(); + /* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */ + node_mask.foreach_index([&](const int i) { + BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); + BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); + }); } static void fill_mask_grids(Main &bmain, @@ -475,9 +494,12 @@ static void fill_mask_grids(Main &bmain, Depsgraph &depsgraph, Object &object, const float value, - const Span nodes) + const IndexMask &node_mask) { - SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + + SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); if (value == 0.0f && !key.has_mask) { @@ -492,54 +514,60 @@ static void fill_mask_grids(Main &bmain, const Span grids = subdiv_ccg.grids; bool any_changed = false; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span grid_indices = bke::pbvh::node_grid_indices(*node); - if (std::all_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - if (CCG_elem_offset_mask(key, elem, i) != value) { - return false; - } - } - return true; - })) - { - continue; - } - undo::push_node(depsgraph, object, node, undo::Type::Mask); - - if (grid_hidden.is_empty()) { - for (const int grid : grid_indices) { + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span grid_indices = bke::pbvh::node_grid_indices(nodes[i]); + if (std::all_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) { CCGElem *elem = grids[grid]; for (const int i : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, i) = value; + if (CCG_elem_offset_mask(key, elem, i) != value) { + return false; + } } - } - } - else { - for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - bits::foreach_0_index(grid_hidden[grid], - [&](const int i) { CCG_elem_offset_mask(key, elem, i) = value; }); - } - } - BKE_pbvh_node_mark_redraw(*node); - any_changed = true; + return true; + })) + { + return; } + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + + if (grid_hidden.is_empty()) { + for (const int grid : grid_indices) { + CCGElem *elem = grids[grid]; + for (const int i : IndexRange(key.grid_area)) { + CCG_elem_offset_mask(key, elem, i) = value; + } + } + } + else { + for (const int grid : grid_indices) { + CCGElem *elem = grids[grid]; + bits::foreach_0_index(grid_hidden[grid], + [&](const int i) { CCG_elem_offset_mask(key, elem, i) = value; }); + } + } + BKE_pbvh_node_mark_redraw(nodes[i]); + any_changed = true; }); if (any_changed) { multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); } + /* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */ + node_mask.foreach_index([&](const int i) { + BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); + BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); + }); } static void fill_mask_bmesh(const Depsgraph &depsgraph, Object &object, const float value, - const Span nodes) + const IndexMask &node_mask) { - BMesh &bm = *object.sculpt->bm; + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + + BMesh &bm = *ss.bm; const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); if (value == 0.0f && offset == -1) { return; @@ -550,22 +578,25 @@ static void fill_mask_bmesh(const Depsgraph &depsgraph, return; } - undo::push_node(depsgraph, object, nodes.first(), undo::Type::Mask); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - bool redraw = false; - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { - if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { - if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) { - BM_ELEM_CD_SET_FLOAT(vert, offset, value); - redraw = true; - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + bool redraw = false; + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { + if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { + if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) { + BM_ELEM_CD_SET_FLOAT(vert, offset, value); + redraw = true; } } - if (redraw) { - BKE_pbvh_node_mark_redraw(*node); - } } + if (redraw) { + BKE_pbvh_node_mark_redraw(nodes[i]); + } + }); + /* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */ + node_mask.foreach_index([&](const int i) { + BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f); + BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f); }); } @@ -573,65 +604,61 @@ static void fill_mask( Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value) { bke::pbvh::Tree &pbvh = *object.sculpt->pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); switch (pbvh.type()) { case bke::pbvh::Type::Mesh: - fill_mask_mesh(depsgraph, object, value, nodes); + fill_mask_mesh(depsgraph, object, value, node_mask); break; case bke::pbvh::Type::Grids: - fill_mask_grids(bmain, scene, depsgraph, object, value, nodes); + fill_mask_grids(bmain, scene, depsgraph, object, value, node_mask); break; case bke::pbvh::Type::BMesh: - fill_mask_bmesh(depsgraph, object, value, nodes); + fill_mask_bmesh(depsgraph, object, value, node_mask); break; } - /* Avoid calling #BKE_pbvh_node_mark_update_mask by doing that update here. */ - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_fully_masked_set(*node, value == 1.0f); - BKE_pbvh_node_fully_unmasked_set(*node, value == 0.0f); - } } static void invert_mask_grids(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { - SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg; + SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); + + SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; MultiresModifierData &mmd = *BKE_sculpt_multires_active(&scene, &object); BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, &mmd); - undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = subdiv_ccg.grids; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - - const Span grid_indices = bke::pbvh::node_grid_indices(*node); - if (grid_hidden.is_empty()) { - for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span grid_indices = bke::pbvh::node_grid_indices(nodes[i]); + if (grid_hidden.is_empty()) { + for (const int grid : grid_indices) { + CCGElem *elem = grids[grid]; + for (const int i : IndexRange(key.grid_area)) { + CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); } } - else { - for (const int grid : grid_indices) { - CCGElem *elem = grids[grid]; - bits::foreach_0_index(grid_hidden[grid], [&](const int i) { - CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); - }); - } - } - BKE_pbvh_node_mark_update_mask(*node); - bke::pbvh::node_update_mask_grids(key, grids, static_cast(*node)); } + else { + for (const int grid : grid_indices) { + CCGElem *elem = grids[grid]; + bits::foreach_0_index(grid_hidden[grid], [&](const int i) { + CCG_elem_offset_mask(key, elem, i) = 1.0f - CCG_elem_offset_mask(key, elem, i); + }); + } + } + BKE_pbvh_node_mark_update_mask(nodes[i]); + bke::pbvh::node_update_mask_grids(key, grids, nodes[i]); }); multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED); @@ -639,8 +666,9 @@ static void invert_mask_grids(Main &bmain, static void invert_mask_bmesh(const Depsgraph &depsgraph, Object &object, - const Span nodes) + const IndexMask &node_mask) { + MutableSpan nodes = object.sculpt->pbvh->nodes(); BMesh &bm = *object.sculpt->bm; const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); if (offset == -1) { @@ -648,37 +676,36 @@ static void invert_mask_bmesh(const Depsgraph &depsgraph, return; } - undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { - if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { - BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset)); - } + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { + if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { + BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset)); } - BKE_pbvh_node_mark_update_mask(*node); - bke::pbvh::node_update_mask_bmesh(offset, static_cast(*node)); } + BKE_pbvh_node_mark_update_mask(nodes[i]); + bke::pbvh::node_update_mask_bmesh(offset, nodes[i]); }); } static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object) { - Vector nodes = bke::pbvh::search_gather(*object.sculpt->pbvh, {}); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*object.sculpt->pbvh, memory); switch (object.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: write_mask_mesh( - depsgraph, object, nodes, [&](MutableSpan mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan mask, const Span verts) { for (const int vert : verts) { mask[vert] = 1.0f - mask[vert]; } }); break; case bke::pbvh::Type::Grids: - invert_mask_grids(bmain, scene, depsgraph, object, nodes); + invert_mask_grids(bmain, scene, depsgraph, object, node_mask); break; case bke::pbvh::Type::BMesh: - invert_mask_bmesh(depsgraph, object, nodes); + invert_mask_bmesh(depsgraph, object, node_mask); break; } } @@ -779,7 +806,8 @@ static float mask_gesture_get_new_value(const float elem, FloodFillMode mode, fl static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureData &gesture_data) { - const Span nodes = gesture_data.nodes; + SculptSession &ss = *gesture_data.ss; + const IndexMask &node_mask = gesture_data.node_mask; const MaskOperation &op = *reinterpret_cast(gesture_data.operation); Object &object = *gesture_data.vc.obact; const Depsgraph &depsgraph = *gesture_data.vc.depsgraph; @@ -788,7 +816,7 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa const Span positions = bke::pbvh::vert_positions_eval(depsgraph, object); const Span normals = bke::pbvh::vert_normals_eval(depsgraph, object); update_mask_mesh( - depsgraph, object, nodes, [&](MutableSpan node_mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan node_mask, const Span verts) { for (const int i : verts.index_range()) { const int vert = verts[i]; if (gesture::is_affected(gesture_data, positions[vert], normals[vert])) { @@ -799,14 +827,15 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *gesture_data.ss->subdiv_ccg; const Span grids = subdiv_ccg.grids; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; - for (const int grid : bke::pbvh::node_grid_indices(*node)) { + for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) { CCGElem *elem = grids[grid]; BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) { if (gesture::is_affected(gesture_data, @@ -816,36 +845,37 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa float &mask = CCG_elem_offset_mask(key, elem, i); if (!any_changed) { any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::Mask); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); } mask = mask_gesture_get_new_value(mask, op.mode, op.value); } }); - BKE_pbvh_node_mark_update_mask(*node); + BKE_pbvh_node_mark_update_mask(nodes[i]); } - } + }); }); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); BMesh &bm = *gesture_data.ss->bm; const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + node_mask.slice(range).foreach_index([&](const int i) { bool any_changed = false; - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { if (gesture::is_affected(gesture_data, vert->co, vert->no)) { const float old_mask = BM_ELEM_CD_GET_FLOAT(vert, offset); if (!any_changed) { any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::Mask); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); } const float new_mask = mask_gesture_get_new_value(old_mask, op.mode, op.value); BM_ELEM_CD_SET_FLOAT(vert, offset, new_mask); } } - BKE_pbvh_node_mark_update_mask(*node); - } + BKE_pbvh_node_mark_update_mask(nodes[i]); + }); }); break; } diff --git a/source/blender/editors/sculpt_paint/paint_mask.hh b/source/blender/editors/sculpt_paint/paint_mask.hh index b13621e2979..59564768ba5 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.hh +++ b/source/blender/editors/sculpt_paint/paint_mask.hh @@ -10,6 +10,7 @@ #include "BLI_array.hh" #include "BLI_function_ref.hh" +#include "BLI_index_mask_fwd.hh" #include "BLI_set.hh" struct BMesh; @@ -46,7 +47,7 @@ void average_neighbor_mask_bmesh(int mask_offset, /** Write to the mask attribute for each node, storing undo data. */ void write_mask_mesh(const Depsgraph &depsgraph, Object &object, - Span nodes, + const IndexMask &node_mask, FunctionRef, Span)> write_fn); /** @@ -55,7 +56,7 @@ void write_mask_mesh(const Depsgraph &depsgraph, */ void update_mask_mesh(const Depsgraph &depsgraph, Object &object, - Span nodes, + const IndexMask &node_mask, FunctionRef, Span)> update_fn); /** Check whether array data is the same as the stored mask for the referenced geometry. */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc index fdb42a3c27a..fb173c25e2a 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex.cc @@ -297,18 +297,19 @@ void init_session_data(const ToolSettings &ts, Object &ob) } } -Vector pbvh_gather_generic(const Depsgraph &depsgraph, - Object &ob, - const VPaint &wp, - const Brush &brush) +IndexMask pbvh_gather_generic(const Depsgraph &depsgraph, + const Object &ob, + const VPaint &wp, + const Brush &brush, + IndexMaskMemory &memory) { SculptSession &ss = *ob.sculpt; const bool use_normal = vwpaint::use_normal(wp); - Vector nodes; + IndexMask nodes; /* Build a list of all nodes that are potentially within the brush's area of influence */ if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) { - nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { + nodes = bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, ss.cache->location, ss.cache->radius_squared, true); }); @@ -318,7 +319,7 @@ Vector pbvh_gather_generic(const Depsgraph &depsgraph, else { const DistRayAABB_Precalc ray_dist_precalc = dist_squared_ray_to_aabb_v3_precalc( ss.cache->location, ss.cache->view_normal); - nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { + nodes = bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_cylinder(ray_dist_precalc, node, ss.cache->radius_squared, true); }); @@ -1045,7 +1046,8 @@ static void do_vpaint_brush_blur_loops(const bContext *C, VPaintData &vpd, Object &ob, Mesh &mesh, - const Span nodes, + const Span nodes, + const IndexMask &node_mask, GMutableSpan attribute) { SculptSession &ss = *ob.sculpt; @@ -1089,10 +1091,10 @@ static void do_vpaint_brush_blur_loops(const bContext *C, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) { + blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1193,7 +1195,7 @@ static void do_vpaint_brush_blur_loops(const bContext *C, } }); } - }; + }); }); } @@ -1202,7 +1204,8 @@ static void do_vpaint_brush_blur_verts(const bContext *C, VPaintData &vpd, Object &ob, Mesh &mesh, - const Span nodes, + const Span nodes, + const IndexMask &node_mask, GMutableSpan attribute) { SculptSession &ss = *ob.sculpt; @@ -1246,10 +1249,10 @@ static void do_vpaint_brush_blur_verts(const bContext *C, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) { + blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1341,7 +1344,7 @@ static void do_vpaint_brush_blur_verts(const bContext *C, Traits::range * brush_strength); }); } - }; + }); }); } @@ -1350,7 +1353,8 @@ static void do_vpaint_brush_smear(const bContext *C, VPaintData &vpd, Object &ob, Mesh &mesh, - const Span nodes, + const Span nodes, + const IndexMask &node_mask, GMutableSpan attribute) { SculptSession &ss = *ob.sculpt; @@ -1406,10 +1410,10 @@ static void do_vpaint_brush_smear(const bContext *C, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) { + blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1544,7 +1548,7 @@ static void do_vpaint_brush_smear(const bContext *C, } }); } - } + }); }); } @@ -1553,7 +1557,8 @@ static void calculate_average_color(VPaintData &vpd, Mesh &mesh, const Brush &brush, const GSpan attribute, - const Span nodes) + const Span nodes, + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; const StrokeCache &cache = *ss.cache; @@ -1587,14 +1592,14 @@ static void calculate_average_color(VPaintData &vpd, const Span colors = attribute.typed().template cast(); Array> accum(nodes.size()); - blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) { + blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { VPaintAverageAccum &accum2 = accum[i]; accum2.len = 0; memset(accum2.value, 0, sizeof(accum2.value)); - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1633,7 +1638,7 @@ static void calculate_average_color(VPaintData &vpd, accum2.value[2] += col.b * col.b; } } - } + }); }); Blend accum_len = 0; @@ -1678,7 +1683,8 @@ static void vpaint_do_draw(const bContext *C, VPaintData &vpd, Object &ob, Mesh &mesh, - const Span nodes, + const Span nodes, + const IndexMask &node_mask, GMutableSpan attribute) { SculptSession &ss = *ob.sculpt; @@ -1721,10 +1727,10 @@ static void vpaint_do_draw(const bContext *C, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - blender::threading::parallel_for(nodes.index_range(), 1LL, [&](IndexRange range) { + blender::threading::parallel_for(node_mask.index_range(), 1LL, [&](IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1835,7 +1841,7 @@ static void vpaint_do_draw(const bContext *C, } }); } - } + }); }); } @@ -1844,14 +1850,15 @@ static void vpaint_do_blur(const bContext *C, VPaintData &vpd, Object &ob, Mesh &mesh, - const Span nodes, + const Span nodes, + const IndexMask &node_mask, GMutableSpan attribute) { if (vpd.domain == AttrDomain::Point) { - do_vpaint_brush_blur_verts(C, vp, vpd, ob, mesh, nodes, attribute); + do_vpaint_brush_blur_verts(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); } else { - do_vpaint_brush_blur_loops(C, vp, vpd, ob, mesh, nodes, attribute); + do_vpaint_brush_blur_loops(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); } } @@ -1861,26 +1868,27 @@ static void vpaint_paint_leaves(bContext *C, Object &ob, Mesh &mesh, GMutableSpan attribute, - const Span nodes) + const Span nodes, + const IndexMask &node_mask) { const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C); - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color); const Brush &brush = *ob.sculpt->cache->brush; switch ((eBrushVertexPaintTool)brush.vertexpaint_tool) { case VPAINT_TOOL_AVERAGE: - calculate_average_color(vpd, ob, mesh, brush, attribute, nodes); - vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, attribute); + calculate_average_color(vpd, ob, mesh, brush, attribute, nodes, node_mask); + vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); break; case VPAINT_TOOL_DRAW: - vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, attribute); + vpaint_do_draw(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); break; case VPAINT_TOOL_BLUR: - vpaint_do_blur(C, vp, vpd, ob, mesh, nodes, attribute); + vpaint_do_blur(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); break; case VPAINT_TOOL_SMEAR: - do_vpaint_brush_smear(C, vp, vpd, ob, mesh, nodes, attribute); + do_vpaint_brush_smear(C, vp, vpd, ob, mesh, nodes, node_mask, attribute); break; default: break; @@ -1903,7 +1911,8 @@ static void vpaint_do_paint(bContext *C, ss.cache->radial_symmetry_pass = i; SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle); - Vector nodes = vwpaint::pbvh_gather_generic(depsgraph, ob, vp, brush); + IndexMaskMemory memory; + const IndexMask node_mask = vwpaint::pbvh_gather_generic(depsgraph, ob, vp, brush, memory); bke::GSpanAttributeWriter attribute = mesh.attributes_for_write().lookup_for_write_span( mesh.active_color_attribute); @@ -1916,7 +1925,8 @@ static void vpaint_do_paint(bContext *C, } /* Paint those leaves. */ - vpaint_paint_leaves(C, vp, vpd, ob, mesh, attribute.span, nodes); + vpaint_paint_leaves( + C, vp, vpd, ob, mesh, attribute.span, ss.pbvh->nodes(), node_mask); attribute.finish(); } @@ -2303,20 +2313,20 @@ static int vertex_color_set_exec(bContext *C, wmOperator *op) BKE_sculpt_update_object_for_edit(CTX_data_ensure_evaluated_depsgraph(C), &obact, true); undo::push_begin(obact, op); - Vector nodes = bke::pbvh::all_leaf_nodes(*obact.sculpt->pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*obact.sculpt->pbvh, memory); const Mesh &mesh = *static_cast(obact.data); /* The sculpt undo system needs bke::pbvh::Tree node corner indices for corner domain * color attributes. */ BKE_pbvh_ensure_node_face_corners(*obact.sculpt->pbvh, mesh.corner_tris()); - undo::push_nodes(depsgraph, obact, nodes, undo::Type::Color); + undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color); fill_active_color(obact, paintcol, true, affect_alpha); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_color(*node); - } + MutableSpan nodes = obact.sculpt->pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); }); undo::push_end(obact); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact); diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc index 4225df03fca..f1766dd62a3 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc +++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc @@ -322,14 +322,14 @@ static void transform_active_color(bContext *C, * attributes. */ BKE_pbvh_ensure_node_face_corners(pbvh, mesh.corner_tris()); - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); - undo::push_nodes(depsgraph, obact, nodes, undo::Type::Color); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color); transform_active_color_data(*BKE_mesh_from_object(&obact), transform_fn); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_color(*node); - } + MutableSpan nodes = pbvh.nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); }); undo::push_end(obact); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact); diff --git a/source/blender/editors/sculpt_paint/paint_weight.cc b/source/blender/editors/sculpt_paint/paint_weight.cc index e7be5f79f18..20b0120db67 100644 --- a/source/blender/editors/sculpt_paint/paint_weight.cc +++ b/source/blender/editors/sculpt_paint/paint_weight.cc @@ -1064,15 +1064,16 @@ static void precompute_weight_values( * \{ */ static void parallel_nodes_loop_with_mirror_check(const Mesh &mesh, - const Span nodes, + const IndexMask &node_mask, FunctionRef fn) { /* NOTE: current mirroring code cannot be run in parallel */ if (ME_USING_MIRROR_X_VERTEX_GROUPS(&mesh)) { - fn(nodes.index_range()); + fn(node_mask.index_range()); } else { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { fn(range); }); + threading::parallel_for( + node_mask.index_range(), 1, [&](const IndexRange range) { fn(range); }); } } @@ -1097,10 +1098,11 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph, WPaintData &wpd, const WeightPaintInfo &wpi, Mesh &mesh, - const Span nodes) + const IndexMask &node_mask) { using namespace blender; SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); const StrokeCache &cache = *ss.cache; const GroupedSpan vert_to_face = mesh.vert_to_face_map(); @@ -1130,10 +1132,10 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) { + parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1192,7 +1194,7 @@ static void do_wpaint_brush_blur(const Depsgraph &depsgraph, weight_final /= total_hit_loops; do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, weight_final); } - } + }); }); } @@ -1204,10 +1206,11 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph, WPaintData &wpd, const WeightPaintInfo &wpi, Mesh &mesh, - const Span nodes) + const IndexMask &node_mask) { using namespace blender; SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); const GroupedSpan vert_to_face = mesh.vert_to_face_map(); const StrokeCache &cache = *ss.cache; if (!cache.is_last_valid) { @@ -1247,10 +1250,10 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) { + parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1317,7 +1320,7 @@ static void do_wpaint_brush_smear(const Depsgraph &depsgraph, do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, float(weight_final)); } } - } + }); }); } @@ -1330,10 +1333,11 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph, const WeightPaintInfo &wpi, Mesh &mesh, const float strength, - const Span nodes) + const IndexMask &node_mask) { using namespace blender; SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); const StrokeCache &cache = *ss.cache; /* NOTE: normally `BKE_brush_weight_get(scene, brush)` is used, @@ -1363,10 +1367,10 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph, Vector distances; }; threading::EnumerableThreadSpecific all_tls; - parallel_nodes_loop_with_mirror_check(mesh, nodes, [&](const IndexRange range) { + parallel_nodes_loop_with_mirror_check(mesh, node_mask, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1408,7 +1412,7 @@ static void do_wpaint_brush_draw(const Depsgraph &depsgraph, do_weight_paint_vertex(vp, ob, wpi, vert, final_alpha, paintweight); } - } + }); }); } @@ -1418,10 +1422,11 @@ static float calculate_average_weight(const Depsgraph &depsgraph, const Brush &brush, const VPaint &vp, WeightPaintInfo &wpi, - const Span nodes) + const IndexMask &node_mask) { using namespace blender; SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); const StrokeCache &cache = *ss.cache; const bool use_normal = vwpaint::use_normal(vp); @@ -1446,13 +1451,13 @@ static float calculate_average_weight(const Depsgraph &depsgraph, }; threading::EnumerableThreadSpecific all_tls; const WPaintAverageAccum value = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, WPaintAverageAccum{}, [&](const IndexRange range, WPaintAverageAccum accum) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide(mesh, verts, factors); @@ -1482,7 +1487,7 @@ static float calculate_average_weight(const Depsgraph &depsgraph, accum.len++; accum.value += wpaint_get_active_weight(dv, wpi); } - } + }); return accum; }, [](const WPaintAverageAccum &a, const WPaintAverageAccum &b) { @@ -1497,7 +1502,7 @@ static void wpaint_paint_leaves(bContext *C, WPaintData &wpd, WeightPaintInfo &wpi, Mesh &mesh, - const Span nodes) + const IndexMask &node_mask) { const Scene &scene = *CTX_data_scene(C); const Brush &brush = *ob.sculpt->cache->brush; @@ -1505,23 +1510,24 @@ static void wpaint_paint_leaves(bContext *C, switch ((eBrushWeightPaintTool)brush.weightpaint_tool) { case WPAINT_TOOL_AVERAGE: { - do_wpaint_brush_draw(depsgraph, - scene, - ob, - brush, - vp, - wpd, - wpi, - mesh, - calculate_average_weight(depsgraph, ob, mesh, brush, vp, wpi, nodes), - nodes); + do_wpaint_brush_draw( + depsgraph, + scene, + ob, + brush, + vp, + wpd, + wpi, + mesh, + calculate_average_weight(depsgraph, ob, mesh, brush, vp, wpi, node_mask), + node_mask); break; } case WPAINT_TOOL_SMEAR: - do_wpaint_brush_smear(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, nodes); + do_wpaint_brush_smear(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, node_mask); break; case WPAINT_TOOL_BLUR: - do_wpaint_brush_blur(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, nodes); + do_wpaint_brush_blur(depsgraph, scene, ob, brush, vp, wpd, wpi, mesh, node_mask); break; case WPAINT_TOOL_DRAW: do_wpaint_brush_draw(depsgraph, @@ -1533,7 +1539,7 @@ static void wpaint_paint_leaves(bContext *C, wpi, mesh, BKE_brush_weight_get(&scene, &brush), - nodes); + node_mask); break; } } @@ -1701,10 +1707,10 @@ static void wpaint_do_paint(bContext *C, ss.cache->radial_symmetry_pass = i; SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle); - Vector nodes = vwpaint::pbvh_gather_generic( - depsgraph, ob, wp, brush); + IndexMaskMemory memory; + const IndexMask node_mask = vwpaint::pbvh_gather_generic(depsgraph, ob, wp, brush, memory); - wpaint_paint_leaves(C, ob, wp, wpd, wpi, mesh, nodes); + wpaint_paint_leaves(C, ob, wp, wpd, wpi, mesh, node_mask); } static void wpaint_do_radial_symmetry(bContext *C, diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 733687c6bea..4671efb5194 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -842,11 +842,12 @@ std::optional nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, const bool use_original) { const float max_distance_sq = max_distance * max_distance; - Vector nodes = bke::pbvh::search_gather( - const_cast(pbvh), [&](bke::pbvh::Node &node) { + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, use_original); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { return std::nullopt; } @@ -855,13 +856,14 @@ std::optional nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, float distance_sq = std::numeric_limits::max(); }; + const Span nodes = pbvh.nodes(); const NearestData nearest = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestData(), [&](const IndexRange range, NearestData nearest) { - for (const int i : range) { - for (const int vert : bke::pbvh::node_unique_verts(*nodes[i])) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { + for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) { if (!hide_vert.is_empty() && hide_vert[vert]) { continue; } @@ -870,7 +872,7 @@ std::optional nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, nearest = {vert, distance_sq}; } } - } + }); return nearest; }, [](const NearestData a, const NearestData b) { @@ -886,11 +888,12 @@ std::optional nearest_vert_calc_grids(const bke::pbvh::Tree &pbv const bool use_original) { const float max_distance_sq = max_distance * max_distance; - Vector nodes = bke::pbvh::search_gather( - const_cast(pbvh), [&](bke::pbvh::Node &node) { + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, use_original); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { return std::nullopt; } @@ -903,13 +906,14 @@ std::optional nearest_vert_calc_grids(const bke::pbvh::Tree &pbv const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span elems = subdiv_ccg.grids; + const Span nodes = pbvh.nodes(); const NearestData nearest = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestData(), [&](const IndexRange range, NearestData nearest) { - for (const int i : range) { - for (const int grid : bke::pbvh::node_grid_indices(*nodes[i])) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { + for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) { CCGElem *elem = elems[grid]; BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) { const float distance_sq = math::distance_squared(CCG_elem_offset_co(key, elem, i), @@ -923,7 +927,7 @@ std::optional nearest_vert_calc_grids(const bke::pbvh::Tree &pbv } }); } - } + }); return nearest; }, [](const NearestData a, const NearestData b) { @@ -938,11 +942,12 @@ std::optional nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, const bool use_original) { const float max_distance_sq = max_distance * max_distance; - Vector nodes = bke::pbvh::search_gather( - const_cast(pbvh), [&](bke::pbvh::Node &node) { + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, use_original); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { return std::nullopt; } @@ -951,13 +956,16 @@ std::optional nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, float distance_sq = std::numeric_limits::max(); }; + const Span nodes = pbvh.nodes(); const NearestData nearest = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestData(), [&](const IndexRange range, NearestData nearest) { - for (const int i : range) { - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(nodes[i])) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { + for (BMVert *vert : + BKE_pbvh_bmesh_node_unique_verts(const_cast(&nodes[i]))) + { if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { continue; } @@ -966,7 +974,7 @@ std::optional nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, nearest = {vert, distance_sq}; } } - } + }); return nearest; }, [](const NearestData a, const NearestData b) { @@ -1160,61 +1168,61 @@ namespace undo { static void restore_mask_from_undo_step(Object &object) { SculptSession &ss = *object.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span( ".sculpt_mask", bke::AttrDomain::Point); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::Mask)) { - const Span verts = bke::pbvh::node_unique_verts(*node); - array_utils::scatter(unode->mask.as_span(), verts, mask.span); - BKE_pbvh_node_mark_update_mask(*node); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + array_utils::scatter(unode->mask.as_span(), verts, mask.span); + BKE_pbvh_node_mark_update_mask(nodes[i]); } }); mask.finish(); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); if (offset != -1) { - for (bke::pbvh::Node *node : nodes) { - if (undo::get_node(node, undo::Type::Mask)) { - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { + node_mask.foreach_index([&](const int i) { + if (undo::get_node(&nodes[i], undo::Type::Mask)) { + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { const float orig_mask = BM_log_original_mask(ss.bm_log, vert); BM_ELEM_CD_SET_FLOAT(vert, offset, orig_mask); } - BKE_pbvh_node_mark_update_mask(*node); + BKE_pbvh_node_mark_update_mask(nodes[i]); } - } + }); } break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = subdiv_ccg.grids; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::Mask)) { - int index = 0; - for (const int grid : unode->grids) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { - CCG_elem_offset_mask(key, elem, i) = unode->mask[index]; - } - index++; + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) { + int index = 0; + for (const int grid : unode->grids) { + CCGElem *elem = grids[grid]; + for (const int i : IndexRange(key.grid_area)) { + if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { + CCG_elem_offset_mask(key, elem, i) = unode->mask[index]; } + index++; } - BKE_pbvh_node_mark_update_mask(*node); } + BKE_pbvh_node_mark_update_mask(nodes[i]); } }); break; @@ -1225,7 +1233,9 @@ static void restore_mask_from_undo_step(Object &object) static void restore_color_from_undo_step(Object &object) { SculptSession &ss = *object.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + MutableSpan nodes = ss.pbvh->nodes(); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BLI_assert(ss.pbvh->type() == bke::pbvh::Type::Mesh); Mesh &mesh = *static_cast(object.data); @@ -1233,19 +1243,17 @@ static void restore_color_from_undo_step(Object &object) const Span corner_verts = mesh.corner_verts(); const GroupedSpan vert_to_face_map = ss.vert_to_face_map; bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::Color)) { - const Span verts = bke::pbvh::node_unique_verts(*node); - for (const int i : verts.index_range()) { - color::color_vert_set(faces, - corner_verts, - vert_to_face_map, - color_attribute.domain, - verts[i], - unode->col[i], - color_attribute.span); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Color)) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); + for (const int i : verts.index_range()) { + color::color_vert_set(faces, + corner_verts, + vert_to_face_map, + color_attribute.domain, + verts[i], + unode->col[i], + color_attribute.span); } } }); @@ -1255,20 +1263,33 @@ static void restore_color_from_undo_step(Object &object) static void restore_face_set_from_undo_step(Object &object) { SculptSession &ss = *object.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (ss.pbvh->type()) { - case bke::pbvh::Type::Mesh: - case bke::pbvh::Type::Grids: { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); bke::SpanAttributeWriter attribute = face_set::ensure_face_sets_mesh(object); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::FaceSet)) { - const Span faces = unode->face_indices; - const Span face_sets = unode->face_sets; - blender::array_utils::scatter(face_sets, faces, attribute.span); - BKE_pbvh_node_mark_update_face_sets(*node); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) { + const Span faces = unode->face_indices; + const Span face_sets = unode->face_sets; + blender::array_utils::scatter(face_sets, faces, attribute.span); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + } + }); + attribute.finish(); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + bke::SpanAttributeWriter attribute = face_set::ensure_face_sets_mesh(object); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) { + const Span faces = unode->face_indices; + const Span face_sets = unode->face_sets; + blender::array_utils::scatter(face_sets, faces, attribute.span); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); } }); attribute.finish(); @@ -1282,10 +1303,12 @@ static void restore_face_set_from_undo_step(Object &object) void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object) { SculptSession &ss = *object.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); MutableSpan positions_eval = bke::pbvh::vert_positions_eval_for_write(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); @@ -1298,11 +1321,11 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object) const bool need_translations = !ss.deform_imats.is_empty() || active_key; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::Position)) { - const Span verts = bke::pbvh::node_unique_verts(*node); + node_mask.slice(range).foreach_index([&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span undo_positions = unode->position.as_span().take_front(verts.size()); if (need_translations) { tls.translations.resize(verts.size()); @@ -1336,48 +1359,46 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object) object, mesh, *active_key, verts, tls.translations, positions_orig); } - BKE_pbvh_node_mark_positions_update(*node); + BKE_pbvh_node_mark_positions_update(nodes[i]); } - } + }); }); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); if (!undo::get_bmesh_log_entry()) { return; } - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(node)) { - if (const float *orig_co = BM_log_find_original_vert_co(ss.bm_log, vert)) { - copy_v3_v3(vert->co, orig_co); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { + if (const float *orig_co = BM_log_find_original_vert_co(ss.bm_log, vert)) { + copy_v3_v3(vert->co, orig_co); } - BKE_pbvh_node_mark_positions_update(*node); } + BKE_pbvh_node_mark_positions_update(nodes[i]); }); break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span grids = subdiv_ccg.grids; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - if (const undo::Node *unode = undo::get_node(node, undo::Type::Position)) { - int index = 0; - for (const int grid : unode->grids) { - CCGElem *elem = grids[grid]; - for (const int i : IndexRange(key.grid_area)) { - if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { - CCG_elem_offset_co(key, elem, i) = unode->position[index]; - } - index++; + node_mask.foreach_index(GrainSize(1), [&](const int i) { + if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) { + int index = 0; + for (const int grid : unode->grids) { + CCGElem *elem = grids[grid]; + for (const int i : IndexRange(key.grid_area)) { + if (grid_hidden.is_empty() || !grid_hidden[grid][i]) { + CCG_elem_offset_co(key, elem, i) = unode->position[index]; } + index++; } - BKE_pbvh_node_mark_positions_update(*node); } + BKE_pbvh_node_mark_positions_update(nodes[i]); } }); break; @@ -1654,7 +1675,7 @@ static void calc_area_normal_and_center_node_mesh(const Object &object, const Brush &brush, const bool use_area_nos, const bool use_area_cos, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, SampleLocalData &tls, AreaNormalCenterData &anctd) { @@ -1737,7 +1758,7 @@ static void calc_area_normal_and_center_node_grids(const Object &object, const Brush &brush, const bool use_area_nos, const bool use_area_cos, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, SampleLocalData &tls, AreaNormalCenterData &anctd) { @@ -2009,7 +2030,7 @@ static AreaNormalCenterData calc_area_normal_and_center_reduce(const AreaNormalC void calc_area_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, - Span nodes, + const IndexMask &node_mask, float r_area_co[3]) { const SculptSession &ss = *ob.sculpt; @@ -2025,13 +2046,14 @@ void calc_area_center(const Depsgraph &depsgraph, const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_mesh(ob, vert_positions, vert_normals, @@ -2039,10 +2061,10 @@ void calc_area_center(const Depsgraph &depsgraph, brush, false, true, - *nodes[i], + nodes[i], tls, anctd); - } + }); return anctd; }, calc_area_normal_and_center_reduce); @@ -2051,39 +2073,33 @@ void calc_area_center(const Depsgraph &depsgraph, case bke::pbvh::Type::BMesh: { const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_bmesh( - ob, - brush, - false, - true, - has_bm_orco, - static_cast(*nodes[i]), - tls, - anctd); - } + ob, brush, false, true, has_bm_orco, nodes[i], tls, anctd); + }); return anctd; }, calc_area_normal_and_center_reduce); break; } case bke::pbvh::Type::Grids: { + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { - calc_area_normal_and_center_node_grids( - ob, brush, false, true, *nodes[i], tls, anctd); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_area_normal_and_center_node_grids(ob, brush, false, true, nodes[i], tls, anctd); + }); return anctd; }, calc_area_normal_and_center_reduce); @@ -2114,8 +2130,8 @@ void calc_area_center(const Depsgraph &depsgraph, std::optional calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, - Object &ob, - Span nodes) + const Object &ob, + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; @@ -2129,13 +2145,14 @@ std::optional calc_area_normal(const Depsgraph &depsgraph, const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_mesh(ob, vert_positions, vert_normals, @@ -2143,10 +2160,10 @@ std::optional calc_area_normal(const Depsgraph &depsgraph, brush, true, false, - *nodes[i], + nodes[i], tls, anctd); - } + }); return anctd; }, calc_area_normal_and_center_reduce); @@ -2155,39 +2172,40 @@ std::optional calc_area_normal(const Depsgraph &depsgraph, case bke::pbvh::Type::BMesh: { const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_bmesh( ob, brush, true, false, has_bm_orco, - static_cast(*nodes[i]), + static_cast(nodes[i]), tls, anctd); - } + }); return anctd; }, calc_area_normal_and_center_reduce); break; } case bke::pbvh::Type::Grids: { + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { - calc_area_normal_and_center_node_grids( - ob, brush, true, false, *nodes[i], tls, anctd); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_area_normal_and_center_node_grids(ob, brush, true, false, nodes[i], tls, anctd); + }); return anctd; }, calc_area_normal_and_center_reduce); @@ -2208,7 +2226,7 @@ std::optional calc_area_normal(const Depsgraph &depsgraph, void calc_area_normal_and_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, - Span nodes, + const IndexMask &node_mask, float r_area_no[3], float r_area_co[3]) { @@ -2225,13 +2243,14 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph, const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_mesh(ob, vert_positions, vert_normals, @@ -2239,10 +2258,10 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph, brush, true, true, - *nodes[i], + nodes[i], tls, anctd); - } + }); return anctd; }, calc_area_normal_and_center_reduce); @@ -2251,37 +2270,32 @@ void calc_area_normal_and_center(const Depsgraph &depsgraph, case bke::pbvh::Type::BMesh: { const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ss, brush); + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_area_normal_and_center_node_bmesh( - ob, - brush, - true, - true, - has_bm_orco, - static_cast(*nodes[i]), - tls, - anctd); - } + ob, brush, true, true, has_bm_orco, nodes[i], tls, anctd); + }); return anctd; }, calc_area_normal_and_center_reduce); break; } case bke::pbvh::Type::Grids: { + const Span nodes = ss.pbvh->nodes(); anctd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AreaNormalCenterData{}, [&](const IndexRange range, AreaNormalCenterData anctd) { SampleLocalData &tls = all_tls.local(); for (const int i : range) { - calc_area_normal_and_center_node_grids(ob, brush, true, true, *nodes[i], tls, anctd); + calc_area_normal_and_center_node_grids(ob, brush, true, true, nodes[i], tls, anctd); } return anctd; }, @@ -2616,87 +2630,69 @@ bool node_in_cylinder(const DistRayAABB_Precalc &ray_dist_precalc, return dist_sq < radius_sq || true; } -static Vector pbvh_gather_cursor_update(Object &ob, bool use_original) +static IndexMask pbvh_gather_cursor_update(Object &ob, bool use_original, IndexMaskMemory &memory) { SculptSession &ss = *ob.sculpt; const float3 center = ss.cache ? ss.cache->location : ss.cursor_location; - return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { + return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, center, ss.cursor_radius, use_original); }); } /** \return All nodes that are potentially within the cursor or brush's area of influence. */ -static Vector pbvh_gather_generic( - Object &ob, const Brush &brush, bool use_original, float radius_scale, PBVHNodeFlags flag) +static IndexMask pbvh_gather_generic( + Object &ob, const Brush &brush, bool use_original, float radius_scale, IndexMaskMemory &memory) { SculptSession &ss = *ob.sculpt; - PBVHNodeFlags leaf_flag = PBVH_Leaf; - if (flag & PBVH_TexLeaf) { - leaf_flag = PBVH_TexLeaf; - } - const float3 center = ss.cache->location; const float radius_sq = math::square(ss.cache->radius * radius_scale); const bool ignore_ineffective = brush.sculpt_tool != SCULPT_TOOL_MASK; switch (brush.falloff_shape) { case PAINT_FALLOFF_SHAPE_SPHERE: { - return bke::pbvh::search_gather( - *ss.pbvh, - [&](bke::pbvh::Node &node) { - if (ignore_ineffective && node_fully_masked_or_hidden(node)) { - return false; - } - return node_in_sphere(node, center, radius_sq, use_original); - }, - leaf_flag); + return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { + if (ignore_ineffective && node_fully_masked_or_hidden(node)) { + return false; + } + return node_in_sphere(node, center, radius_sq, use_original); + }); } case PAINT_FALLOFF_SHAPE_TUBE: { const DistRayAABB_Precalc ray_dist_precalc = dist_squared_ray_to_aabb_v3_precalc( center, ss.cache->view_normal); - return bke::pbvh::search_gather( - *ss.pbvh, - [&](bke::pbvh::Node &node) { - if (ignore_ineffective && node_fully_masked_or_hidden(node)) { - return false; - } - return node_in_cylinder(ray_dist_precalc, node, radius_sq, use_original); - }, - leaf_flag); + return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { + if (ignore_ineffective && node_fully_masked_or_hidden(node)) { + return false; + } + return node_in_cylinder(ray_dist_precalc, node, radius_sq, use_original); + }); } } return {}; } -static Vector pbvh_gather_generic(Object &ob, - const Brush &brush, - const bool use_original, - const float radius_scale) +static IndexMask pbvh_gather_texpaint(Object &ob, + const Brush &brush, + const bool use_original, + const float radius_scale, + IndexMaskMemory &memory) { - return pbvh_gather_generic(ob, brush, use_original, radius_scale, PBVH_Leaf); -} - -static Vector pbvh_gather_texpaint(Object &ob, - const Brush &brush, - const bool use_original, - const float radius_scale) -{ - return pbvh_gather_generic(ob, brush, use_original, radius_scale, PBVH_TexLeaf); + return pbvh_gather_generic(ob, brush, use_original, radius_scale, memory); } /* Calculate primary direction of movement for many brushes. */ static float3 calc_sculpt_normal(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); const SculptSession &ss = *ob.sculpt; switch (brush.sculpt_plane) { case SCULPT_DISP_DIR_AREA: - return calc_area_normal(depsgraph, brush, ob, nodes).value_or(float3(0)); + return calc_area_normal(depsgraph, brush, ob, node_mask).value_or(float3(0)); case SCULPT_DISP_DIR_VIEW: return ss.cache->true_view_normal; case SCULPT_DISP_DIR_X: @@ -2713,7 +2709,7 @@ static float3 calc_sculpt_normal(const Depsgraph &depsgraph, static void update_sculpt_normal(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); StrokeCache &cache = *ob.sculpt->cache; @@ -2727,7 +2723,7 @@ static void update_sculpt_normal(const Depsgraph &depsgraph, if (cache.mirror_symmetry_pass == 0 && cache.radial_symmetry_pass == 0 && (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(cache) || update_normal)) { - cache.sculpt_normal = calc_sculpt_normal(depsgraph, sd, ob, nodes); + cache.sculpt_normal = calc_sculpt_normal(depsgraph, sd, ob, node_mask); if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { project_plane_v3_v3v3(cache.sculpt_normal, cache.sculpt_normal, cache.view_normal); normalize_v3(cache.sculpt_normal); @@ -3064,7 +3060,7 @@ namespace blender::ed::sculpt_paint { void calc_brush_plane(const Depsgraph &depsgraph, const Brush &brush, Object &ob, - Span nodes, + const IndexMask &node_mask, float3 &r_area_no, float3 &r_area_co) { @@ -3095,7 +3091,7 @@ void calc_brush_plane(const Depsgraph &depsgraph, break; case SCULPT_DISP_DIR_AREA: - calc_area_normal_and_center(depsgraph, brush, ob, nodes, r_area_no, r_area_co); + calc_area_normal_and_center(depsgraph, brush, ob, node_mask, r_area_no, r_area_co); if (brush.falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { project_plane_v3_v3v3(r_area_no, r_area_no, ss.cache->view_normal); normalize_v3(r_area_no); @@ -3109,7 +3105,7 @@ void calc_brush_plane(const Depsgraph &depsgraph, /* For flatten center. */ /* Flatten center has not been calculated yet if we are not using the area normal. */ if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA) { - calc_area_center(depsgraph, brush, ob, nodes, r_area_co); + calc_area_center(depsgraph, brush, ob, node_mask, r_area_co); } /* For area normal. */ @@ -3229,13 +3225,15 @@ static void dynamic_topology_update(const Depsgraph &depsgraph, /* Build a list of all nodes that are potentially within the brush's area of influence. */ const bool use_original = tool_needs_original(brush.sculpt_tool) ? true : !ss.cache->accum; const float radius_scale = 1.25f; - Vector nodes = pbvh_gather_generic(ob, brush, use_original, radius_scale); - /* Only act if some verts are inside the brush area. */ - if (nodes.is_empty()) { + IndexMaskMemory memory; + const IndexMask node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory); + if (node_mask.is_empty()) { return; } + MutableSpan nodes = ss.pbvh->nodes(); + /* Free index based vertex info as it will become invalid after modifying the topology during the * stroke. */ ss.vertex_info.boundary.clear(); @@ -3253,18 +3251,17 @@ static void dynamic_topology_update(const Depsgraph &depsgraph, } } - for (bke::pbvh::Node *node : nodes) { + node_mask.foreach_index([&](const int i) { undo::push_node(depsgraph, ob, - node, + &nodes[i], brush.sculpt_tool == SCULPT_TOOL_MASK ? undo::Type::Mask : undo::Type::Position); - BKE_pbvh_node_mark_update(*node); + BKE_pbvh_node_mark_update(nodes[i]); - BKE_pbvh_node_mark_topology_update(*node); - BKE_pbvh_bmesh_node_save_orig( - ss.bm, ss.bm_log, static_cast(node), false); - } + BKE_pbvh_node_mark_topology_update(nodes[i]); + BKE_pbvh_bmesh_node_save_orig(ss.bm, ss.bm_log, &nodes[i], false); + }); float max_edge_len; if (sd.flags & (SCULPT_DYNTOPO_DETAIL_CONSTANT | SCULPT_DYNTOPO_DETAIL_MANUAL)) { @@ -3299,15 +3296,32 @@ static void dynamic_topology_update(const Depsgraph &depsgraph, static void push_undo_nodes(const Depsgraph &depsgraph, Object &ob, const Brush &brush, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; bool need_coords = ss.cache->supports_gravity; if (brush.sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS) { - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_face_sets(*node); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); + break; + } } /* Draw face sets in smooth mode moves the vertices. */ @@ -3315,13 +3329,27 @@ static void push_undo_nodes(const Depsgraph &depsgraph, need_coords = true; } else { - undo::push_nodes(depsgraph, ob, nodes, undo::Type::FaceSet); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::FaceSet); } } else if (brush.sculpt_tool == SCULPT_TOOL_MASK) { - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Mask); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_mask(*node); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); + break; + } } } else if (SCULPT_tool_is_paint(brush.sculpt_tool)) { @@ -3331,9 +3359,23 @@ static void push_undo_nodes(const Depsgraph &depsgraph, BKE_pbvh_ensure_node_face_corners(*ss.pbvh, mesh.corner_tris()); } } - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_color(*node); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); }); + break; + } } } else { @@ -3341,9 +3383,26 @@ static void push_undo_nodes(const Depsgraph &depsgraph, } if (need_coords) { - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Position); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_positions_update(*node); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); }); + break; + } } } } @@ -3357,7 +3416,8 @@ static void do_brush_action(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings) { SculptSession &ss = *ob.sculpt; - Vector nodes, texnodes; + IndexMaskMemory memory; + IndexMask node_mask, texnode_mask; const bool use_original = tool_needs_original(brush.sculpt_tool) ? true : !ss.cache->accum; const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob); @@ -3365,9 +3425,9 @@ static void do_brush_action(const Depsgraph &depsgraph, if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) { sculpt_pbvh_update_pixels(depsgraph, paint_mode_settings, ob); - texnodes = pbvh_gather_texpaint(ob, brush, use_original, 1.0f); + texnode_mask = pbvh_gather_texpaint(ob, brush, use_original, 1.0f, memory); - if (texnodes.is_empty()) { + if (texnode_mask.is_empty()) { return; } } @@ -3376,10 +3436,10 @@ static void do_brush_action(const Depsgraph &depsgraph, if (SCULPT_tool_needs_all_pbvh_nodes(brush)) { /* These brushes need to update all nodes as they are not constrained by the brush radius */ - nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); } else if (brush.sculpt_tool == SCULPT_TOOL_CLOTH) { - nodes = cloth::brush_affected_nodes_gather(ss, brush); + node_mask = cloth::brush_affected_nodes_gather(ss, brush, memory); } else { float radius_scale = 1.0f; @@ -3394,7 +3454,7 @@ static void do_brush_action(const Depsgraph &depsgraph, if (brush.sculpt_tool == SCULPT_TOOL_DRAW && brush.flag & BRUSH_ORIGINAL_NORMAL) { radius_scale = 2.0f; } - nodes = pbvh_gather_generic(ob, brush, use_original, radius_scale); + node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory); } /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the @@ -3416,7 +3476,7 @@ static void do_brush_action(const Depsgraph &depsgraph, /* For anchored brushes with spherical falloff, we start off with zero radius, thus we have no * bke::pbvh::Tree nodes on the first brush step. */ - if (!nodes.is_empty() || + if (!node_mask.is_empty() || ((brush.falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) && (brush.flag & BRUSH_ANCHORED))) { if (SCULPT_stroke_is_first_brush_step(*ss.cache)) { @@ -3437,17 +3497,17 @@ static void do_brush_action(const Depsgraph &depsgraph, } /* Only act if some verts are inside the brush area. */ - if (nodes.is_empty()) { + if (node_mask.is_empty()) { return; } float location[3]; if (!use_pixels) { - push_undo_nodes(depsgraph, ob, brush, nodes); + push_undo_nodes(depsgraph, ob, brush, node_mask); } if (sculpt_brush_needs_normal(ss, sd, brush)) { - update_sculpt_normal(depsgraph, sd, ob, nodes); + update_sculpt_normal(depsgraph, sd, ob, node_mask); } update_brush_local_mat(sd, ob); @@ -3463,7 +3523,7 @@ static void do_brush_action(const Depsgraph &depsgraph, } cloth::brush_store_simulation_state(depsgraph, ob, *ss.cache->cloth_sim); cloth::ensure_nodes_constraints( - sd, ob, nodes, *ss.cache->cloth_sim, ss.cache->location, FLT_MAX); + sd, ob, node_mask, *ss.cache->cloth_sim, ss.cache->location, FLT_MAX); } bool invert = ss.cache->pen_flip || ss.cache->invert; @@ -3477,10 +3537,10 @@ static void do_brush_action(const Depsgraph &depsgraph, const bool use_vector_displacement = (brush.flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT && (brush.mtex.brush_map_mode == MTEX_MAP_MODE_AREA)); if (use_vector_displacement) { - do_draw_vector_displacement_brush(depsgraph, sd, ob, nodes); + do_draw_vector_displacement_brush(depsgraph, sd, ob, node_mask); } else { - do_draw_brush(depsgraph, sd, ob, nodes); + do_draw_brush(depsgraph, sd, ob, node_mask); } break; } @@ -3492,129 +3552,130 @@ static void do_brush_action(const Depsgraph &depsgraph, * enhance brush in the middle of the stroke. */ if (ss.cache->bstrength < 0.0f) { /* Invert mode, intensify details. */ - do_enhance_details_brush(depsgraph, sd, ob, nodes); + do_enhance_details_brush(depsgraph, sd, ob, node_mask); } else { - do_smooth_brush(depsgraph, sd, ob, nodes, std::clamp(ss.cache->bstrength, 0.0f, 1.0f)); + do_smooth_brush( + depsgraph, sd, ob, node_mask, std::clamp(ss.cache->bstrength, 0.0f, 1.0f)); } } else if (brush.smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { - do_surface_smooth_brush(depsgraph, sd, ob, nodes); + do_surface_smooth_brush(depsgraph, sd, ob, node_mask); } break; case SCULPT_TOOL_CREASE: - do_crease_brush(depsgraph, scene, sd, ob, nodes); + do_crease_brush(depsgraph, scene, sd, ob, node_mask); break; case SCULPT_TOOL_BLOB: - do_blob_brush(depsgraph, scene, sd, ob, nodes); + do_blob_brush(depsgraph, scene, sd, ob, node_mask); break; case SCULPT_TOOL_PINCH: - do_pinch_brush(depsgraph, sd, ob, nodes); + do_pinch_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_INFLATE: - do_inflate_brush(depsgraph, sd, ob, nodes); + do_inflate_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_GRAB: - do_grab_brush(depsgraph, sd, ob, nodes); + do_grab_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_ROTATE: - do_rotate_brush(depsgraph, sd, ob, nodes); + do_rotate_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_SNAKE_HOOK: - do_snake_hook_brush(depsgraph, sd, ob, nodes); + do_snake_hook_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_NUDGE: - do_nudge_brush(depsgraph, sd, ob, nodes); + do_nudge_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_THUMB: - do_thumb_brush(depsgraph, sd, ob, nodes); + do_thumb_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_LAYER: - do_layer_brush(depsgraph, sd, ob, nodes); + do_layer_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_FLATTEN: - do_flatten_brush(depsgraph, sd, ob, nodes); + do_flatten_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_CLAY: - do_clay_brush(depsgraph, sd, ob, nodes); + do_clay_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_CLAY_STRIPS: - do_clay_strips_brush(depsgraph, sd, ob, nodes); + do_clay_strips_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_MULTIPLANE_SCRAPE: - do_multiplane_scrape_brush(depsgraph, sd, ob, nodes); + do_multiplane_scrape_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_CLAY_THUMB: - do_clay_thumb_brush(depsgraph, sd, ob, nodes); + do_clay_thumb_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_FILL: if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_scrape_brush(depsgraph, sd, ob, nodes); + do_scrape_brush(depsgraph, sd, ob, node_mask); } else { - do_fill_brush(depsgraph, sd, ob, nodes); + do_fill_brush(depsgraph, sd, ob, node_mask); } break; case SCULPT_TOOL_SCRAPE: if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_fill_brush(depsgraph, sd, ob, nodes); + do_fill_brush(depsgraph, sd, ob, node_mask); } else { - do_scrape_brush(depsgraph, sd, ob, nodes); + do_scrape_brush(depsgraph, sd, ob, node_mask); } break; case SCULPT_TOOL_MASK: switch ((BrushMaskTool)brush.mask_tool) { case BRUSH_MASK_DRAW: - do_mask_brush(depsgraph, sd, ob, nodes); + do_mask_brush(depsgraph, sd, ob, node_mask); break; case BRUSH_MASK_SMOOTH: - do_smooth_mask_brush(depsgraph, sd, ob, nodes, ss.cache->bstrength); + do_smooth_mask_brush(depsgraph, sd, ob, node_mask, ss.cache->bstrength); break; } break; case SCULPT_TOOL_POSE: - pose::do_pose_brush(depsgraph, sd, ob, nodes); + pose::do_pose_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_DRAW_SHARP: - do_draw_sharp_brush(depsgraph, sd, ob, nodes); + do_draw_sharp_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_ELASTIC_DEFORM: - do_elastic_deform_brush(depsgraph, sd, ob, nodes); + do_elastic_deform_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_SLIDE_RELAX: if (ss.cache->alt_smooth) { - do_topology_relax_brush(depsgraph, sd, ob, nodes); + do_topology_relax_brush(depsgraph, sd, ob, node_mask); } else { - do_topology_slide_brush(depsgraph, sd, ob, nodes); + do_topology_slide_brush(depsgraph, sd, ob, node_mask); } break; case SCULPT_TOOL_BOUNDARY: - boundary::do_boundary_brush(depsgraph, sd, ob, nodes); + boundary::do_boundary_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_CLOTH: - cloth::do_cloth_brush(depsgraph, sd, ob, nodes); + cloth::do_cloth_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_DRAW_FACE_SETS: if (!ss.cache->alt_smooth) { - do_draw_face_sets_brush(depsgraph, sd, ob, nodes); + do_draw_face_sets_brush(depsgraph, sd, ob, node_mask); } else { - do_relax_face_sets_brush(depsgraph, sd, ob, nodes); + do_relax_face_sets_brush(depsgraph, sd, ob, node_mask); } break; case SCULPT_TOOL_DISPLACEMENT_ERASER: - do_displacement_eraser_brush(depsgraph, sd, ob, nodes); + do_displacement_eraser_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_DISPLACEMENT_SMEAR: - do_displacement_smear_brush(depsgraph, sd, ob, nodes); + do_displacement_smear_brush(depsgraph, sd, ob, node_mask); break; case SCULPT_TOOL_PAINT: - color::do_paint_brush(depsgraph, paint_mode_settings, sd, ob, nodes, texnodes); + color::do_paint_brush(depsgraph, paint_mode_settings, sd, ob, node_mask, texnode_mask); break; case SCULPT_TOOL_SMEAR: - color::do_smear_brush(depsgraph, sd, ob, nodes); + color::do_smear_brush(depsgraph, sd, ob, node_mask); break; } @@ -3623,15 +3684,15 @@ static void do_brush_action(const Depsgraph &depsgraph, { if (brush.flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { do_smooth_brush( - depsgraph, sd, ob, nodes, brush.autosmooth_factor * (1.0f - ss.cache->pressure)); + depsgraph, sd, ob, node_mask, brush.autosmooth_factor * (1.0f - ss.cache->pressure)); } else { - do_smooth_brush(depsgraph, sd, ob, nodes, brush.autosmooth_factor); + do_smooth_brush(depsgraph, sd, ob, node_mask, brush.autosmooth_factor); } } if (brush_uses_topology_rake(ss, brush)) { - do_bmesh_topology_rake_brush(depsgraph, sd, ob, nodes, brush.topology_rake_factor); + do_bmesh_topology_rake_brush(depsgraph, sd, ob, node_mask, brush.topology_rake_factor); } if (!auto_mask::tool_can_reuse_automask(brush.sculpt_tool) || @@ -3646,13 +3707,13 @@ static void do_brush_action(const Depsgraph &depsgraph, !ELEM( brush.sculpt_tool, SCULPT_TOOL_CLOTH, SCULPT_TOOL_DRAW_FACE_SETS, SCULPT_TOOL_BOUNDARY)) { - do_gravity_brush(depsgraph, sd, ob, nodes); + do_gravity_brush(depsgraph, sd, ob, node_mask); } if (brush.deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { if (SCULPT_stroke_is_main_symmetry_pass(*ss.cache)) { - cloth::sim_activate_nodes(*ss.cache->cloth_sim, nodes); - cloth::do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, nodes); + cloth::sim_activate_nodes(ob, *ss.cache->cloth_sim, node_mask); + cloth::do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, node_mask); } } @@ -4935,16 +4996,18 @@ bool SCULPT_cursor_geometry_info_update(bContext *C, } ss.cursor_radius = radius; - Vector nodes = pbvh_gather_cursor_update(ob, original); + IndexMaskMemory memory; + const IndexMask node_mask = pbvh_gather_cursor_update(ob, original, memory); /* In case there are no nodes under the cursor, return the face normal. */ - if (nodes.is_empty()) { + if (node_mask.is_empty()) { copy_v3_v3(out->normal, srd.face_normal); return true; } /* Calculate the sampled normal. */ - if (const std::optional sampled_normal = calc_area_normal(*depsgraph, brush, ob, nodes)) + if (const std::optional sampled_normal = calc_area_normal( + *depsgraph, brush, ob, node_mask)) { copy_v3_v3(out->normal, *sampled_normal); copy_v3_v3(ss.cursor_sampled_normal, *sampled_normal); @@ -5789,7 +5852,7 @@ static void fake_neighbor_search_mesh(const SculptSession &ss, const float3 &location, const float max_distance_sq, const int island_id, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, NearestVertData &nvtd) { for (const int vert : bke::pbvh::node_unique_verts(node)) { @@ -5817,7 +5880,7 @@ static void fake_neighbor_search_grids(const SculptSession &ss, const float3 &location, const float max_distance_sq, const int island_id, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, NearestVertData &nvtd) { for (const int grid : bke::pbvh::node_grid_indices(node)) { @@ -5846,10 +5909,12 @@ static void fake_neighbor_search_bmesh(const SculptSession &ss, const float3 &location, const float max_distance_sq, const int island_id, - bke::pbvh::Node &node, + const bke::pbvh::BMeshNode &node, NearestVertData &nvtd) { - for (const BMVert *bm_vert : BKE_pbvh_bmesh_node_unique_verts(&node)) { + for (const BMVert *bm_vert : + BKE_pbvh_bmesh_node_unique_verts(const_cast(&node))) + { if (BM_elem_flag_test(bm_vert, BM_ELEM_HIDDEN)) { continue; } @@ -5890,28 +5955,31 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, } const int island_id = islands::vert_id_get(ss, vert); const float3 &location = vert_positions[vert]; - Vector nodes = bke::pbvh::search_gather( - *ss.pbvh, [&](bke::pbvh::Node &node) { + + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + *ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, false); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { continue; } + const Span nodes = ss.pbvh->nodes(); const NearestVertData nvtd = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestVertData(), [&](const IndexRange range, NearestVertData nvtd) { - for (const int i : range) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { fake_neighbor_search_mesh(ss, vert_positions, hide_vert, location, max_distance_sq, island_id, - *nodes[i], + nodes[i], nvtd); - } + }); return nvtd; }, NearestVertData::join); @@ -5935,19 +6003,21 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, const int island_id = islands::vert_id_get(ss, vert); const SubdivCCGCoord coord = SubdivCCGCoord::from_index(key, vert); const float3 &location = CCG_grid_elem_co(key, elems[coord.grid_index], coord.x, coord.y); - Vector nodes = bke::pbvh::search_gather( - *ss.pbvh, [&](bke::pbvh::Node &node) { + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + *ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, false); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { continue; } + const Span nodes = ss.pbvh->nodes(); const NearestVertData nvtd = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestVertData(), [&](const IndexRange range, NearestVertData nvtd) { - for (const int i : range) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { fake_neighbor_search_grids(ss, key, elems, @@ -5955,9 +6025,9 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, location, max_distance_sq, island_id, - *nodes[i], + nodes[i], nvtd); - } + }); return nvtd; }, NearestVertData::join); @@ -5977,22 +6047,24 @@ static void fake_neighbor_search(const Depsgraph &depsgraph, } const int island_id = islands::vert_id_get(ss, vert); const float3 &location = BM_vert_at_index(&const_cast(bm), vert)->co; - Vector nodes = bke::pbvh::search_gather( - *ss.pbvh, [&](bke::pbvh::Node &node) { + IndexMaskMemory memory; + const IndexMask nodes_in_sphere = bke::pbvh::search_nodes( + *ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, location, max_distance_sq, false); }); - if (nodes.is_empty()) { + if (nodes_in_sphere.is_empty()) { continue; } + const Span nodes = ss.pbvh->nodes(); const NearestVertData nvtd = threading::parallel_reduce( - nodes.index_range(), + nodes_in_sphere.index_range(), 1, NearestVertData(), [&](const IndexRange range, NearestVertData nvtd) { - for (const int i : range) { + nodes_in_sphere.slice(range).foreach_index([&](const int i) { fake_neighbor_search_bmesh( - ss, location, max_distance_sq, island_id, *nodes[i], nvtd); - } + ss, location, max_distance_sq, island_id, nodes[i], nvtd); + }); return nvtd; }, NearestVertData::join); @@ -6248,23 +6320,23 @@ static SculptTopologyIslandCache calc_topology_islands_grids(const Object &objec static SculptTopologyIslandCache calc_topology_islands_bmesh(const Object &object) { const SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); BMesh &bm = *ss.bm; BM_mesh_elem_index_ensure(&bm, BM_VERT); bke::pbvh::Tree &pbvh = *object.sculpt->pbvh; - const Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); AtomicDisjointSet disjoint_set(bm.totvert); - threading::parallel_for(nodes.index_range(), 1024, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - for (const BMFace *face : BKE_pbvh_bmesh_node_faces(node)) { - if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) { - continue; - } - disjoint_set.join(BM_elem_index_get(face->l_first->v), - BM_elem_index_get(face->l_first->next->v)); - disjoint_set.join(BM_elem_index_get(face->l_first->v), - BM_elem_index_get(face->l_first->next->next->v)); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const BMFace *face : BKE_pbvh_bmesh_node_faces(&nodes[i])) { + if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) { + continue; } + disjoint_set.join(BM_elem_index_get(face->l_first->v), + BM_elem_index_get(face->l_first->next->v)); + disjoint_set.join(BM_elem_index_get(face->l_first->v), + BM_elem_index_get(face->l_first->next->next->v)); } }); @@ -7320,33 +7392,38 @@ void transform_positions(const float4x4 &transform, const MutableSpan po } } -OffsetIndices create_node_vert_offsets(Span nodes, Array &node_data) -{ - node_data.reinitialize(nodes.size() + 1); - for (const int i : nodes.index_range()) { - node_data[i] = bke::pbvh::node_unique_verts(*nodes[i]).size(); - } - return offset_indices::accumulate_counts_to_offsets(node_data); -} - -OffsetIndices create_node_vert_offsets(Span nodes, - const CCGKey &key, +OffsetIndices create_node_vert_offsets(const Span nodes, + const IndexMask &nodes_mask, Array &node_data) { node_data.reinitialize(nodes.size() + 1); - for (const int i : nodes.index_range()) { - node_data[i] = bke::pbvh::node_grid_indices(*nodes[i]).size() * key.grid_area; - } + nodes_mask.foreach_index([&](const int i, const int pos) { + node_data[pos] = bke::pbvh::node_unique_verts(nodes[i]).size(); + }); return offset_indices::accumulate_counts_to_offsets(node_data); } -OffsetIndices create_node_vert_offsets_bmesh(Span nodes, +OffsetIndices create_node_vert_offsets(const CCGKey &key, + const Span nodes, + const IndexMask &nodes_mask, + Array &node_data) +{ + node_data.reinitialize(nodes.size() + 1); + nodes_mask.foreach_index([&](const int i, const int pos) { + node_data[pos] = bke::pbvh::node_grid_indices(nodes[i]).size() * key.grid_area; + }); + return offset_indices::accumulate_counts_to_offsets(node_data); +} + +OffsetIndices create_node_vert_offsets_bmesh(const Span nodes, + const IndexMask &nodes_mask, Array &node_data) { node_data.reinitialize(nodes.size() + 1); - for (const int i : nodes.index_range()) { - node_data[i] = BKE_pbvh_bmesh_node_unique_verts(nodes[i]).size(); - } + nodes_mask.foreach_index([&](const int i, const int pos) { + node_data[pos] = + BKE_pbvh_bmesh_node_unique_verts(const_cast(&nodes[i])).size(); + }); return offset_indices::accumulate_counts_to_offsets(node_data); } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.cc b/source/blender/editors/sculpt_paint/sculpt_automasking.cc index b8ba9e52e67..43f87d7bebe 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.cc +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.cc @@ -615,7 +615,7 @@ static float factor_get(const Depsgraph &depsgraph, void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, const Span verts, const MutableSpan factors) { @@ -641,7 +641,7 @@ void calc_face_factors(const Depsgraph &depsgraph, const OffsetIndices faces, const Span corner_verts, const Cache &cache, - const bke::pbvh::Node & /*node*/, + const bke::pbvh::MeshNode & /*node*/, const Span face_indices, const MutableSpan factors) { @@ -658,7 +658,7 @@ void calc_face_factors(const Depsgraph &depsgraph, void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, const Span grids, const MutableSpan factors) { @@ -691,7 +691,7 @@ void calc_grids_factors(const Depsgraph &depsgraph, void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, - const bke::pbvh::Node & /*node*/, + const bke::pbvh::BMeshNode & /*node*/, const Set &verts, const MutableSpan factors) { diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.cc b/source/blender/editors/sculpt_paint/sculpt_boundary.cc index 9957b0e15cf..cdfe8ba3123 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.cc +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.cc @@ -1121,7 +1121,7 @@ static void calc_bend_mesh(const Depsgraph &depsgraph, const Span vert_factors, const Span vert_pivot_positions, const Span vert_pivot_axes, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1181,7 +1181,7 @@ static void calc_bend_grids(const Depsgraph &depsgraph, const Span vert_factors, const Span vert_pivot_positions, const Span vert_pivot_axes, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 symmetry_pivot, const float strength, @@ -1246,7 +1246,7 @@ static void calc_bend_bmesh(const Depsgraph &depsgraph, const Span vert_factors, const Span vert_pivot_positions, const Span vert_pivot_axes, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1304,7 +1304,7 @@ static void calc_bend_bmesh(const Depsgraph &depsgraph, static void do_bend_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -1317,9 +1317,10 @@ static void do_bend_brush(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_bend_mesh(depsgraph, sd, object, @@ -1328,23 +1329,24 @@ static void do_bend_brush(const Depsgraph &depsgraph, boundary.edit_info.strength_factor, boundary.bend.pivot_positions, boundary.bend.pivot_rotation_axis, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_bend_grids(depsgraph, sd, object, @@ -1353,20 +1355,21 @@ static void do_bend_brush(const Depsgraph &depsgraph, boundary.edit_info.strength_factor, boundary.bend.pivot_positions, boundary.bend.pivot_rotation_axis, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_bend_bmesh(depsgraph, sd, object, @@ -1374,12 +1377,12 @@ static void do_bend_brush(const Depsgraph &depsgraph, boundary.edit_info.strength_factor, boundary.bend.pivot_positions, boundary.bend.pivot_rotation_axis, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -1413,7 +1416,7 @@ static void calc_slide_mesh(const Depsgraph &depsgraph, const Span vert_propagation_steps, const Span vert_factors, const Span vert_slide_directions, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1472,7 +1475,7 @@ static void calc_slide_grids(const Depsgraph &depsgraph, const Span vert_propagation_steps, const Span vert_factors, const Span vert_slide_directions, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 symmetry_pivot, const float strength, @@ -1535,7 +1538,7 @@ static void calc_slide_bmesh(const Depsgraph &depsgraph, const Span vert_propagation_steps, const Span vert_factors, const Span vert_slide_directions, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1592,7 +1595,7 @@ static void calc_slide_bmesh(const Depsgraph &depsgraph, static void do_slide_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -1605,9 +1608,10 @@ static void do_slide_brush(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_slide_mesh(depsgraph, sd, object, @@ -1615,23 +1619,24 @@ static void do_slide_brush(const Depsgraph &depsgraph, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, boundary.slide.directions, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_slide_grids(depsgraph, sd, object, @@ -1639,32 +1644,33 @@ static void do_slide_brush(const Depsgraph &depsgraph, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, boundary.slide.directions, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_slide_bmesh(depsgraph, sd, object, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, boundary.slide.directions, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -1697,7 +1703,7 @@ static void calc_inflate_mesh(const Depsgraph &depsgraph, const Span positions_eval, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1751,7 +1757,7 @@ static void calc_inflate_grids(const Depsgraph &depsgraph, SubdivCCG &subdiv_ccg, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 symmetry_pivot, const float strength, @@ -1809,7 +1815,7 @@ static void calc_inflate_bmesh(const Depsgraph &depsgraph, Object &object, const Span vert_propagation_steps, const Span vert_factors, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 symmetry_pivot, const float strength, @@ -1863,7 +1869,7 @@ static void calc_inflate_bmesh(const Depsgraph &depsgraph, static void do_inflate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -1876,63 +1882,66 @@ static void do_inflate_brush(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_inflate_mesh(depsgraph, sd, object, positions_eval, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_inflate_grids(depsgraph, sd, object, subdiv_ccg, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_inflate_bmesh(depsgraph, sd, object, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -1964,7 +1973,7 @@ static void calc_grab_mesh(const Depsgraph &depsgraph, const Span positions_eval, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 grab_delta_symmetry, const float3 symmetry_pivot, @@ -2019,7 +2028,7 @@ static void calc_grab_grids(const Depsgraph &depsgraph, SubdivCCG &subdiv_ccg, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 grab_delta_symmetry, const float3 symmetry_pivot, @@ -2078,7 +2087,7 @@ static void calc_grab_bmesh(const Depsgraph &depsgraph, Object &object, const Span vert_propagation_steps, const Span vert_factors, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 grab_delta_symmetry, const float3 symmetry_pivot, @@ -2133,7 +2142,7 @@ static void calc_grab_bmesh(const Depsgraph &depsgraph, static void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -2146,66 +2155,69 @@ static void do_grab_brush(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_grab_mesh(depsgraph, sd, object, positions_eval, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, ss.cache->grab_delta_symmetry, boundary.initial_vert_position, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_grab_grids(depsgraph, sd, object, subdiv_ccg, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, ss.cache->grab_delta_symmetry, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_grab_bmesh(depsgraph, sd, object, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, ss.cache->grab_delta_symmetry, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -2238,7 +2250,7 @@ static void calc_twist_mesh(const Depsgraph &depsgraph, const Span positions_eval, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 twist_pivot_position, const float3 twist_axis, @@ -2297,7 +2309,7 @@ static void calc_twist_grids(const Depsgraph &depsgraph, const Span vert_factors, const float3 twist_pivot_position, const float3 twist_axis, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 symmetry_pivot, const float strength, @@ -2358,7 +2370,7 @@ static void calc_twist_bmesh(const Depsgraph &depsgraph, const Span vert_factors, const float3 twist_pivot_position, const float3 twist_axis, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 symmetry_pivot, const float strength, @@ -2412,7 +2424,7 @@ static void calc_twist_bmesh(const Depsgraph &depsgraph, static void do_twist_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -2425,16 +2437,17 @@ static void do_twist_brush(const Depsgraph &depsgraph, MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_twist_mesh(depsgraph, sd, object, positions_eval, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.twist.pivot_position, boundary.twist.rotation_axis, @@ -2442,17 +2455,18 @@ static void do_twist_brush(const Depsgraph &depsgraph, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_twist_grids(depsgraph, sd, object, @@ -2461,20 +2475,21 @@ static void do_twist_brush(const Depsgraph &depsgraph, boundary.edit_info.strength_factor, boundary.twist.pivot_position, boundary.twist.rotation_axis, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_twist_bmesh(depsgraph, sd, object, @@ -2482,12 +2497,12 @@ static void do_twist_brush(const Depsgraph &depsgraph, boundary.edit_info.strength_factor, boundary.twist.pivot_position, boundary.twist.rotation_axis, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -2611,7 +2626,7 @@ static void calc_smooth_mesh(const Depsgraph &depsgraph, const Span hide_poly, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalDataMesh &tls, const float3 symmetry_pivot, const float strength, @@ -2677,7 +2692,7 @@ static void calc_smooth_grids(const Sculpt &sd, SubdivCCG &subdiv_ccg, const Span vert_propagation_steps, const Span vert_factors, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalDataGrids &tls, const float3 symmetry_pivot, const float strength, @@ -2746,7 +2761,7 @@ static void calc_smooth_bmesh(const Sculpt &sd, Object &object, const Span vert_propagation_steps, const Span vert_factors, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalDataBMesh &tls, const float3 symmetry_pivot, const float strength, @@ -2807,7 +2822,7 @@ static void calc_smooth_bmesh(const Sculpt &sd, static void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, - const Span nodes, + const IndexMask &node_mask, const SculptBoundary &boundary, const float strength, const eBrushDeformTarget deform_target) @@ -2825,9 +2840,10 @@ static void do_smooth_brush(const Depsgraph &depsgraph, const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_smooth_mesh(depsgraph, sd, object, @@ -2838,52 +2854,54 @@ static void do_smooth_brush(const Depsgraph &depsgraph, hide_poly, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataGrids &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_smooth_grids(sd, object, subdiv_ccg, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } case bke::pbvh::Type::BMesh: { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalDataBMesh &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_smooth_bmesh(sd, object, boundary.edit_info.propagation_steps_num, boundary.edit_info.strength_factor, - *nodes[i], + nodes[i], tls, boundary.initial_vert_position, strength, deform_target); - } + }); }); break; } @@ -3327,7 +3345,7 @@ static float get_mesh_strength(const SculptSession &ss, const Brush &brush) void do_boundary_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -3362,7 +3380,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_bend_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); @@ -3371,7 +3389,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_slide_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); @@ -3380,7 +3398,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_inflate_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); @@ -3389,7 +3407,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_grab_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); @@ -3398,7 +3416,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_twist_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); @@ -3407,7 +3425,7 @@ void do_boundary_brush(const Depsgraph &depsgraph, do_smooth_brush(depsgraph, sd, ob, - nodes, + node_mask, *ss.cache->boundaries[symm_area], strength, eBrushDeformTarget(brush.deform_target)); diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 19ad8b4c256..3092d9e1dec 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -174,7 +174,9 @@ static float3 cloth_brush_simulation_location_get(const SculptSession &ss, const return ss.cache->location; } -Vector brush_affected_nodes_gather(SculptSession &ss, const Brush &brush) +IndexMask brush_affected_nodes_gather(SculptSession &ss, + const Brush &brush, + IndexMaskMemory &memory) { BLI_assert(ss.cache); BLI_assert(brush.sculpt_tool == SCULPT_TOOL_CLOTH); @@ -183,15 +185,15 @@ Vector brush_affected_nodes_gather(SculptSession &ss, const B case BRUSH_CLOTH_SIMULATION_AREA_LOCAL: { const float radius_squared = math::square(ss.cache->initial_radius * (1.0 + brush.cloth_sim_limit)); - return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { + return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, ss.cache->initial_location, radius_squared, false); }); } case BRUSH_CLOTH_SIMULATION_AREA_GLOBAL: - return bke::pbvh::all_leaf_nodes(*ss.pbvh); + return bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); case BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC: { const float radius_squared = math::square(ss.cache->radius * (1.0 + brush.cloth_sim_limit)); - return bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { + return bke::pbvh::search_nodes(*ss.pbvh, memory, [&](const bke::pbvh::Node &node) { return node_in_sphere(node, ss.cache->location, radius_squared, false); }); } @@ -475,7 +477,7 @@ static void add_constraints_for_verts(const Object &object, void ensure_nodes_constraints(const Sculpt &sd, const Object &object, - const Span all_nodes, + const IndexMask &node_mask, SimulationData &cloth_sim, const float3 &initial_location, const float radius) @@ -488,20 +490,18 @@ void ensure_nodes_constraints(const Sculpt &sd, /* Currently all constrains are added to the same global array which can't be accessed from * different threads. */ - Vector nodes; - for (bke::pbvh::Node *node : all_nodes) { - const int node_index = cloth_sim.node_state_index.lookup(node); - if (cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED) { - /* The simulation already contains constraints for this node. */ - nodes.append(node); - } - } - + IndexMaskMemory memory; Set created_length_constraints; Vector vert_indices; Vector> vert_neighbors; switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask uninitialized_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED; + }); const Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -523,8 +523,8 @@ void ensure_nodes_constraints(const Sculpt &sd, else { init_positions = persistent_position; } - for (const int i : nodes.index_range()) { - const Span verts = hide::node_visible_verts(*nodes[i], hide_vert, vert_indices); + uninitialized_nodes.foreach_index([&](const int i) { + const Span verts = hide::node_visible_verts(nodes[i], hide_vert, vert_indices); vert_neighbors.resize(verts.size()); calc_vert_neighbors( faces, corner_verts, ss.vert_to_face_map, hide_poly, verts, vert_neighbors); @@ -533,21 +533,27 @@ void ensure_nodes_constraints(const Sculpt &sd, initial_location, radius, init_positions, - cloth_sim.node_state_index.lookup(nodes[i]), + cloth_sim.node_state_index.lookup(&nodes[i]), verts, vert_neighbors, cloth_sim, created_length_constraints); - } + }); break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask uninitialized_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED; + }); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - for (const int i : nodes.index_range()) { + uninitialized_nodes.foreach_index([&](const int i) { const Span verts = calc_visible_vert_indices_grids( - key, grid_hidden, bke::pbvh::node_grid_indices(*nodes[i]), vert_indices); + key, grid_hidden, bke::pbvh::node_grid_indices(nodes[i]), vert_indices); vert_neighbors.resize(verts.size()); calc_vert_neighbor_indices_grids(subdiv_ccg, verts, vert_neighbors); add_constraints_for_verts(object, @@ -555,20 +561,26 @@ void ensure_nodes_constraints(const Sculpt &sd, initial_location, radius, cloth_sim.init_pos, - cloth_sim.node_state_index.lookup(nodes[i]), + cloth_sim.node_state_index.lookup(&nodes[i]), verts, vert_neighbors, cloth_sim, created_length_constraints); - } + }); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask uninitialized_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_UNINITIALIZED; + }); BMesh &bm = *ss.bm; BM_mesh_elem_index_ensure(&bm, BM_VERT); BM_mesh_elem_table_ensure(&bm, BM_VERT); - for (const int i : nodes.index_range()) { - const Set &bm_verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + uninitialized_nodes.foreach_index([&](const int i) { + const Set &bm_verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span verts = calc_visible_vert_indices_bmesh(bm_verts, vert_indices); vert_neighbors.resize(verts.size()); calc_vert_neighbor_indices_bmesh(bm, verts, vert_neighbors); @@ -577,12 +589,12 @@ void ensure_nodes_constraints(const Sculpt &sd, initial_location, radius, cloth_sim.init_pos, - cloth_sim.node_state_index.lookup(nodes[i]), + cloth_sim.node_state_index.lookup(&nodes[i]), verts, vert_neighbors, cloth_sim, created_length_constraints); - } + }); break; } } @@ -718,7 +730,7 @@ static void calc_forces_mesh(const Depsgraph &depsgraph, const std::optional &falloff_plane, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalData &tls) { SculptSession &ss = *ob.sculpt; @@ -825,7 +837,7 @@ static void calc_forces_grids(const Depsgraph &depsgraph, const float3 &sim_location, const float3 &gravity, const std::optional &falloff_plane, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *ob.sculpt; @@ -935,7 +947,7 @@ static void calc_forces_bmesh(const Depsgraph &depsgraph, const float3 &sim_location, const float3 &gravity, const std::optional &falloff_plane, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { SculptSession &ss = *ob.sculpt; @@ -985,7 +997,7 @@ static void calc_forces_bmesh(const Depsgraph &depsgraph, calc_brush_strength_factors(cache, brush, distances, factors); const auto_mask::Cache *automask = auto_mask::active_cache_get(ss); - auto_mask::calc_vert_factors(depsgraph, ob, automask, node, verts, factors); + auto_mask::calc_vert_factors(depsgraph, ob, automask, node, bm_verts, factors); calc_brush_texture_factors(ss, brush, current_positions, factors); @@ -1213,8 +1225,8 @@ static void calc_constraint_factors(const Depsgraph &depsgraph, { const SculptSession &ss = *object.sculpt; const bke::pbvh::Tree &pbvh = *ss.pbvh; - const Vector nodes = bke::pbvh::all_leaf_nodes( - const_cast(pbvh)); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss); @@ -1226,36 +1238,38 @@ static void calc_constraint_factors(const Depsgraph &depsgraph, switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { const Mesh &mesh = *static_cast(object.data); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); - auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors); + auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors); if (ss.cache) { const MutableSpan positions = gather_data_mesh(init_positions, verts, tls.positions); calc_brush_simulation_falloff( *brush, ss.cache->radius, sim_location, positions, factors); } scatter_data_mesh(factors.as_span(), verts, cloth_factors); - } + }); }); break; } case bke::pbvh::Type::Grids: { const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const int grid_verts_num = grids.size() * key.grid_area; tls.factors.resize(grid_verts_num); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); - auto_mask::calc_grids_factors(depsgraph, object, automasking, *nodes[i], grids, factors); + auto_mask::calc_grids_factors(depsgraph, object, automasking, nodes[i], grids, factors); if (ss.cache) { const Span positions = gather_data_grids( subdiv_ccg, init_positions, grids, tls.positions); @@ -1263,20 +1277,22 @@ static void calc_constraint_factors(const Depsgraph &depsgraph, *brush, ss.cache->radius, sim_location, positions, factors); } scatter_data_grids(subdiv_ccg, factors.as_span(), grids, cloth_factors); - } + }); }); break; } case bke::pbvh::Type::BMesh: { const BMesh &bm = *ss.bm; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + const Span nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts( + const_cast(&nodes[i])); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); - auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors); + auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors); if (ss.cache) { const MutableSpan positions = gather_data_vert_bmesh( init_positions, verts, tls.positions); @@ -1284,7 +1300,7 @@ static void calc_constraint_factors(const Depsgraph &depsgraph, *brush, ss.cache->radius, sim_location, positions, factors); } scatter_data_vert_bmesh(factors.as_span(), verts, cloth_factors); - } + }); }); break; } @@ -1366,7 +1382,7 @@ void do_simulation_step(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, SimulationData &cloth_sim, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; const bke::pbvh::Tree &pbvh = *ss.pbvh; @@ -1375,34 +1391,31 @@ void do_simulation_step(const Depsgraph &depsgraph, /* Update the constraints. */ cloth_brush_satisfy_constraints(depsgraph, object, brush, cloth_sim); - Vector active_nodes; - for (bke::pbvh::Node *node : nodes) { - const int node_index = cloth_sim.node_state_index.lookup(node); - if (cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE) { - active_nodes.append(node); - /* Nodes need to be enabled again to continue. */ - cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_INACTIVE; - } - } - const float3 sim_location = cloth_brush_simulation_location_get(ss, brush); + IndexMaskMemory memory; threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask active_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE; + }); Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + active_nodes.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss); - auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors); + auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors); solve_verts_simulation(object, brush, sim_location, verts, factors, tls, cloth_sim); @@ -1413,25 +1426,34 @@ void do_simulation_step(const Depsgraph &depsgraph, } write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - } + + cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] = + SCULPT_CLOTH_NODE_INACTIVE; + }); }); break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask active_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE; + }); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const Span elems = subdiv_ccg.grids; threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + active_nodes.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const int grid_verts_num = grids.size() * key.grid_area; tls.factors.resize(grid_verts_num); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss); - auto_mask::calc_grids_factors(depsgraph, object, automasking, *nodes[i], grids, factors); + auto_mask::calc_grids_factors(depsgraph, object, automasking, nodes[i], grids, factors); const Span verts = calc_vert_indices_grids(key, grids, tls.vert_indices); solve_verts_simulation(object, brush, sim_location, verts, factors, tls, cloth_sim); @@ -1445,22 +1467,31 @@ void do_simulation_step(const Depsgraph &depsgraph, CCG_elem_offset_co(key, elem, offset) = cloth_sim.pos[grid_vert_index]; } } - } + + cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] = + SCULPT_CLOTH_NODE_INACTIVE; + }); }); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask active_nodes = IndexMask::from_predicate( + node_mask, GrainSize(1024), memory, [&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + return cloth_sim.node_state[node_index] == SCULPT_CLOTH_NODE_ACTIVE; + }); BMesh &bm = *ss.bm; threading::parallel_for(active_nodes.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + active_nodes.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); const auto_mask::Cache *automasking = auto_mask::active_cache_get(ss); - auto_mask::calc_vert_factors(depsgraph, object, automasking, *nodes[i], verts, factors); + auto_mask::calc_vert_factors(depsgraph, object, automasking, nodes[i], verts, factors); const Span vert_indices = calc_vert_indices_bmesh(verts, tls.vert_indices); solve_verts_simulation( @@ -1469,7 +1500,10 @@ void do_simulation_step(const Depsgraph &depsgraph, for (BMVert *vert : verts) { copy_v3_v3(vert->co, cloth_sim.pos[BM_elem_index_get(vert)]); } - } + + cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] = + SCULPT_CLOTH_NODE_INACTIVE; + }); }); break; } @@ -1479,7 +1513,7 @@ void do_simulation_step(const Depsgraph &depsgraph, static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; StrokeCache &cache = *ss.cache; @@ -1504,7 +1538,7 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, if (brush.cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR || brush.cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) { - calc_brush_plane(depsgraph, brush, ob, nodes, area_no, area_co); + calc_brush_plane(depsgraph, brush, ob, node_mask, area_no, area_co); /* Initialize stroke local space matrix. */ mat.x_axis() = math::cross(area_no, cache.grab_delta_symmetry); @@ -1545,9 +1579,10 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, case bke::pbvh::Type::Mesh: { const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_forces_mesh(depsgraph, ob, brush, @@ -1558,16 +1593,17 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, falloff_plane, positions_eval, vert_normals, - *nodes[i], + nodes[i], tls); - } + }); }); break; } case bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_forces_grids(depsgraph, ob, brush, @@ -1576,16 +1612,17 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, sim_location, gravity, falloff_plane, - *nodes[i], + nodes[i], tls); - } + }); }); break; } case bke::pbvh::Type::BMesh: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { calc_forces_bmesh(depsgraph, ob, brush, @@ -1594,9 +1631,9 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, sim_location, gravity, falloff_plane, - *nodes[i], + nodes[i], tls); - } + }); }); break; } @@ -1607,12 +1644,35 @@ static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph, * them. */ static void cloth_sim_initialize_default_node_state(SculptSession &ss, SimulationData &cloth_sim) { - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); + cloth_sim.node_state = Array(node_mask.size()); - cloth_sim.node_state = Array(nodes.size()); - for (const int i : nodes.index_range()) { - cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED; - cloth_sim.node_state_index.add(nodes[i], i); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED; + cloth_sim.node_state_index.add(&nodes[i], i); + }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED; + cloth_sim.node_state_index.add(&nodes[i], i); + }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + cloth_sim.node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED; + cloth_sim.node_state_index.add(&nodes[i], i); + }); + break; + } } } @@ -1621,21 +1681,23 @@ static void copy_positions_to_array(const Depsgraph &depsgraph, MutableSpan positions) { const SculptSession &ss = *object.sculpt; - bke::pbvh::Tree &pbvh = *ss.pbvh; + const bke::pbvh::Tree &pbvh = *ss.pbvh; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: positions.copy_from(bke::pbvh::vert_positions_eval(depsgraph, object)); break; case bke::pbvh::Type::Grids: { + const Span nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; - Vector all_nodes = bke::pbvh::all_leaf_nodes(pbvh); - threading::parallel_for(all_nodes.index_range(), 8, [&](const IndexRange range) { + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + threading::parallel_for(node_mask.index_range(), 8, [&](const IndexRange range) { Vector node_positions; - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*all_nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); gather_grids_positions(subdiv_ccg, grids, node_positions); scatter_data_grids(subdiv_ccg, node_positions.as_span(), grids, positions); - } + }); }); break; } @@ -1650,25 +1712,27 @@ static void copy_normals_to_array(const Depsgraph &depsgraph, MutableSpan normals) { const SculptSession &ss = *object.sculpt; - bke::pbvh::Tree &pbvh = *ss.pbvh; + const bke::pbvh::Tree &pbvh = *ss.pbvh; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: normals.copy_from(bke::pbvh::vert_normals_eval(depsgraph, object)); break; case bke::pbvh::Type::Grids: { + const Span nodes = pbvh.nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - Vector all_nodes = bke::pbvh::all_leaf_nodes(pbvh); - threading::parallel_for(all_nodes.index_range(), 8, [&](const IndexRange range) { + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + threading::parallel_for(node_mask.index_range(), 8, [&](const IndexRange range) { Vector node_normals; - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*all_nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const int grid_verts_num = grids.size() * key.grid_area; node_normals.resize(grid_verts_num); gather_grids_normals(subdiv_ccg, grids, node_normals); scatter_data_grids(subdiv_ccg, node_normals.as_span(), grids, normals); - } + }); }); break; } @@ -1734,31 +1798,57 @@ void brush_store_simulation_state(const Depsgraph &depsgraph, copy_positions_to_array(depsgraph, object, cloth_sim.pos); } -void sim_activate_nodes(SimulationData &cloth_sim, Span nodes) +void sim_activate_nodes(const Object &object, + SimulationData &cloth_sim, + const IndexMask &node_mask) { + const SculptSession &ss = *object.sculpt; + /* Activate the nodes inside the simulation area. */ - for (bke::pbvh::Node *node : nodes) { - const int node_index = cloth_sim.node_state_index.lookup(node); - cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE; + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE; + }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE; + }); + break; + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + const int node_index = cloth_sim.node_state_index.lookup(&nodes[i]); + cloth_sim.node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE; + }); + break; + } } } static void sculpt_cloth_ensure_constraints_in_simulation_area(const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; const Brush *brush = BKE_paint_brush_for_read(&sd.paint); const float radius = ss.cache->initial_radius; const float limit = radius + (radius * brush->cloth_sim_limit); const float3 sim_location = cloth_brush_simulation_location_get(ss, brush); - ensure_nodes_constraints(sd, ob, nodes, *ss.cache->cloth_sim, sim_location, limit); + ensure_nodes_constraints(sd, ob, node_mask, *ss.cache->cloth_sim, sim_location, limit); } void do_cloth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; const Brush *brush = BKE_paint_brush_for_read(&sd.paint); @@ -1789,7 +1879,7 @@ void do_cloth_brush(const Depsgraph &depsgraph, * as this will cause the ensure constraints function to skip the node in the next symmetry * passes. It needs to build the constraints here and skip simulating the first step, so all * passes can add their constraints to all affected nodes. */ - sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes); + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, node_mask); } /* The first step of a symmetry pass is never simulated as deformation modes need valid delta * for brush tip alignment. */ @@ -1797,19 +1887,19 @@ void do_cloth_brush(const Depsgraph &depsgraph, } /* Ensure the constraints for the nodes. */ - sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes); + sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, node_mask); /* Store the initial state in the simulation. */ brush_store_simulation_state(depsgraph, ob, *ss.cache->cloth_sim); /* Enable the nodes that should be simulated. */ - sim_activate_nodes(*ss.cache->cloth_sim, nodes); + sim_activate_nodes(ob, *ss.cache->cloth_sim, node_mask); /* Apply forces to the vertices. */ - cloth_brush_apply_brush_foces(depsgraph, sd, ob, nodes); + cloth_brush_apply_brush_foces(depsgraph, sd, ob, node_mask); /* Update and write the simulation to the nodes. */ - do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, nodes); + do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, node_mask); } SimulationData::~SimulationData() = default; @@ -1991,7 +2081,7 @@ static void apply_filter_forces_mesh(const Depsgraph &depsgraph, const float3 &gravity, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, FilterLocalData &tls) { @@ -2059,7 +2149,7 @@ static void apply_filter_forces_grids(const Depsgraph &depsgraph, const ClothFilterType filter_type, const float filter_strength, const float3 &gravity, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, FilterLocalData &tls) { @@ -2130,7 +2220,7 @@ static void apply_filter_forces_bmesh(const Depsgraph &depsgraph, const ClothFilterType filter_type, const float filter_strength, const float3 &gravity, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, FilterLocalData &tls) { @@ -2227,7 +2317,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent brush_store_simulation_state(*depsgraph, object, *ss.filter_cache->cloth_sim); - const Span nodes = ss.filter_cache->nodes; + const IndexMask &node_mask = ss.filter_cache->node_mask; float3 gravity(0.0f); if (sd.gravity_object) { @@ -2243,50 +2333,55 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent case bke::pbvh::Type::Mesh: { const Span positions_eval = bke::pbvh::vert_positions_eval(*depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(*depsgraph, object); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_filter_forces_mesh(*depsgraph, filter_type, filter_strength, gravity, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_filter_forces_grids( - *depsgraph, filter_type, filter_strength, gravity, *nodes[i], object, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + *depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_filter_forces_bmesh( - *depsgraph, filter_type, filter_strength, gravity, *nodes[i], object, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + *depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; + } } /* Activate all nodes. */ - sim_activate_nodes(*ss.filter_cache->cloth_sim, nodes); + sim_activate_nodes(object, *ss.filter_cache->cloth_sim, node_mask); /* Update and write the simulation to the nodes. */ - do_simulation_step(*depsgraph, sd, object, *ss.filter_cache->cloth_sim, nodes); + do_simulation_step(*depsgraph, sd, object, *ss.filter_cache->cloth_sim, node_mask); flush_update_step(C, UpdateType::Position); return OPERATOR_RUNNING_MODAL; @@ -2348,7 +2443,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent float3 origin(0); ensure_nodes_constraints( - sd, ob, ss.filter_cache->nodes, *ss.filter_cache->cloth_sim, origin, FLT_MAX); + sd, ob, ss.filter_cache->node_mask, *ss.filter_cache->cloth_sim, origin, FLT_MAX); const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); if (use_face_sets) { diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.hh b/source/blender/editors/sculpt_paint/sculpt_cloth.hh index c97134b64c9..9a0908880b5 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.hh +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.hh @@ -9,6 +9,7 @@ #pragma once #include "BLI_array.hh" +#include "BLI_index_mask_fwd.hh" #include "BLI_map.hh" #include "BLI_math_vector.hh" #include "BLI_vector.hh" @@ -113,7 +114,9 @@ std::unique_ptr brush_simulation_create(const Depsgraph &depsgra bool use_collisions, bool needs_deform_coords); -void sim_activate_nodes(SimulationData &cloth_sim, Span nodes); +void sim_activate_nodes(const Object &object, + SimulationData &cloth_sim, + const IndexMask &node_mask); void brush_store_simulation_state(const Depsgraph &depsgraph, const Object &object, @@ -123,11 +126,11 @@ void do_simulation_step(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, SimulationData &cloth_sim, - Span nodes); + const IndexMask &node_mask); void ensure_nodes_constraints(const Sculpt &sd, const Object &ob, - Span nodes, + const IndexMask &node_mask, SimulationData &cloth_sim, const float3 &initial_location, float radius); @@ -148,8 +151,9 @@ void plane_falloff_preview_draw(uint gpuattr, const float outline_col[3], float outline_alpha); -Vector brush_affected_nodes_gather(SculptSession &ss, - const Brush &brush); +IndexMask brush_affected_nodes_gather(SculptSession &ss, + const Brush &brush, + IndexMaskMemory &memory); bool is_cloth_deform_brush(const Brush &brush); diff --git a/source/blender/editors/sculpt_paint/sculpt_color.hh b/source/blender/editors/sculpt_paint/sculpt_color.hh index 6e25a0a02b7..ff11d92196c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_color.hh +++ b/source/blender/editors/sculpt_paint/sculpt_color.hh @@ -65,10 +65,10 @@ void do_paint_brush(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, - Span nodes, - Span texnodes); + const IndexMask &node_mask, + const IndexMask &texnode_mask); void do_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); } // namespace blender::ed::sculpt_paint::color diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.cc b/source/blender/editors/sculpt_paint/sculpt_detail.cc index 71b6e10d773..a5bf4196194 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.cc +++ b/source/blender/editors/sculpt_paint/sculpt_detail.cc @@ -108,15 +108,17 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + MutableSpan nodes = ss.pbvh->nodes(); + + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); if (nodes.is_empty()) { return OPERATOR_CANCELLED; } - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_topology_update(*node); - } + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); }); + /* Get the bounding box, its center and size. */ const Bounds bounds = bke::pbvh::bounds_get(*ob.sculpt->pbvh); const float3 center = math::midpoint(bounds.min, bounds.max); @@ -145,9 +147,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *op) false, false)) { - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_topology_update(*node); - } + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); }); } CLOG_INFO(&LOG, 2, "Detail flood fill took %f seconds.", BLI_time_now_seconds() - start_time); diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.cc b/source/blender/editors/sculpt_paint/sculpt_expand.cc index 1e4384f8165..97ace670823 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.cc +++ b/source/blender/editors/sculpt_paint/sculpt_expand.cc @@ -1424,27 +1424,45 @@ static void expand_cache_free(SculptSession &ss) */ static void restore_face_set_data(Object &object, Cache &expand_cache) { + SculptSession &ss = *object.sculpt; bke::SpanAttributeWriter face_sets = face_set::ensure_face_sets_mesh(object); face_sets.span.copy_from(expand_cache.original_face_sets); face_sets.finish(); - for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*object.sculpt->pbvh)) { - BKE_pbvh_node_mark_update_face_sets(*node); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); + break; + } + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); + break; + } + case bke::pbvh::Type::BMesh: { + BLI_assert_unreachable(); + break; + } } } static void restore_color_data(Object &ob, Cache &expand_cache) { SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); const GroupedSpan vert_to_face_map = ss.vert_to_face_map; bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh); - for (bke::pbvh::Node *node : nodes) { - for (const int vert : bke::pbvh::node_unique_verts(*node)) { + node_mask.foreach_index([&](const int i) { + for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) { color::color_vert_set(faces, corner_verts, vert_to_face_map, @@ -1453,14 +1471,16 @@ static void restore_color_data(Object &ob, Cache &expand_cache) expand_cache.original_colors[vert], color_attribute.span); } - BKE_pbvh_node_mark_redraw(*node); - } + BKE_pbvh_node_mark_redraw(nodes[i]); + }); color_attribute.finish(); } static void write_mask_data(Object &object, const Span mask) { SculptSession &ss = *object.sculpt; + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { Mesh &mesh = *static_cast(object.data); @@ -1469,6 +1489,8 @@ static void write_mask_data(Object &object, const Span mask) attributes.add(".sculpt_mask", bke::AttrDomain::Point, bke::AttributeInitVArray(VArray::ForSpan(mask))); + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } case bke::pbvh::Type::BMesh: { @@ -1479,6 +1501,8 @@ static void write_mask_data(Object &object, const Span mask) for (const int i : mask.index_range()) { BM_ELEM_CD_SET_FLOAT(BM_vert_at_index(&bm, i), offset, mask[i]); } + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } case bke::pbvh::Type::Grids: { @@ -1494,13 +1518,11 @@ static void write_mask_data(Object &object, const Span mask) index++; } } + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); }); break; } } - - for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*ss.pbvh)) { - BKE_pbvh_node_mark_update_mask(*node); - } } /* Main function to restore the original state of the data to how it was before starting the expand @@ -1582,7 +1604,7 @@ static void calc_new_mask_mesh(const SculptSession &ss, static void update_mask_grids(const SculptSession &ss, const BitSpan enabled_verts, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, SubdivCCG &subdiv_ccg) { const Cache &expand_cache = *ss.expand_cache; @@ -1638,7 +1660,7 @@ static void update_mask_grids(const SculptSession &ss, static void update_mask_bmesh(SculptSession &ss, const BitSpan enabled_verts, const int mask_offset, - bke::pbvh::Node *node) + bke::pbvh::BMeshNode *node) { const Cache &expand_cache = *ss.expand_cache; @@ -1708,9 +1730,9 @@ static void face_sets_update(Object &object, Cache &expand_cache) face_sets.finish(); - for (bke::pbvh::Node *node : expand_cache.nodes) { - BKE_pbvh_node_mark_update_face_sets(*node); - } + MutableSpan nodes = object.sculpt->pbvh->nodes(); + expand_cache.node_mask.foreach_index( + [&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); }); } /** @@ -1724,7 +1746,7 @@ static void colors_update_task(const Depsgraph &depsgraph, const GroupedSpan vert_to_face_map, const Span hide_vert, const Span mask, - bke::pbvh::Node *node, + bke::pbvh::MeshNode *node, bke::GSpanAttributeWriter &color_attribute) { const SculptSession &ss = *object.sculpt; @@ -1868,7 +1890,7 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex) face_sets_restore(ob, expand_cache); } - const Span nodes = expand_cache.nodes; + const IndexMask &node_mask = expand_cache.node_mask; const BitVector<> enabled_verts = enabled_state_to_bitmap(depsgraph, ob, expand_cache); @@ -1878,26 +1900,24 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex) case bke::pbvh::Type::Mesh: { const Span positions = bke::pbvh::vert_positions_eval(depsgraph, ob); mask::update_mask_mesh( - depsgraph, ob, nodes, [&](const MutableSpan mask, const Span verts) { + depsgraph, ob, node_mask, [&](const MutableSpan mask, const Span verts) { calc_new_mask_mesh(ss, positions, enabled_verts, verts, mask); }); break; } case bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - update_mask_grids(ss, enabled_verts, *nodes[i], *ss.subdiv_ccg); - } + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg); }); break; } case bke::pbvh::Type::BMesh: { const int mask_offset = CustomData_get_offset_named( &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - update_mask_bmesh(ss, enabled_verts, mask_offset, nodes[i]); - } + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]); }); break; } @@ -1920,19 +1940,18 @@ static void update_for_vert(bContext *C, Object &ob, const PBVHVertRef vertex) const VArraySpan mask = *attributes.lookup(".sculpt_mask", bke::AttrDomain::Point); bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - colors_update_task(depsgraph, - ob, - vert_positions, - faces, - corner_verts, - vert_to_face_map, - hide_vert, - mask, - nodes[i], - color_attribute); - } + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + colors_update_task(depsgraph, + ob, + vert_positions, + faces, + corner_verts, + vert_to_face_map, + hide_vert, + mask, + &nodes[i], + color_attribute); }); color_attribute.finish(); flush_update_step(C, UpdateType::Color); @@ -2017,12 +2036,6 @@ static void finish(bContext *C) SculptSession &ss = *ob.sculpt; undo::push_end(ob); - /* Tag all nodes to redraw to avoid artifacts after the fast partial updates. */ - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_update_mask(*node); - } - switch (ss.expand_cache->target) { case TargetType::Mask: flush_update_done(C, ob, UpdateType::Mask); @@ -2485,20 +2498,21 @@ static void cache_initial_config_set(bContext *C, wmOperator *op, Cache &expand_ static void undo_push(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache) { SculptSession &ss = *ob.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (expand_cache.target) { case TargetType::Mask: - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Mask); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask); break; case TargetType::FaceSets: - undo::push_nodes(depsgraph, ob, nodes, undo::Type::FaceSet); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::FaceSet); break; case TargetType::Colors: { const Mesh &mesh = *static_cast(ob.data); /* The sculpt undo system needs corner indices for corner domain color attributes. */ BKE_pbvh_ensure_node_face_corners(*ss.pbvh, mesh.corner_tris()); - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Color); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color); break; } } @@ -2619,7 +2633,8 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even set_initial_components_for_mouse(C, ob, *ss.expand_cache, mouse); /* Cache bke::pbvh::Tree nodes. */ - ss.expand_cache->nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + ss.expand_cache->node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, + ss.expand_cache->node_mask_memory); /* Store initial state. */ original_state_store(ob, *ss.expand_cache); diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.hh b/source/blender/editors/sculpt_paint/sculpt_expand.hh index d810717273e..61032f84007 100644 --- a/source/blender/editors/sculpt_paint/sculpt_expand.hh +++ b/source/blender/editors/sculpt_paint/sculpt_expand.hh @@ -8,6 +8,7 @@ #pragma once #include "BLI_array.hh" +#include "BLI_index_mask.hh" #include "BLI_math_vector.hh" #include "BLI_set.hh" @@ -117,7 +118,8 @@ struct Cache { /* Cached pbvh::Tree nodes. This allows to skip gathering all nodes from the pbvh::Tree each time * expand needs to update the state of the elements. */ - Vector nodes; + IndexMaskMemory node_mask_memory; + IndexMask node_mask; /* Expand state options. */ diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 7c906ff0b71..add30ed5ce8 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -284,7 +284,7 @@ void filter_verts_with_unique_face_sets_bmesh(const bool unique, static void face_sets_update(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const FunctionRef, MutableSpan)> calc_face_sets) { SculptSession &ss = *object.sculpt; @@ -300,29 +300,50 @@ static void face_sets_update(const Depsgraph &depsgraph, }; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - TLS &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span faces = - pbvh.type() == bke::pbvh::Type::Mesh ? - bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), tls.face_indices) : - bke::pbvh::node_face_indices_calc_grids( - *ss.subdiv_ccg, static_cast(*node), tls.face_indices); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = bke::pbvh::node_face_indices_calc_mesh( + tri_faces, nodes[i], tls.face_indices); - tls.new_face_sets.resize(faces.size()); - MutableSpan new_face_sets = tls.new_face_sets; - array_utils::gather(face_sets.span.as_span(), faces, new_face_sets); - calc_face_sets(faces, new_face_sets); - if (array_utils::indexed_data_equal(face_sets.span, faces, new_face_sets)) { - continue; - } + tls.new_face_sets.resize(faces.size()); + MutableSpan new_face_sets = tls.new_face_sets; + array_utils::gather(face_sets.span.as_span(), faces, new_face_sets); + calc_face_sets(faces, new_face_sets); + if (array_utils::indexed_data_equal(face_sets.span, faces, new_face_sets)) { + return; + } - undo::push_node(depsgraph, object, node, undo::Type::FaceSet); - array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span); - BKE_pbvh_node_mark_update_face_sets(*node); - } - }); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); + array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + }); + }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = bke::pbvh::node_face_indices_calc_grids( + *ss.subdiv_ccg, nodes[i], tls.face_indices); + + tls.new_face_sets.resize(faces.size()); + MutableSpan new_face_sets = tls.new_face_sets; + array_utils::gather(face_sets.span.as_span(), faces, new_face_sets); + calc_face_sets(faces, new_face_sets); + if (array_utils::indexed_data_equal(face_sets.span, faces, new_face_sets)) { + return; + } + + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); + array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + }); + }); + } face_sets.finish(); } @@ -334,9 +355,7 @@ enum class CreateMode { Selection = 3, }; -static void clear_face_sets(const Depsgraph &depsgraph, - Object &object, - const Span nodes) +static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask) { Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); @@ -349,24 +368,41 @@ static void clear_face_sets(const Depsgraph &depsgraph, const int default_face_set = mesh.face_sets_color_default; const VArraySpan face_sets = *attributes.lookup(".sculpt_face_set", bke::AttrDomain::Face); threading::EnumerableThreadSpecific> all_face_indices; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - Vector &face_indices = all_face_indices.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span faces = - pbvh.type() == bke::pbvh::Type::Mesh ? - bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), face_indices) : - bke::pbvh::node_face_indices_calc_grids( - *ss.subdiv_ccg, static_cast(*node), face_indices); - if (std::any_of(faces.begin(), faces.end(), [&](const int face) { - return face_sets[face] != default_face_set; - })) - { - undo::push_node(depsgraph, object, node, undo::Type::FaceSet); - BKE_pbvh_node_mark_update_face_sets(*node); - } - } - }); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + Vector &face_indices = all_face_indices.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = + + bke::pbvh::node_face_indices_calc_mesh(tri_faces, nodes[i], face_indices); + if (std::any_of(faces.begin(), faces.end(), [&](const int face) { + return face_sets[face] != default_face_set; + })) + { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + } + }); + }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + Vector &face_indices = all_face_indices.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = bke::pbvh::node_face_indices_calc_grids( + *ss.subdiv_ccg, nodes[i], face_indices); + if (std::any_of(faces.begin(), faces.end(), [&](const int face) { + return face_sets[face] != default_face_set; + })) + { + undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + } + }); + }); + } attributes.remove(".sculpt_face_set"); } @@ -398,7 +434,8 @@ static int create_op_exec(bContext *C, wmOperator *op) const int next_face_set = find_next_available_id(object); - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); switch (mode) { case CreateMode::Masked: { const OffsetIndices faces = mesh.faces(); @@ -408,22 +445,24 @@ static int create_op_exec(bContext *C, wmOperator *op) const VArraySpan mask = *attributes.lookup(".sculpt_mask", bke::AttrDomain::Point); if (!mask.is_empty()) { - face_sets_update( - depsgraph, object, nodes, [&](const Span indices, MutableSpan face_sets) { - for (const int i : indices.index_range()) { - if (!hide_poly.is_empty() && hide_poly[indices[i]]) { - continue; - } - const Span face_verts = corner_verts.slice(faces[indices[i]]); - if (!std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) { - return mask[vert] > 0.5f; - })) - { - continue; - } - face_sets[i] = next_face_set; - } - }); + face_sets_update(depsgraph, + object, + node_mask, + [&](const Span indices, MutableSpan face_sets) { + for (const int i : indices.index_range()) { + if (!hide_poly.is_empty() && hide_poly[indices[i]]) { + continue; + } + const Span face_verts = corner_verts.slice(faces[indices[i]]); + if (!std::any_of(face_verts.begin(), + face_verts.end(), + [&](const int vert) { return mask[vert] > 0.5f; })) + { + continue; + } + face_sets[i] = next_face_set; + } + }); } break; } @@ -436,27 +475,31 @@ static int create_op_exec(bContext *C, wmOperator *op) /* If all vertices in the sculpt are visible, remove face sets and update the default * color. This way the new face set will be white, and it is a quick way of disabling all * face sets and the performance hit of rendering the overlay. */ - clear_face_sets(depsgraph, object, nodes); + clear_face_sets(depsgraph, object, node_mask); break; case array_utils::BooleanMix::Mixed: const VArraySpan hide_poly_span(hide_poly); - face_sets_update( - depsgraph, object, nodes, [&](const Span indices, MutableSpan face_sets) { - for (const int i : indices.index_range()) { - if (!hide_poly_span[indices[i]]) { - face_sets[i] = next_face_set; - } - } - }); + face_sets_update(depsgraph, + object, + node_mask, + [&](const Span indices, MutableSpan face_sets) { + for (const int i : indices.index_range()) { + if (!hide_poly_span[indices[i]]) { + face_sets[i] = next_face_set; + } + } + }); break; } break; } case CreateMode::All: { - face_sets_update( - depsgraph, object, nodes, [&](const Span /*indices*/, MutableSpan face_sets) { - face_sets.fill(next_face_set); - }); + face_sets_update(depsgraph, + object, + node_mask, + [&](const Span /*indices*/, MutableSpan face_sets) { + face_sets.fill(next_face_set); + }); break; } case CreateMode::Selection: { @@ -466,7 +509,7 @@ static int create_op_exec(bContext *C, wmOperator *op) bke::AttrDomain::Face); face_sets_update( - depsgraph, object, nodes, [&](const Span indices, MutableSpan face_sets) { + depsgraph, object, node_mask, [&](const Span indices, MutableSpan face_sets) { for (const int i : indices.index_range()) { if (select_poly[indices[i]]) { if (!hide_poly.is_empty() && hide_poly[i]) { @@ -648,14 +691,14 @@ static int init_op_exec(bContext *C, wmOperator *op) } bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); - - if (nodes.is_empty()) { + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + if (node_mask.is_empty()) { return OPERATOR_CANCELLED; } undo::push_begin(ob, op); - undo::push_nodes(*depsgraph, ob, nodes, undo::Type::FaceSet); + undo::push_nodes(*depsgraph, ob, node_mask, undo::Type::FaceSet); const float threshold = RNA_float_get(op->ptr, "threshold"); @@ -744,8 +787,13 @@ static int init_op_exec(bContext *C, wmOperator *op) undo::push_end(ob); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_redraw(*node); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); } SCULPT_tag_update_overlays(C); @@ -828,7 +876,7 @@ enum class VisibilityMode { static void face_hide_update(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const FunctionRef, MutableSpan)> calc_hide) { SculptSession &ss = *object.sculpt; @@ -846,30 +894,52 @@ static void face_hide_update(const Depsgraph &depsgraph, bool any_changed = false; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - TLS &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - const Span faces = - pbvh.type() == bke::pbvh::Type::Mesh ? - bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), tls.face_indices) : - bke::pbvh::node_face_indices_calc_grids( - *ss.subdiv_ccg, static_cast(*node), tls.face_indices); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = bke::pbvh::node_face_indices_calc_mesh( + tri_faces, nodes[i], tls.face_indices); - tls.new_hide.resize(faces.size()); - MutableSpan new_hide = tls.new_hide; - array_utils::gather(hide_poly.span.as_span(), faces, new_hide); - calc_hide(faces, new_hide); - if (array_utils::indexed_data_equal(hide_poly.span, faces, new_hide)) { - continue; - } + tls.new_hide.resize(faces.size()); + MutableSpan new_hide = tls.new_hide; + array_utils::gather(hide_poly.span.as_span(), faces, new_hide); + calc_hide(faces, new_hide); + if (array_utils::indexed_data_equal(hide_poly.span, faces, new_hide)) { + return; + } - any_changed = true; - undo::push_node(depsgraph, object, node, undo::Type::HideFace); - array_utils::scatter(new_hide.as_span(), faces, hide_poly.span); - BKE_pbvh_node_mark_update_visibility(*node); - } - }); + any_changed = true; + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideFace); + array_utils::scatter(new_hide.as_span(), faces, hide_poly.span); + BKE_pbvh_node_mark_update_visibility(nodes[i]); + }); + }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + const Span faces = bke::pbvh::node_face_indices_calc_grids( + *ss.subdiv_ccg, nodes[i], tls.face_indices); + + tls.new_hide.resize(faces.size()); + MutableSpan new_hide = tls.new_hide; + array_utils::gather(hide_poly.span.as_span(), faces, new_hide); + calc_hide(faces, new_hide); + if (array_utils::indexed_data_equal(hide_poly.span, faces, new_hide)) { + return; + } + + any_changed = true; + undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideFace); + array_utils::scatter(new_hide.as_span(), faces, hide_poly.span); + BKE_pbvh_node_mark_update_visibility(nodes[i]); + }); + }); + } hide_poly.finish(); if (any_changed) { @@ -877,14 +947,14 @@ static void face_hide_update(const Depsgraph &depsgraph, } } -static void show_all(Depsgraph &depsgraph, Object &object, const Span nodes) +static void show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask) { switch (object.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: - hide::mesh_show_all(depsgraph, object, nodes); + hide::mesh_show_all(depsgraph, object, node_mask); break; case bke::pbvh::Type::Grids: - hide::grids_show_all(depsgraph, object, nodes); + hide::grids_show_all(depsgraph, object, node_mask); break; case bke::pbvh::Type::BMesh: BLI_assert_unreachable(); @@ -912,7 +982,8 @@ static int change_visibility_exec(bContext *C, wmOperator *op) undo::push_begin(object, op); bke::pbvh::Tree &pbvh = *object.sculpt->pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); const bke::AttributeAccessor attributes = mesh->attributes(); const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); @@ -922,11 +993,11 @@ static int change_visibility_exec(bContext *C, wmOperator *op) switch (mode) { case VisibilityMode::Toggle: { if (hide_poly.contains(true) || face_sets.is_empty()) { - show_all(depsgraph, object, nodes); + show_all(depsgraph, object, node_mask); } else { face_hide_update( - depsgraph, object, nodes, [&](const Span faces, MutableSpan hide) { + depsgraph, object, node_mask, [&](const Span faces, MutableSpan hide) { for (const int i : hide.index_range()) { hide[i] = face_sets[faces[i]] != active_face_set; } @@ -936,11 +1007,11 @@ static int change_visibility_exec(bContext *C, wmOperator *op) } case VisibilityMode::ShowActive: if (face_sets.is_empty()) { - show_all(depsgraph, object, nodes); + show_all(depsgraph, object, node_mask); } else { face_hide_update( - depsgraph, object, nodes, [&](const Span faces, MutableSpan hide) { + depsgraph, object, node_mask, [&](const Span faces, MutableSpan hide) { for (const int i : hide.index_range()) { if (face_sets[faces[i]] == active_face_set) { hide[i] = false; @@ -952,13 +1023,13 @@ static int change_visibility_exec(bContext *C, wmOperator *op) case VisibilityMode::HideActive: if (face_sets.is_empty()) { face_hide_update( - depsgraph, object, nodes, [&](const Span /*faces*/, MutableSpan hide) { + depsgraph, object, node_mask, [&](const Span /*faces*/, MutableSpan hide) { hide.fill(true); }); } else { face_hide_update( - depsgraph, object, nodes, [&](const Span faces, MutableSpan hide) { + depsgraph, object, node_mask, [&](const Span faces, MutableSpan hide) { for (const int i : hide.index_range()) { if (face_sets[faces[i]] == active_face_set) { hide[i] = true; @@ -1078,9 +1149,15 @@ static int randomize_colors_exec(bContext *C, wmOperator * /*op*/) mesh->face_sets_color_seed += 1; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_redraw(*node); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); } SCULPT_tag_update_overlays(C); @@ -1129,9 +1206,10 @@ static void edit_grow_shrink(const Depsgraph &depsgraph, undo::push_begin(object, op); - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); face_sets_update( - depsgraph, object, nodes, [&](const Span indices, MutableSpan face_sets) { + depsgraph, object, node_mask, [&](const Span indices, MutableSpan face_sets) { for (const int i : indices.index_range()) { const int face = indices[i]; if (!modify_hidden && !hide_poly.is_empty() && hide_poly[face]) { @@ -1289,14 +1367,15 @@ static void edit_fairing(const Depsgraph &depsgraph, Vector translations; }; - Vector nodes = bke::pbvh::search_gather(const_cast(pbvh), - {}); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + MutableSpan nodes = ss.pbvh->nodes(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.translations.resize(verts.size()); const MutableSpan translations = tls.translations; for (const int i : verts.index_range()) { @@ -1304,7 +1383,7 @@ static void edit_fairing(const Depsgraph &depsgraph, } scale_translations(translations, strength); write_translations(depsgraph, sd, ob, positions, verts, translations, positions_orig); - } + }); }); } @@ -1385,15 +1464,23 @@ static void edit_modify_coordinates( const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt; SculptSession &ss = *ob.sculpt; bke::pbvh::Tree &pbvh = *ss.pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); const float strength = RNA_float_get(op->ptr, "strength"); undo::push_begin(ob, op); - undo::push_nodes(depsgraph, ob, nodes, undo::Type::Position); - for (bke::pbvh::Node *node : nodes) { - BKE_pbvh_node_mark_positions_update(*node); + undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position); + + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); }); } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); }); + } + switch (mode) { case EditMode::FairPositions: edit_fairing(depsgraph, sd, ob, active_face_set, MESH_FAIRING_DEPTH_POSITION, strength); @@ -1561,8 +1648,7 @@ static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &ges undo::push_begin(*gesture_data.vc.obact, &op); } -static void gesture_apply_mesh(gesture::GestureData &gesture_data, - const Span nodes) +static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMask &node_mask) { FaceSetOperation *face_set_operation = (FaceSetOperation *)gesture_data.operation; const int new_face_set = face_set_operation->new_face_set_id; @@ -1585,56 +1671,84 @@ static void gesture_apply_mesh(gesture::GestureData &gesture_data, }; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) { - TLS &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.slice(range)) { - undo::push_node(depsgraph, *gesture_data.vc.obact, node, undo::Type::FaceSet); - const Span node_faces = - pbvh.type() == bke::pbvh::Type::Mesh ? - bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), tls.face_indices) : - bke::pbvh::node_face_indices_calc_grids( - *ss.subdiv_ccg, static_cast(*node), tls.face_indices); + if (pbvh.type() == bke::pbvh::Type::Mesh) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet); + const Span node_faces = bke::pbvh::node_face_indices_calc_mesh( + tri_faces, nodes[i], tls.face_indices); - bool any_updated = false; - for (const int face : node_faces) { - if (!hide_poly.is_empty() && hide_poly[face]) { - continue; + bool any_updated = false; + for (const int face : node_faces) { + if (!hide_poly.is_empty() && hide_poly[face]) { + continue; + } + const Span face_verts = corner_verts.slice(faces[face]); + const float3 face_center = bke::mesh::face_center_calc(positions, face_verts); + const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts); + if (!gesture::is_affected(gesture_data, face_center, face_normal)) { + continue; + } + face_sets.span[face] = new_face_set; + any_updated = true; } - const Span face_verts = corner_verts.slice(faces[face]); - const float3 face_center = bke::mesh::face_center_calc(positions, face_verts); - const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts); - if (!gesture::is_affected(gesture_data, face_center, face_normal)) { - continue; + if (any_updated) { + BKE_pbvh_node_mark_update_face_sets(nodes[i]); } - face_sets.span[face] = new_face_set; - any_updated = true; - } - if (any_updated) { - BKE_pbvh_node_mark_update_face_sets(*node); - } - } - }); + }); + }); + } + else if (pbvh.type() == bke::pbvh::Type::Grids) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + TLS &tls = all_tls.local(); + node_mask.slice(range).foreach_index([&](const int i) { + undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet); + const Span node_faces = bke::pbvh::node_face_indices_calc_grids( + *ss.subdiv_ccg, nodes[i], tls.face_indices); + + bool any_updated = false; + for (const int face : node_faces) { + if (!hide_poly.is_empty() && hide_poly[face]) { + continue; + } + const Span face_verts = corner_verts.slice(faces[face]); + const float3 face_center = bke::mesh::face_center_calc(positions, face_verts); + const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts); + if (!gesture::is_affected(gesture_data, face_center, face_normal)) { + continue; + } + face_sets.span[face] = new_face_set; + any_updated = true; + } + if (any_updated) { + BKE_pbvh_node_mark_update_face_sets(nodes[i]); + } + }); + }); + } face_sets.finish(); } -static void gesture_apply_bmesh(gesture::GestureData &gesture_data, - const Span nodes) +static void gesture_apply_bmesh(gesture::GestureData &gesture_data, const IndexMask &node_mask) { FaceSetOperation *face_set_operation = (FaceSetOperation *)gesture_data.operation; const Depsgraph &depsgraph = *gesture_data.vc.depsgraph; const int new_face_set = face_set_operation->new_face_set_id; SculptSession &ss = *gesture_data.ss; + MutableSpan nodes = ss.pbvh->nodes(); BMesh *bm = ss.bm; const int offset = CustomData_get_offset_named(&bm->pdata, CD_PROP_INT32, ".sculpt_face_set"); - threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) { - for (bke::pbvh::Node *node : nodes.slice(range)) { - undo::push_node(depsgraph, *gesture_data.vc.obact, node, undo::Type::FaceSet); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { + node_mask.slice(range).foreach_index([&](const int i) { + undo::push_node(depsgraph, *gesture_data.vc.obact, &nodes[i], undo::Type::FaceSet); bool any_updated = false; - for (BMFace *face : BKE_pbvh_bmesh_node_faces(node)) { + for (BMFace *face : BKE_pbvh_bmesh_node_faces(&nodes[i])) { if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) { continue; } @@ -1648,9 +1762,9 @@ static void gesture_apply_bmesh(gesture::GestureData &gesture_data, } if (any_updated) { - BKE_pbvh_node_mark_update_visibility(*node); + BKE_pbvh_node_mark_update_visibility(nodes[i]); } - } + }); }); } @@ -1659,10 +1773,10 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa switch (gesture_data.ss->pbvh->type()) { case bke::pbvh::Type::Grids: case bke::pbvh::Type::Mesh: - gesture_apply_mesh(gesture_data, gesture_data.nodes); + gesture_apply_mesh(gesture_data, gesture_data.node_mask); break; case bke::pbvh::Type::BMesh: - gesture_apply_bmesh(gesture_data, gesture_data.nodes); + gesture_apply_bmesh(gesture_data, gesture_data.node_mask); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter.hh b/source/blender/editors/sculpt_paint/sculpt_filter.hh index 5ab662f5fc5..7bbce59e7a1 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter.hh +++ b/source/blender/editors/sculpt_paint/sculpt_filter.hh @@ -11,6 +11,7 @@ #include #include "BLI_array.hh" +#include "BLI_index_mask.hh" #include "BLI_math_matrix.hh" #include "BLI_math_vector.hh" #include "BLI_vector.hh" @@ -76,7 +77,8 @@ struct Cache { Array limit_surface_co; /* unmasked nodes */ - Vector nodes; + IndexMaskMemory node_mask_memory; + IndexMask node_mask; /* Cloth filter. */ std::unique_ptr cloth_sim; diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc index ee48c90e6b8..490f862d099 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.cc @@ -103,7 +103,7 @@ static void color_filter_task(const Depsgraph &depsgraph, const FilterType mode, const float filter_strength, const float *filter_fill_color, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalData &tls, bke::GSpanAttributeWriter &color_attribute) { @@ -311,7 +311,8 @@ static void color_filter_task(const Depsgraph &depsgraph, static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss) { - const Span nodes = ss.filter_cache->nodes; + MutableSpan nodes = ss.pbvh->nodes(); + const IndexMask &node_mask = ss.filter_cache->node_mask; const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); const GroupedSpan vert_to_face_map = ss.vert_to_face_map; @@ -323,13 +324,10 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss) } const MutableSpan pre_smoothed_color = ss.filter_cache->pre_smoothed_color; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); - for (const int vert : verts) { - pre_smoothed_color[vert] = color_vert_get( - faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) { + pre_smoothed_color[vert] = color_vert_get( + faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, vert); } }); @@ -339,10 +337,10 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss) }; threading::EnumerableThreadSpecific all_tls; for ([[maybe_unused]] const int iteration : IndexRange(2)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.vert_neighbors.resize(verts.size()); calc_vert_neighbors(faces, corner_verts, vert_to_face_map, {}, verts, tls.vert_neighbors); @@ -357,7 +355,7 @@ static void sculpt_color_presmooth_init(const Mesh &mesh, SculptSession &ss) pre_smoothed_color[verts[i]] = math::interpolate( pre_smoothed_color[verts[i]], averaged_colors[i], 0.5f); } - } + }); }); } } @@ -366,6 +364,7 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob) { const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C); SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); const FilterType mode = FilterType(RNA_enum_get(op->ptr, "type")); float filter_strength = RNA_float_get(op->ptr, "strength"); @@ -379,7 +378,7 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob) sculpt_color_presmooth_init(mesh, ss); } - const Span nodes = ss.filter_cache->nodes; + const IndexMask &node_mask = ss.filter_cache->node_mask; const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -387,9 +386,9 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob) bke::GSpanAttributeWriter color_attribute = active_color_attribute_for_write(mesh); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { color_filter_task(depsgraph, ob, faces, @@ -398,11 +397,11 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob) mode, filter_strength, fill_color, - *nodes[i], + nodes[i], tls, color_attribute); - BKE_pbvh_node_mark_update_color(*nodes[i]); - } + BKE_pbvh_node_mark_update_color(nodes[i]); + }); }); color_attribute.finish(); flush_update_step(C, UpdateType::Color); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc index 1459a76cbf3..1ae05ce93a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.cc @@ -109,24 +109,25 @@ struct FilterLocalData { static void apply_new_mask_mesh(const Depsgraph &depsgraph, Object &object, const Span hide_vert, - const Span nodes, + const IndexMask &node_mask, const OffsetIndices node_verts, const Span new_mask, MutableSpan mask) { + MutableSpan nodes = object.sculpt->pbvh->nodes(); threading::EnumerableThreadSpecific> all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &tls = all_tls.local(); - for (const int i : range) { - const Span verts = hide::node_visible_verts(*nodes[i], hide_vert, tls); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = hide::node_visible_verts(nodes[i], hide_vert, tls); const Span new_node_mask = new_mask.slice(node_verts[i]); if (array_utils::indexed_data_equal(mask, verts, new_node_mask)) { - continue; + return; } - undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask); + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); scatter_data_mesh(new_node_mask, verts, mask); - BKE_pbvh_node_mark_update_mask(*nodes[i]); - } + BKE_pbvh_node_mark_update_mask(nodes[i]); + }); }); } @@ -135,7 +136,7 @@ static void smooth_mask_mesh(const OffsetIndices faces, const GroupedSpan vert_to_face_map, const Span hide_poly, const Span mask, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -153,7 +154,7 @@ static void sharpen_mask_mesh(const OffsetIndices faces, const GroupedSpan vert_to_face_map, const Span hide_poly, const Span mask, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -177,7 +178,7 @@ static void grow_mask_mesh(const OffsetIndices faces, const GroupedSpan vert_to_face_map, const Span hide_poly, const Span mask, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -200,7 +201,7 @@ static void shrink_mask_mesh(const OffsetIndices faces, const GroupedSpan vert_to_face_map, const Span hide_poly, const Span mask, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -221,7 +222,7 @@ static void shrink_mask_mesh(const OffsetIndices faces, static void increase_contrast_mask_mesh(const Depsgraph &depsgraph, const Object &object, const Span hide_vert, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan mask) { @@ -245,7 +246,7 @@ static void increase_contrast_mask_mesh(const Depsgraph &depsgraph, static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph, const Object &object, const Span hide_vert, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, FilterLocalData &tls, MutableSpan mask) { @@ -287,25 +288,24 @@ BLI_NOINLINE static void copy_old_hidden_mask_grids(const SubdivCCG &subdiv_ccg, static void apply_new_mask_grids(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const OffsetIndices node_verts, const Span new_mask) { SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); - const Span new_node_mask = new_mask.slice(node_verts[i]); - if (mask_equals_array_grids(subdiv_ccg.grids, key, grids, new_node_mask)) { - continue; - } - undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask); - scatter_mask_grids(new_node_mask, subdiv_ccg, grids); - BKE_pbvh_node_mark_update_mask(*nodes[i]); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); + const Span new_node_mask = new_mask.slice(node_verts[i]); + if (mask_equals_array_grids(subdiv_ccg.grids, key, grids, new_node_mask)) { + return; } + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + scatter_mask_grids(new_node_mask, subdiv_ccg, grids); + BKE_pbvh_node_mark_update_mask(nodes[i]); }); /* New mask values need propagation across grid boundaries. */ @@ -313,7 +313,7 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph, } static void smooth_mask_grids(const SubdivCCG &subdiv_ccg, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, MutableSpan new_mask) { const Span grids = bke::pbvh::node_grid_indices(node); @@ -322,7 +322,7 @@ static void smooth_mask_grids(const SubdivCCG &subdiv_ccg, } static void sharpen_mask_grids(const SubdivCCG &subdiv_ccg, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -343,7 +343,7 @@ static void sharpen_mask_grids(const SubdivCCG &subdiv_ccg, } static void grow_mask_grids(const SubdivCCG &subdiv_ccg, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, MutableSpan new_mask) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -378,7 +378,7 @@ static void grow_mask_grids(const SubdivCCG &subdiv_ccg, } static void shrink_mask_grids(const SubdivCCG &subdiv_ccg, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, MutableSpan new_mask) { const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -414,7 +414,7 @@ static void shrink_mask_grids(const SubdivCCG &subdiv_ccg, static void increase_contrast_mask_grids(const Depsgraph &depsgraph, const Object &object, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, FilterLocalData &tls) { SculptSession &ss = *object.sculpt; @@ -445,7 +445,7 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph, static void decrease_contrast_mask_grids(const Depsgraph &depsgraph, const Object &object, - bke::pbvh::Node &node, + bke::pbvh::GridsNode &node, FilterLocalData &tls) { SculptSession &ss = *object.sculpt; @@ -490,29 +490,28 @@ BLI_NOINLINE static void copy_old_hidden_mask_bmesh(const int mask_offset, static void apply_new_mask_bmesh(const Depsgraph &depsgraph, Object &object, const int mask_offset, - const Span nodes, + const IndexMask &node_mask, const OffsetIndices node_verts, const Span new_mask) { SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); BMesh &bm = *ss.bm; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); - const Span new_node_mask = new_mask.slice(node_verts[i]); - if (mask_equals_array_bmesh(mask_offset, verts, new_node_mask)) { - continue; - } - undo::push_node(depsgraph, object, nodes[i], undo::Type::Mask); - scatter_mask_bmesh(new_node_mask, bm, verts); - BKE_pbvh_node_mark_update_mask(*nodes[i]); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); + const Span new_node_mask = new_mask.slice(node_verts[i]); + if (mask_equals_array_bmesh(mask_offset, verts, new_node_mask)) { + return; } + undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask); + scatter_mask_bmesh(new_node_mask, bm, verts); + BKE_pbvh_node_mark_update_mask(nodes[i]); }); } static void smooth_mask_bmesh(const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, MutableSpan new_mask) { const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); @@ -522,7 +521,7 @@ static void smooth_mask_bmesh(const int mask_offset, static void sharpen_mask_bmesh(const BMesh &bm, const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, FilterLocalData &tls, MutableSpan new_mask) { @@ -540,7 +539,7 @@ static void sharpen_mask_bmesh(const BMesh &bm, } static void grow_mask_bmesh(const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, MutableSpan new_mask) { const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); @@ -560,7 +559,7 @@ static void grow_mask_bmesh(const int mask_offset, } static void shrink_mask_bmesh(const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, MutableSpan new_mask) { const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&node); @@ -582,7 +581,7 @@ static void shrink_mask_bmesh(const int mask_offset, static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph, Object &object, const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, FilterLocalData &tls) { SculptSession &ss = *object.sculpt; @@ -612,7 +611,7 @@ static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph, static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph, Object &object, const int mask_offset, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, FilterLocalData &tls) { SculptSession &ss = *object.sculpt; @@ -660,7 +659,8 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) SculptSession &ss = *ob.sculpt; bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); undo::push_begin(ob, op); int iterations = RNA_int_get(op->ptr, "iterations"); @@ -676,6 +676,7 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -686,103 +687,98 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) bke::SpanAttributeWriter mask = attributes.lookup_for_write_span(".sculpt_mask"); Array node_vert_offset_data; - OffsetIndices node_offsets = create_node_vert_offsets(nodes, node_vert_offset_data); + OffsetIndices node_offsets = create_node_vert_offsets( + nodes, node_mask, node_vert_offset_data); Array new_masks(node_offsets.total_size()); for ([[maybe_unused]] const int iteration : IndexRange(iterations)) { switch (filter_type) { case FilterType::Smooth: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { smooth_mask_mesh(faces, corner_verts, vert_to_face_map, hide_poly, mask.span, - *nodes[i], + nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); - } + }); }); apply_new_mask_mesh( - *depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span); + *depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span); break; } case FilterType::Sharpen: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { sharpen_mask_mesh(faces, corner_verts, vert_to_face_map, hide_poly, mask.span, - *nodes[i], + nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); - } + }); }); apply_new_mask_mesh( - *depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span); + *depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span); break; } case FilterType::Grow: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { grow_mask_mesh(faces, corner_verts, vert_to_face_map, hide_poly, mask.span, - *nodes[i], + nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); - } + }); }); apply_new_mask_mesh( - *depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span); + *depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span); break; } case FilterType::Shrink: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { shrink_mask_mesh(faces, corner_verts, vert_to_face_map, hide_poly, mask.span, - *nodes[i], + nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); - } + }); }); apply_new_mask_mesh( - *depsgraph, ob, hide_vert, nodes, node_offsets, new_masks, mask.span); + *depsgraph, ob, hide_vert, node_mask, node_offsets, new_masks, mask.span); break; } case FilterType::ContrastIncrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - threading::isolate_task([&]() { - for (const int i : range) { - increase_contrast_mask_mesh( - *depsgraph, ob, hide_vert, *nodes[i], tls, mask.span); - } + node_mask.slice(range).foreach_index([&](const int i) { + increase_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span); }); }); break; } case FilterType::ContrastDecrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - threading::isolate_task([&]() { - for (const int i : range) { - decrease_contrast_mask_mesh( - *depsgraph, ob, hide_vert, *nodes[i], tls, mask.span); - } + node_mask.slice(range).foreach_index([&](const int i) { + decrease_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span); }); }); break; @@ -793,73 +789,66 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Array node_vert_offset_data; OffsetIndices node_offsets = create_node_vert_offsets( - nodes, BKE_subdiv_ccg_key_top_level(subdiv_ccg), node_vert_offset_data); + BKE_subdiv_ccg_key_top_level(subdiv_ccg), nodes, node_mask, node_vert_offset_data); Array new_masks(node_offsets.total_size()); for ([[maybe_unused]] const int iteration : IndexRange(iterations)) { switch (filter_type) { case FilterType::Smooth: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - smooth_mask_grids( - subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + smooth_mask_grids( + subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks); + apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks); break; } case FilterType::Sharpen: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { - sharpen_mask_grids(subdiv_ccg, - *nodes[i], - tls, - new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.slice(range).foreach_index([&](const int i) { + sharpen_mask_grids( + subdiv_ccg, nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); + }); }); - apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks); + apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks); break; } case FilterType::Grow: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - grow_mask_grids( - subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + grow_mask_grids( + subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks); + apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks); break; } case FilterType::Shrink: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - shrink_mask_grids( - subdiv_ccg, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + shrink_mask_grids( + subdiv_ccg, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_grids(*depsgraph, ob, nodes, node_offsets, new_masks); + apply_new_mask_grids(*depsgraph, ob, node_mask, node_offsets, new_masks); break; } case FilterType::ContrastIncrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { - increase_contrast_mask_grids(*depsgraph, ob, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); + }); }); break; } case FilterType::ContrastDecrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { - decrease_contrast_mask_grids(*depsgraph, ob, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls); + }); }); break; } @@ -868,76 +857,72 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); BMesh &bm = *ss.bm; BM_mesh_elem_index_ensure(&bm, BM_VERT); const int mask_offset = CustomData_get_offset_named( &bm.vdata, CD_PROP_FLOAT, ".sculpt_mask"); Array node_vert_offset_data; - OffsetIndices node_offsets = create_node_vert_offsets_bmesh(nodes, node_vert_offset_data); + OffsetIndices node_offsets = create_node_vert_offsets_bmesh( + nodes, node_mask, node_vert_offset_data); Array new_masks(node_offsets.total_size()); for ([[maybe_unused]] const int iteration : IndexRange(iterations)) { switch (filter_type) { case FilterType::Smooth: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - smooth_mask_bmesh( - mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + smooth_mask_bmesh( + mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks); + apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks); break; } case FilterType::Sharpen: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { sharpen_mask_bmesh(bm, mask_offset, - *nodes[i], + nodes[i], tls, new_masks.as_mutable_span().slice(node_offsets[i])); - } + }); }); - apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks); + apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks); break; } case FilterType::Grow: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - grow_mask_bmesh( - mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + grow_mask_bmesh( + mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks); + apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks); break; } case FilterType::Shrink: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - shrink_mask_bmesh( - mask_offset, *nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + shrink_mask_bmesh( + mask_offset, nodes[i], new_masks.as_mutable_span().slice(node_offsets[i])); }); - apply_new_mask_bmesh(*depsgraph, ob, mask_offset, nodes, node_offsets, new_masks); + apply_new_mask_bmesh(*depsgraph, ob, mask_offset, node_mask, node_offsets, new_masks); break; } case FilterType::ContrastIncrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { - increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls); + }); }); break; } case FilterType::ContrastDecrease: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { FilterLocalData &tls = all_tls.local(); - for (const int i : range) { - decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, *nodes[i], tls); - } + node_mask.slice(range).foreach_index([&](const int i) { + decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls); + }); }); break; } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index 4dd7d2b83d6..301c1495413 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -147,10 +147,12 @@ void cache_init(bContext *C, BKE_pbvh_ensure_node_face_corners(pbvh, mesh.corner_tris()); } - ss.filter_cache->nodes = bke::pbvh::search_gather( - pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); }); + ss.filter_cache->node_mask = bke::pbvh::search_nodes( + pbvh, ss.filter_cache->node_mask_memory, [&](const bke::pbvh::Node &node) { + return !node_fully_masked_or_hidden(node); + }); - undo::push_nodes(*depsgraph, ob, ss.filter_cache->nodes, undo_type); + undo::push_nodes(*depsgraph, ob, ss.filter_cache->node_mask, undo_type); /* Setup orientation matrices. */ copy_m4_m4(ss.filter_cache->obmat.ptr(), ob.object_to_world().ptr()); @@ -170,12 +172,10 @@ void cache_init(bContext *C, float3 co; if (vc.rv3d && SCULPT_stroke_get_location(C, co, mval_fl, false)) { - Vector nodes; - /* Get radius from brush. */ const Brush *brush = BKE_paint_brush_for_read(&sd.paint); - float radius; + float radius; if (brush) { if (BKE_brush_use_locked_size(scene, brush)) { radius = paint_calc_object_space_radius( @@ -190,11 +190,14 @@ void cache_init(bContext *C, } const float radius_sq = math::square(radius); - nodes = bke::pbvh::search_gather(pbvh, [&](bke::pbvh::Node &node) { - return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true); - }); - const std::optional area_normal = calc_area_normal(*depsgraph, *brush, ob, nodes); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { + return !node_fully_masked_or_hidden(node) && node_in_sphere(node, co, radius_sq, true); + }); + + const std::optional area_normal = calc_area_normal(*depsgraph, *brush, ob, node_mask); if (BKE_paint_brush_for_read(&sd.paint) && area_normal) { ss.filter_cache->initial_normal = *area_normal; ss.last_normal = ss.filter_cache->initial_normal; @@ -339,7 +342,7 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -357,18 +360,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, -1.0f, 1.0f); @@ -396,8 +400,8 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -408,18 +412,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, -1.0f, 1.0f); @@ -438,18 +443,19 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {}); @@ -458,7 +464,7 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, -1.0f, 1.0f); @@ -476,8 +482,8 @@ static void calc_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -488,7 +494,7 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -502,18 +508,19 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(verts.size()); @@ -526,26 +533,27 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); tls.translations.resize(positions.size()); @@ -558,18 +566,19 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); Array orig_normals(verts.size()); @@ -579,7 +588,7 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(verts.size()); @@ -592,8 +601,8 @@ static void calc_inflate_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -604,7 +613,7 @@ static void calc_scale_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -618,18 +627,19 @@ static void calc_scale_filter(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(verts.size()); @@ -642,26 +652,27 @@ static void calc_scale_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); tls.translations.resize(positions.size()); @@ -674,18 +685,19 @@ static void calc_scale_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {}); @@ -694,7 +706,7 @@ static void calc_scale_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(positions.size()); @@ -707,8 +719,8 @@ static void calc_scale_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -736,7 +748,7 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -750,18 +762,19 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(verts.size()); @@ -773,26 +786,27 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); tls.translations.resize(positions.size()); @@ -804,18 +818,19 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {}); @@ -824,7 +839,7 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); tls.translations.resize(positions.size()); @@ -836,8 +851,8 @@ static void calc_sphere_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -860,7 +875,7 @@ static void calc_random_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -874,18 +889,19 @@ static void calc_random_filter(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors); @@ -899,26 +915,27 @@ static void calc_random_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); randomize_factors(orig_data.positions, ss.filter_cache->random_seed, factors); @@ -932,18 +949,19 @@ static void calc_random_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); Array orig_normals(verts.size()); @@ -953,7 +971,7 @@ static void calc_random_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); randomize_factors(orig_positions, ss.filter_cache->random_seed, factors); @@ -967,8 +985,8 @@ static void calc_random_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -979,7 +997,7 @@ static void calc_relax_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; bke::pbvh::update_normals(depsgraph, object, *ss.pbvh); @@ -1000,20 +1018,17 @@ static void calc_relax_filter(const Depsgraph &depsgraph, const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); - auto_mask::calc_vert_factors(depsgraph, - object, - ss.filter_cache->automasking.get(), - *nodes[node_index], - verts, - factors); + auto_mask::calc_vert_factors( + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1037,8 +1052,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1055,21 +1070,18 @@ static void calc_relax_filter(const Depsgraph &depsgraph, const GroupedSpan vert_to_face_map = base_mesh.vert_to_face_map(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); - auto_mask::calc_grids_factors(depsgraph, - object, - ss.filter_cache->automasking.get(), - *nodes[node_index], - grids, - factors); + auto_mask::calc_grids_factors( + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1092,8 +1104,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1106,21 +1118,18 @@ static void calc_relax_filter(const Depsgraph &depsgraph, }; BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); - auto_mask::calc_vert_factors(depsgraph, - object, - ss.filter_cache->automasking.get(), - *nodes[node_index], - verts, - factors); + auto_mask::calc_vert_factors( + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1133,8 +1142,8 @@ static void calc_relax_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1145,7 +1154,7 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *object.sculpt; bke::pbvh::update_normals(depsgraph, object, *ss.pbvh); @@ -1173,16 +1182,17 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1209,8 +1219,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1227,17 +1237,18 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, const GroupedSpan vert_to_face_map = base_mesh.vert_to_face_map(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1269,8 +1280,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1283,17 +1294,18 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, }; BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1308,8 +1320,8 @@ static void calc_relax_face_sets_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1320,7 +1332,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -1342,18 +1354,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1384,19 +1397,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1422,26 +1435,27 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1467,20 +1481,20 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(orig_data.positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1502,18 +1516,19 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); Array orig_normals(verts.size()); @@ -1523,7 +1538,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1545,13 +1560,13 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); Array orig_positions(verts.size()); Array orig_normals(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals); @@ -1560,7 +1575,7 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, strength); clamp_factors(factors, 0.0f, 1.0f); @@ -1581,8 +1596,8 @@ static void calc_surface_smooth_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1613,7 +1628,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -1634,10 +1649,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int node_index) { + const Span verts = bke::pbvh::node_unique_verts(nodes[node_index]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); tls.factors.resize(verts.size()); @@ -1646,7 +1662,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, auto_mask::calc_vert_factors(depsgraph, object, ss.filter_cache->automasking.get(), - *nodes[node_index], + nodes[node_index], verts, factors); scale_factors(factors, strength); @@ -1698,8 +1714,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[node_index]); + }); }); break; } @@ -1709,10 +1725,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, const Span elems = subdiv_ccg.grids; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int node_index) { + const Span grids = bke::pbvh::node_grid_indices(nodes[node_index]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); tls.factors.resize(positions.size()); @@ -1721,7 +1738,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, auto_mask::calc_grids_factors(depsgraph, object, ss.filter_cache->automasking.get(), - *nodes[node_index], + nodes[node_index], grids, factors); scale_factors(factors, strength); @@ -1787,8 +1804,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[node_index]); + }); }); break; } @@ -1796,10 +1813,11 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, BMesh &bm = *ss.bm; BM_mesh_elem_index_ensure(&bm, BM_VERT); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int node_index) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[node_index]); const Span positions = gather_bmesh_positions(verts, tls.positions); tls.factors.resize(verts.size()); @@ -1808,7 +1826,7 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, auto_mask::calc_vert_factors(depsgraph, object, ss.filter_cache->automasking.get(), - *nodes[node_index], + nodes[node_index], verts, factors); scale_factors(factors, strength); @@ -1861,8 +1879,8 @@ static void calc_sharpen_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[node_index]); - } + BKE_pbvh_node_mark_positions_update(nodes[node_index]); + }); }); break; } @@ -1873,7 +1891,7 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { const float final_strength = -std::abs(strength); struct LocalData { @@ -1888,18 +1906,19 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); const Span positions = gather_data_mesh(positions_eval, verts, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_mesh(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_mesh(object, nodes[i]); tls.factors.resize(verts.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(mesh, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, final_strength); const MutableSpan translations = gather_data_mesh( @@ -1911,26 +1930,27 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, write_translations( depsgraph, sd, object, positions_eval, verts, translations, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, final_strength); const MutableSpan translations = gather_data_grids( @@ -1942,18 +1962,19 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { BMesh &bm = *ss.bm; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const Span positions = gather_bmesh_positions(verts, tls.positions); Array orig_positions(verts.size()); orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, {}); @@ -1962,7 +1983,7 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(bm, verts, factors); auto_mask::calc_vert_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], verts, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], verts, factors); scale_factors(factors, final_strength); const MutableSpan translations = gather_data_vert_bmesh( @@ -1974,8 +1995,8 @@ static void calc_enhance_details_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_positions, translations); apply_translations(translations, verts); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -1986,7 +2007,7 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph, const Sculpt &sd, const float strength, Object &object, - const Span nodes) + const IndexMask &node_mask) { struct LocalData { Vector factors; @@ -1997,18 +2018,19 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph, SculptSession &ss = *object.sculpt; SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const Span positions = gather_grids_positions(subdiv_ccg, grids, tls.positions); - const OrigPositionData orig_data = orig_position_data_get_grids(object, *nodes[i]); + const OrigPositionData orig_data = orig_position_data_get_grids(object, nodes[i]); tls.factors.resize(positions.size()); const MutableSpan factors = tls.factors; fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors); auto_mask::calc_grids_factors( - depsgraph, object, ss.filter_cache->automasking.get(), *nodes[i], grids, factors); + depsgraph, object, ss.filter_cache->automasking.get(), nodes[i], grids, factors); scale_factors(factors, strength); clamp_factors(factors, -1.0f, 1.0f); @@ -2024,8 +2046,8 @@ static void calc_erase_displacement_filter(const Depsgraph &depsgraph, clip_and_lock_translations(sd, ss, orig_data.positions, translations); apply_translations(translations, grids, subdiv_ccg); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); } @@ -2067,7 +2089,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, { const SculptSession &ss = *object.sculpt; const bke::pbvh::Tree &pbvh = *ss.pbvh; - const Span nodes = filter_cache.nodes; + const IndexMask &node_mask = filter_cache.node_mask; const int totvert = SCULPT_vertex_count_get(object); filter_cache.sharpen_smooth_ratio = smooth_ratio; @@ -2078,7 +2100,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, MutableSpan detail_directions = filter_cache.detail_directions; MutableSpan sharpen_factors = filter_cache.sharpen_factor; - calc_smooth_translations(depsgraph, object, filter_cache.nodes, filter_cache.detail_directions); + calc_smooth_translations(depsgraph, object, node_mask, filter_cache.detail_directions); for (int i = 0; i < totvert; i++) { sharpen_factors[i] = math::length(detail_directions[i]); @@ -2111,10 +2133,11 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span verts = bke::pbvh::node_unique_verts(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.vert_neighbors.resize(verts.size()); const MutableSpan> neighbors = tls.vert_neighbors; @@ -2129,17 +2152,18 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, smooth::neighbor_data_average_mesh( sharpen_factors.as_span(), neighbors, tls.smooth_factors.as_mutable_span()); scatter_data_mesh(tls.smooth_factors.as_span(), verts, sharpen_factors); - } + }); }); break; } case bke::pbvh::Type::Grids: { SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const int grid_verts_num = grids.size() * key.grid_area; tls.smooth_directions.resize(grid_verts_num); @@ -2156,15 +2180,16 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, grids, tls.smooth_factors.as_mutable_span()); scatter_data_grids(subdiv_ccg, tls.smooth_factors.as_span(), grids, sharpen_factors); - } + }); }); break; } case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[i]); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); tls.smooth_directions.resize(verts.size()); smooth::average_data_bmesh( @@ -2175,7 +2200,7 @@ static void mesh_filter_sharpen_init(const Depsgraph &depsgraph, smooth::average_data_bmesh( sharpen_factors.as_span(), verts, tls.smooth_factors.as_mutable_span()); scatter_data_vert_bmesh(tls.smooth_factors.as_span(), verts, sharpen_factors); - } + }); }); break; } @@ -2227,40 +2252,40 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op) SCULPT_vertex_random_access_ensure(ss); - const Span nodes = ss.filter_cache->nodes; + const IndexMask &node_mask = ss.filter_cache->node_mask; switch (filter_type) { case MeshFilterType::Smooth: - calc_smooth_filter(depsgraph, sd, strength, ob, nodes); + calc_smooth_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Scale: - calc_scale_filter(depsgraph, sd, strength, ob, nodes); + calc_scale_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Inflate: - calc_inflate_filter(depsgraph, sd, strength, ob, nodes); + calc_inflate_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Sphere: - calc_sphere_filter(depsgraph, sd, strength, ob, nodes); + calc_sphere_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Random: - calc_random_filter(depsgraph, sd, strength, ob, nodes); + calc_random_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Relax: - calc_relax_filter(depsgraph, sd, strength, ob, nodes); + calc_relax_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::RelaxFaceSets: - calc_relax_face_sets_filter(depsgraph, sd, strength, ob, nodes); + calc_relax_face_sets_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::SurfaceSmooth: - calc_surface_smooth_filter(depsgraph, sd, strength, ob, nodes); + calc_surface_smooth_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::Sharpen: - calc_sharpen_filter(depsgraph, sd, strength, ob, nodes); + calc_sharpen_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::EnhanceDetails: - calc_enhance_details_filter(depsgraph, sd, strength, ob, nodes); + calc_enhance_details_filter(depsgraph, sd, strength, ob, node_mask); break; case MeshFilterType::EraseDispacement: - calc_erase_displacement_filter(depsgraph, sd, strength, ob, nodes); + calc_erase_displacement_filter(depsgraph, sd, strength, ob, node_mask); break; } @@ -2445,7 +2470,7 @@ static void sculpt_filter_specific_init(const Depsgraph &depsgraph, case MeshFilterType::EnhanceDetails: { ss.filter_cache->detail_directions.reinitialize(SCULPT_vertex_count_get(object)); calc_smooth_translations( - depsgraph, object, ss.filter_cache->nodes, ss.filter_cache->detail_directions); + depsgraph, object, ss.filter_cache->node_mask, ss.filter_cache->detail_directions); break; } case MeshFilterType::EraseDispacement: { diff --git a/source/blender/editors/sculpt_paint/sculpt_gesture.cc b/source/blender/editors/sculpt_paint/sculpt_gesture.cc index 4fe08410e4a..456b1b7366e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_gesture.cc +++ b/source/blender/editors/sculpt_paint/sculpt_gesture.cc @@ -321,7 +321,7 @@ static void flip_for_symmetry_pass(GestureData &gesture_data, const ePaintSymmet flip_plane(gesture_data.line.side_plane[1], gesture_data.line.true_side_plane[1], symmpass); } -static Vector update_affected_nodes_by_line_plane(GestureData &gesture_data) +static void update_affected_nodes_by_line_plane(GestureData &gesture_data) { SculptSession &ss = *gesture_data.ss; float clip_planes[3][4]; @@ -333,9 +333,10 @@ static Vector update_affected_nodes_by_line_plane(GestureData frustum.planes = clip_planes; frustum.num_planes = gesture_data.line.use_side_planes ? 3 : 1; - return gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { - return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); - }); + gesture_data.node_mask = bke::pbvh::search_nodes( + *ss.pbvh, gesture_data.node_mask_memory, [&](const bke::pbvh::Node &node) { + return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); + }); } static void update_affected_nodes_by_clip_planes(GestureData &gesture_data) @@ -349,23 +350,24 @@ static void update_affected_nodes_by_clip_planes(GestureData &gesture_data) frustum.planes = clip_planes; frustum.num_planes = 4; - gesture_data.nodes = bke::pbvh::search_gather(*ss.pbvh, [&](bke::pbvh::Node &node) { - switch (gesture_data.selection_type) { - case SelectionType::Inside: - return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); - case SelectionType::Outside: - /* Certain degenerate cases of a lasso shape can cause the resulting - * frustum planes to enclose a node's AABB, therefore we must submit it - * to be more thoroughly evaluated. */ - if (gesture_data.shape_type == ShapeType::Lasso) { - return true; + gesture_data.node_mask = bke::pbvh::search_nodes( + *ss.pbvh, gesture_data.node_mask_memory, [&](const bke::pbvh::Node &node) { + switch (gesture_data.selection_type) { + case SelectionType::Inside: + return BKE_pbvh_node_frustum_contain_AABB(&node, &frustum); + case SelectionType::Outside: + /* Certain degenerate cases of a lasso shape can cause the resulting + * frustum planes to enclose a node's AABB, therefore we must submit it + * to be more thoroughly evaluated. */ + if (gesture_data.shape_type == ShapeType::Lasso) { + return true; + } + return BKE_pbvh_node_frustum_exclude_AABB(&node, &frustum); + default: + BLI_assert_unreachable(); + return true; } - return BKE_pbvh_node_frustum_exclude_AABB(&node, &frustum); - default: - BLI_assert_unreachable(); - return true; - } - }); + }); } static void update_affected_nodes(GestureData &gesture_data) diff --git a/source/blender/editors/sculpt_paint/sculpt_gesture.hh b/source/blender/editors/sculpt_paint/sculpt_gesture.hh index ad3c7659b68..555c20267a2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_gesture.hh +++ b/source/blender/editors/sculpt_paint/sculpt_gesture.hh @@ -10,6 +10,7 @@ #include "BLI_array.hh" #include "BLI_bit_vector.hh" +#include "BLI_index_mask.hh" #include "BLI_math_matrix.hh" #include "BLI_vector.hh" @@ -111,7 +112,8 @@ struct GestureData { LineData line; /* Task Callback Data. */ - Vector nodes; + IndexMaskMemory node_mask_memory; + IndexMask node_mask; ~GestureData(); }; diff --git a/source/blender/editors/sculpt_paint/sculpt_hide.cc b/source/blender/editors/sculpt_paint/sculpt_hide.cc index 0630d2bd8b0..efac466e7fc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_hide.cc +++ b/source/blender/editors/sculpt_paint/sculpt_hide.cc @@ -18,7 +18,7 @@ namespace blender::ed::sculpt_paint::hide { -Span node_visible_verts(const bke::pbvh::Node &node, +Span node_visible_verts(const bke::pbvh::MeshNode &node, const Span hide_vert, Vector &indices) { diff --git a/source/blender/editors/sculpt_paint/sculpt_hide.hh b/source/blender/editors/sculpt_paint/sculpt_hide.hh index 177623e886b..ab657587413 100644 --- a/source/blender/editors/sculpt_paint/sculpt_hide.hh +++ b/source/blender/editors/sculpt_paint/sculpt_hide.hh @@ -18,12 +18,12 @@ struct PBVHVertRef; struct SubdivCCG; struct SubdivCCGCoord; namespace blender::bke::pbvh { -class Node; +struct MeshNode; } namespace blender::ed::sculpt_paint::hide { -Span node_visible_verts(const bke::pbvh::Node &node, +Span node_visible_verts(const bke::pbvh::MeshNode &node, Span hide_vert, Vector &indices); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index 744b54a940e..a67da7f2028 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -575,14 +575,14 @@ namespace blender::ed::sculpt_paint { void calc_brush_plane(const Depsgraph &depsgraph, const Brush &brush, Object &ob, - Span nodes, + const IndexMask &node_mask, float3 &r_area_no, float3 &r_area_co); std::optional calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, - Object &ob, - Span nodes); + const Object &ob, + const IndexMask &node_mask); /** * This calculates flatten center and area normal together, @@ -591,13 +591,13 @@ std::optional calc_area_normal(const Depsgraph &depsgraph, void calc_area_normal_and_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, - Span nodes, + const IndexMask &node_mask, float r_area_no[3], float r_area_co[3]); void calc_area_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, - Span nodes, + const IndexMask &node_mask, float r_area_co[3]); PBVHVertRef nearest_vert_calc(const Depsgraph &depsgraph, @@ -696,7 +696,7 @@ namespace blender::ed::sculpt_paint { void calc_smooth_translations(const Depsgraph &depsgraph, const Object &object, - Span nodes, + const IndexMask &node_mask, MutableSpan translations); } @@ -885,7 +885,7 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, - blender::Span texnodes); + const blender::IndexMask &node_mask); bool SCULPT_use_image_paint_brush(PaintModeSettings &settings, Object &ob); namespace blender::ed::sculpt_paint { diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc index be6bdea832b..22b535a5ebc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_init.cc +++ b/source/blender/editors/sculpt_paint/sculpt_mask_init.cc @@ -50,14 +50,14 @@ enum class InitMode { void write_mask_mesh(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, FunctionRef, Span)> write_fn) { Mesh &mesh = *static_cast(object.data); bke::MutableAttributeAccessor attributes = mesh.attributes_for_write(); const VArraySpan hide_vert = *attributes.lookup(".hide_vert", bke::AttrDomain::Point); - undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); bke::SpanAttributeWriter mask = attributes.lookup_or_add_for_write_span( ".sculpt_mask", bke::AttrDomain::Point); @@ -65,12 +65,13 @@ void write_mask_mesh(const Depsgraph &depsgraph, return; } threading::EnumerableThreadSpecific> all_index_data; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = object.sculpt->pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { Vector &index_data = all_index_data.local(); for (const int i : range) { - write_fn(mask.span, hide::node_visible_verts(*nodes[i], hide_vert, index_data)); - BKE_pbvh_node_mark_redraw(*nodes[i]); - bke::pbvh::node_update_mask_mesh(mask.span, static_cast(*nodes[i])); + write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data)); + BKE_pbvh_node_mark_redraw(nodes[i]); + bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); } }); mask.finish(); @@ -80,26 +81,25 @@ static void init_mask_grids(Main &bmain, Scene &scene, Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, FunctionRef &, int, CCGElem *)> write_fn) { MultiresModifierData *mmd = BKE_sculpt_multires_active(&scene, &object); BKE_sculpt_mask_layers_ensure(&depsgraph, &bmain, &object, mmd); SculptSession &ss = *object.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const Span grids = subdiv_ccg.grids; const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; - undo::push_nodes(depsgraph, object, nodes, undo::Type::Mask); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - for (const int grid : bke::pbvh::node_grid_indices(*nodes[i])) { - write_fn(grid_hidden, grid, grids[grid]); - } - BKE_pbvh_node_mark_update_mask(*nodes[i]); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) { + write_fn(grid_hidden, grid, grids[grid]); } + BKE_pbvh_node_mark_update_mask(nodes[i]); }); BKE_subdiv_ccg_average_grids(subdiv_ccg); bke::pbvh::update_mask(object, *ss.pbvh); @@ -119,8 +119,9 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) BKE_sculpt_update_object_for_edit(&depsgraph, &ob, false); bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh; - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); - if (nodes.is_empty()) { + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); + if (node_mask.is_empty()) { return OPERATOR_CANCELLED; } @@ -133,14 +134,14 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) case bke::pbvh::Type::Mesh: { switch (mode) { case InitMode::Random: - write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan mask, Span verts) { + write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan mask, Span verts) { for (const int vert : verts) { mask[vert] = BLI_hash_int_01(vert + seed); } }); break; case InitMode::FaceSet: - write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan mask, Span verts) { + write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan mask, Span verts) { for (const int vert : verts) { const int face_set = face_set::vert_face_set_get(ss, PBVHVertRef{vert}); mask[vert] = BLI_hash_int_01(face_set + seed); @@ -149,7 +150,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) break; case InitMode::Island: islands::ensure_cache(ob); - write_mask_mesh(depsgraph, ob, nodes, [&](MutableSpan mask, Span verts) { + write_mask_mesh(depsgraph, ob, node_mask, [&](MutableSpan mask, Span verts) { for (const int vert : verts) { const int island = islands::vert_id_get(ss, vert); mask[vert] = BLI_hash_int_01(island + seed); @@ -171,7 +172,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) scene, depsgraph, ob, - nodes, + node_mask, [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { const int verts_start = grid_index * key.grid_area; BKE_subdiv_ccg_foreach_visible_grid_vert( @@ -192,7 +193,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) scene, depsgraph, ob, - nodes, + node_mask, [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { const int face_set = face_sets[grid_to_face[grid_index]]; const float value = BLI_hash_int_01(face_set + seed); @@ -210,7 +211,7 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) scene, depsgraph, ob, - nodes, + node_mask, [&](const BitGroupVector<> &grid_hidden, const int grid_index, CCGElem *grid) { const int verts_start = grid_index * key.grid_area; BKE_subdiv_ccg_foreach_visible_grid_vert( @@ -225,32 +226,30 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op) break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(nodes[i])) { - if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { - continue; - } - switch (mode) { - case InitMode::Random: - BM_ELEM_CD_SET_FLOAT( - vert, offset, BLI_hash_int_01(BM_elem_index_get(vert) + seed)); - break; - case InitMode::FaceSet: { - BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f); - break; - } - case InitMode::Island: - BM_ELEM_CD_SET_FLOAT( - vert, - offset, - BLI_hash_int_01(islands::vert_id_get(ss, BM_elem_index_get(vert)) + seed)); - break; - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) { + if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) { + continue; + } + switch (mode) { + case InitMode::Random: + BM_ELEM_CD_SET_FLOAT(vert, offset, BLI_hash_int_01(BM_elem_index_get(vert) + seed)); + break; + case InitMode::FaceSet: { + BM_ELEM_CD_SET_FLOAT(vert, offset, 0.0f); + break; + } + case InitMode::Island: + BM_ELEM_CD_SET_FLOAT( + vert, + offset, + BLI_hash_int_01(islands::vert_id_get(ss, BM_elem_index_get(vert)) + seed)); + break; } - BKE_pbvh_node_mark_update_mask(*nodes[i]); } + BKE_pbvh_node_mark_update_mask(nodes[i]); }); bke::pbvh::update_mask(ob, *ss.pbvh); break; diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 3c85f2385e7..ff07d850439 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -783,10 +783,11 @@ static void sculpt_mask_by_color_contiguous_mesh(const Depsgraph &depsgraph, return len <= threshold; }); - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); update_mask_mesh( - depsgraph, object, nodes, [&](MutableSpan node_mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan node_mask, const Span verts) { for (const int i : verts.index_range()) { node_mask[i] = sculpt_mask_by_color_final_mask_get( node_mask[i], new_mask[verts[i]], invert, preserve_mask); @@ -808,10 +809,11 @@ static void sculpt_mask_by_color_full_mesh(const Depsgraph &depsgraph, mesh.active_color_attribute, bke::AttrDomain::Point, {}); const float4 active_color = float4(colors[vert]); - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); update_mask_mesh( - depsgraph, object, nodes, [&](MutableSpan node_mask, const Span verts) { + depsgraph, object, node_mask, [&](MutableSpan node_mask, const Span verts) { for (const int i : verts.index_range()) { const float current_mask = node_mask[i]; const float new_mask = sculpt_mask_by_color_delta_get( @@ -967,7 +969,7 @@ static void bake_mask_mesh(const Depsgraph &depsgraph, const auto_mask::Cache &automasking, const CavityBakeMixMode mode, const float factor, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, LocalData &tls, const MutableSpan mask) { @@ -991,7 +993,7 @@ static void bake_mask_mesh(const Depsgraph &depsgraph, calc_new_masks(mode, node_mask, new_mask); mix_new_masks(new_mask, factors, node_mask); - array_utils::scatter(node_mask.as_span(), verts, mask); + scatter_data_mesh(node_mask.as_span(), verts, mask); } static void bake_mask_grids(const Depsgraph &depsgraph, @@ -999,7 +1001,7 @@ static void bake_mask_grids(const Depsgraph &depsgraph, const auto_mask::Cache &automasking, const CavityBakeMixMode mode, const float factor, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, LocalData &tls) { SculptSession &ss = *object.sculpt; @@ -1034,7 +1036,7 @@ static void bake_mask_bmesh(const Depsgraph &depsgraph, const auto_mask::Cache &automasking, const CavityBakeMixMode mode, const float factor, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, LocalData &tls) { const SculptSession &ss = *object.sculpt; @@ -1085,7 +1087,8 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) CavityBakeMixMode mode = CavityBakeMixMode(RNA_enum_get(op->ptr, "mix_mode")); float factor = RNA_float_get(op->ptr, "mix_factor"); - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); /* Set up automasking settings. */ Sculpt sd2 = sd; @@ -1150,7 +1153,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) std::unique_ptr automasking = auto_mask::cache_init( *depsgraph, sd2, &brush2, ob); - undo::push_nodes(*depsgraph, ob, nodes, undo::Type::Mask); + undo::push_nodes(*depsgraph, ob, node_mask, undo::Type::Mask); threading::EnumerableThreadSpecific all_tls; switch (ss.pbvh->type()) { @@ -1162,37 +1165,37 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op) if (!mask) { return OPERATOR_CANCELLED; } - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - threading::isolate_task([&]() { - for (const int i : range) { - bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls, mask.span); - BKE_pbvh_node_mark_update_mask(*nodes[i]); - bke::pbvh::node_update_mask_mesh(mask.span, - static_cast(*nodes[i])); - } + node_mask.slice(range).foreach_index([&](const int i) { + bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span); + BKE_pbvh_node_mark_update_mask(nodes[i]); + bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]); }); }); break; } case bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls); - BKE_pbvh_node_mark_update_mask(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); + BKE_pbvh_node_mark_update_mask(nodes[i]); + }); }); bke::pbvh::update_mask(ob, *ss.pbvh); break; } case bke::pbvh::Type::BMesh: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, *nodes[i], tls); - BKE_pbvh_node_mark_update_mask(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls); + BKE_pbvh_node_mark_update_mask(nodes[i]); + }); }); bke::pbvh::update_mask(ob, *ss.pbvh); break; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.cc b/source/blender/editors/sculpt_paint/sculpt_paint_color.cc index e998c961561..493e2076684 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.cc +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.cc @@ -266,7 +266,7 @@ static void do_color_smooth_task(const Depsgraph &depsgraph, const GroupedSpan vert_to_face_map, const Span hide_poly, const Brush &brush, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, bke::GSpanAttributeWriter &color_attribute) { @@ -347,7 +347,7 @@ static void do_paint_brush_task(const Depsgraph &depsgraph, const Brush &brush, const float4x4 &mat, const float4 wet_mix_sampled_color, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, const MutableSpan mix_colors, bke::GSpanAttributeWriter &color_attribute) @@ -491,7 +491,7 @@ static void do_sample_wet_paint_task(const Object &object, const GSpan color_attribute, const bke::AttrDomain color_domain, const Brush &brush, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, SampleWetPaintData &swptd) { @@ -524,16 +524,17 @@ void do_paint_brush(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, - Span nodes, - Span texnodes) + const IndexMask &node_mask, + const IndexMask &texnode_mask) { if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) { - SCULPT_do_paint_brush_image(depsgraph, paint_mode_settings, sd, ob, texnodes); + SCULPT_do_paint_brush_image(depsgraph, paint_mode_settings, sd, ob, texnode_mask); return; } const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(*ss.cache)) { if (SCULPT_stroke_is_first_brush_step(*ss.cache)) { @@ -573,9 +574,9 @@ void do_paint_brush(const Depsgraph &depsgraph, if (ss.cache->alt_smooth) { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { ColorPaintLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { do_color_smooth_task(depsgraph, ob, vert_positions, @@ -585,10 +586,10 @@ void do_paint_brush(const Depsgraph &depsgraph, vert_to_face_map, hide_poly, brush, - *nodes[i], + nodes[i], tls, color_attribute); - } + }); }); color_attribute.finish(); return; @@ -601,12 +602,12 @@ void do_paint_brush(const Depsgraph &depsgraph, if (ss.cache->paint_brush.wet_mix > 0.0f) { threading::EnumerableThreadSpecific all_tls; const SampleWetPaintData swptd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, SampleWetPaintData{}, [&](const IndexRange range, SampleWetPaintData swptd) { ColorPaintLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { do_sample_wet_paint_task(ob, vert_positions, faces, @@ -615,10 +616,10 @@ void do_paint_brush(const Depsgraph &depsgraph, color_attribute.span, color_attribute.domain, brush, - *nodes[i], + nodes[i], tls, swptd); - } + }); return swptd; }, [](const SampleWetPaintData &a, const SampleWetPaintData &b) { @@ -647,9 +648,9 @@ void do_paint_brush(const Depsgraph &depsgraph, } threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { ColorPaintLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { do_paint_brush_task(depsgraph, ob, vert_positions, @@ -660,11 +661,11 @@ void do_paint_brush(const Depsgraph &depsgraph, brush, mat, wet_color, - *nodes[i], + nodes[i], tls, ss.cache->paint_brush.mix_colors, color_attribute); - } + }); }); color_attribute.finish(); } @@ -678,7 +679,7 @@ static void do_smear_brush_task(const Depsgraph &depsgraph, const GroupedSpan vert_to_face_map, const Span hide_poly, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, bke::GSpanAttributeWriter &color_attribute) { @@ -828,10 +829,11 @@ static void do_smear_brush_task(const Depsgraph &depsgraph, void do_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); if (ss.cache->bstrength == 0.0f) { @@ -870,9 +872,9 @@ void do_smear_brush(const Depsgraph &depsgraph, /* Smooth colors mode. */ if (ss.cache->alt_smooth) { threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { ColorPaintLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { do_color_smooth_task(depsgraph, ob, vert_positions, @@ -882,30 +884,28 @@ void do_smear_brush(const Depsgraph &depsgraph, vert_to_face_map, hide_poly, brush, - *nodes[i], + nodes[i], tls, color_attribute); - } + }); }); } else { /* Smear mode. */ - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - for (const int vert : bke::pbvh::node_unique_verts(*nodes[i])) { - ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces, - corner_verts, - vert_to_face_map, - color_attribute.span, - color_attribute.domain, - vert); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + for (const int vert : bke::pbvh::node_unique_verts(nodes[i])) { + ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces, + corner_verts, + vert_to_face_map, + color_attribute.span, + color_attribute.domain, + vert); } }); threading::EnumerableThreadSpecific all_tls; - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { ColorPaintLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { do_smear_brush_task(depsgraph, ob, vert_positions, @@ -915,10 +915,10 @@ void do_smear_brush(const Depsgraph &depsgraph, vert_to_face_map, hide_poly, brush, - *nodes[i], + nodes[i], tls, color_attribute); - } + }); }); } color_attribute.finish(); diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc index 4d12b19c307..a2bfbca58c2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_image.cc +++ b/source/blender/editors/sculpt_paint/sculpt_paint_image.cc @@ -431,12 +431,12 @@ static void do_push_undo_tile(Image &image, ImageUser &image_user, bke::pbvh::No /** \name Fix non-manifold edge bleeding. * \{ */ -static Vector collect_dirty_tiles(Span nodes) +static Vector collect_dirty_tiles(MutableSpan nodes, + const IndexMask &node_mask) { Vector dirty_tiles; - for (bke::pbvh::Node *node : nodes) { - bke::pbvh::pixels::collect_dirty_tiles(*node, dirty_tiles); - } + node_mask.foreach_index( + [&](const int i) { bke::pbvh::pixels::collect_dirty_tiles(nodes[i], dirty_tiles); }); return dirty_tiles; } static void fix_non_manifold_seam_bleeding(bke::pbvh::Tree &pbvh, @@ -452,9 +452,10 @@ static void fix_non_manifold_seam_bleeding(bke::pbvh::Tree &pbvh, static void fix_non_manifold_seam_bleeding(Object &ob, Image &image, ImageUser &image_user, - const Span nodes) + MutableSpan nodes, + const IndexMask &node_mask) { - Vector dirty_tiles = collect_dirty_tiles(nodes); + Vector dirty_tiles = collect_dirty_tiles(nodes, node_mask); fix_non_manifold_seam_bleeding(*ob.sculpt->pbvh, image, image_user, dirty_tiles); } @@ -499,7 +500,7 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, - const blender::Span nodes) + const blender::IndexMask &node_mask) { using namespace blender; const Brush *brush = BKE_paint_brush_for_read(&sd.paint); @@ -509,19 +510,19 @@ void SCULPT_do_paint_brush_image(const Depsgraph &depsgraph, return; } - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - do_push_undo_tile(*image_data.image, *image_data.image_user, *nodes[i]); - } - }); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { - for (const int i : range) { - do_paint_pixels(depsgraph, ob, *brush, image_data, *nodes[i]); - } - }); - fix_non_manifold_seam_bleeding(ob, *image_data.image, *image_data.image_user, nodes); + SculptSession &ss = *ob.sculpt; + MutableSpan nodes = ss.pbvh->nodes(); - for (bke::pbvh::Node *node : nodes) { - bke::pbvh::pixels::mark_image_dirty(*node, *image_data.image, *image_data.image_user); - } + node_mask.foreach_index(GrainSize(1), [&](const int i) { + do_push_undo_tile(*image_data.image, *image_data.image_user, nodes[i]); + }); + node_mask.foreach_index(GrainSize(1), [&](const int i) { + do_paint_pixels(depsgraph, ob, *brush, image_data, nodes[i]); + }); + + fix_non_manifold_seam_bleeding(ob, *image_data.image, *image_data.image_user, nodes, node_mask); + + node_mask.foreach_index([&](const int i) { + bke::pbvh::pixels::mark_image_dirty(nodes[i], *image_data.image, *image_data.image_user); + }); } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index 967cfd5ec31..13295aa002a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -158,7 +158,7 @@ static void calc_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, BrushLocalData &tls, const MutableSpan positions_orig) @@ -210,7 +210,7 @@ static void calc_mesh(const Depsgraph &depsgraph, static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, BrushLocalData &tls) { @@ -263,7 +263,7 @@ static void calc_grids(const Depsgraph &depsgraph, static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, BrushLocalData &tls) { @@ -350,7 +350,7 @@ static void grow_factors_mesh(const ePaintSymmetryFlags symm, const Span hide_poly, const Span fake_neighbors, const Span prev_mask, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, GrowFactorLocalData &tls, const MutableSpan pose_factor, PoseGrowFactorData &gftd) @@ -389,7 +389,7 @@ static void grow_factors_grids(const ePaintSymmetryFlags symm, const SubdivCCG &subdiv_ccg, const Span fake_neighbors, const Span prev_mask, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, const MutableSpan pose_factor, PoseGrowFactorData &gftd) { @@ -441,7 +441,7 @@ static void grow_factors_bmesh(const ePaintSymmetryFlags symm, const float3 &pose_initial_position, const Span fake_neighbors, const Span prev_mask, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, const MutableSpan pose_factor, PoseGrowFactorData &gftd) { @@ -488,7 +488,8 @@ static void grow_pose_factor(const Depsgraph &depsgraph, bke::pbvh::Tree &pbvh = *ob.sculpt->pbvh; const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob); - Vector nodes = bke::pbvh::all_leaf_nodes(pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory); const Span fake_neighbors = ss.fake_neighbors.fake_neighbor_index; bool grow_next_iteration = true; @@ -501,6 +502,7 @@ static void grow_pose_factor(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); const Mesh &mesh = *static_cast(ob.data); const Span vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob); const OffsetIndices faces = mesh.faces(); @@ -512,12 +514,12 @@ static void grow_pose_factor(const Depsgraph &depsgraph, const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); gftd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, PoseGrowFactorData{}, [&](const IndexRange range, PoseGrowFactorData gftd) { GrowFactorLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { grow_factors_mesh(symm, pose_target, vert_positions, @@ -528,48 +530,50 @@ static void grow_pose_factor(const Depsgraph &depsgraph, hide_poly, fake_neighbors, prev_mask, - *nodes[i], + nodes[i], tls, pose_factor, gftd); - } + }); return gftd; }, PoseGrowFactorData::join); break; } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; gftd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, PoseGrowFactorData{}, [&](const IndexRange range, PoseGrowFactorData gftd) { - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { grow_factors_grids(symm, pose_target, subdiv_ccg, fake_neighbors, prev_mask, - *nodes[i], + nodes[i], pose_factor, gftd); - } + }); return gftd; }, PoseGrowFactorData::join); break; } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); gftd = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, PoseGrowFactorData{}, [&](const IndexRange range, PoseGrowFactorData gftd) { - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { grow_factors_bmesh( - symm, pose_target, fake_neighbors, prev_mask, *nodes[i], pose_factor, gftd); - } + symm, pose_target, fake_neighbors, prev_mask, nodes[i], pose_factor, gftd); + }); return gftd; }, PoseGrowFactorData::join); @@ -1386,7 +1390,7 @@ static void align_pivot_local_space(float r_mat[4][4], void do_pose_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes) + const IndexMask &node_mask) { SculptSession &ss = *ob.sculpt; const Brush &brush = *BKE_paint_brush_for_read(&sd.paint); @@ -1470,34 +1474,37 @@ void do_pose_brush(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (ob.sculpt->pbvh->type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BrushLocalData &tls = all_tls.local(); - for (const int i : range) { - calc_mesh(depsgraph, sd, brush, positions_eval, *nodes[i], ob, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + calc_mesh(depsgraph, sd, brush, positions_eval, nodes[i], ob, tls, positions_orig); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } - case bke::pbvh::Type::Grids: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BrushLocalData &tls = all_tls.local(); - for (const int i : range) { - calc_grids(depsgraph, sd, brush, *nodes[i], ob, tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_grids(depsgraph, sd, brush, nodes[i], ob, tls); }); }); break; - case bke::pbvh::Type::BMesh: - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + } + case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { BrushLocalData &tls = all_tls.local(); - for (const int i : range) { - calc_bmesh(depsgraph, sd, brush, *nodes[i], ob, tls); - } + node_mask.slice(range).foreach_index( + [&](const int i) { calc_bmesh(depsgraph, sd, brush, nodes[i], ob, tls); }); }); break; + } } } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.hh b/source/blender/editors/sculpt_paint/sculpt_pose.hh index ff7d26e8130..724fd850386 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.hh +++ b/source/blender/editors/sculpt_paint/sculpt_pose.hh @@ -53,7 +53,7 @@ struct IKChain { void do_pose_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, - Span nodes); + const IndexMask &node_mask); /** * Calculate the pose origin and (Optionally the pose factor) * that is used when using the pose brush. diff --git a/source/blender/editors/sculpt_paint/sculpt_project.cc b/source/blender/editors/sculpt_paint/sculpt_project.cc index 0772f437b8a..37e94b2578f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_project.cc +++ b/source/blender/editors/sculpt_paint/sculpt_project.cc @@ -48,7 +48,7 @@ static void apply_projection_mesh(const Depsgraph &depsgraph, const gesture::GestureData &gesture_data, const Span positions_eval, const Span vert_normals, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const MutableSpan positions_orig) @@ -75,7 +75,7 @@ static void apply_projection_mesh(const Depsgraph &depsgraph, static void apply_projection_grids(const Sculpt &sd, const gesture::GestureData &gesture_data, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, LocalData &tls) { @@ -107,7 +107,7 @@ static void apply_projection_grids(const Sculpt &sd, static void apply_projection_bmesh(const Sculpt &sd, const gesture::GestureData &gesture_data, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, LocalData &tls) { @@ -142,54 +142,57 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g SculptSession &ss = *object.sculpt; bke::pbvh::Tree &pbvh = *ss.pbvh; const Sculpt &sd = *CTX_data_tool_settings(&C)->sculpt; - const Span nodes = gesture_data.nodes; + const IndexMask &node_mask = gesture_data.node_mask; threading::EnumerableThreadSpecific all_tls; switch (gesture_data.shape_type) { case gesture::ShapeType::Line: switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(object.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, object); const Span vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object); MutableSpan positions_orig = mesh.vert_positions_for_write(); - undo::push_nodes(depsgraph, object, nodes, undo::Type::Position); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { apply_projection_mesh(depsgraph, sd, gesture_data, positions_eval, vert_normals, - *nodes[i], + nodes[i], object, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { - undo::push_nodes(depsgraph, object, nodes, undo::Type::Position); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - apply_projection_grids(sd, gesture_data, *nodes[i], object, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + apply_projection_grids(sd, gesture_data, nodes[i], object, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { - undo::push_nodes(depsgraph, object, nodes, undo::Type::Position); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - apply_projection_bmesh(sd, gesture_data, *nodes[i], object, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + apply_projection_bmesh(sd, gesture_data, nodes[i], object, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index ee7a94220ca..90f13dd495e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -737,11 +737,14 @@ void blur_geometry_data_array(const Object &object, Vector new_factors; }; const SculptSession &ss = *object.sculpt; - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); threading::EnumerableThreadSpecific all_tls; switch (ss.pbvh->type()) { case bke::pbvh::Type::Mesh: { + const Span nodes = ss.pbvh->nodes(); + const Mesh &mesh = *static_cast(object.data); const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); @@ -752,11 +755,11 @@ void blur_geometry_data_array(const Object &object, const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); for ([[maybe_unused]] const int _ : IndexRange(iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { const Span verts = hide::node_visible_verts( - *nodes[i], hide_vert, tls.vert_indices); + nodes[i], hide_vert, tls.vert_indices); tls.vert_neighbors.resize(verts.size()); const MutableSpan> neighbors = tls.vert_neighbors; @@ -768,20 +771,21 @@ void blur_geometry_data_array(const Object &object, smooth::neighbor_data_average_mesh(data.as_span(), neighbors, new_factors); scatter_data_mesh(new_factors.as_span(), verts, data); - } + }); }); } break; } case bke::pbvh::Type::Grids: { + const Span nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden; for ([[maybe_unused]] const int _ : IndexRange(iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int i : range) { - const Span grids = bke::pbvh::node_grid_indices(*nodes[i]); + node_mask.slice(range).foreach_index([&](const int node_index) { + const Span grids = bke::pbvh::node_grid_indices(nodes[node_index]); const int grid_verts_num = key.grid_area * grids.size(); tls.new_factors.resize(grid_verts_num); @@ -800,17 +804,19 @@ void blur_geometry_data_array(const Object &object, }); } } - } + }); }); } break; } case bke::pbvh::Type::BMesh: { + const Span nodes = ss.pbvh->nodes(); for ([[maybe_unused]] const int _ : IndexRange(iterations)) { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { LocalData &tls = all_tls.local(); - for (const int node_index : range) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(nodes[node_index]); + node_mask.slice(range).foreach_index([&](const int node_index) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts( + const_cast(&nodes[node_index])); tls.new_factors.resize(verts.size()); const MutableSpan new_factors = tls.new_factors; @@ -825,7 +831,7 @@ void blur_geometry_data_array(const Object &object, data[BM_elem_index_get(vert)] = new_factors[i]; i++; } - } + }); }); } break; diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.cc b/source/blender/editors/sculpt_paint/sculpt_transform.cc index 84948bda3aa..1316ea84c85 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.cc +++ b/source/blender/editors/sculpt_paint/sculpt_transform.cc @@ -192,7 +192,7 @@ static void transform_node_mesh(const Depsgraph &depsgraph, const Sculpt &sd, const std::array &transform_mats, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, TransformLocalData &tls, const MutableSpan positions_orig) @@ -219,7 +219,7 @@ static void transform_node_mesh(const Depsgraph &depsgraph, static void transform_node_grids(const Sculpt &sd, const std::array &transform_mats, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, TransformLocalData &tls) { @@ -251,7 +251,7 @@ static void transform_node_grids(const Sculpt &sd, static void transform_node_bmesh(const Sculpt &sd, const std::array &transform_mats, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, TransformLocalData &tls) { @@ -293,41 +293,44 @@ static void sculpt_transform_all_vertices(const Depsgraph &depsgraph, const Scul /* Regular transform applies all symmetry passes at once as it is split by symmetry areas * (each vertex can only be transformed once by the transform matrix of its area). */ bke::pbvh::Tree &pbvh = *ss.pbvh; - const Span nodes = ss.filter_cache->nodes; + const IndexMask &node_mask = ss.filter_cache->node_mask; threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { transform_node_mesh( - depsgraph, sd, transform_mats, positions_eval, *nodes[i], ob, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + depsgraph, sd, transform_mats, positions_eval, nodes[i], ob, tls, positions_orig); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { - transform_node_grids(sd, transform_mats, *nodes[i], ob, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + transform_node_grids(sd, transform_mats, nodes[i], ob, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { - transform_node_bmesh(sd, transform_mats, *nodes[i], ob, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + node_mask.slice(range).foreach_index([&](const int i) { + transform_node_bmesh(sd, transform_mats, nodes[i], ob, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -361,7 +364,7 @@ static void elastic_transform_node_mesh(const Depsgraph &depsgraph, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, const Span positions_eval, - const bke::pbvh::Node &node, + const bke::pbvh::MeshNode &node, Object &object, TransformLocalData &tls, const MutableSpan positions_orig) @@ -391,7 +394,7 @@ static void elastic_transform_node_grids(const Sculpt &sd, const KelvinletParams ¶ms, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Object &object, TransformLocalData &tls) { @@ -422,7 +425,7 @@ static void elastic_transform_node_bmesh(const Sculpt &sd, const KelvinletParams ¶ms, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, - bke::pbvh::Node &node, + bke::pbvh::BMeshNode &node, Object &object, TransformLocalData &tls) { @@ -462,7 +465,7 @@ static void transform_radius_elastic(const Depsgraph &depsgraph, ss, symm, ss.filter_cache->transform_displacement_mode); bke::pbvh::Tree &pbvh = *ss.pbvh; - const Span nodes = ss.filter_cache->nodes; + const IndexMask &node_mask = ss.filter_cache->node_mask; KelvinletParams params; /* TODO(pablodp606): These parameters can be exposed if needed as transform strength and volume @@ -485,46 +488,49 @@ static void transform_radius_elastic(const Depsgraph &depsgraph, float4x4 elastic_transform_mat = transform_mats[symm_area]; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); Mesh &mesh = *static_cast(ob.data); const Span positions_eval = bke::pbvh::vert_positions_eval(depsgraph, ob); MutableSpan positions_orig = mesh.vert_positions_for_write(); - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { elastic_transform_node_mesh(depsgraph, sd, params, elastic_transform_mat, elastic_transform_pivot, positions_eval, - *nodes[i], + nodes[i], ob, tls, positions_orig); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::Grids: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { elastic_transform_node_grids( - sd, params, elastic_transform_mat, elastic_transform_pivot, *nodes[i], ob, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } case bke::pbvh::Type::BMesh: { - threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + MutableSpan nodes = ss.pbvh->nodes(); + threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) { TransformLocalData &tls = all_tls.local(); - for (const int i : range) { + node_mask.slice(range).foreach_index([&](const int i) { elastic_transform_node_bmesh( - sd, params, elastic_transform_mat, elastic_transform_pivot, *nodes[i], ob, tls); - BKE_pbvh_node_mark_positions_update(*nodes[i]); - } + sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls); + BKE_pbvh_node_mark_positions_update(nodes[i]); + }); }); break; } @@ -659,8 +665,11 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, const SculptSession &ss = *object.sculpt; bke::pbvh::Tree &pbvh = *ss.pbvh; - Vector nodes = bke::pbvh::search_gather( - pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); }); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { + return !node_fully_masked_or_hidden(node); + }); struct LocalData { Vector factors; @@ -670,17 +679,18 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); const Mesh &mesh = *static_cast(object.data); const Span vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object); const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); threading::isolate_task([&]() { - for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Span verts = bke::pbvh::node_unique_verts(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); tls.positions.resize(verts.size()); const MutableSpan positions = tls.positions; @@ -692,7 +702,7 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); }); return sum; }, @@ -700,15 +710,16 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, return float3(math::safe_divide(total.position, total.weight_total)); } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); - for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Span grids = bke::pbvh::node_grid_indices(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const MutableSpan positions = gather_grids_positions( subdiv_ccg, grids, tls.positions); @@ -718,21 +729,22 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); return sum; }, combine_average_position_accumulation); return float3(math::safe_divide(total.position, total.weight_total)); } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(node); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); tls.factors.resize(verts.size()); @@ -741,7 +753,7 @@ static float3 average_unmasked_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); return sum; }, combine_average_position_accumulation); @@ -772,8 +784,11 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph, const SculptSession &ss = *object.sculpt; bke::pbvh::Tree &pbvh = *ss.pbvh; - Vector nodes = bke::pbvh::search_gather( - pbvh, [&](bke::pbvh::Node &node) { return !node_fully_masked_or_hidden(node); }); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::search_nodes( + pbvh, memory, [&](const bke::pbvh::Node &node) { + return !node_fully_masked_or_hidden(node); + }); struct LocalData { Vector factors; @@ -784,19 +799,20 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph, threading::EnumerableThreadSpecific all_tls; switch (pbvh.type()) { case bke::pbvh::Type::Mesh: { + MutableSpan nodes = ss.pbvh->nodes(); const Mesh &mesh = *static_cast(object.data); const Span vert_positions = bke::pbvh::vert_positions_eval(depsgraph, object); const bke::AttributeAccessor attributes = mesh.attributes(); const VArraySpan mask_attr = *attributes.lookup_or_default( ".sculpt_mask", bke::AttrDomain::Point, 0.0f); const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); - for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Span verts = bke::pbvh::node_unique_verts(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span verts = bke::pbvh::node_unique_verts(nodes[i]); MutableSpan positions = gather_data_mesh(vert_positions, verts, tls.positions); MutableSpan masks = gather_data_mesh(mask_attr, verts, tls.masks); @@ -808,22 +824,23 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); return sum; }, combine_average_position_accumulation); return float3(math::safe_divide(total.position, total.weight_total)); } case bke::pbvh::Type::Grids: { + MutableSpan nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); - for (const bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Span grids = bke::pbvh::node_grid_indices(*node); + node_mask.slice(range).foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); const MutableSpan positions = gather_grids_positions( subdiv_ccg, grids, tls.positions); @@ -838,21 +855,22 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); return sum; }, combine_average_position_accumulation); return float3(math::safe_divide(total.position, total.weight_total)); } case bke::pbvh::Type::BMesh: { + MutableSpan nodes = ss.pbvh->nodes(); const AveragePositionAccumulation total = threading::parallel_reduce( - nodes.index_range(), + node_mask.index_range(), 1, AveragePositionAccumulation{}, [&](const IndexRange range, AveragePositionAccumulation sum) { LocalData &tls = all_tls.local(); - for (bke::pbvh::Node *node : nodes.as_span().slice(range)) { - const Set &verts = BKE_pbvh_bmesh_node_unique_verts(node); + node_mask.slice(range).foreach_index([&](const int i) { + const Set &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]); const MutableSpan positions = gather_bmesh_positions(verts, tls.positions); tls.masks.resize(verts.size()); @@ -866,7 +884,7 @@ static float3 average_mask_border_position(const Depsgraph &depsgraph, filter_verts_outside_symmetry_area(positions, pivot, symm, factors); accumulate_weighted_average_position(positions, factors, sum); - } + }); return sum; }, combine_average_position_accumulation); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index 48672bf7ce7..90997e824b2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -605,9 +605,10 @@ static void bmesh_restore_generic(StepData &step_data, Object &object, SculptSes } if (step_data.type == Type::Mask) { - for (bke::pbvh::Node *node : bke::pbvh::all_leaf_nodes(*ss.pbvh)) { - BKE_pbvh_node_mark_redraw(*node); - } + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); + MutableSpan nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); }); } else { BKE_sculptsession_free_pbvh(&ss); @@ -862,7 +863,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) break; } case Type::Position: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { @@ -870,6 +872,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) } if (use_multires_undo(step_data, ss)) { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; MutableSpan grids = subdiv_ccg.grids; const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg); @@ -878,25 +881,26 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) for (std::unique_ptr &unode : step_data.nodes) { restore_position_grids(grids, key, *unode, modified_grids); } - for (bke::pbvh::Node *node : nodes) { - const Span grids = bke::pbvh::node_grid_indices(*node); + node_mask.foreach_index([&](const int i) { + const Span grids = bke::pbvh::node_grid_indices(nodes[i]); if (indices_contain_true(modified_grids, grids)) { - BKE_pbvh_node_mark_positions_update(*node); + BKE_pbvh_node_mark_positions_update(nodes[i]); } - } + }); multires_mark_as_modified(depsgraph, &object, MULTIRES_COORDS_MODIFIED); } else { + MutableSpan nodes = ss.pbvh->nodes(); if (!restore_active_shape_key(*C, *depsgraph, step_data, object)) { return; } Array modified_verts(ss.totvert, false); restore_position_mesh(object, step_data.nodes, modified_verts); - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) { - BKE_pbvh_node_mark_positions_update(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) { + BKE_pbvh_node_mark_positions_update(nodes[i]); } - } + }); } if (tag_update) { @@ -909,7 +913,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) break; } case Type::HideVert: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { @@ -917,27 +922,29 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) } if (use_multires_undo(step_data, ss)) { + MutableSpan nodes = ss.pbvh->nodes(); SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Array modified_grids(subdiv_ccg.grids.size(), false); for (std::unique_ptr &unode : step_data.nodes) { restore_vert_visibility_grids(subdiv_ccg, *unode, modified_grids); } - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(*node))) { - BKE_pbvh_node_mark_update_visibility(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(nodes[i]))) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); } - } + }); } else { + MutableSpan nodes = ss.pbvh->nodes(); Array modified_verts(ss.totvert, false); for (std::unique_ptr &unode : step_data.nodes) { restore_vert_visibility_mesh(object, *unode, modified_verts); } - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) { - BKE_pbvh_node_mark_update_visibility(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); } - } + }); } BKE_pbvh_sync_visibility_from_verts(object); @@ -948,7 +955,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) break; } case Type::HideFace: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { @@ -961,28 +969,30 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) } if (use_multires_undo(step_data, ss)) { + MutableSpan nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Vector faces_vector; - for (bke::pbvh::Node *node : nodes) { + node_mask.foreach_index([&](const int i) { faces_vector.clear(); const Span faces = bke::pbvh::node_face_indices_calc_grids( - subdiv_ccg, static_cast(*node), faces_vector); + subdiv_ccg, nodes[i], faces_vector); if (indices_contain_true(modified_faces, faces)) { - BKE_pbvh_node_mark_update_visibility(*node); + BKE_pbvh_node_mark_update_visibility(nodes[i]); } - } + }); } else { + MutableSpan nodes = ss.pbvh->nodes(); const Span tri_faces = mesh.corner_tri_faces(); Vector faces_vector; - for (bke::pbvh::Node *node : nodes) { + node_mask.foreach_index([&](const int i) { faces_vector.clear(); const Span faces = bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), faces_vector); + tri_faces, static_cast(nodes[i]), faces_vector); if (indices_contain_true(modified_faces, faces)) { - BKE_pbvh_node_mark_update_visibility(*node); + BKE_pbvh_node_mark_update_visibility(nodes[i]); } - } + }); } hide::sync_all_from_faces(object); @@ -990,7 +1000,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) break; } case Type::Mask: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { @@ -998,33 +1009,36 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) } if (use_multires_undo(step_data, ss)) { + MutableSpan nodes = ss.pbvh->nodes(); Array modified_grids(ss.subdiv_ccg->grids.size(), false); for (std::unique_ptr &unode : step_data.nodes) { restore_mask_grids(object, *unode, modified_grids); } - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(*node))) { - BKE_pbvh_node_mark_update_mask(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(nodes[i]))) { + BKE_pbvh_node_mark_update_mask(nodes[i]); } - } + }); } else { + MutableSpan nodes = ss.pbvh->nodes(); Array modified_verts(ss.totvert, false); for (std::unique_ptr &unode : step_data.nodes) { restore_mask_mesh(object, *unode, modified_verts); } - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) { - BKE_pbvh_node_mark_update_mask(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) { + BKE_pbvh_node_mark_update_mask(nodes[i]); } - } + }); } bke::pbvh::update_mask(object, *ss.pbvh); break; } case Type::FaceSet: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { @@ -1036,46 +1050,50 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data) restore_face_sets(object, *unode, modified_faces); } if (use_multires_undo(step_data, ss)) { + MutableSpan nodes = ss.pbvh->nodes(); const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg; Vector faces_vector; - for (bke::pbvh::Node *node : nodes) { + node_mask.foreach_index([&](const int i) { faces_vector.clear(); const Span faces = bke::pbvh::node_face_indices_calc_grids( - subdiv_ccg, static_cast(*node), faces_vector); + subdiv_ccg, nodes[i], faces_vector); if (indices_contain_true(modified_faces, faces)) { - BKE_pbvh_node_mark_update_face_sets(*node); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); } - } + }); } else { + MutableSpan nodes = ss.pbvh->nodes(); const Span tri_faces = mesh.corner_tri_faces(); Vector faces_vector; - for (bke::pbvh::Node *node : nodes) { + node_mask.foreach_index([&](const int i) { faces_vector.clear(); const Span faces = bke::pbvh::node_face_indices_calc_mesh( - tri_faces, static_cast(*node), faces_vector); + tri_faces, static_cast(nodes[i]), faces_vector); if (indices_contain_true(modified_faces, faces)) { - BKE_pbvh_node_mark_update_face_sets(*node); + BKE_pbvh_node_mark_update_face_sets(nodes[i]); } - } + }); } break; } case Type::Color: { - const Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); BKE_sculpt_update_object_for_edit(depsgraph, &object, false); if (!topology_matches(step_data, object)) { return; } + MutableSpan nodes = ss.pbvh->nodes(); Array modified_verts(ss.totvert, false); restore_color(object, step_data, modified_verts); - for (bke::pbvh::Node *node : nodes) { - if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) { - BKE_pbvh_node_mark_update_color(*node); + node_mask.foreach_index([&](const int i) { + if (indices_contain_true(modified_verts, bke::pbvh::node_verts(nodes[i]))) { + BKE_pbvh_node_mark_update_color(nodes[i]); } - } + }); break; } case Type::Geometry: { @@ -1131,7 +1149,7 @@ const Node *get_node(const bke::pbvh::Node *node, const Type type) } static void alloc_and_store_hidden(const SculptSession &ss, - const bke::pbvh::Node &node, + const bke::pbvh::GridsNode &node, Node &unode) { if (!ss.subdiv_ccg) { @@ -1207,7 +1225,7 @@ static void store_hidden(const Object &object, const bke::pbvh::Node &node, Node return; } - const Span verts = bke::pbvh::node_verts(node); + const Span verts = bke::pbvh::node_verts(static_cast(node)); for (const int i : verts.index_range()) { unode.vert_hidden[i].set(hide_vert[verts[i]]); } @@ -1274,7 +1292,8 @@ static void store_color(const Object &object, const bke::pbvh::Node &node, Node /* NOTE: even with loop colors we still store (derived) * vertex colors for original data lookup. */ - const Span verts = bke::pbvh::node_unique_verts(node); + const Span verts = bke::pbvh::node_unique_verts( + static_cast(node)); unode.col.reinitialize(verts.size()); color::gather_colors_vert( faces, corner_verts, vert_to_face_map, colors, color_attribute.domain, verts, unode.col); @@ -1330,14 +1349,15 @@ static void fill_node_data(const Depsgraph &depsgraph, int verts_num; if (ss.pbvh->type() == bke::pbvh::Type::Grids) { - unode.grids = bke::pbvh::node_grid_indices(*node); + unode.grids = bke::pbvh::node_grid_indices(static_cast(*node)); const int grid_area = ss.subdiv_ccg->grid_size * ss.subdiv_ccg->grid_size; verts_num = unode.grids.size() * grid_area; } else { - unode.vert_indices = bke::pbvh::node_verts(*node); - unode.unique_verts_num = bke::pbvh::node_unique_verts(*node).size(); + unode.vert_indices = bke::pbvh::node_verts(static_cast(*node)); + unode.unique_verts_num = + bke::pbvh::node_unique_verts(static_cast(*node)).size(); verts_num = unode.vert_indices.size(); } @@ -1379,7 +1399,7 @@ static void fill_node_data(const Depsgraph &depsgraph, } case Type::HideVert: { if (ss.pbvh->type() == bke::pbvh::Type::Grids) { - alloc_and_store_hidden(ss, *node, unode); + alloc_and_store_hidden(ss, static_cast(*node), unode); } else { unode.vert_hidden.resize(unode.vert_indices.size()); @@ -1423,7 +1443,9 @@ static void fill_node_data(const Depsgraph &depsgraph, * Dynamic topology stores only one undo node per stroke, regardless of the number of * bke::pbvh::Tree nodes modified. */ -BLI_NOINLINE static void bmesh_push(const Object &object, const bke::pbvh::Node *node, Type type) +BLI_NOINLINE static void bmesh_push(const Object &object, + const bke::pbvh::BMeshNode *node, + Type type) { StepData *step_data = get_step_data(); const SculptSession &ss = *object.sculpt; @@ -1465,7 +1487,7 @@ BLI_NOINLINE static void bmesh_push(const Object &object, const bke::pbvh::Node &ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask"); /* The vertices and node aren't changed, though pointers to them are stored in the log. */ - bke::pbvh::Node *node_mut = const_cast(node); + bke::pbvh::BMeshNode *node_mut = const_cast(node); switch (type) { case Type::None: @@ -1532,7 +1554,7 @@ void push_node(const Depsgraph &depsgraph, { SculptSession &ss = *object.sculpt; if (ss.bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) { - bmesh_push(object, node, type); + bmesh_push(object, static_cast(node), type); return; } @@ -1554,14 +1576,13 @@ void push_node(const Depsgraph &depsgraph, void push_nodes(const Depsgraph &depsgraph, Object &object, - const Span nodes, + const IndexMask &node_mask, const Type type) { SculptSession &ss = *object.sculpt; if (ss.bm || ELEM(type, Type::DyntopoBegin, Type::DyntopoEnd)) { - for (const bke::pbvh::Node *node : nodes) { - bmesh_push(object, node, type); - } + const Span nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { bmesh_push(object, &nodes[i], type); }); return; } @@ -1570,11 +1591,32 @@ void push_nodes(const Depsgraph &depsgraph, step_data->type = type; Vector, 32> nodes_to_fill; - for (const bke::pbvh::Node *node : nodes) { - bool newly_added; - Node *unode = ensure_node(*step_data, *node, newly_added); - if (newly_added) { - nodes_to_fill.append({node, unode}); + switch (ss.pbvh->type()) { + case bke::pbvh::Type::Mesh: { + const Span nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + bool newly_added; + Node *unode = ensure_node(*step_data, nodes[i], newly_added); + if (newly_added) { + nodes_to_fill.append({&nodes[i], unode}); + } + }); + break; + } + case bke::pbvh::Type::Grids: { + const Span nodes = ss.pbvh->nodes(); + node_mask.foreach_index([&](const int i) { + bool newly_added; + Node *unode = ensure_node(*step_data, nodes[i], newly_added); + if (newly_added) { + nodes_to_fill.append({&nodes[i], unode}); + } + }); + break; + } + case bke::pbvh::Type::BMesh: { + BLI_assert_unreachable(); + break; } } @@ -2040,8 +2082,9 @@ static void push_all_grids(const Depsgraph &depsgraph, Object *object) return; } - Vector nodes = bke::pbvh::all_leaf_nodes(*ss.pbvh); - push_nodes(depsgraph, *object, nodes, Type::Position); + IndexMaskMemory memory; + const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*ss.pbvh, memory); + push_nodes(depsgraph, *object, node_mask, Type::Position); } void push_multires_mesh_begin(bContext *C, const char *str) diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.hh b/source/blender/editors/sculpt_paint/sculpt_undo.hh index 74f0b18caec..a5ec51eac65 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.hh +++ b/source/blender/editors/sculpt_paint/sculpt_undo.hh @@ -13,6 +13,7 @@ #include "BLI_array.hh" #include "BLI_bit_group_vector.hh" #include "BLI_bit_vector.hh" +#include "BLI_index_mask_fwd.hh" #include "BLI_map.hh" #include "BLI_math_vector.hh" #include "BLI_vector.hh" @@ -174,7 +175,7 @@ void push_node(const Depsgraph &depsgraph, undo::Type type); void push_nodes(const Depsgraph &depsgraph, Object &object, - Span nodes, + const IndexMask &node_mask, undo::Type type); /**