Point Cloud: Add cached full points BVH tree

Instead of rebuilding the BVH tree every time it's requested.
This commit is contained in:
Hans Goudey
2025-02-17 10:49:07 -05:00
parent 00c3b564b8
commit 901b18d17b
7 changed files with 58 additions and 14 deletions

View File

@@ -93,11 +93,13 @@ float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray,
const float v2[3]);
struct BVHTreeFromPointCloud {
std::unique_ptr<BVHTree, BVHTreeDeleter> tree;
const BVHTree *tree = nullptr;
BVHTree_NearestPointCallback nearest_callback;
const float (*coords)[3];
Span<float3> positions;
std::unique_ptr<BVHTree, BVHTreeDeleter> owned_tree;
};
BVHTreeFromPointCloud bvhtree_from_pointcloud_get(const PointCloud &pointcloud,

View File

@@ -10,6 +10,7 @@
*/
#include "BLI_bounds_types.hh"
#include "BLI_kdopbvh.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_shared_cache.hh"
#include "BLI_string_ref.hh"
@@ -42,6 +43,8 @@ struct PointCloudRuntime {
/** Stores weak references to material data blocks. */
std::unique_ptr<bake::BakeMaterialsList> bake_materials;
SharedCache<std::unique_ptr<BVHTree, BVHTreeDeleter>> bvh_cache;
MEM_CXX_CLASS_ALLOC_FUNCS("PointCloudRuntime");
};

View File

@@ -15,6 +15,7 @@
#include "BKE_bvhutils.hh"
#include "BKE_editmesh.hh"
#include "BKE_mesh.hh"
#include "BKE_pointcloud.hh"
namespace blender::bke {
@@ -811,21 +812,54 @@ BVHTreeFromMesh bvhtree_from_mesh_verts_init(const Mesh &mesh, const IndexMask &
/** \name Point Cloud BVH Building
* \{ */
BVHTreeFromPointCloud bvhtree_from_pointcloud_get(const PointCloud &pointcloud,
const IndexMask &points_mask)
static BVHTreeFromPointCloud create_points_tree_data(const BVHTree *tree,
const Span<float3> positions)
{
const Span<float3> positions = pointcloud.positions();
std::unique_ptr<BVHTree, BVHTreeDeleter> tree = create_tree_from_verts(positions, points_mask);
if (!tree) {
return {};
}
BVHTreeFromPointCloud data{};
data.tree = std::move(tree);
data.tree = tree;
data.positions = positions;
data.nearest_callback = nullptr;
data.coords = (const float(*)[3])positions.data();
return data;
}
/** \} */
static BVHTreeFromPointCloud create_point_cloud_tree_data(const BVHTree *tree,
const Span<float3> positions)
{
BVHTreeFromPointCloud data{};
data.tree = tree;
data.positions = positions;
return data;
}
static BVHTreeFromPointCloud create_point_cloud_tree_data(
std::unique_ptr<BVHTree, BVHTreeDeleter> tree, const Span<float3> positions)
{
BVHTreeFromPointCloud data = create_points_tree_data(tree.get(), positions);
data.owned_tree = std::move(tree);
return data;
}
BVHTreeFromPointCloud bvhtree_from_pointcloud_get(const PointCloud &pointcloud,
const IndexMask &points_mask)
{
if (points_mask.size() == pointcloud.totpoint) {
return pointcloud.bvh_tree();
}
const Span<float3> positions = pointcloud.positions();
return create_point_cloud_tree_data(create_tree_from_verts(positions, points_mask), positions);
}
} // namespace blender::bke
blender::bke::BVHTreeFromPointCloud PointCloud::bvh_tree() const
{
using namespace blender;
using namespace blender::bke;
const Span<float3> positions = this->positions();
this->runtime->bvh_cache.ensure([&](std::unique_ptr<BVHTree, BVHTreeDeleter> &data) {
data = create_tree_from_verts(positions, positions.index_range());
});
return create_point_cloud_tree_data(this->runtime->bvh_cache.data().get(), positions);
}
/** \} */

View File

@@ -85,6 +85,7 @@ static void pointcloud_copy_data(Main * /*bmain*/,
pointcloud_dst->runtime = new blender::bke::PointCloudRuntime();
pointcloud_dst->runtime->bounds_cache = pointcloud_src->runtime->bounds_cache;
pointcloud_dst->runtime->bvh_cache = pointcloud_src->runtime->bvh_cache;
if (pointcloud_src->runtime->bake_materials) {
pointcloud_dst->runtime->bake_materials =
std::make_unique<blender::bke::bake::BakeMaterialsList>(
@@ -457,6 +458,7 @@ void BKE_pointcloud_data_update(Depsgraph *depsgraph, Scene *scene, Object *obje
void PointCloud::tag_positions_changed()
{
this->runtime->bounds_cache.tag_dirty();
this->runtime->bvh_cache.tag_dirty();
}
void PointCloud::tag_radii_changed()

View File

@@ -26,6 +26,7 @@ namespace blender {
template<typename T> class Span;
namespace bke {
class AttributeAccessor;
struct BVHTreeFromPointCloud;
class MutableAttributeAccessor;
struct PointCloudRuntime;
} // namespace bke
@@ -73,6 +74,8 @@ typedef struct PointCloud {
/** Get the largest material index used by the point-cloud or `nullopt` if it is empty. */
std::optional<int> material_index_max() const;
blender::bke::BVHTreeFromPointCloud bvh_tree() const;
void count_memory(blender::MemoryCounter &memory) const;
#endif

View File

@@ -228,7 +228,7 @@ class ProximityFunction : public mf::MultiFunction {
const_cast<bke::BVHTreeFromMesh *>(&trees.mesh_bvh));
}
if (trees.pointcloud_bvh.tree != nullptr) {
BLI_bvhtree_find_nearest(trees.pointcloud_bvh.tree.get(),
BLI_bvhtree_find_nearest(trees.pointcloud_bvh.tree,
sample_position,
&nearest,
trees.pointcloud_bvh.nearest_callback,

View File

@@ -91,7 +91,7 @@ static void get_closest_pointcloud_points(const bke::BVHTreeFromPointCloud &tree
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
const float3 position = positions[i];
BLI_bvhtree_find_nearest(tree_data.tree.get(),
BLI_bvhtree_find_nearest(tree_data.tree,
position,
&nearest,
tree_data.nearest_callback,