Cleanup: Make paint BVH update tags proper private members

Move some functions to be methods of pbvh::Tree instead.

Pull Request: https://projects.blender.org/blender/blender/pulls/133989
This commit is contained in:
Hans Goudey
2025-02-03 19:36:33 +01:00
committed by Hans Goudey
parent 7d54bfb49c
commit 4e18ebee1b
38 changed files with 128 additions and 130 deletions

View File

@@ -226,9 +226,6 @@ class Tree {
/** Memory backing for #Node::prim_indices. Without an inline buffer to make #Tree movable. */
Array<int, 0> prim_indices_;
public:
std::variant<Vector<MeshNode>, Vector<GridsNode>, Vector<BMeshNode>> nodes_;
/**
* If true, the bounds for the corresponding node index is out of date.
* \note Values are only meaningful for leaf nodes.
@@ -250,6 +247,9 @@ class Tree {
*/
BitVector<> visibility_dirty_;
public:
std::variant<Vector<MeshNode>, Vector<GridsNode>, Vector<BMeshNode>> nodes_;
pixels::PBVHData *pixels_ = nullptr;
std::unique_ptr<DrawCache> draw_data;
@@ -273,7 +273,7 @@ class Tree {
Type type() const
{
return this->type_;
return type_;
}
/**
@@ -302,6 +302,26 @@ class Tree {
*/
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name);
/**
* 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();
/**
* Recalculate node bounding boxes based on the current coordinates. Calculation is only done for
* affected nodes that have been tagged by #PBVH::tag_positions_changed().
*/
void update_bounds(const Depsgraph &depsgraph, const Object &object);
void update_bounds_mesh(Span<float3> vert_positions);
void update_bounds_grids(Span<float3> positions, int grid_area);
void update_bounds_bmesh(const BMesh &bm);
void update_normals(Object &object_orig, Object &object_eval);
void update_visibility(const Object &object);
private:
explicit Tree(Type type);
};
@@ -505,15 +525,6 @@ void BKE_pbvh_bmesh_after_stroke(BMesh &bm, blender::bke::pbvh::Tree &pbvh);
namespace blender::bke::pbvh {
/**
* Recalculate node bounding boxes based on the current coordinates. Calculation is only done for
* affected nodes that have been tagged by #PBVH::tag_positions_changed().
*/
void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh);
void update_bounds_mesh(Span<float3> vert_positions, Tree &pbvh);
void update_bounds_grids(const CCGKey &key, Span<float3> positions, Tree &pbvh);
void update_bounds_bmesh(const BMesh &bm, Tree &pbvh);
/**
* Copy all current node bounds to the original bounds. "Original" bounds are typically from before
* a brush stroke started (while the "regular" bounds update on every change of positions). These
@@ -527,7 +538,6 @@ void update_mask_mesh(const Mesh &mesh, const IndexMask &node_mask, Tree &pbvh);
void update_mask_grids(const SubdivCCG &subdiv_ccg, const IndexMask &node_mask, Tree &pbvh);
void update_mask_bmesh(const BMesh &bm, const IndexMask &node_mask, Tree &pbvh);
void update_visibility(const Object &object, Tree &pbvh);
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh);
/** Update geometry normals (potentially on the original object geometry). */
void update_normals_from_eval(Object &object_eval, Tree &pbvh);
@@ -602,13 +612,6 @@ void update_node_bounds_mesh(Span<float3> positions, MeshNode &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

@@ -273,7 +273,7 @@ Tree Tree::from_mesh(const Mesh &mesh)
pbvh.tag_positions_changed(nodes.index_range());
update_bounds_mesh(vert_positions, pbvh);
pbvh.update_bounds_mesh(vert_positions);
store_bounds_orig(pbvh);
if (!hide_vert.is_empty()) {
@@ -457,7 +457,7 @@ Tree Tree::from_grids(const Mesh &base_mesh, const SubdivCCG &subdiv_ccg)
pbvh.tag_positions_changed(nodes.index_range());
update_bounds_grids(key, positions, pbvh);
pbvh.update_bounds_grids(positions, key.grid_area);
store_bounds_orig(pbvh);
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
@@ -536,12 +536,10 @@ Tree::~Tree()
void Tree::tag_positions_changed(const IndexMask &node_mask)
{
this->bounds_dirty_.resize(std::max(this->bounds_dirty_.size(), node_mask.min_array_size()),
false);
this->normals_dirty_.resize(std::max(this->normals_dirty_.size(), node_mask.min_array_size()),
false);
node_mask.set_bits(this->bounds_dirty_);
node_mask.set_bits(this->normals_dirty_);
bounds_dirty_.resize(std::max(bounds_dirty_.size(), node_mask.min_array_size()), false);
normals_dirty_.resize(std::max(normals_dirty_.size(), node_mask.min_array_size()), false);
node_mask.set_bits(bounds_dirty_);
node_mask.set_bits(normals_dirty_);
if (this->draw_data) {
this->draw_data->tag_positions_changed(node_mask);
}
@@ -549,9 +547,8 @@ void Tree::tag_positions_changed(const IndexMask &node_mask)
void Tree::tag_visibility_changed(const IndexMask &node_mask)
{
this->visibility_dirty_.resize(std::max(this->bounds_dirty_.size(), node_mask.min_array_size()),
false);
node_mask.set_bits(this->visibility_dirty_);
visibility_dirty_.resize(std::max(visibility_dirty_.size(), node_mask.min_array_size()), false);
node_mask.set_bits(visibility_dirty_);
if (this->draw_data) {
this->draw_data->tag_visibility_changed(node_mask);
}
@@ -1015,20 +1012,20 @@ static void update_normals_mesh(Object &object_orig,
}
}
static void update_normals(Object &object_orig, Object &object_eval, Tree &pbvh)
void Tree::update_normals(Object &object_orig, Object &object_eval)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.normals_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(normals_dirty_, memory);
switch (pbvh.type()) {
switch (this->type()) {
case Type::Mesh: {
update_normals_mesh(object_orig, object_eval, pbvh.nodes<MeshNode>(), nodes_to_update);
update_normals_mesh(object_orig, object_eval, this->nodes<MeshNode>(), nodes_to_update);
break;
}
case Type::Grids: {
SculptSession &ss = *object_orig.sculpt;
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
MutableSpan<GridsNode> nodes = pbvh.nodes<GridsNode>();
MutableSpan<GridsNode> nodes = this->nodes<GridsNode>();
IndexMaskMemory memory;
const IndexMask faces_to_update = nodes_to_face_selection_grids(
subdiv_ccg, nodes, nodes_to_update, memory);
@@ -1036,18 +1033,18 @@ static void update_normals(Object &object_orig, Object &object_eval, Tree &pbvh)
break;
}
case Type::BMesh: {
bmesh_normals_update(pbvh, nodes_to_update);
bmesh_normals_update(*this, nodes_to_update);
break;
}
}
pbvh.normals_dirty_.clear_and_shrink();
normals_dirty_.clear_and_shrink();
}
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
{
BLI_assert(DEG_is_original_object(&object_orig));
Object &object_eval = *DEG_get_evaluated_object(&depsgraph, &object_orig);
update_normals(object_orig, object_eval, pbvh);
pbvh.update_normals(object_orig, object_eval);
}
void update_normals_from_eval(Object &object_eval, Tree &pbvh)
@@ -1057,7 +1054,7 @@ void update_normals_from_eval(Object &object_eval, Tree &pbvh)
* their result), and also because (currently) sculpt deformations skip tagging the mesh normals
* caches dirty. */
Object &object_orig = *DEG_get_original_object(&object_eval);
update_normals(object_orig, object_eval, pbvh);
pbvh.update_normals(object_orig, object_eval);
}
void update_node_bounds_mesh(const Span<float3> positions, MeshNode &node)
@@ -1117,75 +1114,74 @@ static BoundsMergeInfo merge_child_bounds(MutableSpan<NodeT> nodes,
return {node.bounds_, update};
}
void flush_bounds_to_parents(Tree &pbvh)
void Tree::flush_bounds_to_parents()
{
std::visit(
[&](auto &nodes) {
nodes.first().bounds_ =
merge_child_bounds(nodes.as_mutable_span(), pbvh.bounds_dirty_, 0).bounds;
merge_child_bounds(nodes.as_mutable_span(), bounds_dirty_, 0).bounds;
},
pbvh.nodes_);
pbvh.bounds_dirty_.clear_and_shrink();
this->nodes_);
bounds_dirty_.clear_and_shrink();
}
void update_bounds_mesh(const Span<float3> vert_positions, Tree &pbvh)
void Tree::update_bounds_mesh(const Span<float3> vert_positions)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}
MutableSpan<MeshNode> nodes = pbvh.nodes<MeshNode>();
MutableSpan<MeshNode> nodes = this->nodes<MeshNode>();
nodes_to_update.foreach_index(
GrainSize(1), [&](const int i) { update_node_bounds_mesh(vert_positions, nodes[i]); });
flush_bounds_to_parents(pbvh);
this->flush_bounds_to_parents();
}
void update_bounds_grids(const CCGKey &key, const Span<float3> positions, Tree &pbvh)
void Tree::update_bounds_grids(const Span<float3> positions, const int grid_area)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}
MutableSpan<GridsNode> nodes = pbvh.nodes<GridsNode>();
MutableSpan<GridsNode> nodes = this->nodes<GridsNode>();
nodes_to_update.foreach_index(GrainSize(1), [&](const int i) {
update_node_bounds_grids(key.grid_area, positions, nodes[i]);
update_node_bounds_grids(grid_area, positions, nodes[i]);
});
flush_bounds_to_parents(pbvh);
this->flush_bounds_to_parents();
}
void update_bounds_bmesh(const BMesh & /*bm*/, Tree &pbvh)
void Tree::update_bounds_bmesh(const BMesh & /*bm*/)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}
MutableSpan<BMeshNode> nodes = pbvh.nodes<BMeshNode>();
MutableSpan<BMeshNode> nodes = this->nodes<BMeshNode>();
nodes_to_update.foreach_index(GrainSize(1),
[&](const int i) { update_node_bounds_bmesh(nodes[i]); });
flush_bounds_to_parents(pbvh);
this->flush_bounds_to_parents();
}
void update_bounds(const Depsgraph &depsgraph, const Object &object, Tree &pbvh)
void Tree::update_bounds(const Depsgraph &depsgraph, const Object &object)
{
switch (pbvh.type()) {
switch (this->type()) {
case Type::Mesh: {
const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, object);
update_bounds_mesh(positions, pbvh);
this->update_bounds_mesh(positions);
break;
}
case Type::Grids: {
const SculptSession &ss = *object.sculpt;
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
update_bounds_grids(key, subdiv_ccg.positions, pbvh);
this->update_bounds_grids(subdiv_ccg.positions, subdiv_ccg.grid_area);
break;
}
case Type::BMesh: {
const SculptSession &ss = *object.sculpt;
update_bounds_bmesh(*ss.bm, pbvh);
this->update_bounds_bmesh(*ss.bm);
break;
}
}
@@ -1362,27 +1358,27 @@ static void update_visibility_bmesh(const MutableSpan<BMeshNode> nodes, const In
[&](const int i) { node_update_visibility_bmesh(nodes[i]); });
}
void update_visibility(const Object &object, Tree &pbvh)
void Tree::update_visibility(const Object &object)
{
IndexMaskMemory memory;
const IndexMask node_mask = IndexMask::from_bits(pbvh.visibility_dirty_, memory);
const IndexMask node_mask = IndexMask::from_bits(visibility_dirty_, memory);
if (node_mask.is_empty()) {
return;
}
pbvh.visibility_dirty_.clear_and_shrink();
switch (pbvh.type()) {
visibility_dirty_.clear_and_shrink();
switch (this->type()) {
case Type::Mesh: {
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
update_visibility_faces(mesh, pbvh.nodes<MeshNode>(), node_mask);
update_visibility_faces(mesh, this->nodes<MeshNode>(), node_mask);
break;
}
case Type::Grids: {
const SculptSession &ss = *object.sculpt;
update_visibility_grids(*ss.subdiv_ccg, pbvh.nodes<GridsNode>(), node_mask);
update_visibility_grids(*ss.subdiv_ccg, this->nodes<GridsNode>(), node_mask);
break;
}
case Type::BMesh: {
update_visibility_bmesh(pbvh.nodes<BMeshNode>(), node_mask);
update_visibility_bmesh(this->nodes<BMeshNode>(), node_mask);
break;
}
}
@@ -2356,7 +2352,7 @@ void BKE_pbvh_vert_coords_apply(blender::bke::pbvh::Tree &pbvh,
{
using namespace blender::bke::pbvh;
pbvh.tag_positions_changed(blender::IndexRange(pbvh.nodes_num()));
update_bounds_mesh(vert_positions, pbvh);
pbvh.update_bounds_mesh(vert_positions);
store_bounds_orig(pbvh);
}

View File

@@ -2262,7 +2262,7 @@ Tree Tree::from_bmesh(BMesh &bm)
nodes, cd_vert_node_offset, cd_face_node_offset, nodeinfo, face_bounds, &rootnode, 0);
pbvh.tag_positions_changed(nodes.index_range());
update_bounds_bmesh(bm, pbvh);
pbvh.update_bounds_bmesh(bm);
store_bounds_orig(pbvh);
threading::parallel_for(nodes.index_range(), 8, [&](const IndexRange range) {