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

Revision 465, 16.9 KB checked in by mattausch, 19 years ago (diff)

worked on vspkd leaves merge, implemented post merge collapse

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
36class VspKdLeaf;
37class ViewCellsManager;
38class VspKdViewCell;
39class ViewCellsStatistics;
40
41
42/**
43        Candidate for leaf merging based on priority.
44*/
45class MergeCandidate
46
47public:
48
49        MergeCandidate(VspKdLeaf *l1, VspKdLeaf *l2);
50
51        /** Computes PVS difference between the leaves.
52        */
53        //int ComputePvsDifference() const;
54
55        /** If this merge pair is still valid.
56        */
57        bool Valid() const;
58
59        /** Sets this merge candidate to be valid.
60        */
61        void SetValid();
62
63        friend bool operator<(const MergeCandidate &leafa, const MergeCandidate &leafb)
64        {
65                return leafb.GetMergeCost() < leafa.GetMergeCost();
66        }
67
68        void SetLeaf1(VspKdLeaf *l);
69        void SetLeaf2(VspKdLeaf *l);
70
71        VspKdLeaf *GetLeaf1();
72        VspKdLeaf *GetLeaf2();
73
74        /** Merge cost of this candidate pair.
75        */
76        float GetMergeCost() const;
77
78        /// maximal pvs size
79        static int sMaxPvsSize;
80
81protected:
82       
83        /** Evaluates the merge costs of the leaves.
84        */
85        void EvalMergeCost();
86
87        int mLeaf1Id;
88        int mLeaf2Id;
89
90        float mMergeCost;
91       
92        VspKdLeaf *mLeaf1;
93        VspKdLeaf *mLeaf2;
94};
95
96
97
98/**
99        Static statistics for vsp kd-tree search
100*/
101class VspKdStatistics:  public StatisticsBase
102{
103public: 
104        // total number of nodes
105        int nodes;
106        // number of splits along each of the axes
107        int splits[3];
108        // totals number of rays
109        int rays;
110        // initial size of the pvs
111        int initialPvsSize;
112        // total number of query domains
113        int queryDomains;
114        // total number of ray references
115        int rayRefs;
116
117        // max depth nodes
118        int maxDepthNodes;
119        // max depth nodes
120        int minPvsNodes;
121        // nodes with minimum PVS
122        int minRaysNodes;
123        // max ray contribution nodes
124        int maxRayContribNodes;
125        // max depth nodes
126        int minSizeNodes;
127       
128        // max number of rays per node
129        int maxRayRefs;
130        // maximal PVS size / leaf
131        int maxPvsSize;
132
133        // number of dynamically added ray refs
134        int addedRayRefs;
135        // number of dynamically removed ray refs
136        int removedRayRefs;
137 
138        /** Default constructor.
139        */
140        VspKdStatistics() {     Reset(); }
141        int Nodes() const { return nodes; }
142        int Interior() const { return nodes / 2; }
143        int Leaves() const { return (nodes / 2) + 1; }
144
145        void Reset()
146        {
147                nodes = 0;
148
149                for (int i=0; i<3; i++)
150                        splits[i] = 0;
151
152                rays = queryDomains = 0;
153                rayRefs = 0;
154               
155                maxDepthNodes = 0;
156                minPvsNodes = 0;
157                minRaysNodes = 0;
158                maxRayContribNodes = 0;
159                minSizeNodes = 0;
160
161                maxRayRefs = 0;
162                addedRayRefs = removedRayRefs = 0;
163               
164                initialPvsSize = 0;
165                maxPvsSize = 0;
166        }
167
168        void Print(ostream &app) const;
169        friend ostream &operator<<(ostream &s, const VspKdStatistics &stat)
170        {
171            stat.Print(s);
172            return s;
173        } 
174};
175
176
177class VspKdInterior;
178
179
180/** Abstract superclass of Vsp-Kd-Tree nodes.
181*/
182class VspKdNode
183{
184public:
185
186        friend class VspKdTree;
187
188        enum {EInterior, ELeaf};
189
190        /** Constructs new interior node from the parent node.
191        */
192        inline VspKdNode(VspKdInterior *p);
193
194        /** Destroys this node and the subtree.
195        */
196        virtual ~VspKdNode();
197
198        /** Type of the node (Einterior or ELeaf)
199        */
200        virtual int Type() const = 0;
201 
202        /** Returns true if this node is a leaf.
203        */
204        bool IsLeaf() const;
205       
206        /** Prints node stats.
207        */
208        virtual void Print(ostream &s) const = 0;
209
210        /** Returns time needed to access this node.
211        */
212        virtual int GetAccessTime(); // NOTE: don't really know how it is used!
213
214        /** Returns parent node.
215        */
216        VspKdInterior *GetParent() const;
217
218        /** Sets parent node.
219        */
220        void SetParent(VspKdInterior *p);
221
222protected:
223        /////////////////////////////////
224        // The actual data goes here
225 
226        /// link to the parent
227        VspKdInterior *mParent;
228
229        enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
230 
231        /// splitting axis
232        char mAxis;
233       
234        /// depth
235        unsigned char mDepth;
236};
237
238// --------------------------------------------------------------
239// KD-tree node - interior node
240// --------------------------------------------------------------
241class VspKdInterior: public VspKdNode
242{
243public:
244        friend class VspKdTree;
245
246        /** Constructs new interior node from parent node.
247        */
248        VspKdInterior(VspKdInterior *p);
249                       
250        virtual int GetAccessTime();
251       
252        virtual int Type() const;
253 
254        virtual ~VspKdInterior();
255   
256        virtual void Print(ostream &s) const;
257
258        /** Returns back child.
259        */
260        inline VspKdNode *GetBack() const;
261        /** Returns front child.
262        */
263        inline VspKdNode *GetFront() const;
264
265protected:
266
267        /** Sets pointers to back child and front child.
268        */
269        void SetupChildLinks(VspKdNode *b, VspKdNode *f);
270
271        /** Replaces the pointer to oldChild with a pointer to newChild.
272        */
273        void ReplaceChildLink(VspKdNode *oldChild, VspKdNode *newChild);
274 
275        /** Computes intersection of the ray with the node boundaries.
276        */
277        int ComputeRayIntersection(const RayInfo &rayData, float &t);
278
279        // plane in local modelling coordinates
280        float mPosition;
281
282        // pointers to children
283        VspKdNode *mBack;
284        VspKdNode *mFront;
285
286        // the bbox of the node
287        AxisAlignedBox3 mBox;
288
289        // data for caching
290        long mAccesses;
291        long mLastAccessTime;
292};
293
294
295// --------------------------------------------------------------
296// KD-tree node - leaf node
297// --------------------------------------------------------------
298class VspKdLeaf: public VspKdNode
299{
300public:
301
302        friend class VspKdTree;
303
304        /** Constructs leaf from parent node.
305                @param p the parent node
306                @param nRays preallocates memory to store this number of rays
307        */
308        VspKdLeaf(VspKdInterior *p,     const int nRays);
309       
310        virtual ~VspKdLeaf();
311
312        virtual int Type() const; 
313
314        virtual void Print(ostream &s) const;
315 
316        /** Adds a ray to the leaf ray container.
317        */
318        void AddRay(const RayInfo &data);
319        /** Returns size of the leaf PVS as induced by the rays
320                @note returns precomputed PVS size, which may not be valid
321                anymore. Run UpdatePvsSize to get a valid PVS.
322        */
323        int GetPvsSize() const;
324
325        /** If PVS is not valid, this function recomputes the leaf
326                PVS as induced by the rays.
327        */
328        void UpdatePvsSize();
329
330        /** Returns stored rays.
331        */
332        RayInfoContainer &GetRays();
333
334        /** Returns rays into this ray container.
335        */
336        void GetRays(VssRayContainer &rays);
337        /** Returns average contribution of a ray to the PVS
338        */
339        inline float GetAvgRayContribution() const;
340        /** Returns square of average contribution of a ray.
341        */
342        inline float GetSqrRayContribution() const;
343
344        /** Extracts PVS from ray set.
345        */
346        void ExtractPvs(ObjectContainer &objects) const;
347
348        //-- mailing options
349        void Mail();
350
351        bool Mailed() const;
352 
353        /** Returns true if mail equals the leaf mail box.
354        */
355        bool Mailed(const int mail) const;
356
357        void SetViewCell(VspKdViewCell *viewCell);
358
359        /** Returns mail box of this leaf.
360        */
361        int GetMailbox() const;
362
363        /** Returns view cell associated with this leaf.
364        */
365        VspKdViewCell *GetViewCell();
366
367        ////////////////////////////////////////////
368       
369        static void NewMail();
370
371        static int sMailId;
372
373
374protected:
375
376        /** Manually sets PVS size.
377                @param s the PVS size
378        */
379        void SetPvsSize(const int s);
380
381        int mMailbox;
382 
383        RayInfoContainer mRays;
384       
385        /// true if mPvsSize is valid => PVS does not have to be updated
386        bool mValidPvs;
387
388        /// the view cell associated with this leaf
389        VspKdViewCell *mViewCell;
390
391private:
392        /// stores PVS size so we have to evaluate PVS size only once
393        int mPvsSize;
394};
395
396
397
398// ---------------------------------------------------------------
399// Main LSDS search class
400// ---------------------------------------------------------------
401class VspKdTree
402{
403        // --------------------------------------------------------------
404        // For sorting rays
405        // -------------------------------------------------------------
406        struct SortableEntry
407        {
408                enum EType
409                {
410                        ERayMin,
411                        ERayMax
412                };
413
414                int type;
415                float value;
416                void *data;
417 
418                SortableEntry() {}
419                SortableEntry(const int t, const float v, void *d):type(t),
420                                          value(v), data(d)
421                {
422                }
423               
424                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
425                {
426                        return a.value < b.value;
427                }
428        };
429
430        struct TraversalData
431        { 
432                VspKdNode *mNode;
433                AxisAlignedBox3 mBox;
434                int mDepth;
435                //float mPriority;
436       
437                TraversalData() {}
438
439                TraversalData(VspKdNode *n, const float p):
440                mNode(n)//, mPriority(p)
441                {}
442
443                TraversalData(VspKdNode *n,     const AxisAlignedBox3 &b, const int d):
444                mNode(n), mBox(b), mDepth(d) {}
445   
446                // comparator for the priority queue
447                /*struct less_priority : public binary_function<const TraversalData, const TraversalData, bool>
448                {
449                        bool operator()(const TraversalData a, const TraversalData b) {                 
450                        return a.mPriority < b.mPriority;               }       };*/
451
452                //    ~TraversalData() {}
453                //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
454   
455                friend bool operator<(const TraversalData &a, const TraversalData &b)
456                {
457                        // return a.node->queries.size() < b.node->queries.size();
458                        VspKdLeaf *leafa = (VspKdLeaf *) a.mNode;
459                        VspKdLeaf *leafb = (VspKdLeaf *) b.mNode;
460#if 0
461                        return
462                                leafa->rays.size()*a.mBox.GetVolume()
463                                <
464                                leafb->rays.size()*b.mBox.GetVolume();
465#endif
466#if 1
467                        return
468                                leafa->GetPvsSize()*a.mBox.GetVolume()
469                                <
470                                leafb->GetPvsSize()*b.mBox.GetVolume();
471#endif
472#if 0
473                        return
474                                leafa->GetPvsSize()
475                                <
476                                leafb->GetPvsSize();
477#endif
478#if 0
479                        return
480                                leafa->GetPvsSize() / (float)(leafa->rays.size() + Limits::Small())
481                                >
482                                leafb->GetPvsSize() / (float)(leafb->rays.size() + Limits::Small());
483#endif
484#if 0
485                        return
486                                leafa->GetPvsSize() * (float)leafa->rays.size()
487                                <
488                                leafb->GetPvsSize() * (float)leafb->rays.size();
489#endif
490    }
491  };
492 
493  /** Simplified data for ray traversal only.
494  */
495  struct RayTraversalData
496  {
497          RayInfo mRayData;
498          VspKdNode *mNode;
499     
500          RayTraversalData() {}
501         
502          RayTraversalData(VspKdNode *n, const RayInfo &data):
503          mRayData(data), mNode(n) {}
504  };
505       
506public:
507
508        VspKdTree();
509        virtual ~VspKdTree();
510
511        virtual void Construct(const VssRayContainer &rays,
512                                                   AxisAlignedBox3 *forcedBoundingBox = NULL);
513
514        /** Returns bounding box of the specified node.
515        */
516        AxisAlignedBox3 GetBBox(VspKdNode *node) const;
517
518        const VspKdStatistics &GetStatistics() const;
519
520        /** Get the root of the tree.
521        */
522        VspKdNode *GetRoot() const;
523
524        /** Returns average PVS size in tree.
525        */
526        float GetAvgPvsSize();
527
528        /** Returns memory usage in MB.
529        */
530        float GetMemUsage() const;
531       
532        float GetRayMemUsage() const;
533
534        /** Collects leaves of this tree.
535        */
536        void CollectLeaves(vector<VspKdLeaf *> &leaves) const;
537
538        /** Merges leaves of this tree according to some criteria.
539        */
540        int MergeLeaves();
541
542        /** Finds neighbours of this node.
543                @param n the input node
544                @param neighbours the neighbors of the input node
545                @param onlyUnmailed if only unmailed neighbors are collected
546        */
547        int FindNeighbors(VspKdLeaf *n,
548                                          vector<VspKdLeaf *> &neighbors,
549                                          bool onlyUnmailed);
550
551       
552        /** Sets pointer to view cells manager.
553        */
554        void SetViewCellsManager(ViewCellsManager *vcm);
555
556        /** A ray is cast possible intersecting the tree.
557                @param the ray that is cast.
558                @returns the number of intersections with objects stored in the tree.
559        */
560        int CastRay(Ray &ray);
561
562        /** Collects view cells generated by this tree.
563        */
564        void CollectViewCells(ViewCellContainer &viewCells) const;
565
566        /** Traverses tree and counts all view cells as well as their PVS size.
567        */
568        void EvaluateViewCellsStats(ViewCellsStatistics &stat) const;
569
570protected:
571
572        // incremental construction
573        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
574
575        virtual void AddRays(VssRayContainer &add);
576
577        VspKdNode *Locate(const Vector3 &v);
578       
579        VspKdNode *SubdivideNode(VspKdLeaf *leaf,
580                                                                 const AxisAlignedBox3 &box,
581                                                                 AxisAlignedBox3 &backBox,
582                                                                 AxisAlignedBox3 &frontBox);
583       
584        VspKdNode *Subdivide(const TraversalData &tdata);
585       
586        int SelectPlane(VspKdLeaf *leaf,
587                                        const AxisAlignedBox3 &box,
588                                        float &position,
589                                        int &raysBack,
590                                        int &raysFront,
591                                        int &pvsBack,
592                                        int &pvsFront);
593
594        void SortSplitCandidates(VspKdLeaf *node,
595                                                         const int axis);       
596 
597        float BestCostRatioHeuristic(VspKdLeaf *node,
598                                                                 int &axis,
599                                                                 float &position,
600                                                                 int &raysBack,
601                                                                 int &raysFront,
602                                                                 int &pvsBack,
603                                                                 int &pvsFront);
604
605        float BestCostRatioRegular(VspKdLeaf *node,
606                                                           int &axis,
607                                                           float &position,
608                                                           int &raysBack,
609                                                           int &raysFront,
610                                                           int &pvsBack,
611                                                           int &pvsFront);
612       
613        float EvalCostRatio(VspKdLeaf *node,
614                                                const int axis,
615                                                const float position,
616                                                int &raysBack,
617                                                int &raysFront,
618                                                int &pvsBack,
619                                                int &pvsFront);
620
621
622        VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
623                                                                  const float SAThreshold);
624
625        void RemoveRay(VssRay *ray,
626                                   vector<VspKdLeaf *> *affectedLeaves,
627                                   const bool removeAllScheduledRays);
628
629        void AddRay(VssRay *ray);
630       
631        void TraverseInternalNode(RayTraversalData &data,
632                                                         stack<RayTraversalData> &tstack);
633
634        void EvaluateLeafStats(const TraversalData &data);
635
636
637        int     GetRootPvsSize() const;
638       
639        int     GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
640
641        void GetRayContributionStatistics(float &minRayContribution,
642                                                                          float &maxRayContribution,
643                                                                          float &avgRayContribution);
644
645        int GenerateRays(const float ratioPerLeaf,
646                                         SimpleRayContainer &rays);
647
648        /** Collapses this subtree and releases the memory.
649                @returns number of collapsed rays.
650        */
651        int CollapseSubtree(VspKdNode *sroot, const int time);
652       
653        int ReleaseMemory(const int time);
654
655        bool TerminationCriteriaMet(const VspKdLeaf *leaf,
656                                                                const AxisAlignedBox3 &box) const;
657
658        /** Computes PVS size of this node given a global ray set.
659                @returns PVS size of the intersection of this node bounding box with the rays.
660        */
661        int ComputePvsSize(VspKdNode *node,
662                                           const RayInfoContainer &globalRays) const;
663
664
665        /** Generates view cell for this leaf taking the ray contributions.
666        */
667        void GenerateViewCell(VspKdLeaf *leaf);
668
669        /** Merges view cells of the two leaves.
670        */
671        bool MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2);
672
673        /** Collapses the tree with respect to the view cell partition.
674                @returns node of type leaf if the node could be collapsed, this node otherwise
675        */
676        VspKdNode *CollapseTree(VspKdNode *node);
677       
678        /** Helper function revalidating the view cell leaf list after merge.
679        */
680        void ValidateViewCellLeaves();
681
682protected:
683       
684
685        /////////////////////////////
686        // The core pointer
687        VspKdNode *mRoot;
688 
689        /////////////////////////////
690        // Basic properties
691
692        // total number of nodes of the tree
693        int mNumNodes;
694       
695        // axis aligned bounding box of the scene
696        AxisAlignedBox3 mBox;
697
698        // epsilon used for the construction
699        float mEpsilon;
700
701        // ratio between traversal and intersection costs
702        float mCtDivCi;
703       
704        // type of the splitting to use for the tree construction
705        enum {ESplitRegular, ESplitHeuristic};
706        int splitType;
707       
708        // maximum alovable memory in MB
709        float mMaxTotalMemory;
710
711        // maximum alovable memory for static kd tree in MB
712        float mMaxStaticMemory;
713
714        // this is used during the construction depending
715        // on the type of the tree and queries...
716        float mMaxMemory;
717
718        // minimal acess time for collapse
719        int mAccessTimeThreshold;
720
721        // minimal depth at which to perform collapse
722        int mMinCollapseDepth;
723       
724        // reusable array of split candidates
725        vector<SortableEntry> *mSplitCandidates;
726       
727        ViewCellsManager *mViewCellsManager;
728
729        /// maximal cost ratio of a merge
730        float mMaxCostRatio;
731
732        /////////////////////////////
733        // Construction parameters
734
735        /// max depth of the tree
736        int mTermMaxDepth;
737
738        /// minimal ratio of the volume of the cell and the query volume
739        float mTermMinSize;
740
741        /// minimal pvs per node to still get subdivided
742        int mTermMinPvs;
743
744        /// minimal ray number per node to still get subdivided
745        int mTermMinRays;
746       
747        /// maximal cost ration to subdivide a node
748        float mTermMaxCostRatio;
749       
750        /// maximal contribution per ray to subdivide the node
751        float mTermMaxRayContribution;
752
753        /// if only the "driving axis", i.e., the axis with the biggest extent
754        /// should be used for subdivision
755        bool mOnlyDrivingAxis;
756
757        /// maximal numbers of view cells
758        int mMaxViewCells;
759
760        /// minimal number of view cells
761        int mMinViewCells;
762
763        /////////////////////////////
764        VspKdStatistics mStat; 
765};
766
767
768#endif // __VSP_KDTREE_H__
769
Note: See TracBrowser for help on using the repository browser.