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

Revision 311, 10.2 KB checked in by mattausch, 19 years ago (diff)

removed sampling prep bug

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