Helios++
Helios software for LiDAR simulations
FastSAHKDTreeFactory Class Reference

Class providing building methods for k-dimensional trees with a fast strategy to approximate Surface Area Heuristic (SAH) More...

#include <FastSAHKDTreeFactory.h>

Inheritance diagram for FastSAHKDTreeFactory:
Collaboration diagram for FastSAHKDTreeFactory:

Public Member Functions

 FastSAHKDTreeFactory (size_t const lossNodes=32, double const ci=1, double const cl=1, double const co=1)
 Fast surface area heuristic KDTree factory default constructor. More...
 
KDTreeFactoryclone () const override
 
void _clone (KDTreeFactory *kdtf) const override
 Assign attributes from FastSAHKDTreeFactory to its clone.
 
double findSplitPositionBySAH (KDTreeNode *node, vector< Primitive * > &primitives) const override
 Find the best split position using an min-max like approximation for the loss function of Surface Area Heuristic (SAH) More...
 
virtual double findSplitPositionByFastSAHRecipe (KDTreeNode *node, vector< Primitive * > &primitives, std::function< void(vector< Primitive * > &primitives, int const splitAxis, double const minp, double const deltap, size_t const lossNodes, size_t const lossCases, vector< size_t > &cForward, vector< size_t > &cBackward)> f_recount) const
 The recipe for finding split position by Fast-SAH algorithm. It is meant to be used by the FastSAHKDTreeFactory::findSplitPositionBySAH but also by any alternative implementation which shares the same recipe (global logic) but changes the way some parts are computed. For instance, it is used to handle geometry-level parallelization. More...
 
- Public Member Functions inherited from SAHKDTreeFactory
 SAHKDTreeFactory (size_t const lossNodes=21, double const ci=1, double const cl=1, double const co=1)
 Surface area heuristic KDTree factory default constructor. More...
 
KDTreeFactoryclone () const override
 
void _clone (KDTreeFactory *kdtf) const override
 Assign attributes from SAHKDTreeFactory to its clone.
 
void defineSplit (KDTreeNode *node, KDTreeNode *parent, vector< Primitive * > &primitives, int const depth) const override
 Define the split axis and position for current node. More...
 
void computeKDTreeStats (KDTreeNodeRoot *root) const override
 Compute the simple stats of the KDTree but also its cost based on surface area heuristic defined in defineSplit function. More...
 
void buildChildrenNodes (KDTreeNode *node, KDTreeNode *parent, vector< Primitive * > const &primitives, int const depth, int const index, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives) override
 Build children nodes using \(C_T\) heuristic to handle KDTree in-depth partitioning. More...
 
virtual void buildChildrenNodesRecipe (KDTreeNode *node, KDTreeNode *parent, vector< Primitive * > const &primitives, int const depth, int const index, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives, std::function< void(KDTreeNode *node, int const depth, int const index, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives)>f_buildChildrenNodes)
 The recipe for building of children nodes by SAH algorithm. It is meant to be used by the SAHKDTreeFactory::buildChildrenNodes but also by any alternative implementation which shared the same recipe (global logic) but changes the way some parts are computed. For instance, it is used to handle geometry-level parallelization. More...
 
virtual size_t getLossNodes () const
 Obtain the loss nodes used to compute the Surface Area Heuristic. More...
 
virtual void setLossNodes (size_t const lossNodes)
 Set the number loss nodes used to compute the Surface Area Heuristic. More...
 
virtual double getInteriorCost () const
 Obtain the cost-weight of interior nodes. More...
 
virtual void setInteriorCost (double const ci)
 Set the cost-weight of interior nodes. More...
 
virtual double getLeafCost () const
 Obtain the cost-weight for leaf nodes. More...
 
virtual void setLeafCost (double const cl)
 Set the cost-weight for leaf nodes. More...
 
virtual double getObjectCost () const
 Obtain the cost-weight of testing an object for intersection. More...
 
virtual void setObjectCost (double const co)
 Set the cost-weight of testing an object for intersection. More...
 
