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

Revision 1112, 12.2 KB checked in by bittner, 18 years ago (diff)

Merge with Olivers code

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