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

Revision 1002, 11.7 KB checked in by mattausch, 18 years ago (diff)

debug run: fixing memory holes

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