- Public Member Functions inherited from SimpleKDTreeFactory
 SimpleKDTreeFactory ()
 SimpleKDTreeFactory default constructor. More...
 
KDTreeFactoryclone () const override
 
KDTreeNodeRootmakeFromPrimitivesUnsafe (vector< Primitive * > &primitives, bool const computeStats=false, bool const reportStats=false) override
 Build a simple KDTree from given primitives. More...
 
- Public Member Functions inherited from KDTreeFactory
 KDTreeFactory ()
 K dimensional tree factory default constructor.
 
virtual KDTreeNodeRootmakeFromPrimitives (vector< Primitive * > const &primitives, bool const computeStats=false, bool const reportStats=false)
 Safe wrapper from makeFromPrimitivesUnsafe which handles a copy to make from primitives by default. This function behavior might be overridden by any derived/child class. It is expected that any implementation of makeFromPrimitives provides a way to implement the makeFromPrimitivesUnsafe method without modifying vector of input primitives. Notice this does not mean primitives themselves cannot be modified, that depends on the type of KDTreeFactory. It only means that the vector itself will not be modified, for instance due to sorting purposes. More...
 
virtual bool isBuildingLightNodes ()
 Check if KDTreeFactory is building light nodes. More...
 
virtual void setBuildingLightNodes (bool const buildLightNodes)
 Set KDTreeFactory so it build light nodes (true) or not (false) More...
 
virtual void setChild (LightKDTreeNode *&child, KDTreeNode *node)
 Set child to given node if and only if node is not null. It must be used to assign children nodes in a thread-safe way. More...
 

Private Member Functions

template<typename Archive >
void serialize (Archive &ar, unsigned int const version)
 Serialize a fast surface area heuristic KDTree factory to a stream of bytes. More...
 

Private Attributes

size_t lossNodes
 How many loss nodes must be computed when optimizing the loss function \(\mathcal{L}_2\) to determine the best split position for a given KDTree node. More...
 
double ci
 Cost-weight for traversing interior nodes. More...
 
double cl
 Cost-weight for traversing leaf nodes. More...
 
double co
 Cost-weight for testing an object for intersection. More...
 

Friends

class boost::serialization::access
 

Additional Inherited Members

- Protected Member Functions inherited from SAHKDTreeFactory
bool checkNodeMustSplit (vector< Primitive * > const &primitives, vector< Primitive * > const &leftPrimitives, vector< Primitive * > const &rightPrimitives) const override
 Check wheter the node must be splitted (true) or not (false) depending on its total primitives. More...
 
virtual double splitLoss (vector< Primitive * > const &primitives, int const splitAxis, double const splitPos, double const r) const
 Compute the loss function for the splitting hyperplane. More...
 
virtual void computeBestSplit (vector< Primitive * > &primitives, size_t const lossNodes, double const start, double const step, int const splitAxis, double const minBound, double const boundLength, double &loss, double &splitPos) const
 Iteratively compute the best split position, it is the one with smaller loss. More...
 
virtual double findSplitPositionBySAHRecipe (KDTreeNode *node, vector< Primitive * > &primitives, std::function< void(vector< Primitive * >::iterator begin, vector< Primitive * >::iterator end, KDTreePrimitiveComparator comparator)> f_sortPrimitives, std::function< void(vector< Primitive * > &primitives, size_t const lossNodes, double const start, double const step, int const splitAxis, double const minBound, double const boundLength, double &loss, double &splitPos)> f_computeLossNodes) const
 The recipe for finding split position by SAH algorithm. It is meant to be used by the SAHKDTreeFactory::findSplitPositionBySAH but also by any alternative implementation which shares the same recipe ( global logic) but changes the way some parts are computed. For instance, it is used to handle geometry-level parallelization. More...
 
virtual double heuristicILOT (double &hi, double &hl, double &ho, double &ht, double const surfaceAreaRoot, double const surfaceAreaInterior, double const surfaceAreaLeaf, vector< Primitive * > const &primitives) const
 Compute the \(C_T\) heuristic preserving partials result of interest. More...
 
