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

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