Refactor: Sculpt: Use static constructors for PBVH build
This commit is contained in:
@@ -199,12 +199,12 @@ class Tree {
|
||||
friend Node;
|
||||
Type type_;
|
||||
|
||||
public:
|
||||
std::variant<Vector<MeshNode>, Vector<GridsNode>, Vector<BMeshNode>> nodes_;
|
||||
|
||||
/* Memory backing for Node.prim_indices. */
|
||||
Array<int> 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.
|
||||
@@ -235,9 +235,19 @@ class Tree {
|
||||
std::unique_ptr<DrawCache> draw_data;
|
||||
|
||||
public:
|
||||
explicit Tree(Type type);
|
||||
Tree(const Tree &other) = default;
|
||||
Tree(Tree &&other) = default;
|
||||
Tree &operator=(const Tree &other) = default;
|
||||
Tree &operator=(Tree &&other) = default;
|
||||
~Tree();
|
||||
|
||||
/** Build a BVH tree from base mesh triangles. */
|
||||
static Tree from_mesh(const Mesh &mesh);
|
||||
/** Build a BVH tree from grids geometry. */
|
||||
static Tree from_grids(const Mesh &base_mesh, const SubdivCCG &subdiv_ccg);
|
||||
/** Build a BVH tree from a triangle BMesh. */
|
||||
static Tree from_bmesh(BMesh &bm);
|
||||
|
||||
int nodes_num() const;
|
||||
template<typename NodeT> Span<NodeT> nodes() const;
|
||||
template<typename NodeT> MutableSpan<NodeT> nodes();
|
||||
@@ -272,6 +282,9 @@ class Tree {
|
||||
* Tag nodes where generic attribute data has changed (not positions, masks, or face sets).
|
||||
*/
|
||||
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name);
|
||||
|
||||
private:
|
||||
explicit Tree(Type type);
|
||||
};
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
@@ -285,13 +298,6 @@ struct PBVHFrustumPlanes {
|
||||
|
||||
namespace blender::bke::pbvh {
|
||||
|
||||
/** Build a BVH tree from base mesh triangles. */
|
||||
std::unique_ptr<Tree> build_mesh(const Mesh &mesh);
|
||||
/** Build a BVH tree from grids geometry. */
|
||||
std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv_ccg);
|
||||
/** Build a BVH tree from a triangle BMesh. */
|
||||
std::unique_ptr<Tree> build_bmesh(BMesh *bm);
|
||||
|
||||
void build_pixels(const Depsgraph &depsgraph, Object &object, Image &image, ImageUser &image_user);
|
||||
|
||||
/* Ray-cast
|
||||
|
||||
@@ -2348,14 +2348,14 @@ static std::unique_ptr<pbvh::Tree> build_pbvh_for_dynamic_topology(Object *ob)
|
||||
BM_data_layer_ensure_named(&bm, &bm.vdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_vertex");
|
||||
BM_data_layer_ensure_named(&bm, &bm.pdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_face");
|
||||
|
||||
return pbvh::build_bmesh(&bm);
|
||||
return std::make_unique<pbvh::Tree>(pbvh::Tree::from_bmesh(bm));
|
||||
}
|
||||
|
||||
static std::unique_ptr<pbvh::Tree> build_pbvh_from_regular_mesh(Object *ob,
|
||||
const Mesh *me_eval_deform)
|
||||
{
|
||||
const Mesh &mesh = *BKE_object_get_original_mesh(ob);
|
||||
std::unique_ptr<pbvh::Tree> pbvh = pbvh::build_mesh(mesh);
|
||||
std::unique_ptr<pbvh::Tree> pbvh = std::make_unique<pbvh::Tree>(pbvh::Tree::from_mesh(mesh));
|
||||
|
||||
const bool is_deformed = check_sculpt_object_deformed(ob, true);
|
||||
if (is_deformed && me_eval_deform != nullptr) {
|
||||
@@ -2370,7 +2370,7 @@ static std::unique_ptr<pbvh::Tree> build_pbvh_from_ccg(Object *ob, SubdivCCG &su
|
||||
const Mesh &base_mesh = *BKE_mesh_from_object(ob);
|
||||
BKE_sculpt_sync_face_visibility_to_grids(base_mesh, subdiv_ccg);
|
||||
|
||||
return pbvh::build_grids(base_mesh, subdiv_ccg);
|
||||
return std::make_unique<pbvh::Tree>(pbvh::Tree::from_grids(base_mesh, subdiv_ccg));
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
@@ -227,12 +227,12 @@ inline Bounds<float3> calc_face_bounds(const Span<float3> vert_positions,
|
||||
return bounds;
|
||||
}
|
||||
|
||||
std::unique_ptr<Tree> build_mesh(const Mesh &mesh)
|
||||
Tree Tree::from_mesh(const Mesh &mesh)
|
||||
{
|
||||
#ifdef DEBUG_BUILD_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
#endif
|
||||
std::unique_ptr<Tree> pbvh = std::make_unique<Tree>(Type::Mesh);
|
||||
Tree pbvh(Type::Mesh);
|
||||
const Span<float3> vert_positions = mesh.vert_positions();
|
||||
const OffsetIndices<int> faces = mesh.faces();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
@@ -264,25 +264,25 @@ std::unique_ptr<Tree> build_mesh(const Mesh &mesh)
|
||||
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", AttrDomain::Point);
|
||||
const VArraySpan material_index = *attributes.lookup<int>("material_index", AttrDomain::Face);
|
||||
|
||||
pbvh->prim_indices_.reinitialize(faces.size());
|
||||
array_utils::fill_index_range<int>(pbvh->prim_indices_);
|
||||
pbvh.prim_indices_.reinitialize(faces.size());
|
||||
array_utils::fill_index_range<int>(pbvh.prim_indices_);
|
||||
|
||||
Vector<MeshNode> &nodes = std::get<Vector<MeshNode>>(pbvh->nodes_);
|
||||
Vector<MeshNode> &nodes = std::get<Vector<MeshNode>>(pbvh.nodes_);
|
||||
nodes.resize(1);
|
||||
{
|
||||
#ifdef DEBUG_BUILD_TIME
|
||||
SCOPED_TIMER_AVERAGED("build_nodes_recursive_mesh");
|
||||
#endif
|
||||
build_nodes_recursive_mesh(
|
||||
material_index, leaf_limit, 0, bounds, face_centers, 0, pbvh->prim_indices_, nodes);
|
||||
material_index, leaf_limit, 0, bounds, face_centers, 0, pbvh.prim_indices_, nodes);
|
||||
}
|
||||
|
||||
build_mesh_leaf_nodes(mesh.verts_num, faces, corner_verts, nodes);
|
||||
|
||||
pbvh->tag_positions_changed(nodes.index_range());
|
||||
pbvh.tag_positions_changed(nodes.index_range());
|
||||
|
||||
update_bounds_mesh(vert_positions, *pbvh);
|
||||
store_bounds_orig(*pbvh);
|
||||
update_bounds_mesh(vert_positions, pbvh);
|
||||
store_bounds_orig(pbvh);
|
||||
|
||||
if (!hide_vert.is_empty()) {
|
||||
threading::parallel_for(nodes.index_range(), 8, [&](const IndexRange range) {
|
||||
@@ -292,7 +292,7 @@ std::unique_ptr<Tree> build_mesh(const Mesh &mesh)
|
||||
});
|
||||
}
|
||||
|
||||
update_mask_mesh(mesh, nodes.index_range(), *pbvh);
|
||||
update_mask_mesh(mesh, nodes.index_range(), pbvh);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
@@ -382,13 +382,12 @@ static Bounds<float3> calc_face_grid_bounds(const OffsetIndices<int> faces,
|
||||
return bounds;
|
||||
}
|
||||
|
||||
std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv_ccg)
|
||||
Tree Tree::from_grids(const Mesh &base_mesh, const SubdivCCG &subdiv_ccg)
|
||||
{
|
||||
#ifdef DEBUG_BUILD_TIME
|
||||
SCOPED_TIMER_AVERAGED(__func__);
|
||||
#endif
|
||||
std::unique_ptr<Tree> pbvh = std::make_unique<Tree>(Type::Grids);
|
||||
|
||||
Tree pbvh(Type::Grids);
|
||||
const OffsetIndices faces = base_mesh.faces();
|
||||
if (faces.is_empty()) {
|
||||
return pbvh;
|
||||
@@ -424,7 +423,7 @@ std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv
|
||||
Array<int> face_indices(faces.size());
|
||||
array_utils::fill_index_range<int>(face_indices);
|
||||
|
||||
Vector<GridsNode> &nodes = std::get<Vector<GridsNode>>(pbvh->nodes_);
|
||||
Vector<GridsNode> &nodes = std::get<Vector<GridsNode>>(pbvh.nodes_);
|
||||
nodes.resize(1);
|
||||
{
|
||||
#ifdef DEBUG_BUILD_TIME
|
||||
@@ -435,12 +434,12 @@ std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv
|
||||
}
|
||||
|
||||
/* Convert face indices into grid indices. */
|
||||
pbvh->prim_indices_.reinitialize(faces.total_size());
|
||||
pbvh.prim_indices_.reinitialize(faces.total_size());
|
||||
{
|
||||
int offset = 0;
|
||||
for (const int face : face_indices) {
|
||||
for (const int corner : faces[face]) {
|
||||
pbvh->prim_indices_[offset] = corner;
|
||||
pbvh.prim_indices_[offset] = corner;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
@@ -458,14 +457,14 @@ std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv
|
||||
|
||||
threading::parallel_for(nodes.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
nodes[i].prim_indices_ = pbvh->prim_indices_.as_span().slice(node_grid_offsets[i]);
|
||||
nodes[i].prim_indices_ = pbvh.prim_indices_.as_span().slice(node_grid_offsets[i]);
|
||||
}
|
||||
});
|
||||
|
||||
pbvh->tag_positions_changed(nodes.index_range());
|
||||
pbvh.tag_positions_changed(nodes.index_range());
|
||||
|
||||
update_bounds_grids(key, positions, *pbvh);
|
||||
store_bounds_orig(*pbvh);
|
||||
update_bounds_grids(key, positions, pbvh);
|
||||
store_bounds_orig(pbvh);
|
||||
|
||||
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
|
||||
if (!grid_hidden.is_empty()) {
|
||||
@@ -476,7 +475,7 @@ std::unique_ptr<Tree> build_grids(const Mesh &base_mesh, const SubdivCCG &subdiv
|
||||
});
|
||||
}
|
||||
|
||||
update_mask_grids(subdiv_ccg, nodes.index_range(), *pbvh);
|
||||
update_mask_grids(subdiv_ccg, nodes.index_range(), pbvh);
|
||||
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
@@ -2209,28 +2209,27 @@ static void pbvh_bmesh_create_nodes_fast_recursive(Vector<BMeshNode> &nodes,
|
||||
|
||||
/***************************** Public API *****************************/
|
||||
|
||||
std::unique_ptr<Tree> build_bmesh(BMesh *bm)
|
||||
Tree Tree::from_bmesh(BMesh &bm)
|
||||
{
|
||||
std::unique_ptr<Tree> pbvh = std::make_unique<Tree>(Type::BMesh);
|
||||
|
||||
const int cd_vert_node_offset = CustomData_get_offset_named(
|
||||
&bm->vdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_vertex");
|
||||
const int cd_face_node_offset = CustomData_get_offset_named(
|
||||
&bm->pdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_face");
|
||||
|
||||
if (bm->totface == 0) {
|
||||
Tree pbvh(Type::BMesh);
|
||||
if (bm.totface == 0) {
|
||||
return pbvh;
|
||||
}
|
||||
|
||||
const int cd_vert_node_offset = CustomData_get_offset_named(
|
||||
&bm.vdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_vertex");
|
||||
const int cd_face_node_offset = CustomData_get_offset_named(
|
||||
&bm.pdata, CD_PROP_INT32, ".sculpt_dyntopo_node_id_face");
|
||||
|
||||
/* bounding box array of all faces, no need to recalculate every time. */
|
||||
Array<Bounds<float3>> face_bounds(bm->totface);
|
||||
Array<BMFace *> nodeinfo(bm->totface);
|
||||
Array<Bounds<float3>> face_bounds(bm.totface);
|
||||
Array<BMFace *> nodeinfo(bm.totface);
|
||||
MemArena *arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "fast Tree node storage");
|
||||
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
int i;
|
||||
BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
|
||||
BM_ITER_MESH_INDEX (f, &iter, &bm, BM_FACES_OF_MESH, i) {
|
||||
face_bounds[i] = negative_bounds();
|
||||
|
||||
BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
|
||||
@@ -2245,16 +2244,16 @@ std::unique_ptr<Tree> build_bmesh(BMesh *bm)
|
||||
BM_ELEM_CD_SET_INT(f, cd_face_node_offset, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
/* Likely this is already dirty. */
|
||||
bm->elem_index_dirty |= BM_FACE;
|
||||
bm.elem_index_dirty |= BM_FACE;
|
||||
|
||||
BMVert *v;
|
||||
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
BM_ITER_MESH (v, &iter, &bm, BM_VERTS_OF_MESH) {
|
||||
BM_ELEM_CD_SET_INT(v, cd_vert_node_offset, DYNTOPO_NODE_NONE);
|
||||
}
|
||||
|
||||
/* Set up root node. */
|
||||
FastNodeBuildInfo rootnode = {0};
|
||||
rootnode.totface = bm->totface;
|
||||
rootnode.totface = bm.totface;
|
||||
|
||||
/* Start recursion, assign faces to nodes accordingly. */
|
||||
pbvh_bmesh_node_limit_ensure_fast(nodeinfo, face_bounds, &rootnode, arena);
|
||||
@@ -2264,14 +2263,14 @@ std::unique_ptr<Tree> build_bmesh(BMesh *bm)
|
||||
|
||||
/* Start with all faces in the root node. */
|
||||
/* Take root node and visit and populate children recursively. */
|
||||
Vector<BMeshNode> &nodes = std::get<Vector<BMeshNode>>(pbvh->nodes_);
|
||||
Vector<BMeshNode> &nodes = std::get<Vector<BMeshNode>>(pbvh.nodes_);
|
||||
nodes.resize(1);
|
||||
pbvh_bmesh_create_nodes_fast_recursive(
|
||||
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);
|
||||
store_bounds_orig(*pbvh);
|
||||
pbvh.tag_positions_changed(nodes.index_range());
|
||||
update_bounds_bmesh(bm, pbvh);
|
||||
store_bounds_orig(pbvh);
|
||||
|
||||
threading::parallel_for(nodes.index_range(), 8, [&](const IndexRange range) {
|
||||
for (const int i : range) {
|
||||
@@ -2285,7 +2284,7 @@ std::unique_ptr<Tree> build_bmesh(BMesh *bm)
|
||||
}
|
||||
});
|
||||
|
||||
update_mask_bmesh(*bm, nodes.index_range(), *pbvh);
|
||||
update_mask_bmesh(bm, nodes.index_range(), pbvh);
|
||||
|
||||
BLI_memarena_free(arena);
|
||||
return pbvh;
|
||||
|
||||
Reference in New Issue
Block a user