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

Revision 403, 17.2 KB checked in by bittner, 19 years ago (diff)

vvs preprocessor update

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