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

Revision 1109, 12.1 KB checked in by mattausch, 19 years ago (diff)

erronous version using kd viewcell pvss

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