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

Revision 1974, 13.8 KB checked in by bittner, 17 years ago (diff)

mutation updates, ray sorting, merge

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