Refactor: Sculpt: Simplify access to BVH nodes in undo code

Use the same method for retrieving "all nodes" that we do elsewhere.
Even though this requires a temporary vector, it makes it an easier
target for optimization later and makes the sculpt BVH iteration
easier to refactor in the meantime.
This commit is contained in:
Hans Goudey
2024-08-19 17:56:26 -04:00
parent 98308757cd
commit 18a7aff3e2
3 changed files with 56 additions and 72 deletions

View File

@@ -277,15 +277,6 @@ std::unique_ptr<Tree> build_bmesh(BMesh *bm);
void build_pixels(const Depsgraph &depsgraph, Object &object, Image &image, ImageUser &image_user);
void free(std::unique_ptr<Tree> &pbvh);
/* Hierarchical Search in the BVH, two methods:
* - For each hit calling a callback.
* - Gather nodes in an array (easy to multi-thread) see search_gather.
*/
void search_callback(Tree &pbvh,
FunctionRef<bool(Node &)> filter_fn,
FunctionRef<void(Node &)> hit_fn);
/* Ray-cast
* the hit callback is called for all leaf nodes intersecting the ray;
* it's up to the callback to find the primitive within the leaves that is

View File

@@ -796,25 +796,6 @@ float BKE_pbvh_node_get_tmin(const blender::bke::pbvh::Node *node)
namespace blender::bke::pbvh {
void search_callback(Tree &pbvh,
FunctionRef<bool(Node &)> filter_fn,
FunctionRef<void(Node &)> hit_fn)
{
if (pbvh.nodes_.is_empty()) {
return;
}
PBVHIter iter;
Node *node;
pbvh_iter_begin(&iter, pbvh, filter_fn);
while ((node = pbvh_iter_next(&iter, PBVH_Leaf))) {
if (node->flag_ & PBVH_Leaf) {
hit_fn(*node);
}
}
}
static void search_callback_occluded(Tree &pbvh,
const FunctionRef<bool(Node &)> scb,
const FunctionRef<void(Node &node, float *tmin)> hit_fn)

View File

@@ -856,6 +856,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::Position: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -870,12 +872,12 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_position_grids(grids, key, *unode, modified_grids);
}
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
const Span<int> grids = bke::pbvh::node_grid_indices(node);
for (bke::pbvh::Node *node : nodes) {
const Span<int> grids = bke::pbvh::node_grid_indices(*node);
if (indices_contain_true(modified_grids, grids)) {
BKE_pbvh_node_mark_positions_update(&node);
BKE_pbvh_node_mark_positions_update(node);
}
});
}
multires_mark_as_modified(depsgraph, &object, MULTIRES_COORDS_MODIFIED);
}
else {
@@ -884,11 +886,11 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
Array<bool> modified_verts(ss.totvert, false);
restore_position_mesh(object, step_data.nodes, modified_verts);
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(node))) {
BKE_pbvh_node_mark_positions_update(&node);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_positions_update(node);
}
});
}
}
if (tag_update) {
@@ -901,6 +903,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::HideVert: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -912,22 +916,22 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_vert_visibility_grids(subdiv_ccg, *unode, modified_grids);
}
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(node))) {
BKE_pbvh_node_mark_update_visibility(&node);
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);
}
});
}
}
else {
Array<bool> modified_verts(ss.totvert, false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_vert_visibility_mesh(object, *unode, modified_verts);
}
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(node))) {
BKE_pbvh_node_mark_update_visibility(&node);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_visibility(node);
}
});
}
}
BKE_pbvh_sync_visibility_from_verts(object);
@@ -938,6 +942,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::HideFace: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -950,26 +956,26 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
if (use_multires_undo(step_data, ss)) {
Vector<int> faces_vector;
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
for (bke::pbvh::Node *node : nodes) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
*ss.pbvh, node, faces_vector);
*ss.pbvh, *node, faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_visibility(&node);
BKE_pbvh_node_mark_update_visibility(node);
}
});
}
}
else {
const Span<int> tri_faces = mesh.corner_tri_faces();
Vector<int> faces_vector;
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
for (bke::pbvh::Node *node : nodes) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, node, faces_vector);
tri_faces, *node, faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_visibility(&node);
BKE_pbvh_node_mark_update_visibility(node);
}
});
}
}
hide::sync_all_from_faces(object);
@@ -977,6 +983,8 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
break;
}
case Type::Mask: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -987,28 +995,30 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_mask_grids(object, *unode, modified_grids);
}
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_grids, bke::pbvh::node_grid_indices(node))) {
BKE_pbvh_node_mark_update_mask(&node);
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);
}
});
}
}
else {
Array<bool> modified_verts(ss.totvert, false);
for (std::unique_ptr<Node> &unode : step_data.nodes) {
restore_mask_mesh(object, *unode, modified_verts);
}
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(node))) {
BKE_pbvh_node_mark_update_mask(&node);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_mask(node);
}
});
}
}
bke::pbvh::update_mask(object, *ss.pbvh);
break;
}
case Type::FaceSet: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -1020,30 +1030,32 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
}
if (use_multires_undo(step_data, ss)) {
Vector<int> faces_vector;
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
for (bke::pbvh::Node *node : nodes) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
*ss.pbvh, node, faces_vector);
*ss.pbvh, *node, faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(&node);
BKE_pbvh_node_mark_update_face_sets(node);
}
});
}
}
else {
const Span<int> tri_faces = mesh.corner_tri_faces();
Vector<int> faces_vector;
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
for (bke::pbvh::Node *node : nodes) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(
tri_faces, node, faces_vector);
tri_faces, *node, faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(&node);
BKE_pbvh_node_mark_update_face_sets(node);
}
});
}
}
break;
}
case Type::Color: {
const Span<bke::pbvh::Node *> nodes = bke::pbvh::search_gather(*ss.pbvh, {});
BKE_sculpt_update_object_for_edit(depsgraph, &object, false);
if (!topology_matches(step_data, object)) {
return;
@@ -1051,11 +1063,11 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
Array<bool> modified_verts(ss.totvert, false);
restore_color(object, step_data, modified_verts);
bke::pbvh::search_callback(*ss.pbvh, {}, [&](bke::pbvh::Node &node) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(node))) {
BKE_pbvh_node_mark_update_color(&node);
for (bke::pbvh::Node *node : nodes) {
if (indices_contain_true(modified_verts, bke::pbvh::node_verts(*node))) {
BKE_pbvh_node_mark_update_color(node);
}
});
}
break;
}
case Type::Geometry: {