virtual double cumulativeILOT (double &hi, double &hl, double &ho, double &ht, double const _hi, double const _hl, double const _ho, double const saRoot) const
 Compute the cumulative of \(C_T\) heuristic ILOT. More...
 
virtual void internalizeILOT (double &hi, double &hl, double &ho, double &ht, KDTreeNode *node, vector< Primitive * > const &primitives, vector< Primitive * > const &leftPrimitives, vector< Primitive * > const &rightPrimitives)
 Compute ILOT corresponding to internalization (make interior) of given node and its corresponding left and right splits. More...
 
virtual void toILOTCache (double const I, double const L, double const O, double const T)
 Set ILOT cache from given values. More...
 
virtual void fromILOTCache (double &I, double &L, double &O, double &T) const
 Set references from ILOT cache. More...
 
virtual void fromILOCache (double &I, double &L, double &O) const
 Set references from ILOT cache but only for ILO components. More...
 
virtual double getCacheT () const
 Obtain the T component of ILOT cache. More...
 
virtual void initILOT (KDTreeNode *root, vector< Primitive * > const &primitives)
 Initialize the ILOT cache from given root node. More...
 
virtual void setCacheRoot (KDTreeNode *root)
 Set the cached root node. More...
 
- Protected Member Functions inherited from SimpleKDTreeFactory
virtual KDTreeNodebuildRecursive (KDTreeNode *parent, bool const left, vector< Primitive * > &primitives, int const depth, int const index)
 Recursively build a KDTree for given primitives. More...
 
virtual KDTreeNodebuildRecursiveRecipe (KDTreeNode *parent, bool const left, vector< Primitive * > &primitives, int const depth, int const index, std::function< void(KDTreeNode *node, KDTreeNode *parent, bool const left, vector< Primitive * > const &primitives)> f_computeNodeBoundaries, std::function< void(KDTreeNode *node, KDTreeNode *parent, vector< Primitive * > &primitives, int const depth)> f_defineSplit, std::function< void(vector< Primitive * > const &primitives, int const splitAxis, double const splitPos, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives)> f_populateSplits, std::function< void(KDTreeNode *node, KDTreeNode *parent, vector< Primitive * > const &primitives, int const depth, int const index, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives)> f_buildChildrenNodes)
 The recipe of the recursive building algorithm. It is meant to be used by the SimpleKDTreeFactory::buildRecursive but also by any alternative implementation which shares the same recipe (global logic) but changes the way some parts are computed. For instance, it is used by the MultiThreadKDTreeFactory to handle geometry-level parallelization. More...
 
virtual void reportKDTreeStats (KDTreeNodeRoot *root, vector< Primitive * > const &primitives) const
 Report KDTree stats of given root node at INFO logging level. More...
 
virtual void populateSplits (vector< Primitive * > const &primitives, int const splitAxis, double const splitPos, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives) const
 Populate list of primitives for left and right splits from given primitives of node being splitted. More...
 
virtual void computeNodeBoundaries (KDTreeNode *node, KDTreeNode *parent, bool const left, vector< Primitive * > const &primitives) const
 Compute min and max position and surface area of bounding cuboid for given node. More...
 
virtual void onPopulateSplitsDigestPrimitive (Primitive *p, int const splitAxis, double const splitPos, vector< Primitive * > &leftPrimitives, vector< Primitive * > &rightPrimitives) const
 Function to assist SimpleKDTreeFactory::populateSplits by providing the logic of digesting a primitive. More...
 
virtual void computeMinMaxSAHForChild (KDTreeNode *node, KDTreeNode *parent, bool const left, vector< Primitive * > const &primitives) const
 Function to assist SimpleKDTreeFactory::computeNodeBoundaries when computing surface area heuristic and minimum and maximum positions for child nodes. More...
 
virtual void onRootBoundariesDigestPrimitive (Primitive *primitive, double &ax, double &ay, double &az, double &bx, double &by, double &bz) const
 Function to assist SimpleKDTreeFactory::computeNodeBoundaries by providing the logic of digesting a primitive. More...
 
