Sculpt: Update BVH node bounds in deformation loops

Updating the node bounds just after deforming the vertices in the
node is faster because the position data is still fresh in CPU caches.
Updating it later on means all the other nodes have been processed
in the meantime which will evict that position data from the caches.

This results in a 1.11x improvement in the brush benchmark timing,
from 0.495s to 0.438s on a Ryzen 7950x (best of 5 runs).

As part of the change, the update tagging has completely moved
to each brush implementation. This continues the process of
making each brush more independent.

Part of #118145.

Pull Request: https://projects.blender.org/blender/blender/pulls/127536
This commit is contained in:
Hans Goudey
2024-09-12 23:45:52 +02:00
committed by Hans Goudey
parent dd9b3e4fac
commit d64f62e4fa
41 changed files with 366 additions and 137 deletions

View File

@@ -536,9 +536,16 @@ void node_update_visibility_grids(const BitGroupVector<> &grid_hidden, GridsNode
void node_update_visibility_bmesh(BMeshNode &node);
void update_node_bounds_mesh(Span<float3> positions, MeshNode &node);
void update_node_bounds_grids(const CCGKey &key, Span<float3> positions, GridsNode &node);
void update_node_bounds_grids(int grid_area, Span<float3> positions, GridsNode &node);
void update_node_bounds_bmesh(BMeshNode &node);
/**
* Run the last step of the BVH bounds recalculation process, propagating updated leaf node bounds
* to their parent/ancestor inner nodes. This is meant to be used after leaf node bounds have been
* computed separately.
*/
void flush_bounds_to_parents(Tree &pbvh);
inline Span<int> MeshNode::faces() const
{
return this->face_indices_;

View File

@@ -1038,11 +1038,11 @@ void update_node_bounds_mesh(const Span<float3> positions, MeshNode &node)
node.bounds_ = bounds;
}
void update_node_bounds_grids(const CCGKey &key, const Span<float3> positions, GridsNode &node)
void update_node_bounds_grids(const int grid_area, const Span<float3> positions, GridsNode &node)
{
Bounds<float3> bounds = negative_bounds();
for (const int grid : node.grids()) {
for (const float3 &position : positions.slice(bke::ccg::grid_range(key, grid))) {
for (const float3 &position : positions.slice(bke::ccg::grid_range(grid_area, grid))) {
math::min_max(position, bounds.min, bounds.max);
}
}
@@ -1086,7 +1086,7 @@ static BoundsMergeInfo merge_child_bounds(MutableSpan<NodeT> nodes, const int no
return {node.bounds_, update};
}
static void flush_bounds_to_parents(Tree &pbvh)
void flush_bounds_to_parents(Tree &pbvh)
{
std::visit(
[](auto &nodes) {
@@ -1116,8 +1116,9 @@ void update_bounds_grids(const CCGKey &key, const Span<float3> positions, Tree &
pbvh, memory, [&](const Node &node) { return update_search(node, PBVH_UpdateBB); });
MutableSpan<GridsNode> nodes = pbvh.nodes<GridsNode>();
nodes_to_update.foreach_index(
GrainSize(1), [&](const int i) { update_node_bounds_grids(key, positions, nodes[i]); });
nodes_to_update.foreach_index(GrainSize(1), [&](const int i) {
update_node_bounds_grids(key.grid_area, positions, nodes[i]);
});
if (!nodes.is_empty()) {
flush_bounds_to_parents(pbvh);
}

View File

@@ -127,9 +127,12 @@ void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph,
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(
depsgraph, sd, object, brush, direction, factor * ss.cache->pressure, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -245,16 +245,21 @@ void do_clay_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -265,11 +270,14 @@ void do_clay_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, test_plane, bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -299,16 +299,21 @@ void do_clay_strips_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -319,11 +324,14 @@ void do_clay_strips_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -278,16 +278,21 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, brush, plane_tilt, clay_strength, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -298,11 +303,14 @@ void do_clay_thumb_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, brush, plane_tilt, clay_strength, object, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
float clay_thumb_get_stabilized_pressure(const StrokeCache &cache)

View File

@@ -281,16 +281,21 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, offset, strength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -301,11 +306,14 @@ static void do_crease_or_blob_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, offset, strength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace crease_cc

View File

@@ -196,16 +196,22 @@ static void offset_positions(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -213,12 +219,16 @@ static void offset_positions(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
void do_draw_brush(const Depsgraph &depsgraph,

View File

@@ -184,7 +184,6 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
MeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
const Span<int> face_indices = nodes[i].faces();
calc_faces(depsgraph,
object,
brush,
@@ -195,6 +194,7 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
face_indices,
tls,
face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
});
});

View File

@@ -192,16 +192,22 @@ static void offset_positions(const Depsgraph &depsgraph,
calc_faces(
depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -209,12 +215,16 @@ static void offset_positions(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
void do_draw_sharp_brush(const Depsgraph &depsgraph,

View File

@@ -245,16 +245,22 @@ void do_draw_vector_displacement_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -262,12 +268,16 @@ void do_draw_vector_displacement_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -259,16 +259,21 @@ void do_elastic_deform_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -279,10 +284,13 @@ void do_elastic_deform_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
} break;
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -334,16 +334,21 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, translations, strength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -354,11 +359,14 @@ void do_enhance_details_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, translations, strength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -231,16 +231,21 @@ void do_fill_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -251,11 +256,14 @@ void do_fill_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -224,16 +224,21 @@ void do_flatten_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -244,6 +249,8 @@ void do_flatten_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;

View File

@@ -233,16 +233,21 @@ void do_grab_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -253,11 +258,14 @@ void do_grab_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -209,16 +209,22 @@ void do_inflate_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -226,12 +232,16 @@ void do_inflate_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -410,14 +410,18 @@ void do_layer_brush(const Depsgraph &depsgraph,
tls,
displacement,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
persistent_disp_attr.finish();
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
if (ss.cache->layer_displacement_factor.is_empty()) {
ss.cache->layer_displacement_factor = Array<float>(SCULPT_vertex_count_get(object), 0.0f);
ss.cache->layer_displacement_factor = Array<float>(positions.size(), 0.0f);
}
const MutableSpan<float> displacement = ss.cache->layer_displacement_factor;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
@@ -425,6 +429,8 @@ void do_layer_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, brush, object, nodes[i], tls, displacement);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -439,11 +445,14 @@ void do_layer_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, brush, object, nodes[i], tls, displacement);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -244,6 +244,7 @@ void do_mask_brush(const Depsgraph &depsgraph,
mesh,
tls,
mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
mask.finish();
@@ -253,8 +254,10 @@ void do_mask_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
}
@@ -262,8 +265,10 @@ void do_mask_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
}

View File

@@ -663,11 +663,14 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
}
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
@@ -682,6 +685,8 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
nodes[i],
object,
tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -701,11 +706,14 @@ void do_multiplane_scrape_brush(const Depsgraph &depsgraph,
nodes[i],
object,
tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
void multiplane_scrape_preview_draw(const uint gpuattr,

View File

@@ -100,6 +100,8 @@ void do_displacement_eraser_brush(const Depsgraph &depsgraph,
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
const float strength = std::min(ss.cache->bstrength, 1.0f);
@@ -108,9 +110,13 @@ void do_displacement_eraser_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -204,9 +204,13 @@ void do_displacement_smear_brush(const Depsgraph &depsgraph,
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -270,16 +270,21 @@ void do_pinch_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -290,11 +295,14 @@ void do_pinch_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -535,7 +535,10 @@ static void do_topology_relax_brush_mesh(const Depsgraph &depsgraph,
object,
translations.as_mutable_span().slice(node_vert_offsets[pos]),
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
bke::pbvh::flush_bounds_to_parents(pbvh);
}
BLI_NOINLINE static void calc_topology_relax_factors_grids(const Depsgraph &depsgraph,
@@ -589,7 +592,8 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
const SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
Mesh &mesh = *static_cast<Mesh *>(object.data);
@@ -643,7 +647,10 @@ static void do_topology_relax_brush_grids(const Depsgraph &depsgraph,
object,
current_positions.as_mutable_span().slice(node_vert_offsets[pos]),
translations.as_mutable_span().slice(node_vert_offsets[pos]));
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
bke::pbvh::flush_bounds_to_parents(pbvh);
}
static void calc_topology_relax_factors_bmesh(const Depsgraph &depsgraph,
@@ -735,7 +742,10 @@ static void do_topology_relax_brush_bmesh(const Depsgraph &depsgraph,
object,
translations.as_mutable_span().slice(node_vert_offsets[pos]),
current_positions.as_span().slice(node_vert_offsets[pos]));
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */

View File

@@ -223,16 +223,22 @@ void do_rotate_brush(const Depsgraph &depsgraph,
calc_faces(
depsgraph, sd, brush, angle, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -240,12 +246,16 @@ void do_rotate_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -232,16 +232,21 @@ void do_scrape_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -252,11 +257,14 @@ void do_scrape_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, plane, ss.cache->bstrength, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -330,6 +330,7 @@ void do_smooth_brush(const Depsgraph &depsgraph,
break;
}
}
bke::pbvh::update_bounds(depsgraph, object, pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -172,6 +172,7 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
tls,
new_masks.as_span().slice(node_vert_offsets[pos]),
mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
}
mask.finish();
@@ -304,8 +305,10 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
}
break;
@@ -322,6 +325,7 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, object, mask_offset, brush, strength, nodes[i], tls);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
}

View File

@@ -396,16 +396,21 @@ void do_snake_hook_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -416,11 +421,14 @@ void do_snake_hook_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, sd, object, brush, &spvc, grab_delta, nodes[i], tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -376,9 +376,10 @@ void do_surface_smooth_brush(const Depsgraph &depsgraph,
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
switch (bke::object::pbvh_get(object)->type()) {
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh:
do_surface_smooth_brush_mesh(
depsgraph, sd, brush, node_mask, object, ss.cache->surface_smooth_laplacian_disp);
@@ -395,6 +396,7 @@ void do_surface_smooth_brush(const Depsgraph &depsgraph,
break;
}
}
bke::pbvh::update_bounds(depsgraph, object, pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -199,16 +199,22 @@ void do_thumb_brush(const Depsgraph &depsgraph,
calc_faces(
depsgraph, sd, brush, offset, positions_eval, nodes[i], object, tls, positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -216,12 +222,16 @@ void do_thumb_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -343,16 +343,22 @@ void do_topology_slide_brush(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -360,12 +366,16 @@ void do_topology_slide_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -3347,27 +3347,6 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
bool need_coords = ss.cache->supports_gravity;
if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_DRAW_FACE_SETS) {
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
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. */
if (ss.cache->alt_smooth) {
need_coords = true;
@@ -3378,43 +3357,9 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
}
else if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK) {
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
}
}
else if (SCULPT_brush_type_is_paint(brush.sculpt_brush_type)) {
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Color);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
break;
}
}
}
else {
need_coords = true;
@@ -3422,26 +3367,6 @@ static void push_undo_nodes(const Depsgraph &depsgraph,
if (need_coords) {
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_positions_update(nodes[i]); });
break;
}
}
}
}
@@ -5395,10 +5320,6 @@ void flush_update_step(bContext *C, UpdateType update_type)
* only the part of the 3D viewport where changes happened. */
rcti r;
if (update_type == UpdateType::Position) {
bke::pbvh::update_bounds(depsgraph, ob, pbvh);
}
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d && SCULPT_get_redraw_rect(region, *rv3d, ob, r)) {
if (ss.cache) {

View File

@@ -1312,12 +1312,14 @@ static void do_bend_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -1336,6 +1338,8 @@ static void do_bend_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -1358,11 +1362,14 @@ static void do_bend_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */
@@ -1603,12 +1610,14 @@ static void do_slide_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -1626,6 +1635,8 @@ static void do_slide_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -1647,11 +1658,14 @@ static void do_slide_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */
@@ -1877,12 +1891,14 @@ static void do_inflate_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -1899,6 +1915,8 @@ static void do_inflate_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -1919,11 +1937,14 @@ static void do_inflate_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */
@@ -2152,12 +2173,14 @@ static void do_grab_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -2175,6 +2198,8 @@ static void do_grab_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -2196,11 +2221,14 @@ static void do_grab_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */
@@ -2436,12 +2464,14 @@ static void do_twist_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -2460,6 +2490,8 @@ static void do_twist_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -2482,11 +2514,14 @@ static void do_twist_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/** \} */
@@ -2841,12 +2876,14 @@ static void do_smooth_brush(const Depsgraph &depsgraph,
deform_target,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
threading::EnumerableThreadSpecific<LocalDataGrids> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -2862,6 +2899,8 @@ static void do_smooth_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -2881,11 +2920,14 @@ static void do_smooth_brush(const Depsgraph &depsgraph,
boundary.initial_vert_position,
strength,
deform_target);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
/* -------------------------------------------------------------------- */

View File

@@ -1431,6 +1431,8 @@ void do_simulation_step(const Depsgraph &depsgraph,
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
@@ -1468,6 +1470,8 @@ void do_simulation_step(const Depsgraph &depsgraph,
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -1501,11 +1505,14 @@ void do_simulation_step(const Depsgraph &depsgraph,
cloth_sim.node_state[cloth_sim.node_state_index.lookup(&nodes[i])] =
SCULPT_CLOTH_NODE_INACTIVE;
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
static void cloth_brush_apply_brush_foces(const Depsgraph &depsgraph,
@@ -2342,11 +2349,14 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
object,
tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
@@ -2354,6 +2364,7 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
apply_filter_forces_grids(
*depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -2366,11 +2377,13 @@ static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent
apply_filter_forces_bmesh(
*depsgraph, filter_type, filter_strength, gravity, nodes[i], object, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
/* Activate all nodes. */
sim_activate_nodes(object, *ss.filter_cache->cloth_sim, node_mask);

View File

@@ -1470,6 +1470,7 @@ static void edit_modify_coordinates(
BLI_assert_unreachable();
}
bke::pbvh::update_bounds(depsgraph, ob, pbvh);
flush_update_step(C, UpdateType::Position);
flush_update_done(C, ob, UpdateType::Position);
undo::push_end(ob);

View File

@@ -2297,6 +2297,7 @@ static void sculpt_mesh_filter_apply(bContext *C, wmOperator *op)
ss.filter_cache->iteration_count++;
bke::pbvh::update_bounds(depsgraph, ob, *bke::object::pbvh_get(ob));
flush_update_step(C, UpdateType::Position);
}

View File

@@ -591,6 +591,7 @@ void do_paint_brush(const Depsgraph &depsgraph,
nodes[i],
tls,
color_attribute);
BKE_pbvh_node_mark_update_color(nodes[i]);
});
});
color_attribute.finish();
@@ -667,6 +668,7 @@ void do_paint_brush(const Depsgraph &depsgraph,
tls,
ss.cache->paint_brush.mix_colors,
color_attribute);
BKE_pbvh_node_mark_update_color(nodes[i]);
});
});
color_attribute.finish();
@@ -890,6 +892,7 @@ void do_smear_brush(const Depsgraph &depsgraph,
nodes[i],
tls,
color_attribute);
BKE_pbvh_node_mark_update_color(nodes[i]);
});
});
}
@@ -921,6 +924,7 @@ void do_smear_brush(const Depsgraph &depsgraph,
nodes[i],
tls,
color_attribute);
BKE_pbvh_node_mark_update_color(nodes[i]);
});
});
}

