source: trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h @ 408

Revision 408, 17.3 KB checked in by mattausch, 19 years ago (diff)
Line 
1// ================================================================
2// $Id$
3// ****************************************************************
4//
5// Initial coding by
6/**
7   @author Jiri Bittner
8*/
9
10#ifndef __VSPKDTREE_H__
11#define __VSPKDTREE_H__
12
13// Standard headers
14#include <iomanip>
15#include <vector>
16#include <functional>
17#include <stack>
18
19
20// User headers
21#include "VssRay.h"
22#include "AxisAlignedBox3.h"
23
24
25#define USE_KDNODE_VECTORS 1
26#define _RSS_STATISTICS
27#define _RSS_TRAVERSAL_STATISTICS
28
29
30#include "Statistics.h"
31#include "Ray.h"
32
33// --------------------------------------------------------------
34// Static statistics for kd-tree search
35// --------------------------------------------------------------
36class VspKdStatistics:  public StatisticsBase
37{
38public: 
39  // total number of nodes
40  int nodes;
41  // number of splits along each of the axes
42  int splits[7];
43  // totals number of rays
44  int rays;
45        // initial size of the pvs
46  int initialPvsSize;
47        // total number of query domains
48  int queryDomains;
49  // total number of ray references
50  int rayRefs;
51
52        // max depth nodes
53  int maxDepthNodes;
54  // max depth nodes
55  int minPvsNodes;
56  int minRaysNodes;
57        // max ray contribution nodes
58  int maxRayContribNodes;
59        // max depth nodes
60  int minSizeNodes;
61       
62  // max number of rays per node
63  int maxRayRefs;
64  // number of dynamically added ray refs
65  int addedRayRefs;
66  // number of dynamically removed ray refs
67  int removedRayRefs;
68 
69  // Constructor
70  VspKdStatistics() {
71    Reset();
72  }
73
74  int Nodes() const {return nodes;}
75  int Interior() const { return nodes/2; }
76  int Leaves() const { return (nodes/2) + 1; }
77
78  void Reset() {
79    nodes = 0;
80    for (int i=0; i<7; i++)
81      splits[i] = 0;
82    rays = queryDomains = 0;
83    rayRefs = 0;
84    maxDepthNodes = 0;
85    minPvsNodes = 0;
86    minRaysNodes = 0;
87    maxRayRefs = 0;
88    addedRayRefs = removedRayRefs = 0;
89                initialPvsSize = 0;
90                maxRayContribNodes = 0;
91                minSizeNodes = 0;
92  }
93
94 
95  void
96  Print(ostream &app) const;
97
98  friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) {
99    stat.Print(s);
100    return s;
101  }
102 
103};
104
105
106// --------------------------------------------------------------
107// For sorting rays
108// --------------------------------------------------------------
109struct  SortableEntry
110{
111  enum EType {
112    ERayMin,
113    ERayMax
114  };
115
116  int type;
117  float value;
118  void *data;
119 
120  SortableEntry() {}
121  SortableEntry(const int t, const float v, void *d):type(t),
122                                                                                                                                                                                                                 value(v),
123                                                                                                                                                                                                                 data(d) {}
124       
125  friend bool operator<(const SortableEntry &a, const SortableEntry &b) {
126    return a.value < b.value;
127  }
128};
129
130
131class VspKdTreeInterior;
132
133
134// --------------------------------------------------------------
135// KD-tree node - abstract class
136// --------------------------------------------------------------
137class VspKdTreeNode
138{
139public:
140
141#define USE_FIXEDPOINT_T 1
142
143struct RayInfo
144{
145        // pointer to the actual ray
146        VssRay *mRay;
147       
148        // endpoints  - do we need them?
149#if USE_FIXEDPOINT_T
150        short mMinT, mMaxT;
151#else
152        float mMinT, mMaxT;
153#endif
154       
155        RayInfo():mRay(NULL) {}
156       
157        RayInfo(VssRay *r):mRay(r), mMinT(0),
158#if USE_FIXEDPOINT_T
159#define FIXEDPOINT_ONE 0x7FFE
160                                                                                                //                        mMaxT(0xFFFF)
161                                                                                                                                                        mMaxT(FIXEDPOINT_ONE)
162#else
163                mMaxT(1.0f)
164#endif
165        {}
166       
167        RayInfo(VssRay *r,
168                                                                                const float _min,
169                                                                                const float _max
170                                                                                ):mRay(r) {
171                SetMinT(_min);
172                SetMaxT(_max);
173        }
174       
175        RayInfo(VssRay *r,
176                                                                                const short _min,
177                                                                                const float _max
178                                                                                ):mRay(r), mMinT(_min) {
179                SetMaxT(_max);
180        }
181       
182        RayInfo(VssRay *r,
183                                                                                const float _min,
184                                                                                const short _max
185                                                                                ):mRay(r), mMaxT(_max) {
186                SetMinT(_min);
187        }
188       
189        friend bool operator<(const RayInfo &a, const RayInfo &b) {
190                return a.mRay < b.mRay;
191        }
192 
193       
194        float ExtrapOrigin(const int axis) const {
195                return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
196        }
197       
198        float ExtrapTermination(const int axis) const {
199                return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
200        }
201       
202#if USE_FIXEDPOINT_T
203        float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); }
204        float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); }
205       
206        void SetMinT (const float t) {
207                mMinT = (short) (t*(float)(FIXEDPOINT_ONE));
208        }
209       
210        void SetMaxT (const float t) {
211                mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
212                mMaxT++;
213                //      if (mMaxT!=0xFFFF)
214                //      mMaxT++;
215        }
216#else
217        float GetMinT () const { return mMinT; }
218        float GetMaxT () const { return mMaxT; }
219       
220        void SetMinT (const float t) { mMinT = t; }
221        void SetMaxT (const float t) { mMaxT = t; }
222#endif
223
224
225  int ComputeRayIntersection(const float axis,
226                                                                                                                 const float position,
227                                                                                                                 float &t
228                                                                                                                 ) const {
229               
230                // intersect the ray with the plane
231    float denom = mRay->GetDir(axis);
232   
233    if (fabs(denom) < 1e-20)
234      //if (denom == 0.0f)
235      return (mRay->GetOrigin(axis) > position) ? 1 : -1;
236   
237    t = (position - mRay->GetOrigin(axis))/denom;
238
239    if (t < GetMinT())
240      return (denom > 0) ? 1 : -1;
241
242    if (t > GetMaxT())
243      return (denom > 0) ? -1 : 1;
244
245                return 0;
246        }
247
248
249};
250
251
252        typedef vector<RayInfo> RayInfoContainer;
253       
254  enum { EInterior, ELeaf };
255
256  /////////////////////////////////
257  // The actual data goes here
258 
259  // link to the parent
260  VspKdTreeInterior *parent;
261
262  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
263 
264  // splitting axis
265  char axis;
266       
267  // depth
268  unsigned char depth;
269 
270  //  short depth;
271  //
272  /////////////////////////////////
273 
274  inline VspKdTreeNode(VspKdTreeInterior *p);
275
276 
277  virtual ~VspKdTreeNode() {};
278  virtual int Type() const  = 0;
279 
280
281  bool IsLeaf() const { return axis == -1; }
282 
283  virtual void Print(ostream &s) const = 0;
284
285  virtual int GetAccessTime() {
286    return 0x7FFFFFF;
287  }
288
289 
290       
291};
292
293// --------------------------------------------------------------
294// KD-tree node - interior node
295// --------------------------------------------------------------
296class VspKdTreeInterior :
297  public VspKdTreeNode
298{
299public:
300  // plane in local modelling coordinates
301  float position;
302
303  // pointers to children
304  VspKdTreeNode *back, *front;
305
306  // the bbox of the node
307  AxisAlignedBox3 bbox;
308
309  // the bbox of the node
310  AxisAlignedBox3 dirBBox;
311 
312  // data for caching
313  long accesses;
314  long lastAccessTime;
315 
316  VspKdTreeInterior(VspKdTreeInterior *p):VspKdTreeNode(p),
317                                        back(NULL),
318                                        front(NULL),
319                                        accesses(0),
320                                        lastAccessTime(-1)
321  { }
322
323  virtual int GetAccessTime() {
324    return lastAccessTime;
325  }
326
327  void SetupChildLinks(VspKdTreeNode *b, VspKdTreeNode *f) {
328    back = b;
329    front = f;
330    b->parent = f->parent = this;
331  }
332
333  void ReplaceChildLink(VspKdTreeNode *oldChild, VspKdTreeNode *newChild) {
334    if (back == oldChild)
335      back = newChild;
336    else
337      front = newChild;
338  }
339
340  virtual int Type() const  { return EInterior; }
341 
342  virtual ~VspKdTreeInterior() {
343    if (back)
344      delete back;
345    if (front)
346      delete front;
347  }
348 
349  virtual void Print(ostream &s) const {
350    if (axis == 0)
351      s<<"x ";
352    else
353      if (axis == 1)
354        s<<"y ";
355      else
356        s<<"z ";
357    s<<position<<" ";
358    back->Print(s);
359    front->Print(s);
360  }
361
362 
363       
364  int ComputeRayIntersection(const RayInfo &rayData,
365                                                                                                                 float &t
366                                                                                                                 ) {
367                return rayData.ComputeRayIntersection(axis, position, t);
368  }
369
370};
371
372
373// --------------------------------------------------------------
374// KD-tree node - leaf node
375// --------------------------------------------------------------
376class VspKdTreeLeaf :
377  public VspKdTreeNode
378{
379private:
380        int mPvsSize;
381public:
382  static int mailID;
383  int mailbox;
384 
385  RayInfoContainer rays;
386        bool mValidPvs;
387       
388  VspKdTreeLeaf(VspKdTreeInterior *p,
389                                                        const int nRays
390                                                        ):VspKdTreeNode(p), rays(), mPvsSize(0), mValidPvs(false) {
391    rays.reserve(nRays);
392  }
393 
394  virtual ~VspKdTreeLeaf() { }
395
396  virtual int Type() const  { return ELeaf; }
397
398  virtual void Print(ostream &s) const {
399    s<<endl<<"L: r="<<rays.size()<<endl;
400  };
401 
402  void AddRay(const RayInfo &data) {
403                mValidPvs = false;
404    rays.push_back(data);
405    data.mRay->Ref();
406  }
407       
408        int GetPvsSize() const {
409                return mPvsSize;
410        }
411        void SetPvsSize(const int s) {
412                mPvsSize = s;
413        }
414
415        void
416        UpdatePvsSize();
417
418  void Mail() { mailbox = mailID; }
419  static void NewMail() { mailID++; }
420  bool Mailed() const { return mailbox == mailID; }
421 
422  bool Mailed(const int mail) {
423    return mailbox >= mailID + mail;
424  }
425
426        float GetAvgRayContribution() const {
427                return GetPvsSize()/((float)rays.size() + Limits::Small);
428        }
429
430        float GetSqrRayContribution() const {
431                return sqr(GetPvsSize()/((float)rays.size() + Limits::Small));
432        }
433
434};
435
436// Inline functions
437inline
438VspKdTreeNode::VspKdTreeNode(VspKdTreeInterior *p):
439  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {}
440
441
442
443// ---------------------------------------------------------------
444// Main LSDS search class
445// ---------------------------------------------------------------
446class VspKdTree
447{
448  struct TraversalData
449  { 
450    VspKdTreeNode *node;
451    AxisAlignedBox3 bbox;
452    int depth;
453    float priority;
454   
455    TraversalData() {}
456
457    TraversalData(VspKdTreeNode *n, const float p):
458      node(n), priority(p)
459    {}
460
461    TraversalData(VspKdTreeNode *n,
462                   const AxisAlignedBox3 &b,
463                   const int d):
464      node(n), bbox(b), depth(d) {}
465   
466               
467    // comparator for the
468    struct less_priority : public
469    binary_function<const TraversalData, const TraversalData, bool> {
470                       
471      bool operator()(const TraversalData a, const TraversalData b) {
472                                return a.priority < b.priority;
473      }
474     
475    };
476
477    //    ~TraversalData() {}
478    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
479   
480    friend bool operator<(const TraversalData &a,
481                                                                                                        const TraversalData &b) {
482      //      return a.node->queries.size() < b.node->queries.size();
483      VspKdTreeLeaf *leafa = (VspKdTreeLeaf *) a.node;
484      VspKdTreeLeaf *leafb = (VspKdTreeLeaf *) b.node;
485#if 0
486                        return
487                                leafa->rays.size()*a.bbox.GetVolume()
488                                <
489                                leafb->rays.size()*b.bbox.GetVolume();
490#endif
491#if 1
492                        return
493                                leafa->GetPvsSize()*a.bbox.GetVolume()
494                                <
495                                leafb->GetPvsSize()*b.bbox.GetVolume();
496#endif
497#if 0
498                        return
499                                leafa->GetPvsSize()
500                                <
501                                leafb->GetPvsSize();
502#endif
503#if 0
504                        return
505                                leafa->GetPvsSize()/(leafa->rays.size()+1)
506                                >
507                                leafb->GetPvsSize()/(leafb->rays.size()+1);
508#endif
509#if 0
510                        return
511                                leafa->GetPvsSize()*leafa->rays.size()
512                                <
513                                leafb->GetPvsSize()*leafb->rays.size();
514#endif
515    }
516  };
517 
518  // simplified data for ray traversal only...
519
520  struct RayTraversalData {
521   
522    VspKdTreeNode::RayInfo rayData;
523    VspKdTreeNode *node;
524   
525    RayTraversalData() {}
526    RayTraversalData(VspKdTreeNode *n,
527                                                                                 const VspKdTreeNode::RayInfo &data):
528      rayData(data), node(n) {}
529  };
530       
531public:
532  /////////////////////////////
533  // The core pointer
534  VspKdTreeNode *root;
535 
536  /////////////////////////////
537  // Basic properties
538
539  // total number of nodes of the tree
540  int nodes;
541  // axis aligned bounding box of the scene
542  AxisAlignedBox3 bbox;
543
544  // axis aligned bounding box of directions
545  AxisAlignedBox3 dirBBox;
546 
547  /////////////////////////////
548  // Construction parameters
549
550  // epsilon used for the construction
551  float epsilon;
552
553  // ratio between traversal and intersection costs
554  float ct_div_ci;
555  // max depth of the tree
556  int termMaxDepth;
557  // minimal ratio of the volume of the cell and the query volume
558  float termMinSize;
559
560        // minimal pvs per node to still get subdivided
561  int termMinPvs;
562
563        // minimal ray number per node to still get subdivided
564  int termMinRays;
565       
566  // maximal cost ration to subdivide a node
567  float termMaxCostRatio;
568       
569        // maximal contribution per ray to subdivide the node
570        float termMaxRayContribution;
571
572       
573  // randomized construction
574  bool randomize;
575
576  // type of the splitting to use fo rthe tree construction
577  enum {ESplitRegular, ESplitHeuristic };
578  int splitType;
579       
580  // maximal size of the box on which the refdir splitting can be performed
581  // (relative to the scene bbox
582  float refDirBoxMaxSize;
583 
584  // maximum alovable memory in MB
585  float maxTotalMemory;
586
587  // maximum alovable memory for static kd tree in MB
588  float maxStaticMemory;
589
590  // this is used during the construction depending
591  // on the type of the tree and queries...
592  float maxMemory;
593
594
595  // minimal acess time for collapse
596  int accessTimeThreshold;
597
598        // minimal depth at which to perform collapse
599  int minCollapseDepth;
600
601 
602  // reusable array of split candidates
603  vector<SortableEntry> *splitCandidates;
604  /////////////////////////////
605
606  VspKdStatistics stat;
607       
608 
609  VspKdTree();
610  virtual ~VspKdTree();
611
612  virtual void
613  Construct(
614                                                VssRayContainer &rays,
615                                                AxisAlignedBox3 *forcedBoundingBox = NULL
616                                                );
617       
618  // incemental construction
619  virtual void UpdateRays(VssRayContainer &remove,
620                                                                                                        VssRayContainer &add
621                                                                                                        );
622
623        virtual void AddRays(
624                                                                                         VssRayContainer &add
625                                                                                         )
626        {
627                VssRayContainer remove;
628                UpdateRays(remove, add);
629        }
630
631 
632       
633  VspKdTreeNode *
634  Locate(const Vector3 &v);
635       
636  VspKdTreeNode *
637  SubdivideNode(VspKdTreeLeaf *leaf,
638                                                                const AxisAlignedBox3 &box,
639                                                                AxisAlignedBox3 &backBox,
640                                                                AxisAlignedBox3 &frontBox
641                                                                );
642       
643  VspKdTreeNode *
644  Subdivide(const TraversalData &tdata);
645       
646  int
647  SelectPlane(VspKdTreeLeaf *leaf,
648                                                        const AxisAlignedBox3 &box,
649                                                        float &position,
650                                                        int &raysBack,
651                                                        int &raysFront,
652                                                        int &pvsBack,
653                                                        int &pvsFront
654                                                        );
655
656  void
657  SortSplitCandidates(
658                                                                                        VspKdTreeLeaf *node,
659                                                                                        const int axis
660                                                                                        );
661       
662 
663  // return memory usage in MB
664  float GetMemUsage() const {
665    return
666      (sizeof(VspKdTree) +
667       stat.Leaves()*sizeof(VspKdTreeLeaf) +
668       stat.Interior()*sizeof(VspKdTreeInterior) +
669       stat.rayRefs*sizeof(VspKdTreeNode::RayInfo))/(1024.0f*1024.0f);
670  }
671       
672  float GetRayMemUsage() const {
673    return
674      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
675  }
676 
677        float
678        BestCostRatioHeuristic(
679                                                                                                 VspKdTreeLeaf *node,
680                                                                                                 int &axis,
681                                                                                                 float &position,
682                                                                                                 int &raysBack,
683                                                                                                 int &raysFront,
684                                                                                                 int &pvsBack,
685                                                                                                 int &pvsFront
686                                                                                                 );
687
688        float
689        BestCostRatioRegular(
690                                                                                         VspKdTreeLeaf *node,
691                                                                                         int &axis,
692                                                                                         float &position,
693                                                                                         int &raysBack,
694                                                                                         int &raysFront,
695                                                                                         int &pvsBack,
696                                                                                         int &pvsFront
697
698                                                                                         );
699       
700        float
701        EvalCostRatio(
702                                                                VspKdTreeLeaf *node,
703                                                                const int axis,
704                                                                const float position,
705                                                                int &raysBack,
706                                                                int &raysFront,
707                                                                int &pvsBack,
708                                                                int &pvsFront
709                                                                );
710
711  AxisAlignedBox3 GetBBox(const VspKdTreeNode *node) {
712    if (node->parent == NULL)
713      return bbox;
714
715    if (!node->IsLeaf())
716      return ((VspKdTreeInterior *)node)->bbox;
717
718    if (node->parent->axis >= 3)
719      return node->parent->bbox;
720     
721    AxisAlignedBox3 box(node->parent->bbox);
722    if (node->parent->front == node)
723      box.SetMin(node->parent->axis, node->parent->position);
724    else
725      box.SetMax(node->parent->axis, node->parent->position);
726    return box;
727  }
728
729  AxisAlignedBox3 GetDirBBox(const VspKdTreeNode *node) {
730
731    if (node->parent == NULL)
732      return dirBBox;
733   
734    if (!node->IsLeaf() )
735      return ((VspKdTreeInterior *)node)->dirBBox;
736
737    if (node->parent->axis < 3)
738      return node->parent->dirBBox;
739   
740    AxisAlignedBox3 dBBox(node->parent->dirBBox);
741
742    if (node->parent->front == node)
743      dBBox.SetMin(node->parent->axis - 3, node->parent->position);
744    else
745      dBBox.SetMax(node->parent->axis - 3, node->parent->position);
746    return dBBox;
747  }
748 
749  int
750  ReleaseMemory(const int time);
751
752  int
753  CollapseSubtree(VspKdTreeNode *node, const int time);
754
755  void
756  CountAccess(VspKdTreeInterior *node, const long time) {
757    node->accesses++;
758    node->lastAccessTime = time;
759  }
760
761  VspKdTreeNode *
762  SubdivideLeaf(
763                                                                VspKdTreeLeaf *leaf,
764                                                                const float SAThreshold
765                                                                );
766
767  void
768  RemoveRay(VssRay *ray,
769                                                vector<VspKdTreeLeaf *> *affectedLeaves,
770                                                const bool removeAllScheduledRays
771                                                );
772
773  void
774  AddRay(VssRay *ray);
775       
776  void
777  TraverseInternalNode(
778                                                                                         RayTraversalData &data,
779                                                                                         stack<RayTraversalData> &tstack);
780
781        void
782  EvaluateLeafStats(const TraversalData &data);
783
784
785        int
786        GetRootPvsSize() const {
787                return GetPvsSize(root, bbox);
788        }
789       
790        int
791        GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const;
792
793        void
794        GetRayContributionStatistics(
795                                                                                                                         float &minRayContribution,
796                                                                                                                         float &maxRayContribution,
797                                                                                                                         float &avgRayContribution
798                                                                                                                         );
799
800        int
801        GenerateRays(const float ratioPerLeaf,
802                                                         SimpleRayContainer &rays);
803
804        float
805        GetAvgPvsSize();
806
807};
808
809
810#endif // __LSDS_KDTREE_H__
811
Note: See TracBrowser for help on using the repository browser.