virtual void onComputeNodeBoundariesCalcSAH (KDTreeNode *node, double const ax, double const ay, double const az, double const bx, double const by, double const bz) const
 Function to assist SimpleKDTreeFactory::computeNodeBoundaries when computing the SAH for a node. More...
 
virtual void makeLeaf (KDTreeNode *node, vector< Primitive * > const &primitives) const
 Make given node a leaf one. More...
 
- Protected Member Functions inherited from KDTreeFactory
virtual void lighten (KDTreeNodeRoot *root)
 Rebuild all children of given root KDTree node as LightKDTeeeNode nodes. More...
 
virtual LightKDTreeNode_lighten (KDTreeNode *node)
 Assist KDTreeFactory::lighten function by handling the lighten of a given non-root node. More...
 
- Protected Attributes inherited from SAHKDTreeFactory
size_t lossNodes
 How many loss nodes must be computed when optimizing the loss function \(\mathcal{L}_2\) to determine the best split position for a given KDTree node. More...
 
double ci
 Cost-weight for traversing interior nodes. More...
 
double cl
 Cost-weight for traversing leaf nodes. More...
 
double co
 Cost-weight for testing an object for intersection. More...
 
KDTreeNodecacheRoot = nullptr
 Cache pointer to root node of current KDTree being built.
 
double cacheI
 Cache last valid interior cost. More...
 
double cacheL
 Cache last valid leaves cost. More...
 
double cacheO
 Cache last valid object cost. More...
 
double cacheT
 Cache last valid tree cost. More...
 
std::function< void(void)> _lockILOT
 Function to lock the ILOT cache on a unique way (no thread but locker one must be able to use it). By default it is a void function, it must be overridden to provide concurrency handling. More...
 
std::function< void(void)> _unlockILOT
 Function to unlock the ILOT cache. It is the counterpart of the _lockILOT function. More...
 
- Protected Attributes inherited from SimpleKDTreeFactory
std::function< KDTreeNode *(KDTreeNode *, bool const, vector< Primitive * > &, int const, int const)> _buildRecursive
 The member function as attribute used to recursively build KDTree nodes. By default it will be assigned to the buildRecursive member function but it might be overridden by other implementations. For instance, to wrap the buildRecursive behavior to handle parallel building of KDTrees. More...
 
size_t minSplitPrimitives
 How many primitives are required for a node to be splitted. More...
 
- Protected Attributes inherited from KDTreeFactory
bool buildLightNodes = true
 When it is true, the KDTreeFactory is expected to build light nodes. It is, built KDTree must have a KDTreeRootNode which children are all LightKDTreeNode. When it is false, KDTreeFactory is allowed to build KDTree with KDTreeNode children, which might require more memory. More...
 
LightKDTreeNodeBlockAllocator lkdtnBlockAllocator
 The block allocator to speed-up lighten of KDTree by reducing allocation calls when instantiating multiple LightKDTreeNode. More...
 

Detailed Description

Class providing building methods for k-dimensional trees with a fast strategy to approximate Surface Area Heuristic (SAH)

Author
Alberto M. Esmoris Pena
Version
1.0

The fast strategy to approximate Surface Area Heuristic (SAH) is based on min-max histograms. Now, let \(H_*\) and \(H^*\) be the min and max histograms respectively with bins \(\left\{[a_1, b_1), \ldots, [a_{m-1}, b_{m-1}), [a_m, b_m]\right\}\), where \(a_i\) is the start point of \(i\)-th bin and \(b_i\) is the end point of \(i\)-th bin. The min histogram is populated from minimum vertices of axis aligned bounding boxes containing each primitive, while the max histogram does the same with maximum vertices. For the sake of convenience, let \(b_0 = a_1\) so the optimum split position can be approximated as \(b_i\) with \(i \in [0, m]\) such that:

