[2197] | 1 | // declaration of kd-tree members
|
---|
| 2 |
|
---|
| 3 | #pragma once
|
---|
| 4 |
|
---|
| 5 | #include "malloc.h"
|
---|
| 6 | #include "Heap.hpp"
|
---|
| 7 | #include "Vector.hpp"
|
---|
| 8 | #include "BoundingBox.hpp"
|
---|
| 9 | #include "Intersectable.hpp"
|
---|
| 10 |
|
---|
| 11 | #include "Ray.hpp"
|
---|
| 12 | #include "HitRec.hpp"
|
---|
| 13 | #include "Material.hpp"
|
---|
| 14 |
|
---|
| 15 | #define KDTREE_CACHE_LINE_BYTES 128
|
---|
| 16 |
|
---|
| 17 | /*! This class implements a kd-tree. Splitting, termination and cutting of empty space is
|
---|
| 18 | based on cost estimation. Memory representation uses cache-line sized sub-trees and
|
---|
| 19 | mapping of an unbalanced tree into an array. */
|
---|
| 20 | class KDTree {
|
---|
| 21 | unsigned int nCacheLines; //!< #cache line sized memory segments used
|
---|
| 22 | unsigned int maxNCacheLines; //!< #nodes per cache line
|
---|
| 23 | unsigned int nCacheLineNodes; //!< #nodes per cache line
|
---|
| 24 | unsigned int nCacheLineBytes; //!< bytes per cache line
|
---|
| 25 |
|
---|
| 26 | BoundingBox boundingBox; //!< bounding box containing all objects
|
---|
| 27 |
|
---|
| 28 | float* poolNodeTable; //!< memory allocated for nodes
|
---|
| 29 | float* nodeTable; //!< array aligned on cache lines
|
---|
| 30 |
|
---|
| 31 | unsigned int nObjects; //!< #objects
|
---|
| 32 | Intersectable** objects; //!< array objects
|
---|
| 33 |
|
---|
| 34 | //! minimum heap to store indices of free nodes during the build
|
---|
| 35 | Heap<unsigned int>* freeNodes;
|
---|
| 36 |
|
---|
| 37 | //! stack to implement the recursive traversal algorithm
|
---|
| 38 | struct TraverseStack{
|
---|
| 39 | float rayMin; //!< minimum distance from origin
|
---|
| 40 | float rayMax; //!< maximum distance from origin
|
---|
| 41 | unsigned int tNode; //!< node index of kd-tree node to be traced
|
---|
| 42 | } *traverseStack;
|
---|
| 43 | unsigned int depth;
|
---|
| 44 | unsigned int currentDepth;
|
---|
| 45 |
|
---|
| 46 | float epsilon;
|
---|
| 47 |
|
---|
| 48 | //! traces the tree defined by root node index 'nodeID',
|
---|
| 49 | //! and frees the memory occupied by the object lists
|
---|
| 50 | void deleteLeaves(unsigned int nodeID);
|
---|
| 51 |
|
---|
| 52 | //! recursive algorithm to build the tree
|
---|
| 53 | void build(unsigned int nodeID, //!< node index of kd-tree node to be created
|
---|
| 54 | unsigned int* boundsArray, //!< array of duplicated object indices,
|
---|
| 55 | //!< first bit tells mimima and maxima apart
|
---|
| 56 | unsigned int nObjects, //!< #objects (boundsArray's size is 2*nObjects)
|
---|
| 57 | BoundingBox& limits, //!< kd-tree node volume
|
---|
| 58 | unsigned char axisNmask); //!< bits 5,4,3 indicate z,y,x failed cut attempts
|
---|
| 59 | //!< bits 1,0 identify cut axis to be used
|
---|
| 60 |
|
---|
| 61 | //! qSort an array segment of object extremes
|
---|
| 62 | void quickSort(unsigned int* lo0, unsigned int* hi0, unsigned char axis);
|
---|
| 63 | //! compare two object extrema according to the coordinate specified
|
---|
| 64 | bool inline compare(unsigned int aIndex, unsigned int bIndex, unsigned char axis);
|
---|
| 65 | //! return the value of the object extreme referenced
|
---|
| 66 | float inline getBoundValue(unsigned int * extremeIndex, unsigned char axis);
|
---|
| 67 | //! binary search: finds the position of value 'loc' in a sorted array partition
|
---|
| 68 | unsigned int* findBound(unsigned int* extremeArrayStart, unsigned int nBounds, float loc, unsigned char axis);
|
---|
| 69 |
|
---|
| 70 | //! tell if a node is a leaf
|
---|
| 71 | bool inline isLeaf(unsigned int xnode);
|
---|
| 72 | //! retrieve the node indices corresponding to the children of the specified node
|
---|
| 73 | //! return false if the node is a leaf
|
---|
| 74 | bool inline followChildren(unsigned int& parent, unsigned int &leftChild, unsigned int &rightChild);
|
---|
| 75 |
|
---|
| 76 | //! retrieve the node indices corresponding to the children of the specified node
|
---|
| 77 | //! if they are not suitable to be the root of a free sub-tree, return false
|
---|
| 78 | bool inline getFreeNodes(unsigned int parent, unsigned int& leftFree, unsigned int& rightFree);
|
---|
| 79 |
|
---|
| 80 | //! accumulate object extrema
|
---|
| 81 | inline void createBoundingBox (Intersectable** iObjects, int nObjects)
|
---|
| 82 | {
|
---|
| 83 | if(!nObjects)
|
---|
| 84 | return;
|
---|
| 85 | boundingBox.minPoint = iObjects [0]->bbox.minPoint;
|
---|
| 86 | boundingBox.maxPoint = iObjects [0]->bbox.maxPoint;
|
---|
| 87 | for (int i=1; i<nObjects; i++) {
|
---|
| 88 | // check accumulate operators of Vector class
|
---|
| 89 | boundingBox.minPoint <= iObjects [i]->bbox.minPoint;
|
---|
| 90 | boundingBox.maxPoint >= iObjects [i]->bbox.maxPoint;
|
---|
| 91 | }
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | /*! If the node referenced by oNode is on the last level of a cache-line sized sub-tree,
|
---|
| 95 | a pointer to a free node is placed, and the index of this free
|
---|
| 96 | node is returned. Else, originalNode is returned. */
|
---|
| 97 | inline unsigned int makePointer(unsigned int originalNode);
|
---|
| 98 |
|
---|
| 99 | public:
|
---|
| 100 | KDTree (Intersectable** objects, int nObjects);
|
---|
| 101 | ~KDTree () {
|
---|
| 102 | deleteLeaves(0);
|
---|
| 103 | delete traverseStack;
|
---|
| 104 | free(poolNodeTable);
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 107 | bool traverse (const Ray& ray, HitRec& hitRec, float minT, float maxT);
|
---|
| 108 | bool traverseBackSide (const Ray& ray, HitRec& hitRec, float minT, float maxT);
|
---|
| 109 | BoundingBox& getBoundingBox()
|
---|
| 110 | {
|
---|
| 111 | return boundingBox;
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | Intersectable* forbidden;
|
---|
| 115 | };
|
---|