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

Revision 1989, 14.0 KB checked in by bittner, 17 years ago (diff)

mutation updates

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