source: trunk/VUT/GtpVisibilityPreprocessor/src/RssTree.h @ 447

Revision 447, 17.7 KB checked in by bittner, 19 years ago (diff)

non-functional merged version

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