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

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