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); /**