|
EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
|
Namespace for various bounding volume hierarchy (BVH) functionalities. More...
Classes | |
| struct | ClusterSpec |
| Configuration for the ClusterSAH direct PackedBVH construction path. More... | |
| class | PackedBVH |
| Forward declaration of the linearised BVH. Needed so that TreeBVH::pack() and TreeBVH::packWith() can name their return types before PackedBVH is fully defined. More... | |
| struct | SharedPtrStorage |
| Default storage policy for PackedBVH: primitives stored as std::shared_ptr<const P>, exactly as PackedBVH has always stored them. More... | |
| class | TreeBVH |
| Forward declaration of the tree-structured BVH. Needed by LeafPredicate and the default-partitioner lambdas defined below. More... | |
| struct | ValueStorage |
| Storage policy that stores primitives directly by value, with no pointer indirection at all. More... | |
Typedefs | |
| template<class P > | |
| using | PrimitiveList = std::vector< std::shared_ptr< const P > > |
| Convenience alias for a list of shared primitive pointers. | |
| template<class P , class BV > | |
| using | PrimAndBV = std::pair< std::shared_ptr< const P >, BV > |
| Convenience alias for a (primitive, bounding-volume) pair. | |
| template<class P , class BV > | |
| using | PrimAndBVList = std::vector< PrimAndBV< P, BV > > |
| Convenience alias for a list of (primitive, bounding-volume) pairs. | |
| template<class P , class BV , size_t K> | |
| using | Partitioner = std::function< std::array< PrimAndBVList< P, BV >, K >(PrimAndBVList< P, BV > a_primsAndBVs)> |
| Polymorphic partitioner: splits a list of (primitive, BV) pairs into K sub-lists. | |
| template<class T , class P , class BV , size_t K> | |
| using | LeafPredicate = std::function< bool(const TreeBVH< T, P, BV, K > &a_node)> |
| Predicate for deciding when a TreeBVH node should become a leaf (i.e., no further splitting). | |
| template<class P > | |
| using | LeafEvaluator = std::function< void(const PrimitiveList< P > &a_primitives)> |
| Leaf-evaluation callback for TreeBVH::traverse. | |
| template<class P , class StoragePolicy = SharedPtrStorage<P>> | |
| using | PackedLeafEvaluator = std::function< void(const std::vector< typename StoragePolicy::StorageType > &a_primitives, size_t a_offset, size_t a_count)> |
| Leaf-evaluation callback for PackedBVH::traverse. | |
| template<class NodeType , class NodeKey > | |
| using | PrunePredicate = std::function< bool(const NodeType &a_node, const NodeKey &a_nodeKey)> |
| Node-visit predicate for BVH traversal. | |
| template<class NodeType , class NodeKey , size_t K> | |
| using | ChildOrderer = std::function< void(std::array< std::pair< std::shared_ptr< const NodeType >, NodeKey >, K > &a_children)> |
| Child-ordering callback for TreeBVH traversal. | |
| template<class NodeKey , size_t K> | |
| using | PackedChildOrderer = std::function< void(std::array< std::pair< uint32_t, NodeKey >, K > &a_children)> |
| Child-ordering callback for PackedBVH traversal. | |
| template<class NodeType , class NodeKey > | |
| using | NodeKeyFactory = std::function< NodeKey(const NodeType &a_node)> |
| Node-key factory called once per node during BVH traversal. | |
Enumerations | |
| enum class | Build { TopDown , Morton , Nested , SAH } |
| Enum for specifying the BVH construction strategy. More... | |
Functions | |
| template<typename T > | |
| constexpr size_t | DefaultBranchingRatio () noexcept |
| Returns the SIMD-optimal BVH branching factor for type T on the current target ISA. | |
| template<class T , class P , class BV > | |
| 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). | |
| template<class T , class P , class BV > | |
| 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. | |
| template<class T , class P , class BV > | |
| 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). | |
| template<class T , class P , class BV > | |
| 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. | |
Variables | |
| template<class X , size_t K> | |
| auto | EqualCounts |
| Utility: split a vector into K almost-equal contiguous chunks. | |
| template<class T , class P , class BV , size_t K> | |
| auto | PrimitiveCentroidPartitioner |
| Partitioner that sorts primitives by centroid along the longest axis and splits into K pieces. | |
| template<class T , class P , class BV , size_t K> | |
| auto | BVCentroidPartitioner |
| Partitioner that sorts primitives by bounding-volume centroid along the longest axis and splits into K pieces. | |
| template<class T , class P , class BV , size_t K, bool LongestAxisOnly = false> | |
| auto | BinnedSAHPartitioner |
| Partitioner using binned SAH with recursive 2-way subdivision into K groups. | |
| template<class T , class P , class BV , size_t K> | |
| auto | MidpointPartitioner |
| Partitioner that recursively bisects primitives by spatial midpoint (no sorting). | |
| template<class T , class P , class BV , size_t K> | |
| auto | DefaultLeafPredicate |
| Default stop function: stop partitioning when the node holds fewer than K primitives. | |
Namespace for various bounding volume hierarchy (BVH) functionalities.
| using EBGeometry::BVH::ChildOrderer = typedef std::function<void(std::array<std::pair<std::shared_ptr<const NodeType>, NodeKey>, K>& a_children)> |
Child-ordering callback for TreeBVH traversal.
Sorts an array of (child-node-pointer, key) pairs in-place so that the most promising child is visited first.
| NodeType | Node type (TreeBVH). |
| NodeKey | Per-node key attached to each stack entry. |
| K | Tree branching factor. |
| [in,out] | a_children | K child nodes together with their node keys. |
| using EBGeometry::BVH::LeafEvaluator = typedef std::function<void(const PrimitiveList<P>& a_primitives)> |
Leaf-evaluation callback for TreeBVH::traverse.
Called once for every leaf node visited during traversal.
| P | Primitive type. |
| [in] | a_primitives | Primitive list stored in the leaf. |
| using EBGeometry::BVH::LeafPredicate = typedef std::function<bool(const TreeBVH<T, P, BV, K>& a_node)> |
Predicate for deciding when a TreeBVH node should become a leaf (i.e., no further splitting).
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding volume type. |
| K | Tree branching factor. |
| [in] | a_node | BVH node under consideration. |
Node-key factory called once per node during BVH traversal.
Produces the NodeKey value that will be passed to PrunePredicate and ChildOrderer for each child of the current node.
| NodeType | Node type (TreeBVH or PackedBVH::Node). |
| NodeKey | Per-node key type to produce. |
| [in] | a_node | Current node. |
| using EBGeometry::BVH::PackedChildOrderer = typedef std::function<void(std::array<std::pair<uint32_t, NodeKey>, K>& a_children)> |
Child-ordering callback for PackedBVH traversal.
Same role as ChildOrderer but uses 32-bit node indices instead of shared_ptrs, halving the stack-entry size.
| NodeKey | Per-node key attached to each stack entry. |
| K | Tree branching factor. |
| [in,out] | a_children | K (node-index, key) pairs to sort. |
| using EBGeometry::BVH::PackedLeafEvaluator = typedef std::function<void( const std::vector<typename StoragePolicy::StorageType>& a_primitives, size_t a_offset, size_t a_count)> |
Leaf-evaluation callback for PackedBVH::traverse.
Receives a view into the global primitive array (offset + count) rather than a temporary sub-list, avoiding a heap allocation per leaf visit. The primitive array's element type depends on the PackedBVH's storage policy (StorageType), not necessarily std::shared_ptr<const P> – see SharedPtrStorage/ValueStorage.
| P | Primitive type. |
| StoragePolicy | PackedBVH storage policy (default: SharedPtrStorage |
, matching every PackedBVH<T, P, K> that does not name a storage policy explicitly).
| [in] | a_primitives | Global primitive array (element type StoragePolicy::StorageType). |
| [in] | a_offset | Index of the first primitive belonging to this leaf. |
| [in] | a_count | Number of primitives in this leaf. |
| using EBGeometry::BVH::Partitioner = typedef std::function<std::array<PrimAndBVList<P, BV>, K>(PrimAndBVList<P, BV> a_primsAndBVs)> |
Polymorphic partitioner: splits a list of (primitive, BV) pairs into K sub-lists.
The input list is taken by value (a sink): callers move their list in, and an implementation should partition it in place and move the K sub-lists out – so a whole top-down build reorders primitive handles rather than repeatedly copying them (the built-in partitioners all do this). The split arithmetic is the cheap part; avoiding the copies is what keeps construction fast.
| P | Primitive type. |
| BV | Bounding volume type. |
| K | Tree branching factor. |
| [in] | a_primsAndBVs | Input primitives and their bounding volumes (consumed). |
| using EBGeometry::BVH::PrimAndBV = typedef std::pair<std::shared_ptr<const P>, BV> |
Convenience alias for a (primitive, bounding-volume) pair.
| P | Primitive type. |
| BV | Bounding volume type. |
| using EBGeometry::BVH::PrimAndBVList = typedef std::vector<PrimAndBV<P, BV> > |
Convenience alias for a list of (primitive, bounding-volume) pairs.
| P | Primitive type. |
| BV | Bounding volume type enclosing the implicit surface of each primitive. |
| using EBGeometry::BVH::PrimitiveList = typedef std::vector<std::shared_ptr<const P> > |
Convenience alias for a list of shared primitive pointers.
| P | Primitive type bounded by the BVH. |
| using EBGeometry::BVH::PrunePredicate = typedef std::function<bool(const NodeType& a_node, const NodeKey& a_nodeKey)> |
Node-visit predicate for BVH traversal.
Must return true to descend into the node and false to prune it.
| NodeType | Node type (TreeBVH or PackedBVH::Node). |
| NodeKey | Caller-supplied per-node key attached to each stack entry (e.g. a running minimum distance). |
| [in] | a_node | Node under consideration. |
| [in] | a_nodeKey | Caller-supplied key for this stack entry. |
|
strong |
Enum for specifying the BVH construction strategy.
Returns the SIMD-optimal BVH branching factor for type T on the current target ISA.
Maps the floating-point type and the compile-time ISA to the K that fills one SIMD register exactly:
| ISA | T=float | T=double |
|---|---|---|
| AVX-512F | 16 | 8 |
| AVX | 8 | 4 |
| SSE4.1 | 4 | 4 |
| fallback | 4 | 4 |
Usage: size_t K = BVH::DefaultBranchingRatio<T>() as a template-parameter default.
| T | Floating-point precision type (float or double). |
|
inlinenoexcept |
Internal helper: 2-way spatial-midpoint split on the sub-range [a_begin, a_end).
Unlike SAH2WaySplit (which evaluates 32 binned candidate planes) or BVCentroidPartitioner (which sorts by centroid), this computes exactly one split plane – the midpoint of the centroid bounding box along its longest axis – and partitions around it with a single std::partition pass. No sorting and no per-plane cost evaluation, at the cost of not adapting to the primitive distribution the way SAH does: entirely sort-less, O(N) per split.
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type. |
| [in,out] | a_list | Primitives and their bounding volumes; partitioned in place around the split. |
| [in] | a_begin | First index of the sub-range to split. |
| [in] | a_end | One-past-the-last index of the sub-range to split. |
|
inlinenoexcept |
Internal helper: recursively split [a_begin, a_end) into a_K groups via 2-way midpoint splits.
Splits into std::floor(a_K/2) and std::ceil(a_K/2) sub-groups recursively – exact for power-of-two K; a reasonable approximation for other values. Structurally identical to SAHKWaySplit, just calling Midpoint2WaySplit instead of SAH2WaySplit at each level.
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type. |
| [in,out] | a_list | Primitives and their bounding volumes; partitioned in place. |
| [in] | a_begin | First index of the sub-range to split. |
| [in] | a_end | One-past-the-last index of the sub-range to split. |
| [in] | a_K | Number of groups to split the sub-range into. |
| [out] | a_groups | Resulting groups as [begin, end) index pairs. |
|
inlinenoexcept |
Internal helper: 2-way binned SAH split on the sub-range [a_begin, a_end).
Evaluates 32 bins per axis and picks the split plane that minimises SA(left)*N_left + SA(right)*N_right. Partitions a_list in-place and returns the split index (first element of the right group).
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type (must be AABBT<T>). |
| [in,out] | a_list | Primitives and their bounding volumes; partitioned in place around the split. |
| [in] | a_begin | First index of the sub-range to split. |
| [in] | a_end | One-past-the-last index of the sub-range to split. |
| [in] | a_longestAxisOnly | If true, evaluate candidate planes on only the longest centroid-bbox axis instead of all three – roughly a third of the binning work, for a small tree-quality cost that is negligible on near-uniform inputs (e.g. point clouds). Default false (full 3-axis SAH). |
|
inlinenoexcept |
Internal helper: recursively split [a_begin, a_end) into a_K groups via 2-way SAH.
Splits into std::floor(a_K/2) and std::ceil(a_K/2) sub-groups recursively. For power-of-two K this is equivalent to a balanced binary subdivision tree applied a_K times.
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type (must be AABBT<T>). |
| [in,out] | a_list | Primitives and their bounding volumes; partitioned in place. |
| [in] | a_begin | First index of the sub-range to split. |
| [in] | a_end | One-past-the-last index of the sub-range to split. |
| [in] | a_K | Number of groups to split the sub-range into. |
| [out] | a_groups | Resulting groups as [begin, end) index pairs. |
| [in] | a_longestAxisOnly | Forwarded to SAH2WaySplit: bin only the longest centroid-bbox axis. |
| auto EBGeometry::BVH::BinnedSAHPartitioner |
Partitioner using binned SAH with recursive 2-way subdivision into K groups.
For each split, evaluates 32 candidate planes per axis and picks the one minimising SA(left)*N_left + SA(right)*N_right (the standard ray-tracing SAH cost without the traversal constant). K groups are produced by recursively splitting into std::floor(K/2) and std::ceil(K/2) subsets — exact for power-of-two K; a reasonable approximation for other values.
Recommended K values by ISA:
_mm512_load_ps covers all K children)_mm512_load_pd covers all K children)_mm256_load_ps)_mm256_load_pd)_mm_load_ps)| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type (must be AABBT<T>). |
| K | Number of output sub-lists (branching factor of the resulting BVH). |
| LongestAxisOnly | If true, bin candidate planes on only the longest centroid-bbox axis per split instead of all three – ~a third of the binning work (measured ~20% faster builds on point clouds) for a tree-quality cost that is negligible on near-uniform inputs. Default false. |
| [in] | a_primsAndBVs | Input (primitive, BV) pairs. |
Partitioner that sorts primitives by bounding-volume centroid along the longest axis and splits into K pieces.
| T | Floating-point precision used for centroid comparisons. |
| P | Primitive type. |
| BV | Bounding volume type. |
| K | Number of output sub-lists (tree branching factor). |
| [in] | a_primsAndBVs | Input (primitive, BV) pairs. |
Default stop function: stop partitioning when the node holds fewer than K primitives.
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding volume type. |
| K | Tree branching factor. |
| [in] | a_node | BVH node. |
Utility: split a vector into K almost-equal contiguous chunks.
| X | Element type. |
| K | Number of chunks. |
| [in] | a_primitives | Input vector. |
Partitioner that recursively bisects primitives by spatial midpoint (no sorting).
At every split, computes the midpoint of the centroid bounding box along its longest axis and partitions primitives around it in one O(N) std::partition pass – unlike BVCentroidPartitioner (sorts by centroid) or BinnedSAHPartitioner (evaluates 32 candidate planes per axis), no sorting or per-plane cost evaluation happens anywhere. K groups are produced by recursively splitting into std::floor(K/2) and std::ceil(K/2) subsets, mirroring BinnedSAHPartitioner's own K-way structure exactly (see MidpointKWaySplit).
This is the fastest of the three top-down partitioners to build (no sort, no per-axis binning), at the cost of build quality: it does not adapt to the primitive distribution at all, so a heavily clustered or skewed input can produce noticeably less balanced (and less query-efficient) trees than BVCentroidPartitioner or BinnedSAHPartitioner would.
| T | Floating-point precision. |
| P | Primitive type. |
| BV | Bounding-volume type. |
| K | Number of output sub-lists (branching factor of the resulting BVH). |
| [in] | a_primsAndBVs | Input (primitive, BV) pairs. |
| auto EBGeometry::BVH::PrimitiveCentroidPartitioner |
Partitioner that sorts primitives by centroid along the longest axis and splits into K pieces.
| T | Floating-point precision used for centroid comparisons. |
| P | Primitive type. |
| BV | Bounding volume type. |
| K | Number of output sub-lists (tree branching factor). |
| [in] | a_primsAndBVs | Input (primitive, BV) pairs. |