View File

@@ -1595,16 +1595,22 @@ void do_pose_brush(const Depsgraph &depsgraph,
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]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ob.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BrushLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
}
@@ -1612,12 +1618,16 @@ void do_pose_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BrushLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index(
[&](const int i) { 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);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
} // namespace blender::ed::sculpt_paint::pose

View File

@@ -167,11 +167,14 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Position);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
@@ -179,6 +182,7 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g
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]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -191,6 +195,7 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g
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]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
@@ -203,6 +208,7 @@ static void gesture_apply_for_symmetry_pass(bContext &C, gesture::GestureData &g
BLI_assert_unreachable();
break;
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
static void gesture_end(bContext &C, gesture::GestureData &gesture_data)

View File

@@ -506,11 +506,14 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
tls,
positions_orig);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_mesh(positions_eval, nodes[i]);
});
});
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ob.sculpt->subdiv_ccg;
MutableSpan<float3> positions = subdiv_ccg.positions;
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
TransformLocalData &tls = all_tls.local();
@@ -518,6 +521,7 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
elastic_transform_node_grids(
sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
});
});
break;
@@ -530,12 +534,14 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
elastic_transform_node_bmesh(
sd, params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
BKE_pbvh_node_mark_positions_update(nodes[i]);
bke::pbvh::update_node_bounds_bmesh(nodes[i]);
});
});
break;
}
}
}
bke::pbvh::flush_bounds_to_parents(pbvh);
}
void update_modal_transform(bContext *C, Object &ob)