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

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