EBGeometry 1.0
Loading...
Searching...
No Matches
EBGeometry_BVH.hpp
Go to the documentation of this file.
1/* EBGeometry
2 * Copyright © 2022 Robert Marskar
3 * Please refer to Copyright.txt and LICENSE in the EBGeometry root directory.
4 */
5
12#ifndef EBGeometry_BVH
13#define EBGeometry_BVH
14
15// Std includes
16#include <memory>
17#include <vector>
18#include <array>
19#include <functional>
20#include <queue>
21
22// Our includes
23#include "EBGeometry_Vec.hpp"
24#include "EBGeometry_SFC.hpp"
26
30namespace BVH {
31
35 enum class Build
36 {
37 TopDown,
38 Morton,
39 Nested
40 };
41
48 template <class T, class P, class BV, size_t K>
49 class NodeT;
50
56 template <class T, class P, class BV, size_t K>
57 class LinearNodeT;
58
64 template <class T, class P, class BV, size_t K>
65 class LinearBVH;
66
71 template <class P>
72 using PrimitiveListT = std::vector<std::shared_ptr<const P>>;
73
77 template <class P, class BV>
78 using PrimAndBV = std::pair<std::shared_ptr<const P>, BV>;
79
84 template <class P, class BV>
85 using PrimAndBVListT = std::vector<PrimAndBV<P, BV>>;
86
93 template <class P, class BV, size_t K>
94 using PartitionerT = std::function<std::array<PrimAndBVListT<P, BV>, K>(const PrimAndBVListT<P, BV>& a_primsAndBVs)>;
95
104 template <class T, class P, class BV, size_t K>
105 using StopFunctionT = std::function<bool(const NodeT<T, P, BV, K>& a_node)>;
106
111 template <class P>
112 using Updater = std::function<void(const PrimitiveListT<P>& a_primitives)>;
113
121 template <class NodeType, class Meta>
122 using Visiter = std::function<bool(const NodeType& a_node, const Meta& a_meta)>;
123
130 template <class NodeType, class Meta, size_t K>
131 using Sorter = std::function<void(std::array<std::pair<std::shared_ptr<const NodeType>, Meta>, K>& a_children)>;
132
136 template <class NodeType, class Meta>
137 using MetaUpdater = std::function<Meta(const NodeType& a_node)>;
138
142 template <class X, size_t K>
143 auto equalCounts = [](const std::vector<X>& a_primitives) noexcept -> std::array<std::vector<X>, K> {
144 int length = a_primitives.size() / K;
145 int remain = a_primitives.size() % K;
146
147 int begin = 0;
148 int end = 0;
149
150 std::array<std::vector<X>, K> chunks;
151
152 for (size_t k = 0; k < K; k++) {
153 end += (remain > 0) ? length + 1 : length;
154 remain--;
155
156 chunks[k] = std::vector<X>(a_primitives.begin() + begin, a_primitives.begin() + end);
157
158 begin = end;
159 }
160
161 return chunks;
162 };
163
168 template <class T, class P, class BV, size_t K>
170 [](const PrimAndBVListT<P, BV>& a_primsAndBVs) noexcept -> std::array<PrimAndBVListT<P, BV>, K> {
173
174 for (const auto& pbv : a_primsAndBVs) {
175 lo = min(lo, pbv.first->getCentroid());
176 hi = max(hi, pbv.first->getCentroid());
177 }
178
179 const size_t splitDir = (hi - lo).maxDir(true);
180
181 // Sort the primitives along the above coordinate direction.
183
184 std::sort(sortedPrimsAndBVs.begin(),
185 sortedPrimsAndBVs.end(),
186 [splitDir](const PrimAndBV<P, BV>& pbv1, const PrimAndBV<P, BV>& pbv2) -> bool {
187 return pbv1.first->getCentroid(splitDir) < pbv2.first->getCentroid(splitDir);
188 });
189
190 return BVH::equalCounts<PrimAndBV<P, BV>, K>(sortedPrimsAndBVs);
191 };
192
197 template <class T, class P, class BV, size_t K>
201
202 for (const auto& pbv : a_primsAndBVs) {
203 lo = min(lo, pbv.second.getCentroid());
204 hi = max(hi, pbv.second.getCentroid());
205 }
206
207 const size_t splitDir = (hi - lo).maxDir(true);
208
209 // Sort the primitives along the above coordinate direction.
211
212 std::sort(sortedPrimsAndBVs.begin(),
213 sortedPrimsAndBVs.end(),
214 [splitDir](const PrimAndBV<P, BV>& pbv1, const PrimAndBV<P, BV>& pbv2) -> bool {
215 return pbv1.second.getCentroid()[splitDir] < pbv2.second.getCentroid()[splitDir];
216 });
217
218 return BVH::equalCounts<PrimAndBV<P, BV>, K>(sortedPrimsAndBVs);
219 };
220
225 template <class T, class P, class BV, size_t K>
227 [](const BVH::NodeT<T, P, BV, K>& a_node) noexcept -> bool { return (a_node.getPrimitives()).size() < K; };
228
236 template <class T, class P, class BV, size_t K>
237 class NodeT : public std::enable_shared_from_this<NodeT<T, P, BV, K>>
238 {
239 public:
244
248 using Vec3 = Vec3T<T>;
249
254
258 using NodePtr = std::shared_ptr<Node>;
259
264
269
274
280
285
294 inline void
297
308 inline void
310
314 inline bool
316
320 inline bool
322
329
336
341 inline const std::vector<BV>&
343
350 inline T
352
357 inline const std::array<std::shared_ptr<NodeT<T, P, BV, K>>, K>&
359
369 inline void
374
381 inline std::shared_ptr<LinearBVH<T, P, BV, K>>
383
384 protected:
389
394
399
404
408 std::array<std::shared_ptr<NodeT<T, P, BV, K>>, K> m_children;
409
416
421 inline std::vector<BV>&
423
429 inline void
431
444 inline size_t
447 size_t& a_offset) const noexcept;
448 };
449
480 template <class T, class P, class BV, size_t K>
482 {
483 public:
487 using Vec3 = Vec3T<T>;
488
493
498
503 inline void
504 setBoundingVolume(const BV& a_boundingVolume) noexcept;
505
509 inline void
510 setPrimitivesOffset(const size_t a_primitivesOffset) noexcept;
511
516 inline void
517 setNumPrimitives(const size_t a_numPrimitives) noexcept;
518
524 inline void
525 setChildOffset(const size_t a_childOffset, const size_t a_whichChild) noexcept;
526
533
538 inline const size_t&
539 getPrimitivesOffset() const noexcept;
540
545 inline const size_t&
546 getNumPrimitives() const noexcept;
547
552 inline const std::array<size_t, K>&
553 getChildOffsets() const noexcept;
554
558 inline bool
560
564 inline bool
566
573 inline T
575
582 inline std::vector<T>
584
585 protected:
590
595
599 size_t m_primitivesOffset;
600
604 size_t m_numPrimitives;
605
609 std::array<size_t, K> m_childOffsets;
610 };
611
615 template <class T, class P, class BV, size_t K>
617 {
618 public:
622 using Vec3 = Vec3T<T>;
623
628
632 using PrimitiveList = std::vector<std::shared_ptr<const P>>;
633
637 inline LinearBVH() = default;
638
642 inline LinearBVH(const LinearBVH&) = default;
643
649 inline LinearBVH(const std::vector<std::shared_ptr<const LinearNodeT<T, P, BV, K>>>& a_linearNodes,
650 const std::vector<std::shared_ptr<const P>>& a_primitives);
651
657 inline LinearBVH(const std::vector<std::shared_ptr<LinearNodeT<T, P, BV, K>>>& a_linearNodes,
658 const std::vector<std::shared_ptr<const P>>& a_primitives);
659
663 inline virtual ~LinearBVH();
664
668 inline const BV&
670
680 inline void
685
686 protected:
690 std::vector<std::shared_ptr<const LinearNodeT<T, P, BV, K>>> m_linearNodes;
691
697 };
698} // namespace BVH
699
700#include "EBGeometry_NamespaceFooter.hpp"
701
702#include "EBGeometry_BVHImplem.hpp"
703
704#endif
Declaration of various space-filling curves.
Declaration of 2D and 3D point/vector classes with templated precision. Used with DCEL tools.
Vec2T< T > max(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Maximum function. Returns new vector with component-wise minimums.
Vec2T< T > min(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Minimum function. Returns new vector with component-wise minimums.
T length(const Vec2T< T > &v) noexcept
Length function.
Forward declare linear BVH class.
Definition EBGeometry_BVH.hpp:617
LinearBVH(const std::vector< std::shared_ptr< const LinearNodeT< T, P, BV, K > > > &a_linearNodes, const std::vector< std::shared_ptr< const P > > &a_primitives)
Full constructor. Associates the nodes and primitives.
LinearBVH(const std::vector< std::shared_ptr< LinearNodeT< T, P, BV, K > > > &a_linearNodes, const std::vector< std::shared_ptr< const P > > &a_primitives)
Full constructor. Associates the nodes and primitives.
LinearBVH()=default
Disallowed. Use the full constructor please.
LinearBVH(const LinearBVH &)=default
Copy constructor.
std::vector< std::shared_ptr< const P > > PrimitiveList
Alias for list of primitives.
Definition EBGeometry_BVH.hpp:632
virtual ~LinearBVH()
Destructor. Does nothing.
const BV & getBoundingVolume() const noexcept
Get the bounding volume for this BVH.
Forward declare linear node class.
Definition EBGeometry_BVH.hpp:482
LinearNodeT() noexcept
Constructor.
Forward declare the BVH node since it is needed for the polymorphic lambdas.
Definition EBGeometry_BVH.hpp:238
std::shared_ptr< Node > NodePtr
Alias for node type pointer.
Definition EBGeometry_BVH.hpp:258
const BV & getBoundingVolume() const noexcept
Get bounding volume.
void setChildren(const std::array< std::shared_ptr< NodeT< T, P, BV, K > >, K > &a_children) noexcept
Explicitly set this node's children.
std::vector< std::shared_ptr< const P > > m_primitives
Primitives list. This will be empty for regular nodes.
Definition EBGeometry_BVH.hpp:398
const PrimitiveList & getPrimitives() const noexcept
Get the primitives stored in this node.
bool isLeaf() const noexcept
Get node type.
bool m_partitioned
Determines whether or not the partitioning function has already been called.
Definition EBGeometry_BVH.hpp:393
NodeT() noexcept
Default constructor which sets a regular node.
BV m_boundingVolume
Bounding volume object for enclosing everything in this node.
Definition EBGeometry_BVH.hpp:388
T getDistanceToBoundingVolume(const Vec3 &a_point) const noexcept
Get the distance from a 3D point to the bounding volume.
void topDownSortAndPartition(const Partitioner &a_partitioner=BVCentroidPartitioner< T, P, BV, K >, const StopFunction &a_stopCrit=DefaultStopFunction< T, P, BV, K >) noexcept
Function for using top-down construction of the bounding volume hierarchy.
std::vector< BV > m_boundingVolumes
List of bounding volumes for the primitives. This will be empty for regular nodes.
Definition EBGeometry_BVH.hpp:403
const std::vector< BV > & getBoundingVolumes() const noexcept
Get the bounding volumes for the primitives in this node (can be empty if regular node)
bool isPartitioned() const noexcept
Check if BVH is already partitioned.
void bottomUpSortAndPartition() noexcept
Function for doing bottom-up construction using a specified space-filling curve.
const std::array< std::shared_ptr< NodeT< T, P, BV, K > >, K > & getChildren() const noexcept
Return this node's children.
std::shared_ptr< LinearBVH< T, P, BV, K > > flattenTree() const noexcept
Flatten everything beneath this node into a depth-first sorted BVH hierarchy.
void traverse(const BVH::Updater< P > &a_updater, const BVH::Visiter< Node, Meta > &a_visiter, const BVH::Sorter< Node, Meta, K > &a_sorter, const BVH::MetaUpdater< Node, Meta > &a_metaUpdater) const noexcept
Recursion-less BVH traversal algorithm. The user inputs the update rule, a pruning criterion,...
std::array< std::shared_ptr< NodeT< T, P, BV, K > >, K > m_children
Children nodes.
Definition EBGeometry_BVH.hpp:408
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:218
static constexpr Vec3T< T > max() noexcept
Return a vector with maximum representable components.
Namespace for various bounding volume hierarchy (BVH) functionality.
Definition EBGeometry_BVH.hpp:30
std::vector< PrimAndBV< P, BV > > PrimAndBVListT
List of primitives and their bounding volumes.
Definition EBGeometry_BVH.hpp:85
auto DefaultStopFunction
Simple stop function which ends the recursion when there aren't enough primitives in the node.
Definition EBGeometry_BVH.hpp:226
std::pair< std::shared_ptr< const P >, BV > PrimAndBV
Alias for a list geometric primitive and BV.
Definition EBGeometry_BVH.hpp:78
auto BVCentroidPartitioner
Simple partitioner which sorts the BVs based on their bounding volume centroids, and then splits into...
Definition EBGeometry_BVH.hpp:198
Build
Enum for specifying whether or not the construction is top-down or bottom-up.
Definition EBGeometry_BVH.hpp:36
std::function< bool(const NodeType &a_node, const Meta &a_meta)> Visiter
Visiter pattern for LinearBVH::traverse. Must return true if we should visit the node and false other...
Definition EBGeometry_BVH.hpp:122
std::function< void(const PrimitiveListT< P > &a_primitives)> Updater
Updater for tree traversal.
Definition EBGeometry_BVH.hpp:112
std::function< void(std::array< std::pair< std::shared_ptr< const NodeType >, Meta >, K > &a_children)> Sorter
Sorting criterion for which child node to visit first. This takes an input list of child nodes and so...
Definition EBGeometry_BVH.hpp:131
std::vector< std::shared_ptr< const P > > PrimitiveListT
List of primitives.
Definition EBGeometry_BVH.hpp:72
auto PrimitiveCentroidPartitioner
Simple partitioner which sorts the primitives based on their centroids, and then splits into K pieces...
Definition EBGeometry_BVH.hpp:169
std::function< Meta(const NodeType &a_node)> MetaUpdater
Updater for when user wants to add some meta-data to his BVH traversal.
Definition EBGeometry_BVH.hpp:137
std::function< std::array< PrimAndBVListT< P, BV >, K >(const PrimAndBVListT< P, BV > &a_primsAndBVs)> PartitionerT
Polymorphic partitioner for splitting a list of primitives and BVs into K new subsets.
Definition EBGeometry_BVH.hpp:94
std::function< bool(const NodeT< T, P, BV, K > &a_node)> StopFunctionT
Stop function for deciding when a BVH node can't be divided into sub-volumes.
Definition EBGeometry_BVH.hpp:105
auto equalCounts
Function for splitting a vector of some size into K almost-equal chunks. This is a utility function.
Definition EBGeometry_BVH.hpp:143