source: trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h @ 245

Revision 245, 10.1 KB checked in by bittner, 19 years ago (diff)

Merged sources with ViewCellBsp?

Line 
1#ifndef _KdTree_H__
2#define _KdTree_H__
3
4#include <functional>
5using namespace std;
6
7#include "Containers.h"
8#include "AxisAlignedBox3.h"
9#include "Ray.h"
10#include "Pvs.h"
11
12 
13class KdNode;
14class KdLeaf;
15class KdInterior;
16class Intersectable;
17
18
19// --------------------------------------------------------------
20// Static statistics for kd-tree search
21// --------------------------------------------------------------
22class KdTreeStatistics
23{
24public: 
25  // total number of nodes
26  int nodes;
27  // number of splits along each of the axes
28  int splits[7];
29  // totals number of rays
30  int rays;
31  // total number of query domains
32  int queryDomains;
33  // total number of ray references
34  int rayRefs;
35  // refs in non empty leafs
36  int rayRefsNonZeroQuery;
37  // total number of query references
38  int objectRefs;
39  // nodes with zero queries
40  int zeroQueryNodes;
41  // max depth nodes
42  int maxDepthNodes;
43  // max depth nodes
44  int minCostNodes;
45  // max number of rays per node
46  int maxObjectRefs;
47  // number of dynamically added ray refs
48  int addedRayRefs;
49  // number of dynamically removed ray refs
50  int removedRayRefs;
51 
52  // Constructor
53  KdTreeStatistics() {
54    Reset();
55  }
56
57  int Nodes() const {return nodes;}
58  int Interior() const { return nodes/2; }
59  int Leaves() const { return (nodes/2) + 1; }
60
61  void Reset() {
62    nodes = 0;
63    for (int i=0; i<7; i++)
64      splits[i] = 0;
65    rays = queryDomains = 0;
66    rayRefs = rayRefsNonZeroQuery = objectRefs = 0;
67    zeroQueryNodes = 0;
68    maxDepthNodes = 0;
69    minCostNodes = 0;
70    maxObjectRefs = 0;
71    addedRayRefs = removedRayRefs = 0;
72  }
73
74  void
75  Print(ostream &app) const;
76
77  friend ostream &operator<<(ostream &s, const KdTreeStatistics &stat) {
78    stat.Print(s);
79    return s;
80  }
81 
82};
83
84 
85class KdInterior;
86/** Abstract class for kd-tree node */
87class KdNode {
88public:
89  static int mailID;
90  int mailbox;
91 
92  void Mail() { mailbox = mailID; }
93  static void NewMail() { mailID++; }
94  bool Mailed() const { return mailbox == mailID; }
95
96
97  KdNode(KdInterior *parent);
98
99  /** Determines whether this node is a leaf or interior node
100      @return true if leaf
101  */
102  virtual bool IsLeaf() const = 0;
103
104  /** Determines whether this node is the root of the tree
105      @return true if root
106  */
107  virtual bool IsRoot() const {
108    return mParent == NULL;
109  }
110
111  /** Parent of the node - the parent is a little overhead for maintanance of the tree,
112      but allows various optimizations of tree traversal algorithms */
113  KdInterior *mParent;
114  int mDepth;
115};
116
117/** Implementation of the kd-tree interior node */
118class KdInterior : public KdNode {
119
120public:
121   
122  KdInterior(KdInterior *parent):KdNode(parent), mBack(NULL), mFront(NULL) {}
123
124  /** \sa KdNode::IsLeaf() */
125  virtual bool IsLeaf() const { return false; }
126
127  /** splitting axis */
128  int mAxis;
129  /** splitting position, absolute position within the bounding box of this node */
130  float mPosition;
131  /** bounding box of interior node */
132  AxisAlignedBox3 mBox;
133
134  /** back node */
135  KdNode *mBack;
136  /** front node */
137  KdNode *mFront;
138
139  void SetupChildLinks(KdNode *b, KdNode *f) {
140    mBack = b;
141    mFront = f;
142    b->mParent = f->mParent = this;
143  }
144 
145  void ReplaceChildLink(KdNode *oldChild, KdNode *newChild) {
146    if (mBack == oldChild)
147      mBack = newChild;
148    else
149      mFront = newChild;
150  }
151 
152 
153};
154 
155 
156/** Implementation of the kd-tree leaf node */
157class KdLeaf : public KdNode {
158public:
159  KdLeaf(KdInterior *parent, const int objects):KdNode(parent) {
160    mObjects.reserve(objects);
161  }
162 
163  void AddPassingRay(const Ray &ray, const int contributions) {
164    mPassingRays.AddRay(ray, contributions);
165  }
166 
167  /** \sa KdNode::IsLeaf() */
168  virtual bool IsLeaf() const { return true; }
169 
170
171 
172
173  /** pointers to occluders contained in this node */
174  ObjectContainer mObjects;
175 
176  /** pointers to viewcells contained in this node */
177  //  ViewCellContainer mViewCells;
178
179  /** Ray set description of the rays passing through this node */
180  PassingRaySet mPassingRays;
181
182  /** PVS consisting of visible KdTree nodes */
183  KdPvs mKdPvs;
184 
185};
186 
187 
188
189/** KdTree for indexing scene entities - occluders/occludees/viewcells */
190class KdTree {
191
192protected:
193  struct TraversalData
194  { 
195    KdNode *mNode;
196    AxisAlignedBox3 mBox;
197    int mDepth;
198    float mPriority;
199   
200    TraversalData() {}
201
202    TraversalData(KdNode *n, const float p):
203      mNode(n), mPriority(p)
204    {}
205   
206    TraversalData(KdNode *n,
207                   const AxisAlignedBox3 &b,
208                   const int d):
209      mNode(n), mBox(b), mDepth(d) {}
210   
211
212    bool operator<(
213                   const TraversalData &b) const {
214      KdLeaf *leafa = (KdLeaf *) mNode;
215      KdLeaf *leafb = (KdLeaf *) b.mNode;
216      return
217        leafa->mObjects.size()*mBox.SurfaceArea()
218        <
219        leafb->mObjects.size()*b.mBox.SurfaceArea();
220    }
221
222
223    // comparator for the
224    struct less_priority : public
225    binary_function<const TraversalData, const TraversalData, bool> {
226     
227      bool operator()(const TraversalData a, const TraversalData b) {
228        return a.mPriority < b.mPriority;
229      }
230     
231    };
232
233  };
234
235 
236
237public:
238
239  enum {SPLIT_OBJECT_MEDIAN,
240        SPLIT_SPATIAL_MEDIAN,
241        SPLIT_SAH};
242 
243  KdTree();
244 
245   
246  /** Insert view cell into the tree */
247  virtual void InsertViewCell(ViewCell *viewCell) {
248    //      mRoot->mViewcells.push_back(viewCell);
249  }
250
251  virtual bool Construct();
252
253  /** Check whether subdivision criteria are met for the given subtree.
254      If not subdivide the leafs of the subtree. The criteria are specified in
255      the environment as well as the subdivision method. By default surface area
256      heuristics is used.
257       
258      @param subtree root of the subtree
259
260      @return true if subdivision was performed, false if subdivision criteria
261      were already met
262  */
263  virtual KdNode *Subdivide(const TraversalData &tdata);
264
265  /** Get the root of the tree */
266  KdNode *GetRoot() const {
267    return mRoot;
268  }
269
270
271  AxisAlignedBox3 GetBox() const { return mBox; }
272
273  int
274  CastRay(
275          Ray &ray
276          );
277
278  const KdTreeStatistics &GetStatistics() const {
279    return mStat;
280  }
281
282  void
283  CollectObjects(KdNode *n, ObjectContainer &objects);
284
285  void
286  CollectLeaves(vector<KdLeaf *> &leaves);
287
288  AxisAlignedBox3 GetBox(const KdNode *node) const {
289    KdInterior *parent = node->mParent;
290    if (parent == NULL)
291      return mBox;
292   
293    if (!node->IsLeaf())
294      return ((KdInterior *)node)->mBox;
295   
296    AxisAlignedBox3 box(parent->mBox);
297    if (parent->mFront == node)
298      box.SetMin(parent->mAxis, parent->mPosition);
299    else
300      box.SetMax(parent->mAxis, parent->mPosition);
301    return box;
302  }
303
304  KdNode *
305  FindRandomNeighbor(KdNode *n,
306                     bool onlyUnmailed
307                     );
308
309 
310  KdNode *
311  KdTree::GetRandomLeaf(const Plane3 &halfspace);
312 
313  int
314  FindNeighbors(KdNode *n,
315                vector<KdNode *> &neighbors,
316                bool onlyUnmailed
317                );
318
319  int
320  CollectLeafPvs();
321
322protected:
323
324  struct RayData {
325    // pointer to the actual ray
326    Ray *ray;
327   
328    // endpoints  - do we need them?
329#if USE_FIXEDPOINT_T
330    short tmin, tmax;
331#else
332    float tmin, tmax;
333#endif
334
335    RayData():ray(NULL) {}
336    RayData(Ray *r):ray(r), tmin(0),
337
338#if USE_FIXEDPOINT_T
339#define FIXEDPOINT_ONE 0x7FFE
340                          //                      tmax(0xFFFF)
341                          tmax(FIXEDPOINT_ONE)
342#else
343      tmax(1.0f)
344#endif
345    {}
346
347    RayData(Ray *r,
348            const float _min,
349            const float _max
350            ):ray(r) {
351      SetTMin(_min);
352      SetTMax(_max);
353    }
354
355    RayData(Ray *r,
356            const short _min,
357            const float _max
358            ):ray(r), tmin(_min) {
359      SetTMax(_max);
360    }
361
362    RayData(Ray *r,
363            const float _min,
364            const short _max
365            ):ray(r), tmax(_max) {
366      SetTMin(_min);
367    }
368
369    friend bool operator<(const RayData &a, const RayData &b) {
370      return a.ray < b.ray;
371    }
372   
373   
374    float ExtrapOrigin(const int axis) const {
375      return ray->GetLoc(axis) + GetTMin()*ray->GetDir(axis);
376    }
377   
378    float ExtrapTermination(const int axis) const {
379      return ray->GetLoc(axis) + GetTMax()*ray->GetDir(axis);
380    }
381   
382#if USE_FIXEDPOINT_T
383    float GetTMin () const { return tmin/(float)(FIXEDPOINT_ONE); }
384    float GetTMax () const { return tmax/(float)(FIXEDPOINT_ONE); }
385
386    void SetTMin (const float t) {
387      tmin = (short) (t*(float)(FIXEDPOINT_ONE));
388    }
389   
390    void SetTMax (const float t) {
391      tmax = (short) (t*(float)(FIXEDPOINT_ONE));
392      tmax++;
393      //      if (tmax!=0xFFFF)
394      //        tmax++;
395    }
396#else
397    float GetTMin () const { return tmin; }
398    float GetTMax () const { return tmax; }
399
400    void SetTMin (const float t) { tmin = t; }
401    void SetTMax (const float t) { tmax = t; }
402#endif
403  };
404
405  struct RayTraversalData {
406    KdNode *mNode;
407    Vector3 mExitPoint;
408    float mMaxT;
409   
410    RayTraversalData() {}
411    RayTraversalData(KdNode *n,
412                     const Vector3 &p,
413                     const float maxt):
414      mNode(n), mExitPoint(p), mMaxT(maxt) {}
415  };
416
417  // --------------------------------------------------------------
418  // For sorting objects
419  // --------------------------------------------------------------
420  struct  SortableEntry
421  {
422    enum {
423      BOX_MIN,
424      BOX_MAX
425    };
426   
427    int type;
428    float value;
429    Intersectable *intersectable;
430   
431    SortableEntry() {}
432    SortableEntry(const int t, const float v, Intersectable *i):type(t),
433                                                                value(v),
434                                                                intersectable(i) {}
435   
436    bool operator<(const SortableEntry &b) const {
437      return value < b.value;
438    }
439   
440  };
441 
442  // reusable array of split candidates
443  vector<SortableEntry> *splitCandidates;
444
445  float
446  BestCostRatio(
447                KdLeaf *node,
448                const AxisAlignedBox3 &box,
449                const int axis,
450                float &position,
451                int &objectsBack,
452                int &objectsFront
453                );
454
455  void
456  SortSplitCandidates(
457                      KdLeaf *node,
458                      const int axis
459                      );
460
461  void
462  EvaluateLeafStats(const TraversalData &data);
463
464  KdNode *
465  SubdivideNode(
466                KdLeaf *leaf,
467                const AxisAlignedBox3 &box,
468                AxisAlignedBox3 &backBBox,
469                AxisAlignedBox3 &frontBBox
470                );
471
472  bool
473  TerminationCriteriaMet(const KdLeaf *leaf);
474 
475  int
476  SelectPlane(KdLeaf *leaf,
477              const AxisAlignedBox3 &box,
478              float &position
479              );
480
481
482
483  float mSplitBorder;
484  int mTermMaxDepth;
485  int mTermMinCost;
486  float mMaxCostRatio;
487  float mCt_div_ci;
488  int mSplitMethod;
489  bool mSahUseFaces;
490  /// root of the tree
491  KdNode *mRoot;
492  /// bounding box of the tree root
493  AxisAlignedBox3 mBox;
494  KdTreeStatistics mStat;
495 
496};
497 
498
499
500
501
502
503#endif
Note: See TracBrowser for help on using the repository browser.