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

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