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;
00218 float _split;
00219 unsigned int _nPrims;
00220 };
00221 union
00222 {
00223 unsigned int _aboveChild;
00224 Primitive* _onePrimitive;
00225 Primitive** _primitives;
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