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

Revision 191, 10.1 KB checked in by bittner, 19 years ago (diff)

basic sampling strategies

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