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

Revision 2691, 15.6 KB checked in by mattausch, 16 years ago (diff)

fixed several errors

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