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

Revision 1633, 13.7 KB checked in by mattausch, 18 years ago (diff)

worked on gradient method for vsposp

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