source: trunk/VUT/GtpVisibilityPreprocessor/src/VssTree.h @ 401

Revision 401, 17.0 KB checked in by bittner, 19 years ago (diff)

vsspreprocessor updates

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