11#ifndef EBGEOMETRY_BVH_HPP
12#define EBGEOMETRY_BVH_HPP
27#if defined(__SSE4_1__) || defined(__AVX__)
93 static_assert(std::is_floating_point_v<T>,
"BVH::DefaultBranchingRatio requires a floating-point T");
94#if defined(__AVX512F__)
95 if constexpr (std::is_same_v<T, double>) {
101#elif defined(__AVX__)
102 if constexpr (std::is_same_v<T, double>) {
117template <
class T,
class P,
class BV,
size_t K>
191 for (
size_t i = 0;
i <
a_block->size();
i++) {
278template <
class T,
class P,
size_t K,
class StoragePolicy = SharedPtrStorage<P>>
286template <
class P,
class BV>
287using PrimAndBV = std::pair<std::shared_ptr<const P>, BV>;
294template <
class P,
class BV>
310template <
class P,
class BV,
size_t K>
322template <
class T,
class P,
class BV,
size_t K>
347template <
class P,
class StoragePolicy = SharedPtrStorage<P>>
361template <
class NodeType,
class NodeKey>
373template <
class NodeType,
class NodeKey,
size_t K>
385template <
class NodeKey,
size_t K>
397template <
class NodeType,
class NodeKey>
407template <
class X,
size_t K>
409 static_assert(K >= 2,
"EqualCounts<X, K>: branching factor K must be at least 2");
419 std::array<std::vector<X>, K>
chunks;
421 for (
size_t k = 0;
k < K;
k++) {
445template <
class T,
class P,
class BV,
size_t K>
464 return pbv1.first->getCentroid(splitDir) < pbv2.first->getCentroid(splitDir);
467 return BVH::EqualCounts<PrimAndBV<P, BV>, K>(std::move(
a_primsAndBVs));
479template <
class T,
class P,
class BV,
size_t K>
497 return pbv1.second.getCentroid()[splitDir] < pbv2.second.getCentroid()[splitDir];
500 return BVH::EqualCounts<PrimAndBV<P, BV>, K>(std::move(
a_primsAndBVs));
521template <
class T,
class P,
class BV>
528 static_assert(std::is_same_v<BV, EBGeometry::BoundingVolumes::AABBT<T>>,
"SAH2WaySplit requires BV == AABBT<T>");
532 constexpr int BINS = 32;
541 const auto&
c =
a_list[
i].second.getCentroid();
547 T
bestCost = std::numeric_limits<T>::max();
573 for (
int b = 0;
b <
BINS;
b++) {
591 for (
int b = 0;
b <
BINS - 1;
b++) {
607 for (
int b =
BINS - 1;
b >= 1;
b--) {
632 auto mid = std::partition(
634 return pbv.second.getCentroid()[bestAxis] < bestPlane;
657template <
class T,
class P,
class BV>
663 std::vector<std::pair<size_t, size_t>>&
a_groups,
666 static_assert(std::is_same_v<BV, EBGeometry::BoundingVolumes::AABBT<T>>,
"SAHKWaySplit requires BV == AABBT<T>");
674 const size_t K1 =
a_K / 2;
715template <
class T,
class P,
class BV,
size_t K,
bool LongestAxisOnly = false>
721 std::vector<std::pair<size_t, size_t>>
groups;
726 std::array<PrimAndBVList<P, BV>, K>
result;
727 for (
size_t k = 0;
k < K;
k++) {
751template <
class T,
class P,
class BV>
763 const auto&
c =
a_list[
i].second.getCentroid();
772 auto mid = std::partition(
774 return pbv.second.getCentroid()[splitDir] < midpoint;
800template <
class T,
class P,
class BV>
806 std::vector<std::pair<size_t, size_t>>&
a_groups)
noexcept
814 const size_t K1 =
a_K / 2;
848template <
class T,
class P,
class BV,
size_t K>
856 std::vector<std::pair<size_t, size_t>>
groups;
861 std::array<PrimAndBVList<P, BV>, K>
result;
862 for (
size_t k = 0;
k < K;
k++) {
880template <
class T,
class P,
class BV,
size_t K>
901template <
class T,
class P,
class BV,
size_t K>
902class TreeBVH :
public std::enable_shared_from_this<TreeBVH<T, P, BV, K>>
904 static_assert(std::is_floating_point_v<T>,
"TreeBVH: T must be a floating-point type");
905 static_assert(K >= 2,
"TreeBVH: branching factor K must be at least 2");
1239 static_assert(std::is_floating_point_v<T>,
"PackedBVH: T must be a floating-point type");
1240 static_assert(K >= 2,
"PackedBVH: branching factor K must be at least 2");
1281 std::array<uint32_t, K> m_childOff{};
1359 [[
nodiscard]]
inline const std::array<uint32_t, K>&
1372 return m_numPrims > 0;
1383 return m_bv.getDistance(
a_point);
1397 return m_bv.getDistance2(
a_point);
1445 template <
class Q,
class Converter>
1476 template <
class S = SFC::Morton>
1578 [[
nodiscard]]
inline const std::vector<StorageType>&
1723 alignas(
sizeof(T) * K) T m_lo[3][K];
1728 alignas(
sizeof(T) * K) T m_hi[3][K];
1748#include "EBGeometry_BVHImplem.hpp"
Declarations of bounding volume types used in bounding volume hierarchies.
Utility macros for EBGeometry.
#define EBGEOMETRY_EXPECT(cond)
Runtime precondition assertion for EBGeometry.
Definition EBGeometry_Macros.hpp:62
Declaration of various space-filling curves.
Declaration of 2D and 3D point/vector classes with templated precision. Used with DCEL tools.
Forward declaration of the linearised BVH. Needed so that TreeBVH::pack() and TreeBVH::packWith() can...
Definition EBGeometry_BVH.hpp:1238
PackedBVH()=delete
Deleted default constructor. Use TreeBVH::pack() or TreeBVH::packWith() to construct.
~PackedBVH()=default
Destructor.
void buildSoA()
Populate m_childAabbSoA from the completed m_linearNodes array.
std::vector< StorageType > m_primitives
Global primitive list in leaf-traversal order.
Definition EBGeometry_BVH.hpp:1710
typename StoragePolicy::StorageType StorageType
Storage representation of one entry in the primitive array, as determined by StoragePolicy (std::shar...
Definition EBGeometry_BVH.hpp:1253
PackedBVH & operator=(const PackedBVH &a_other)=default
Copy assignment operator.
PackedBVH(const TreeBVH< T, P, BV, K > &a_tree)
Construct by packing a TreeBVH (identity primitive type).
std::vector< ChildAABBSoA > m_childAabbSoA
Per-node SoA AABB cache used by the SIMD traversal in pruneTraverse().
Definition EBGeometry_BVH.hpp:1734
PackedBVH & operator=(PackedBVH &&a_other) noexcept=default
Move assignment operator.
PackedBVH(std::vector< std::pair< P, BV > > a_primsAndBVs, size_t a_targetLeafSize, S a_sfc=S{})
Construct directly from a flat primitive list, without ever building a TreeBVH.
PackedBVH(const PackedBVH &a_other)=default
Copy constructor.
PackedBVH(std::vector< std::pair< P, BV > > a_primsAndBVs, const BVH::Partitioner< P, BV, K > &a_partitioner=BVCentroidPartitioner< T, P, BV, K >, const BVH::LeafPredicate< T, P, BV, K > &a_stopCrit=DefaultLeafPredicate< T, P, BV, K >)
Construct directly from a flat primitive list via top-down (optionally SAH) recursive partitioning,...
const std::vector< StorageType > & getPrimitives() const noexcept
Get the global primitive list (in leaf-traversal order).
PackedBVH(const TreeBVH< T, Q, BV, K > &a_tree, Converter &&a_converter)
Construct by packing a TreeBVH with primitive-type conversion.
PackedBVH(PackedBVH &&a_other) noexcept=default
Move constructor.
PackedBVH(std::vector< std::pair< P, BV > > a_primsAndBVs, BVH::ClusterSpec a_spec)
Construct directly via ClusterSAH: cluster primitives, then SAH over the clusters.
std::vector< Node > m_linearNodes
Flat depth-first node array.
Definition EBGeometry_BVH.hpp:1705
Forward declaration of the tree-structured BVH. Needed by LeafPredicate and the default-partitioner l...
Definition EBGeometry_BVH.hpp:903
BVH::Partitioner< P, BV, K > Partitioner
Alias for the partitioner type.
Definition EBGeometry_BVH.hpp:931
bool isLeaf() const noexcept
Return true if this is a leaf node (no children, non-empty primitive list).
const std::vector< BV > & getBoundingVolumes() const noexcept
Get the per-primitive bounding volumes stored in this node.
std::vector< BV > m_boundingVolumes
Per-primitive bounding volumes. Non-empty for leaf nodes only.
Definition EBGeometry_BVH.hpp:1175
std::shared_ptr< PackedBVH< T, P, K, StoragePolicy > > pack() const
Flatten this tree into a cache-friendly PackedBVH with the same primitive type.
void bottomUpSortAndPartition()
Recursively partition this node bottom-up along a space-filling curve.
std::shared_ptr< TreeBVH< T, P, BV, K > > deepCopy() const
Produce an independent deep copy of this tree.
BVH::PrimitiveList< P > PrimitiveList
Alias for the primitive list type.
Definition EBGeometry_BVH.hpp:911
bool m_partitioned
True after topDownSortAndPartition() or bottomUpSortAndPartition() has been called.
Definition EBGeometry_BVH.hpp:1165
std::vector< std::shared_ptr< const P > > m_primitives
Primitives stored in this node. Non-empty for leaf nodes only.
Definition EBGeometry_BVH.hpp:1170
const PrimitiveList & getPrimitives() const noexcept
Get the primitives stored in this node.
T getDistanceToBoundingVolume(const Vec3 &a_point) const noexcept
Get the distance from a_point to this node's bounding volume.
std::array< std::shared_ptr< TreeBVH< T, P, BV, K > >, K > m_children
K child nodes. Non-null for interior nodes only.
Definition EBGeometry_BVH.hpp:1180
void topDownSortAndPartition(const Partitioner &a_partitioner=BVCentroidPartitioner< T, P, BV, K >, const LeafPredicate &a_stopCrit=DefaultLeafPredicate< T, P, BV, K >)
Recursively partition this node top-down.
BVH::LeafPredicate< T, P, BV, K > LeafPredicate
Alias for the stop-function type.
Definition EBGeometry_BVH.hpp:936
void traverse(const BVH::LeafEvaluator< P > &a_leafEvaluator, const BVH::PrunePredicate< Node, NodeKey > &a_prunePredicate, const BVH::ChildOrderer< Node, NodeKey, K > &a_childOrderer, const BVH::NodeKeyFactory< Node, NodeKey > &a_nodeKeyFactory) const noexcept
Recursion-free BVH traversal using an explicit LIFO stack (depth-first order).
std::shared_ptr< PackedBVH< T, Q, K, StoragePolicy > > packWith(Converter &&a_converter) const
Flatten and convert this tree into a PackedBVH with a different primitive type Q.
BV m_boundingVolume
Bounding volume enclosing all primitives in this subtree.
Definition EBGeometry_BVH.hpp:1160
TreeBVH() noexcept
Default constructor. Creates an empty interior node.
const std::array< std::shared_ptr< TreeBVH< T, P, BV, K > >, K > & getChildren() const noexcept
Get the K child nodes of this interior node.
const BV & getBoundingVolume() const noexcept
Get the bounding volume for this node.
std::shared_ptr< Node > NodePtr
Alias for a shared pointer to a node.
Definition EBGeometry_BVH.hpp:926
void setChildren(const std::array< std::shared_ptr< TreeBVH< T, P, BV, K > >, K > &a_children) noexcept
Set the K child nodes, converting this node from a leaf into an interior node.
bool isPartitioned() const noexcept
Return true if the tree has already been partitioned.
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:247
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:225
static constexpr Vec3T< T > max() noexcept
Return the most-positive representable vector.
size_t SAH2WaySplit(PrimAndBVList< P, BV > &a_list, const size_t a_begin, const size_t a_end, const bool a_longestAxisOnly=false) noexcept
Internal helper: 2-way binned SAH split on the sub-range [a_begin, a_end).
Definition EBGeometry_BVH.hpp:523
auto EqualCounts
Utility: split a vector into K almost-equal contiguous chunks.
Definition EBGeometry_BVH.hpp:408
std::function< std::array< PrimAndBVList< P, BV >, K >(PrimAndBVList< P, BV > a_primsAndBVs)> Partitioner
Polymorphic partitioner: splits a list of (primitive, BV) pairs into K sub-lists.
Definition EBGeometry_BVH.hpp:311
std::vector< std::shared_ptr< const P > > PrimitiveList
Convenience alias for a list of shared primitive pointers.
Definition EBGeometry_BVH.hpp:125
std::function< bool(const NodeType &a_node, const NodeKey &a_nodeKey)> PrunePredicate
Node-visit predicate for BVH traversal.
Definition EBGeometry_BVH.hpp:362
std::function< void(const std::vector< typename StoragePolicy::StorageType > &a_primitives, size_t a_offset, size_t a_count)> PackedLeafEvaluator
Leaf-evaluation callback for PackedBVH::traverse.
Definition EBGeometry_BVH.hpp:349
void SAHKWaySplit(PrimAndBVList< P, BV > &a_list, const size_t a_begin, const size_t a_end, const size_t a_K, std::vector< std::pair< size_t, size_t > > &a_groups, const bool a_longestAxisOnly=false) noexcept
Internal helper: recursively split [a_begin, a_end) into a_K groups via 2-way SAH.
Definition EBGeometry_BVH.hpp:659
std::vector< PrimAndBV< P, BV > > PrimAndBVList
Convenience alias for a list of (primitive, bounding-volume) pairs.
Definition EBGeometry_BVH.hpp:295
std::function< bool(const TreeBVH< T, P, BV, K > &a_node)> LeafPredicate
Predicate for deciding when a TreeBVH node should become a leaf (i.e., no further splitting).
Definition EBGeometry_BVH.hpp:323
std::pair< std::shared_ptr< const P >, BV > PrimAndBV
Convenience alias for a (primitive, bounding-volume) pair.
Definition EBGeometry_BVH.hpp:287
std::function< void(const PrimitiveList< P > &a_primitives)> LeafEvaluator
Leaf-evaluation callback for TreeBVH::traverse.
Definition EBGeometry_BVH.hpp:332
std::function< void(std::array< std::pair< std::shared_ptr< const NodeType >, NodeKey >, K > &a_children)> ChildOrderer
Child-ordering callback for TreeBVH traversal.
Definition EBGeometry_BVH.hpp:375
std::function< NodeKey(const NodeType &a_node)> NodeKeyFactory
Node-key factory called once per node during BVH traversal.
Definition EBGeometry_BVH.hpp:398
size_t Midpoint2WaySplit(PrimAndBVList< P, BV > &a_list, const size_t a_begin, const size_t a_end) noexcept
Internal helper: 2-way spatial-midpoint split on the sub-range [a_begin, a_end).
Definition EBGeometry_BVH.hpp:753
auto PrimitiveCentroidPartitioner
Partitioner that sorts primitives by centroid along the longest axis and splits into K pieces.
Definition EBGeometry_BVH.hpp:446
auto BVCentroidPartitioner
Partitioner that sorts primitives by bounding-volume centroid along the longest axis and splits into ...
Definition EBGeometry_BVH.hpp:480
auto BinnedSAHPartitioner
Partitioner using binned SAH with recursive 2-way subdivision into K groups.
Definition EBGeometry_BVH.hpp:716
void MidpointKWaySplit(PrimAndBVList< P, BV > &a_list, const size_t a_begin, const size_t a_end, const size_t a_K, std::vector< std::pair< size_t, size_t > > &a_groups) noexcept
Internal helper: recursively split [a_begin, a_end) into a_K groups via 2-way midpoint splits.
Definition EBGeometry_BVH.hpp:802
auto DefaultLeafPredicate
Default stop function: stop partitioning when the node holds fewer than K primitives.
Definition EBGeometry_BVH.hpp:881
Build
Enum for specifying the BVH construction strategy.
Definition EBGeometry_BVH.hpp:48
@ Nested
Bottom-up construction along a Nested space-filling curve.
@ TopDown
Recursive top-down partitioning.
@ Morton
Bottom-up construction along a Morton space-filling curve.
constexpr size_t DefaultBranchingRatio() noexcept
Returns the SIMD-optimal BVH branching factor for type T on the current target ISA.
Definition EBGeometry_BVH.hpp:91
auto MidpointPartitioner
Partitioner that recursively bisects primitives by spatial midpoint (no sorting).
Definition EBGeometry_BVH.hpp:849
std::function< void(std::array< std::pair< uint32_t, NodeKey >, K > &a_children)> PackedChildOrderer
Child-ordering callback for PackedBVH traversal.
Definition EBGeometry_BVH.hpp:386
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_AnalyticDistanceFunctions.hpp:31
Vec2T< T > min(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise minimum of two vectors.
T length(const Vec2T< T > &v) noexcept
Euclidean length of a 2D vector.
Vec2T< T > max(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Component-wise maximum of two vectors.
Configuration for the ClusterSAH direct PackedBVH construction path.
Definition EBGeometry_BVH.hpp:69
size_t maxClusterSize
Maximum primitives per cluster (the leaf/bucket granularity). Must be > 0.
Definition EBGeometry_BVH.hpp:70
SoA layout of K children's AABBs for a single interior node.
Definition EBGeometry_BVH.hpp:1719
Compact BVH node stored in the flat node array.
Definition EBGeometry_BVH.hpp:1262
const std::array< uint32_t, K > & getChildOffsets() const noexcept
Get the child index table.
Definition EBGeometry_BVH.hpp:1360
void setBoundingVolume(const BV &a_bv) noexcept
Set the bounding volume for this node.
Definition EBGeometry_BVH.hpp:1288
uint32_t getNumPrimitives() const noexcept
Get the primitive count.
Definition EBGeometry_BVH.hpp:1350
T getDistanceToBoundingVolume2(const Vec3T< T > &a_point) const noexcept
Get the squared distance from a_point to this node's bounding volume.
Definition EBGeometry_BVH.hpp:1395
uint32_t getPrimitivesOffset() const noexcept
Get the primitive offset (leaf nodes only).
Definition EBGeometry_BVH.hpp:1340
void setNumPrimitives(uint32_t a_n) noexcept
Set the primitive count for this leaf node.
Definition EBGeometry_BVH.hpp:1308
const BV & getBoundingVolume() const noexcept
Get the bounding volume.
Definition EBGeometry_BVH.hpp:1330
void setPrimitivesOffset(uint32_t a_off) noexcept
Set the primitive offset for this leaf node.
Definition EBGeometry_BVH.hpp:1298
T getDistanceToBoundingVolume(const Vec3T< T > &a_point) const noexcept
Get the distance from a_point to this node's bounding volume.
Definition EBGeometry_BVH.hpp:1381
void setChildOffset(uint32_t a_off, size_t a_k) noexcept
Set the depth-first index of the k-th child.
Definition EBGeometry_BVH.hpp:1319
bool isLeaf() const noexcept
Return true if this is a leaf node.
Definition EBGeometry_BVH.hpp:1370
Default storage policy for PackedBVH: primitives stored as std::shared_ptr<const P>,...
Definition EBGeometry_BVH.hpp:146
static const P & get(const StorageType &a_stored) noexcept
Dereference stored element to the primitive it refers to.
Definition EBGeometry_BVH.hpp:159
static void appendAliased(std::vector< StorageType > &a_dst, const std::shared_ptr< std::vector< P > > &a_block)
Materialise a converting packWith() constructor's single contiguous conversion buffer into PackedBVH'...
Definition EBGeometry_BVH.hpp:187
static void appendTreeLeaf(std::vector< StorageType > &a_dst, const PrimitiveList< P > &a_leafPrims)
Append one TreeBVH leaf's primitives to PackedBVH's flat primitive array.
Definition EBGeometry_BVH.hpp:172
std::shared_ptr< const P > StorageType
Storage representation: a shared pointer to a const primitive, as PackedBVH has always stored it.
Definition EBGeometry_BVH.hpp:151
Storage policy that stores primitives directly by value, with no pointer indirection at all.
Definition EBGeometry_BVH.hpp:208
static void appendAliased(std::vector< StorageType > &a_dst, const std::shared_ptr< std::vector< P > > &a_block)
Materialise a converting packWith() constructor's single contiguous conversion buffer into PackedBVH'...
Definition EBGeometry_BVH.hpp:261
static void appendTreeLeaf(std::vector< StorageType > &a_dst, const PrimitiveList< P > &a_leafPrims)
Append one TreeBVH leaf's primitives to PackedBVH's flat primitive array.
Definition EBGeometry_BVH.hpp:235
static const P & get(const StorageType &a_stored) noexcept
Identity access – the stored element already is the primitive.
Definition EBGeometry_BVH.hpp:220