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

Revision 482, 18.1 KB checked in by mattausch, 19 years ago (diff)

added visualizations

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