\[ \mathrm{argmin}_{i} \;\;\;\; \frac{i}{m} \left|\left\{x \in H_*: x < b_i\right\}\right| + \left(1-\frac{i}{m}\right) \left|\left\{x \in H^*: x \geq b_i\right\}\right| \]

Thus, by means of modifying how the loss function is computed, sorting is no longer required and can be replaced by a cheap approximation based on min-max method.

The approach here proposed is based on "Highly parallel fast KD-tree construction for interactive ray tracing of dynamic scenes" by Maxim Shevtsov, Alexei Soupikov and Alexander Kapustin

See also
SAHKDTreeFactory::defineSplit

Constructor & Destructor Documentation

◆ FastSAHKDTreeFactory()

FastSAHKDTreeFactory::FastSAHKDTreeFactory ( size_t const  lossNodes = 32,
double const  ci = 1,
double const  cl = 1,
double const  co = 1 
)

Fast surface area heuristic KDTree factory default constructor.

Parameters
lossNodesHow many bins use for the min-max approximation of loss function
See also
SAHKDTreeFactory::SAHKDTreeFactory
FastSAHKDTreeFactory

Member Function Documentation

◆ clone()

KDTreeFactory * FastSAHKDTreeFactory::clone ( ) const
overridevirtual
See also
KDTreeFactory::clone

Implements KDTreeFactory.

◆ findSplitPositionByFastSAHRecipe()

double FastSAHKDTreeFactory::findSplitPositionByFastSAHRecipe ( KDTreeNode node,
vector< Primitive * > &  primitives,
std::function< void(vector< Primitive * > &primitives, int const splitAxis, double const minp, double const deltap, size_t const lossNodes, size_t const lossCases, vector< size_t > &cForward, vector< size_t > &cBackward)>  f_recount 
) const
virtual

The recipe for finding split position by Fast-SAH algorithm. It is meant to be used by the FastSAHKDTreeFactory::findSplitPositionBySAH but also by any alternative implementation which shares the same recipe (global logic) but changes the way some parts are computed. For instance, it is used to handle geometry-level parallelization.

Parameters
f_recountFunction to count min and max vertices forward and backward from binning
See also
FastSAHKDTreeFactory::findSplitPositionBySAH
FastSAHKDTreeFactory::GEOM_findSplitPositionBySAH
MultiThreadKDTreeFactory
Returns
Loss of best split position. The position itself is already stored in given node.

◆ findSplitPositionBySAH()

double FastSAHKDTreeFactory::findSplitPositionBySAH ( KDTreeNode node,
vector< Primitive * > &  primitives 
) const
overridevirtual

Find the best split position using an min-max like approximation for the loss function of Surface Area Heuristic (SAH)

Returns
Approximate loss of best split position. The position itself is already stored in given node
See also
SAHKDTreeFactory::findSplitPositionBySAH
SAHKDTreeFactory::defineSplit

Reimplemented from SAHKDTreeFactory.

◆ serialize()

template<typename Archive >
void FastSAHKDTreeFactory::serialize ( Archive &  ar,
unsigned int const  version 
)
inlineprivate

Serialize a fast surface area heuristic KDTree factory to a stream of bytes.

Template Parameters
ArchiveType of rendering
Parameters
arSpecific rendering for the stream of bytes
versionVersion number for the fast surface area heuristic KDTRee factory

Member Data Documentation

◆ ci

double SAHKDTreeFactory::ci
private

Cost-weight for traversing interior nodes.

See also
SAHKDTreeFactory::defineSplit

◆ cl

double SAHKDTreeFactory::cl
private

Cost-weight for traversing leaf nodes.

See also
SAHKDTreeFactory::defineSplit

◆ co

double SAHKDTreeFactory::co
private

Cost-weight for testing an object for intersection.

See also
SAHKDTreeFactory::defineSplit

◆ lossNodes

size_t SAHKDTreeFactory::lossNodes
private

How many loss nodes must be computed when optimizing the loss function \(\mathcal{L}_2\) to determine the best split position for a given KDTree node.

See also
SAHKDTreeFactory::splitLoss

The documentation for this class was generated from the following files: