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

Revision 420, 12.9 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#include "RayInfo.h"
34
35
36/**
37        Static statistics for vsp kd-tree search
38*/
39class VspKdStatistics:  public StatisticsBase
40{
41public: 
42        // total number of nodes
43        int nodes;
44        // number of splits along each of the axes
45        int splits[7];
46        // totals number of rays
47        int rays;
48        // initial size of the pvs
49        int initialPvsSize;
50        // total number of query domains
51        int queryDomains;
52        // total number of ray references
53        int rayRefs;
54
55        // max depth nodes
56        int maxDepthNodes;
57        // max depth nodes
58        int minPvsNodes;
59        int minRaysNodes;
60        // max ray contribution nodes
61        int maxRayContribNodes;
62        // max depth nodes
63        int minSizeNodes;
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        /** Default constructor.
73        */
74        VspKdStatistics() {     Reset(); }
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
83                for (int i=0; i<7; i++)
84                        splits[i] = 0;
85
86                rays = queryDomains = 0;
87                rayRefs = 0;
88                maxDepthNodes = 0;
89                minPvsNodes = 0;
90                minRaysNodes = 0;
91                maxRayRefs = 0;
92                addedRayRefs = removedRayRefs = 0;
93                initialPvsSize = 0;
94                maxRayContribNodes = 0;
95                minSizeNodes = 0;
96        }
97
98        void Print(ostream &app) const;
99        friend ostream &operator<<(ostream &s, const VspKdStatistics &stat)
100        {
101            stat.Print(s);
102            return s;
103        } 
104};
105
106
107class VspKdTreeInterior;
108
109
110/** Abstract superclass of Vsp-Kd-Tree nodes.
111*/
112class VspKdTreeNode
113{
114public:
115
116        friend class VspKdTree;
117#define USE_FIXEDPOINT_T 1
118
119        enum {EInterior, ELeaf};
120
121        /** Constructs new interior node from the parent node.
122        */
123        inline VspKdTreeNode(VspKdTreeInterior *p);
124
125        /** Destroys this node and the subtree.
126        */
127        virtual ~VspKdTreeNode();
128
129        /** Type of the node (Einterior or ELeaf)
130        */
131        virtual int Type() const = 0;
132 
133        /** Returns true if this node is a leaf.
134        */
135        bool IsLeaf() const;
136       
137        /** Prints node stats.
138        */
139        virtual void Print(ostream &s) const = 0;
140
141        /** Returns time needed to access this node.
142        */
143        virtual int GetAccessTime(); // NOTE: don't really know how it is used!
144
145        /** Returns parent node.
146        */
147        VspKdTreeInterior *GetParent() const;
148        /** Sets parent node.
149        */
150        void SetParent(VspKdTreeInterior *p);
151
152protected:
153        /////////////////////////////////
154        // The actual data goes here
155 
156        /// link to the parent
157        VspKdTreeInterior *mParent;
158
159        enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
160 
161        /// splitting axis
162        char mAxis;
163       
164        /// depth
165        unsigned char mDepth;
166};
167
168// --------------------------------------------------------------
169// KD-tree node - interior node
170// --------------------------------------------------------------
171class VspKdTreeInterior: public VspKdTreeNode
172{
173public:
174        friend class VspKdTree;
175
176        /** Constructs new interior node from parent node.
177        */
178        VspKdTreeInterior(VspKdTreeInterior *p);
179                       
180        virtual int GetAccessTime();
181       
182        virtual int Type() const;
183 
184        virtual ~VspKdTreeInterior();
185   
186        virtual void Print(ostream &s) const;
187
188        /** Returns back child.
189        */
190        inline VspKdTreeNode *GetBack() const;
191        /** Returns front child.
192        */
193        inline VspKdTreeNode *GetFront() const;
194
195protected:
196
197        /** Sets pointers to back child and front child.
198        */
199        void SetupChildLinks(VspKdTreeNode *b, VspKdTreeNode *f);
200
201        /** Replaces the pointer to oldChild with a pointer to newChild.
202        */
203        void ReplaceChildLink(VspKdTreeNode *oldChild, VspKdTreeNode *newChild);
204 
205        /** Computes intersection of the ray with the node boundaries.
206        */
207        int ComputeRayIntersection(const RayInfo &rayData, float &t);
208
209        // plane in local modelling coordinates
210        float mPosition;
211
212        // pointers to children
213        VspKdTreeNode *mBack;
214        VspKdTreeNode *mFront;
215
216        // the bbox of the node
217        AxisAlignedBox3 mBox;
218
219        // data for caching
220        long mAccesses;
221        long mLastAccessTime;
222};
223
224
225// --------------------------------------------------------------
226// KD-tree node - leaf node
227// --------------------------------------------------------------
228class VspKdTreeLeaf: public VspKdTreeNode
229{
230public:
231        friend class VspKdTree;
232
233        /** Constructs leaf from parent node.
234                @param p the parent node
235                @param nRays preallocates memory to store this number of rays
236        */
237        VspKdTreeLeaf(VspKdTreeInterior *p,     const int nRays);
238       
239        virtual ~VspKdTreeLeaf();
240
241        virtual int Type() const; 
242
243        virtual void Print(ostream &s) const;
244 
245        /** Adds a ray to the leaf ray container.
246        */
247        void AddRay(const RayInfo &data);
248        /** Returns size of the leaf PVS as induced by the rays
249                @note returns precomputed PVS size, which may not be valid
250                anymore. Run UpdatePvsSize to get a valid PVS.
251        */
252        int GetPvsSize() const;
253        void SetPvsSize(const int s);
254
255        /** If PVS is not valid, this function recomputes the leaf
256                PVS as induced by the rays.
257        */
258        void UpdatePvsSize();
259
260        void Mail();
261
262        bool Mailed() const;
263 
264        bool Mailed(const int mail);
265
266        /** Returns average contribution of a ray to the PVS
267        */
268        inline float GetAvgRayContribution() const;
269        /** Returns square of average contribution of a ray.
270        */
271        inline float GetSqrRayContribution() const;
272
273        static void NewMail();
274
275        static int mailID;
276
277protected:
278       
279        int mMailbox;
280 
281        RayInfoContainer mRays;
282        bool mValidPvs;
283       
284private:
285        int mPvsSize;
286};
287
288
289
290// ---------------------------------------------------------------
291// Main LSDS search class
292// ---------------------------------------------------------------
293class VspKdTree
294{
295        // --------------------------------------------------------------
296        // For sorting rays
297        // -------------------------------------------------------------
298        struct SortableEntry
299        {
300                enum EType
301                {
302                        ERayMin,
303                        ERayMax
304                };
305
306                int type;
307                float value;
308                void *data;
309 
310                SortableEntry() {}
311                SortableEntry(const int t, const float v, void *d):type(t),
312                                          value(v), data(d)
313                {
314                }
315               
316                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
317                {
318                        return a.value < b.value;
319                }
320        };
321
322        struct TraversalData
323        { 
324                VspKdTreeNode *mNode;
325                AxisAlignedBox3 mBox;
326                int mDepth;
327                float mPriority;
328       
329                TraversalData() {}
330
331                TraversalData(VspKdTreeNode *n, const float p):
332                mNode(n), mPriority(p)
333                {}
334
335                TraversalData(VspKdTreeNode *n, const AxisAlignedBox3 &b, const int d):
336                mNode(n), mBox(b), mDepth(d) {}
337   
338                // comparator for the
339                struct less_priority : public binary_function<const TraversalData, const TraversalData, bool>
340                {
341                        bool operator()(const TraversalData a, const TraversalData b)
342                        {
343                                return a.mPriority < b.mPriority;
344                        }
345                };
346
347                //    ~TraversalData() {}
348                //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
349   
350                friend bool operator<(const TraversalData &a, const TraversalData &b)
351                {
352                        // return a.node->queries.size() < b.node->queries.size();
353                        VspKdTreeLeaf *leafa = (VspKdTreeLeaf *) a.mNode;
354                        VspKdTreeLeaf *leafb = (VspKdTreeLeaf *) b.mNode;
355#if 0
356                        return
357                                leafa->rays.size()*a.mBox.GetVolume()
358                                <
359                                leafb->rays.size()*b.mBox.GetVolume();
360#endif
361#if 1
362                        return
363                                leafa->GetPvsSize()*a.mBox.GetVolume()
364                                <
365                                leafb->GetPvsSize()*b.mBox.GetVolume();
366#endif
367#if 0
368                        return
369                                leafa->GetPvsSize()
370                                <
371                                leafb->GetPvsSize();
372#endif
373#if 0
374                        return
375                                leafa->GetPvsSize() / (float)(leafa->rays.size() + 1)
376                                >
377                                leafb->GetPvsSize() / (float)(leafb->rays.size() + 1);
378#endif
379#if 0
380                        return
381                                leafa->GetPvsSize() * (float)leafa->rays.size()
382                                <
383                                leafb->GetPvsSize() * (float)leafb->rays.size();
384#endif
385    }
386  };
387 
388  /** Simplified data for ray traversal only.
389  */
390  struct RayTraversalData
391  {
392          RayInfo mRayData;
393          VspKdTreeNode *mNode;
394     
395          RayTraversalData() {}
396         
397          RayTraversalData(VspKdTreeNode *n, const RayInfo &data):
398          mRayData(data), mNode(n) {}
399  };
400       
401public:
402
403        VspKdTree();
404        virtual ~VspKdTree();
405
406        virtual void Construct(VssRayContainer &rays,
407                                                   AxisAlignedBox3 *forcedBoundingBox = NULL);
408
409        /** Returns bounding box of the specified node.
410        */
411        AxisAlignedBox3 GetBBox(VspKdTreeNode *node) const;
412
413        const VspKdStatistics &GetStatistics() const;
414
415        /** Get the root of the tree.
416        */
417        VspKdTreeNode *GetRoot() const;
418
419        /** Returns average PVS size in tree.
420        */
421        float GetAvgPvsSize();
422
423        /** Parses the environment and stores the global VspKd tree parameters
424        */
425        static void ParseEnvironment();
426
427        /////////////////////////////
428        // Construction parameters
429
430        /// max depth of the tree
431        static int sTermMaxDepth;
432
433        /// minimal ratio of the volume of the cell and the query volume
434        static float sTermMinSize;
435
436        /// minimal pvs per node to still get subdivided
437        static int sTermMinPvs;
438
439        /// minimal ray number per node to still get subdivided
440        static int sTermMinRays;
441       
442        /// maximal cost ration to subdivide a node
443        static float sTermMaxCostRatio;
444       
445        /// maximal contribution per ray to subdivide the node
446        static float sTermMaxRayContribution;
447
448        /** Returns memory usage in MB.
449        */
450        float GetMemUsage() const;
451       
452        float GetRayMemUsage() const;
453
454protected:
455        // incremental construction
456        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
457
458        virtual void AddRays(VssRayContainer &add);
459
460        VspKdTreeNode *Locate(const Vector3 &v);
461       
462        VspKdTreeNode *SubdivideNode(VspKdTreeLeaf *leaf,
463                                                                 const AxisAlignedBox3 &box,
464                                                                 AxisAlignedBox3 &backBox,
465                                                                 AxisAlignedBox3 &frontBox);
466       
467        VspKdTreeNode *Subdivide(const TraversalData &tdata);
468       
469        int SelectPlane(VspKdTreeLeaf *leaf,
470                                        const AxisAlignedBox3 &box,
471                                        float &position,
472                                        int &raysBack,
473                                        int &raysFront,
474                                        int &pvsBack,
475                                        int &pvsFront);
476
477        void SortSplitCandidates(VspKdTreeLeaf *node,
478                                                         const int axis);       
479 
480        float BestCostRatioHeuristic(VspKdTreeLeaf *node,
481                                                                 int &axis,
482                                                                 float &position,
483                                                                 int &raysBack,
484                                                                 int &raysFront,
485                                                                 int &pvsBack,
486                                                                 int &pvsFront);
487
488        float BestCostRatioRegular(VspKdTreeLeaf *node,
489                                                           int &axis,
490                                                           float &position,
491                                                           int &raysBack,
492                                                           int &raysFront,
493                                                           int &pvsBack,
494                                                           int &pvsFront);
495       
496        float EvalCostRatio(VspKdTreeLeaf *node,
497                                                const int axis,
498                                                const float position,
499                                                int &raysBack,
500                                                int &raysFront,
501                                                int &pvsBack,
502                                                int &pvsFront);
503
504
505        VspKdTreeNode * SubdivideLeaf(VspKdTreeLeaf *leaf,
506                                                                  const float SAThreshold);
507
508        void RemoveRay(VssRay *ray,
509                                   vector<VspKdTreeLeaf *> *affectedLeaves,
510                                   const bool removeAllScheduledRays);
511
512        void AddRay(VssRay *ray);
513       
514        void TraverseInternalNode(RayTraversalData &data,
515                                                         stack<RayTraversalData> &tstack);
516
517        void EvaluateLeafStats(const TraversalData &data);
518
519
520        int     GetRootPvsSize() const;
521       
522        int     GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const;
523
524        void GetRayContributionStatistics(float &minRayContribution,
525                                                                          float &maxRayContribution,
526                                                                          float &avgRayContribution);
527
528        int GenerateRays(const float ratioPerLeaf,
529                                         SimpleRayContainer &rays);
530
531        int CollapseSubtree(VspKdTreeNode *sroot, const int time);
532       
533        int ReleaseMemory(const int time);
534
535protected:
536        /////////////////////////////
537        // The core pointer
538        VspKdTreeNode *mRoot;
539 
540        /////////////////////////////
541        // Basic properties
542
543        // total number of nodes of the tree
544        int nodes;
545       
546        // axis aligned bounding box of the scene
547        AxisAlignedBox3 mBox;
548
549        // epsilon used for the construction
550        float epsilon;
551
552        // ratio between traversal and intersection costs
553        float ct_div_ci;
554       
555        // type of the splitting to use for the tree construction
556        enum {ESplitRegular, ESplitHeuristic };
557        int splitType;
558       
559        // maximum alovable memory in MB
560        float maxTotalMemory;
561
562        // maximum alovable memory for static kd tree in MB
563        float maxStaticMemory;
564
565        // this is used during the construction depending
566        // on the type of the tree and queries...
567        float maxMemory;
568
569        // minimal acess time for collapse
570        int accessTimeThreshold;
571
572        // minimal depth at which to perform collapse
573        int minCollapseDepth;
574       
575        // reusable array of split candidates
576        vector<SortableEntry> *splitCandidates;
577       
578        /////////////////////////////
579        VspKdStatistics mStat; 
580};
581
582
583#endif // __LSDS_KDTREE_H__
584
Note: See TracBrowser for help on using the repository browser.