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

Revision 469, 11.4 KB checked in by mattausch, 19 years ago (diff)

updated view cells, view cell manager. changed rendersimulator

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