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

Revision 463, 17.8 KB checked in by bittner, 19 years ago (diff)

removed mT from vss ray

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  // forced bounding box for from viewcell visibility
518  AxisAlignedBox3 *mForcedBoundingBox;
519
520  /////////////////////////////
521  // Construction parameters
522
523  // epsilon used for the construction
524  float epsilon;
525
526  // ratio between traversal and intersection costs
527  float ct_div_ci;
528  // max depth of the tree
529  int termMaxDepth;
530  // minimal ratio of the volume of the cell and the query volume
531  float termMinSize;
532
533  // minimal pvs per node to still get subdivided
534  int termMinPvs;
535
536  // minimal ray number per node to still get subdivided
537  int termMinRays;
538       
539  // maximal cost ration to subdivide a node
540  float termMaxCostRatio;
541       
542  // maximal contribution per ray to subdivide the node
543  float termMaxRayContribution;
544
545       
546  // randomized construction
547  bool randomize;
548 
549  // type of the splitting to use fo rthe tree construction
550  enum {ESplitRegular, ESplitHeuristic, ESplitHybrid };
551  int splitType;
552
553  bool mSplitUseOnlyDrivingAxis;
554 
555  // use ray space subdivision instead of view space subdivision
556  bool mUseRss;
557
558  // interleave directional and spatial splits based on their costs
559  // if false directional splits are only performed after spatial splits
560  bool mInterleaveDirSplits;
561
562  // depth at which directional splits are performed if mInterleaveDirSplits is false
563  int mDirSplitDepth;
564 
565  // maximal size of the box on which the refdir splitting can be performed
566  // (relative to the scene bbox
567  float refDirBoxMaxSize;
568 
569  // maximum alovable memory in MB
570  float maxTotalMemory;
571
572  // maximum alovable memory for static kd tree in MB
573  float maxStaticMemory;
574
575  // this is used during the construction depending
576  // on the type of the tree and queries...
577  float maxMemory;
578
579
580  // minimal acess time for collapse
581  int accessTimeThreshold;
582
583  // minimal depth at which to perform collapse
584  int minCollapseDepth;
585
586 
587  // reusable array of split candidates
588  vector<SortableEntry> *splitCandidates;
589  /////////////////////////////
590
591  RssStatistics stat;
592       
593 
594  RssTree();
595  virtual ~RssTree();
596
597  virtual void
598  Construct(
599                        VssRayContainer &rays,
600                        AxisAlignedBox3 *forcedBoundingBox = NULL
601                        );
602       
603  // incemental construction
604  virtual void UpdateRays(VssRayContainer &remove,
605                                                  VssRayContainer &add
606                                                  );
607
608  virtual void AddRays(
609                                           VssRayContainer &add
610                                           )
611  {
612        VssRayContainer remove;
613        UpdateRays(remove, add);
614  }
615
616 
617       
618  RssTreeNode *
619  Locate(const Vector3 &v);
620       
621  RssTreeNode *
622  SubdivideNode(RssTreeLeaf *leaf,
623                                const AxisAlignedBox3 &box,
624                                AxisAlignedBox3 &backBox,
625                                AxisAlignedBox3 &frontBox
626                                );
627       
628  RssTreeNode *
629  Subdivide(const TraversalData &tdata);
630       
631  int
632  SelectPlane(RssTreeLeaf *leaf,
633                          const AxisAlignedBox3 &box,
634                          float &position,
635                          int &raysBack,
636                          int &raysFront,
637                          int &pvsBack,
638                          int &pvsFront
639                          );
640
641  void
642  SortSplitCandidates(
643                                          RssTreeLeaf *node,
644                                          const int axis
645                                          );
646       
647 
648  // return memory usage in MB
649  float GetMemUsage() const {
650    return
651      (sizeof(RssTree) +
652       stat.Leaves()*sizeof(RssTreeLeaf) +
653       stat.Interior()*sizeof(RssTreeInterior) +
654       stat.rayRefs*sizeof(RssTreeNode::RayInfo))/(1024.0f*1024.0f);
655  }
656       
657  float GetRayMemUsage() const {
658    return
659      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
660  }
661 
662
663  float
664  BestCostRatio(
665                                RssTreeLeaf *node,
666                                int &axis,
667                                float &position,
668                                int &raysBack,
669                                int &raysFront,
670                                int &pvsBack,
671                                int &pvsFront
672                                );
673       
674  float
675  EvalCostRatio(
676                                RssTreeLeaf *node,
677                                const int axis,
678                                const float position,
679                                int &raysBack,
680                                int &raysFront,
681                                int &pvsBack,
682                                int &pvsFront
683                                );
684
685  float
686  EvalCostRatioHeuristic(
687                                                 RssTreeLeaf *node,
688                                                 const int axis,
689                                                 float &position,
690                                                 int &raysBack,
691                                                 int &raysFront,
692                                                 int &pvsBack,
693                                                 int &pvsFront
694                                                 );
695
696  float
697  GetCostRatio(
698                           RssTreeLeaf *leaf,
699                           const int axis,
700                           const float position,
701                           const int raysBack,
702                           const int raysFront,
703                           const int pvsBack,
704                           const int pvsFront
705                           );
706
707  AxisAlignedBox3 GetBBox(const RssTreeNode *node) const {
708    if (node->parent == NULL)
709      return bbox;
710
711    if (!node->IsLeaf())
712      return ((RssTreeInterior *)node)->bbox;
713
714    if (node->parent->axis >= 3)
715      return node->parent->bbox;
716     
717    AxisAlignedBox3 box(node->parent->bbox);
718    if (node->parent->front == node)
719      box.SetMin(node->parent->axis, node->parent->position);
720    else
721      box.SetMax(node->parent->axis, node->parent->position);
722    return box;
723  }
724
725  AxisAlignedBox3 GetShrankedBBox(const RssTreeNode *node) const;
726
727  AxisAlignedBox3 GetDirBBox(const RssTreeNode *node) const {
728
729    if (node->parent == NULL)
730      return dirBBox;
731   
732    if (!node->IsLeaf() )
733      return ((RssTreeInterior *)node)->dirBBox;
734
735    if (node->parent->axis < 3)
736      return node->parent->dirBBox;
737   
738    AxisAlignedBox3 dBBox(node->parent->dirBBox);
739
740    if (node->parent->front == node)
741      dBBox.SetMin(node->parent->axis - 3, node->parent->position);
742    else
743      dBBox.SetMax(node->parent->axis - 3, node->parent->position);
744    return dBBox;
745  }
746 
747  int
748  ReleaseMemory(const int time);
749
750  int
751  CollapseSubtree(RssTreeNode *node, const int time);
752
753  void
754  CountAccess(RssTreeInterior *node, const long time) {
755    node->accesses++;
756    node->lastAccessTime = time;
757  }
758
759  RssTreeNode *
760  SubdivideLeaf(
761                                RssTreeLeaf *leaf
762                                );
763
764  void
765  RemoveRay(VssRay *ray,
766                        vector<RssTreeLeaf *> *affectedLeaves,
767                        const bool removeAllScheduledRays
768                        );
769
770  //  void
771  //  AddRay(VssRay *ray);
772  void
773  AddRay(RssTreeNode::RayInfo &info);
774 
775  void
776  TraverseInternalNode(
777                                           RayTraversalData &data,
778                                           stack<RayTraversalData> &tstack);
779
780  void
781  EvaluateLeafStats(const TraversalData &data);
782
783
784  int
785  GetRootPvsSize() const {
786        return GetPvsSize(bbox);
787  }
788 
789  int
790  GetPvsSize(const AxisAlignedBox3 &box) const;
791
792  int
793  CollectPvs(const AxisAlignedBox3 &box,
794                         ObjectContainer &pvs
795                         ) const;
796
797  int
798  CollectRootPvs(
799                                 ObjectContainer &pvs
800                                 ) const
801  {
802        return CollectPvs(bbox, pvs);
803  }
804 
805       
806  void
807  GetTreeStatistics(
808                                        float &avgPvsSize,
809                                        float &avgRays,
810                                        float &avgRayContribution,
811                                        float &avgPvsEntropy,
812                                        float &avgRayLengthEntropy,
813                                        float &avgImportance
814                                        );
815
816
817  int
818  GenerateRays(const float ratioPerLeaf,
819                           SimpleRayContainer &rays);
820
821  int
822  GenerateRays(const int numberOfRays,
823                           const int numberOfLeaves,
824                           SimpleRayContainer &rays);
825               
826  float
827  GetAvgPvsSize();
828
829  int
830  UpdateSubdivision();
831
832  bool
833  TerminationCriteriaSatisfied(RssTreeLeaf *leaf);
834
835  void
836  CollectLeaves(vector<RssTreeLeaf *> &leaves);
837
838  bool
839  ClipRay(
840                  RssTreeNode::RayInfo &rayInfo,
841                  const AxisAlignedBox3 &box
842                  );
843
844  RssTreeNode *GetRoot() const { return root; }
845
846  bool
847  ValidLeaf(RssTreeLeaf *leaf) const;
848
849  void
850  GenerateLeafRays(RssTreeLeaf *leaf,
851                                   const int numberOfRays,
852                                   SimpleRayContainer &rays);
853
854
855};
856
857
858#endif // __LSDS_KDTREE_H__
859
Note: See TracBrowser for help on using the repository browser.