source: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.h @ 1089

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