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

Revision 483, 18.2 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        // 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 LineTraversalData
532        {
533                VspKdNode *mNode;
534                Vector3 mExitPoint;
535               
536                float mMaxT;
537   
538                LineTraversalData () {}
539                LineTraversalData (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
611        /** Collects candidates for the merge in the merge queue.
612        */
613        void CollectMergeCandidates();
614
615protected:
616
617        // incremental construction
618        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
619
620        virtual void AddRays(VssRayContainer &add);
621
622        VspKdNode *Locate(const Vector3 &v);
623       
624        VspKdNode *SubdivideNode(VspKdLeaf *leaf,
625                                                                 const AxisAlignedBox3 &box,
626                                                                 AxisAlignedBox3 &backBox,
627                                                                 AxisAlignedBox3 &frontBox);
628       
629        VspKdNode *Subdivide(const TraversalData &tdata);
630       
631        int SelectPlane(VspKdLeaf *leaf,
632                                        const AxisAlignedBox3 &box,
633                                        float &position,
634                                        int &raysBack,
635                                        int &raysFront,
636                                        int &pvsBack,
637                                        int &pvsFront);
638
639        void SortSplitCandidates(VspKdLeaf *node,
640                                                         const int axis);       
641 
642        float BestCostRatioHeuristic(VspKdLeaf *node,
643                                                                 const AxisAlignedBox3 &box,
644                                                                 int &axis,
645                                                                 float &position,
646                                                                 int &raysBack,
647                                                                 int &raysFront,
648                                                                 int &pvsBack,
649                                                                 int &pvsFront);
650
651        float BestCostRatioRegular(VspKdLeaf *node,
652                                                           const AxisAlignedBox3 &box,
653                                                           int &axis,
654                                                           float &position,
655                                                           int &raysBack,
656                                                           int &raysFront,
657                                                           int &pvsBack,
658                                                           int &pvsFront);
659       
660        float EvalCostRatio(VspKdLeaf *node,
661                                                const AxisAlignedBox3 &box,
662                                                const int axis,
663                                                const float position,
664                                                int &raysBack,
665                                                int &raysFront,
666                                                int &pvsBack,
667                                                int &pvsFront);
668
669
670        VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
671                                                                  const float SAThreshold);
672
673        void RemoveRay(VssRay *ray,
674                                   vector<VspKdLeaf *> *affectedLeaves,
675                                   const bool removeAllScheduledRays);
676
677        void AddRay(VssRay *ray);
678       
679        void TraverseInternalNode(RayTraversalData &data,
680                                                         stack<RayTraversalData> &tstack);
681
682        void EvaluateLeafStats(const TraversalData &data);
683
684
685        int     GetRootPvsSize() const;
686       
687        int     GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
688
689        void GetRayContributionStatistics(float &minRayContribution,
690                                                                          float &maxRayContribution,
691                                                                          float &avgRayContribution);
692
693        int GenerateRays(const float ratioPerLeaf,
694                                         SimpleRayContainer &rays);
695
696        /** Collapses this subtree and releases the memory.
697                @returns number of collapsed rays.
698        */
699        int CollapseSubtree(VspKdNode *sroot, const int time);
700       
701        int ReleaseMemory(const int time);
702
703        bool TerminationCriteriaMet(const VspKdLeaf *leaf,
704                                                                const AxisAlignedBox3 &box) const;
705
706        /** Computes PVS size of this node given a global ray set.
707                @returns PVS size of the intersection of this node bounding box with the rays.
708        */
709        int ComputePvsSize(VspKdNode *node,
710                                           const RayInfoContainer &globalRays) const;
711
712
713        /** Generates view cell for this leaf taking the ray contributions.
714        */
715        void GenerateViewCell(VspKdLeaf *leaf);
716
717        /** Merges view cells of the two leaves.
718        */
719        bool MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2);
720
721        /** Collapses the tree with respect to the view cell partition.
722                @returns node of type leaf if the node could be collapsed, this node otherwise
723        */
724        VspKdNode *CollapseTree(VspKdNode *node);
725       
726        /** Helper function revalidating the view cell leaf list after merge.
727        */
728        void RepairVcLeafLists();
729
730protected:
731       
732
733        /////////////////////////////
734        // The core pointer
735        VspKdNode *mRoot;
736 
737        /////////////////////////////
738        // Basic properties
739
740        // total number of nodes of the tree
741        int mNumNodes;
742       
743        // axis aligned bounding box of the scene
744        AxisAlignedBox3 mBox;
745
746        // epsilon used for the construction
747        float mEpsilon;
748
749        // ratio between traversal and intersection costs
750        float mCtDivCi;
751       
752        // type of the splitting to use for the tree construction
753        enum {ESplitRegular, ESplitHeuristic};
754        int splitType;
755       
756        // maximum alovable memory in MB
757        float mMaxTotalMemory;
758
759        // maximum alovable memory for static kd tree in MB
760        float mMaxStaticMemory;
761
762        // this is used during the construction depending
763        // on the type of the tree and queries...
764        float mMaxMemory;
765
766        // minimal acess time for collapse
767        int mAccessTimeThreshold;
768
769        // minimal depth at which to perform collapse
770        int mMinCollapseDepth;
771       
772        // reusable array of split candidates
773        vector<SortableEntry> *mSplitCandidates;
774       
775        ViewCellsManager *mViewCellsManager;
776
777        priority_queue<MergeCandidate> mMergeQueue;
778
779
780        /////////////////////////////
781        // Construction parameters
782
783        /// max depth of the tree
784        int mTermMaxDepth;
785        /// minimal ratio of the volume of the cell and the query volume
786        float mTermMinSize;
787        /// minimal pvs per node to still get subdivided
788        int mTermMinPvs;
789        /// minimal ray number per node to still get subdivided
790        int mTermMinRays;
791        /// maximal acceptable cost ratio to continue subdivision
792        float mTermMaxCostRatio;
793        /// maximal contribution per ray to subdivide the node
794        float mTermMaxRayContribution;
795        /// tolerance value indicating how often the max cost ratio can be failed
796        int mTermMissTolerance;
797
798        /// maximal numbers of view cells
799        int mMaxViewCells;
800
801        /// maximal cost ratio of a merge
802        float mMergeMaxCostRatio;
803       
804        /// minimal number of view cells
805        int mMergeMinViewCells;
806
807        /// if only the "driving axis", i.e., the axis with the biggest extent
808        /// should be used for subdivision
809        bool mOnlyDrivingAxis;
810
811        /////////////////////////////
812        VspKdStatistics mStat; 
813};
814
815
816#endif // __VSP_KDTREE_H__
817
Note: See TracBrowser for help on using the repository browser.