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

Revision 1144, 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  /** Ray set description of the rays passing through this node */
198  PassingRaySet mPassingRays;
199       
200  /** PVS consisting of visible KdTree nodes */
201  KdPvs mKdPvs;
202
203  /// pvs of view cells seeing this node.
204  SplitCandidate *mSplitCandidate;
205
206  /// pointer to view cell.
207  KdViewCell *mViewCell;
208
209   /// Objects that are referenced in more than one leaf.
210  ObjectContainer mMultipleObjects;
211
212  /// universal counter
213  int mCounter;
214};
215
216 
217
218/** KdTree for indexing scene entities - occluders/occludees/viewcells */
219class KdTree {
220 
221protected:
222  struct TraversalData
223  { 
224    KdNode *mNode;
225    AxisAlignedBox3 mBox;
226    int mDepth;
227    float mPriority;
228   
229    TraversalData() {}
230
231    TraversalData(KdNode *n, const float p):
232      mNode(n), mPriority(p)
233    {}
234   
235    TraversalData(KdNode *n,
236                   const AxisAlignedBox3 &b,
237                   const int d):
238      mNode(n), mBox(b), mDepth(d) {}
239   
240
241    bool operator<(
242                                   const TraversalData &b) const {
243      KdLeaf *leafa = (KdLeaf *) mNode;
244      KdLeaf *leafb = (KdLeaf *) b.mNode;
245      return
246                leafa->mObjects.size()*mBox.SurfaceArea()
247                <
248                leafb->mObjects.size()*b.mBox.SurfaceArea();
249    }
250
251
252    // comparator for the
253    struct less_priority : public
254    binary_function<const TraversalData, const TraversalData, bool> {
255     
256      bool operator()(const TraversalData a, const TraversalData b) {
257                                return a.mPriority < b.mPriority;
258      }
259     
260    };
261
262  };
263
264 
265
266public:
267
268  enum {SPLIT_OBJECT_MEDIAN,
269        SPLIT_SPATIAL_MEDIAN,
270        SPLIT_SAH};
271 
272  KdTree();
273
274  ~KdTree();
275   
276  /** Insert view cell into the tree */
277  virtual void InsertViewCell(ViewCell *viewCell) {
278    //      mRoot->mViewcells.push_back(viewCell);
279  }
280
281  virtual bool Construct();
282
283  /** Check whether subdivision criteria are met for the given subtree.
284      If not subdivide the leafs of the subtree. The criteria are specified in
285      the environment as well as the subdivision method. By default surface area
286      heuristics is used.
287       
288      @param subtree root of the subtree
289
290      @return true if subdivision was performed, false if subdivision criteria
291      were already met
292  */
293  virtual KdNode *Subdivide(const TraversalData &tdata);
294
295  /** Get the root of the tree */
296  KdNode *GetRoot() const {
297    return mRoot;
298  }
299
300
301  AxisAlignedBox3 GetBox() const { return mBox; }
302
303  int
304  CastRay(
305                  Ray &ray
306                  );
307 
308
309  int
310  CastBeam(
311                   Beam &beam
312                   );
313 
314 
315  /** Casts line segment into tree.
316          @returns intersected view cells.
317  */
318  int CastLineSegment(const Vector3 &origin,
319                                          const Vector3 &termination,
320                                          vector<ViewCell *> &viewcells);
321
322
323  const KdTreeStatistics &GetStatistics() const {
324    return mStat;
325  }
326
327  void
328  CollectObjects(KdNode *n, ObjectContainer &objects);
329
330  void
331  CollectObjects(const AxisAlignedBox3 &box,
332                                 ObjectContainer &objects);
333
334  void
335  CollectLeaves(vector<KdLeaf *> &leaves);
336       
337  /** If the kd tree is used as view cell container, this
338          methods creates the view cells.
339          @returns the newly created view cells in a view cell container
340  */
341  void
342  CreateAndCollectViewCells(ViewCellContainer &viewCells) const;
343
344  AxisAlignedBox3 GetBox(const KdNode *node) const {
345    KdInterior *parent = node->mParent;
346    if (parent == NULL)
347      return mBox;
348   
349    if (!node->IsLeaf())
350      return ((KdInterior *)node)->mBox;
351   
352    AxisAlignedBox3 box(parent->mBox);
353    if (parent->mFront == node)
354      box.SetMin(parent->mAxis, parent->mPosition);
355    else
356      box.SetMax(parent->mAxis, parent->mPosition);
357    return box;
358  }
359       
360  KdNode *
361  FindRandomNeighbor(KdNode *n,
362                                         bool onlyUnmailed
363                                         );
364 
365  KdNode *
366  KdTree::GetRandomLeaf(const Plane3 &halfspace);
367
368  KdNode *
369  GetRandomLeaf(const bool onlyUnmailed = false);
370 
371  int
372  FindNeighbors(KdNode *n,
373                                vector<KdNode *> &neighbors,
374                                bool onlyUnmailed
375                                );
376
377  int
378  CollectLeafPvs();
379
380protected:
381
382  struct RayData {
383    // pointer to the actual ray
384    Ray *ray;
385   
386    // endpoints  - do we need them?
387#if USE_FIXEDPOINT_T
388    short tmin, tmax;
389#else
390    float tmin, tmax;
391#endif
392
393    RayData():ray(NULL) {}
394    RayData(Ray *r):ray(r), tmin(0),
395
396#if USE_FIXEDPOINT_T
397#define FIXEDPOINT_ONE 0x7FFE
398                          //                      tmax(0xFFFF)
399                          tmax(FIXEDPOINT_ONE)
400#else
401      tmax(1.0f)
402#endif
403    {}
404
405    RayData(Ray *r,
406            const float _min,
407            const float _max
408            ):ray(r) {
409      SetTMin(_min);
410      SetTMax(_max);
411    }
412
413    RayData(Ray *r,
414            const short _min,
415            const float _max
416            ):ray(r), tmin(_min) {
417      SetTMax(_max);
418    }
419
420    RayData(Ray *r,
421            const float _min,
422            const short _max
423            ):ray(r), tmax(_max) {
424      SetTMin(_min);
425    }
426
427    friend bool operator<(const RayData &a, const RayData &b) {
428      return a.ray < b.ray;
429    }
430   
431   
432    float ExtrapOrigin(const int axis) const {
433      return ray->GetLoc(axis) + GetTMin()*ray->GetDir(axis);
434    }
435   
436    float ExtrapTermination(const int axis) const {
437      return ray->GetLoc(axis) + GetTMax()*ray->GetDir(axis);
438    }
439   
440#if USE_FIXEDPOINT_T
441    float GetTMin () const { return tmin/(float)(FIXEDPOINT_ONE); }
442    float GetTMax () const { return tmax/(float)(FIXEDPOINT_ONE); }
443
444    void SetTMin (const float t) {
445      tmin = (short) (t*(float)(FIXEDPOINT_ONE));
446    }
447   
448    void SetTMax (const float t) {
449      tmax = (short) (t*(float)(FIXEDPOINT_ONE));
450      tmax++;
451      //      if (tmax!=0xFFFF)
452      //        tmax++;
453    }
454#else
455    float GetTMin () const { return tmin; }
456    float GetTMax () const { return tmax; }
457
458    void SetTMin (const float t) { tmin = t; }
459    void SetTMax (const float t) { tmax = t; }
460#endif
461  };
462
463  struct RayTraversalData {
464    KdNode *mNode;
465    Vector3 mExitPoint;
466    float mMaxT;
467   
468    RayTraversalData() {}
469    RayTraversalData(KdNode *n,
470                     const Vector3 &p,
471                     const float maxt):
472      mNode(n), mExitPoint(p), mMaxT(maxt) {}
473  };
474
475  // --------------------------------------------------------------
476  // For sorting objects
477  // --------------------------------------------------------------
478  struct  SortableEntry
479  {
480    enum {
481      BOX_MIN,
482      BOX_MAX
483    };
484   
485    int type;
486    float value;
487    Intersectable *intersectable;
488   
489    SortableEntry() {}
490    SortableEntry(const int t, const float v, Intersectable *i):type(t),
491                                                                value(v),
492                                                                intersectable(i) {}
493   
494    bool operator<(const SortableEntry &b) const {
495      return value < b.value;
496    }
497   
498  };
499 
500  // reusable array of split candidates
501  vector<SortableEntry> *splitCandidates;
502
503  float
504  BestCostRatio(
505                KdLeaf *node,
506                const AxisAlignedBox3 &box,
507                const int axis,
508                float &position,
509                int &objectsBack,
510                int &objectsFront
511                );
512
513  void
514  SortSplitCandidates(
515                      KdLeaf *node,
516                      const int axis
517                      );
518
519  void
520  EvaluateLeafStats(const TraversalData &data);
521
522  KdNode *
523  SubdivideNode(
524                KdLeaf *leaf,
525                const AxisAlignedBox3 &box,
526                AxisAlignedBox3 &backBBox,
527                AxisAlignedBox3 &frontBBox
528                );
529
530  bool
531  TerminationCriteriaMet(const KdLeaf *leaf);
532 
533  int
534  SelectPlane(KdLeaf *leaf,
535              const AxisAlignedBox3 &box,
536              float &position
537              );
538
539        /** does some post processing on the objects in the new child leaves.
540        */
541        void ProcessMultipleRefs(KdLeaf *leaf) const;
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.