KDTree.h

Go to the documentation of this file.
00001 
00007 #ifndef KDTREE_H
00008 #define KDTREE_H KDTREE_H
00009 
00010 #include <vector>
00011 #include "Primitive.h"
00012 
00022 class KDTree
00023 {
00028     enum Axis
00029     {
00030         X_AXIS = 0,
00031         Y_AXIS = 1,
00032         Z_AXIS = 2,
00033         NO_AXIS = 3
00034     };
00035     
00044     struct BoundEdge
00045     {
00050         float t;
00051         
00056         int primNum;
00057         
00062         enum {START, END} type;
00063         
00068         BoundEdge() { }             
00069         
00077         BoundEdge(float tt, int pn, bool starting)
00078         {
00079             t = tt;
00080             primNum = pn;
00081             type = starting ? START : END;
00082         }
00083         
00091         bool operator<(const BoundEdge& e) const
00092         {
00093             if (t == e.t)
00094                 return (int)type < (int)e.type;
00095             else
00096                 return t < e.t;
00097         }
00098     };
00099     
00111     class KDNode
00112     {
00113         friend class KDTree;
00114         private:
00115         
00120             Axis _splitAxis;
00121             
00126             float _splitPlane;
00127             
00132             KDNode* _left;
00133 
00138             KDNode* _right;
00139             
00144             std::vector<Primitive*> _primitives;
00145             
00150             KDNode();
00151             
00156             ~KDNode();
00157             
00163             inline bool isLeafNode() const { return _splitAxis == NO_AXIS; }
00164             
00176             bool leafIntersect(Ray& ray, float min, float max);
00177                         
00188             inline void getNearFar(const Ray& r, KDNode*& near, KDNode*& far)
00189             {
00190                 if (_splitPlane >= r.org[_splitAxis])
00191                 {
00192                     near = _left;
00193                     far = _right;
00194                 }else
00195                 {
00196                     near = _right;
00197                     far = _left;
00198                 }
00199             }           
00200             
00206             inline float distanceToSplitPlane(const Ray& ray) const
00207             {
00208                  return (_splitPlane - ray.org[_splitAxis]) / ray.dir[_splitAxis];
00209             }
00210     };
00211     
00212     
00213     class KDNodeSmall 
00214     {
00215         union 
00216         {
00217             unsigned int _flags;    // Interior/Leaf
00218             float _split;   // Interior
00219             unsigned int _nPrims;   // Leaf
00220         };
00221         union 
00222         {
00223             unsigned int _aboveChild;           // Interior
00224             Primitive* _onePrimitive;   // leaf
00225             Primitive** _primitives;    // leaf
00226         };
00227         
00228         KDNodeSmall()
00229         {
00230         }
00231 
00232         ~KDNodeSmall()
00233         {
00234             if (_primitives != 0)
00235                 delete[] _primitives;
00236         }
00237         
00238         void initLeaf(int *primNums, int np, std::vector<Primitive*> primitives)
00239         {
00240             _nPrims = np << 2;
00241             _flags |= 3;
00242             
00243             if (np == 0)
00244             {
00245                 _onePrimitive = 0;
00246                 _primitives = 0;
00247             }
00248             else if (np == 1)
00249             {
00250                 _onePrimitive = primitives[primNums[0]];
00251                 _primitives = 0;
00252             }
00253             else 
00254             {   
00255                 _primitives = new Primitive*[np];
00256                 for (int i=0; i<np; ++i)
00257                 {
00258                     _primitives[i] = primitives[primNums[i]];
00259                 }
00260             }
00261         }
00262         
00263         void initInterior(Axis axis, float s)
00264         {
00265             _split = s;
00266             _flags &= ~3;
00267             _flags |= (int)axis;
00268         } 
00269         
00270         float splitPos() const { return _split; }
00271         int nPrimitives() const { return _nPrims >> 2; }
00272         Axis splitAxis() const { return Axis(_flags & 3); }
00273         bool isLeaf() const { return (_flags & 3) == 3; }
00274     };
00275     
00276     private:
00277 
00282         int _maxPrimitives;
00283         
00288         int _maxDepth;
00289         
00294         KDNode* _root;
00295         
00300         int _isectCost;
00301 
00306         int _traversalCost;
00307         
00312         float _emptyBonus;
00313 
00321         BoundEdge *_edges[3];
00322 
00332         bool Intersect(KDNode* node, Ray& ray, float min, float max);
00333 
00342         void BuildTree(KDNode* node, const Box& nodeBounds, int depth, int badRefines);
00343         
00353         void retrySplit(KDNode* node, Box nodeBounds, Axis& bestAxis, float& bestCost, int& bestOffset, int retries);
00354 
00355     public:
00356 
00361         Box _boundingBox;
00362         
00371         bool Intersect(Ray& ray);
00372         
00379         void BuildTree(const std::vector<Primitive*>& list, const Box& bbox);
00384         KDTree();
00385         
00390         ~KDTree();
00391 };
00392 
00393 #endif //KDTREE_H_
00394 

Generated on Thu Jan 31 21:48:48 2008 for RayTracer by  doxygen 1.5.4