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

Revision 1201, 13.0 KB checked in by mattausch, 18 years ago (diff)

added loader for osp trees

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