source: trunk/VUT/GtpVisibilityPreprocessor/src/KdTree.h @ 372

Revision 372, 11.0 KB checked in by bittner, 19 years ago (diff)

preparation for vss preprocessor. converted all .cpp and .h to dos new line format

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