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

Revision 495, 18.9 KB checked in by mattausch, 19 years ago (diff)

fixed bug in tree 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#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        /** Replaces the pointer to oldChild with a pointer to newChild.
288        */
289        void ReplaceChildLink(VspKdNode *oldChild, VspKdNode *newChild);
290        /** Computes intersection of the ray with the node boundaries.
291        */
292        int ComputeRayIntersection(const RayInfo &rayData, float &t);
293
294        // plane in local modelling coordinates
295        float mPosition;
296
297        // pointers to children
298        VspKdNode *mBack;
299        VspKdNode *mFront;
300
301        // the bbox of the node
302        AxisAlignedBox3 mBox;
303
304        // data for caching
305        long mAccesses;
306        long mLastAccessTime;
307};
308
309
310// --------------------------------------------------------------
311// KD-tree node - leaf node
312// --------------------------------------------------------------
313class VspKdLeaf: public VspKdNode
314{
315public:
316
317        friend class VspKdTree;
318
319        /** Constructs leaf from parent node.
320                @param p the parent node
321                @param nRays preallocates memory to store this number of rays
322                @parma maxMisses how many times the max cost ratio was missed on the path to the leaf
323        */
324        VspKdLeaf(VspKdInterior *p,     const int nRays, const int maxCostMisses = 0);
325       
326        virtual ~VspKdLeaf();
327
328        virtual int Type() const; 
329
330        virtual void Print(ostream &s) const;
331 
332        /** Adds a ray to the leaf ray container.
333        */
334        void AddRay(const RayInfo &data);
335        /** Returns size of the leaf PVS as induced by the rays
336                @note returns precomputed PVS size, which may not be valid
337                anymore. Run UpdatePvsSize to get a valid PVS.
338        */
339        int GetPvsSize() const;
340
341        /** If PVS is not valid, this function recomputes the leaf
342                PVS as induced by the rays.
343        */
344        void UpdatePvsSize();
345
346        /** Returns stored rays.
347        */
348        RayInfoContainer &GetRays();
349
350        /** Returns rays into this ray container.
351        */
352        void GetRays(VssRayContainer &rays);
353        /** Returns average contribution of a ray to the PVS
354        */
355        inline float GetAvgRayContribution() const;
356        /** Returns square of average contribution of a ray.
357        */
358        inline float GetSqrRayContribution() const;
359
360        /** Extracts PVS from ray set.
361        */
362        void ExtractPvs(ObjectContainer &objects) const;
363
364        //-- mailing options
365        void Mail();
366
367        bool Mailed() const;
368 
369        /** Returns true if mail equals the leaf mail box.
370        */
371        bool Mailed(const int mail) const;
372
373        void SetViewCell(VspKdViewCell *viewCell);
374
375        /** Returns mail box of this leaf.
376        */
377        int GetMailbox() const;
378
379        /** Returns view cell associated with this leaf.
380        */
381        VspKdViewCell *GetViewCell();
382
383        /** Returns number of times the max cost ratio was missed until
384                this leaf.
385        */
386        int GetMaxCostMisses();
387
388
389        ////////////////////////////////////////////
390       
391        static void NewMail();
392        static int sMailId;
393
394        ObjectPvs *mPvs;
395        float mVolume;
396
397protected:
398
399        /** Manually sets PVS size.
400                @param s the PVS size
401        */
402        void SetPvsSize(const int s);
403
404        int mMailbox;
405 
406        /// rays intersecting this leaf.
407        RayInfoContainer mRays;
408        /// true if mPvsSize is valid => PVS does not have to be updated
409        bool mValidPvs;
410        /// the view cell associated with this leaf
411        VspKdViewCell *mViewCell;
412        /// number of times the max cost ratio was missed on the way to the leaf.
413        int mMaxCostMisses;
414
415private:
416        /// stores PVS size so we have to evaluate PVS size only once
417        int mPvsSize;
418};
419
420
421
422// ---------------------------------------------------------------
423// Main LSDS search class
424// ---------------------------------------------------------------
425class VspKdTree
426{
427        // --------------------------------------------------------------
428        // For sorting rays
429        // -------------------------------------------------------------
430        struct SortableEntry
431        {
432                enum EType
433                {
434                        ERayMin,
435                        ERayMax
436                };
437
438                int type;
439                float value;
440                VssRay *ray;
441 
442                SortableEntry() {}
443                SortableEntry(const int t, const float v, VssRay *r): type(t),
444                                          value(v), ray(r)
445                {
446                }
447               
448                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
449                {
450                        return a.value < b.value;
451                }
452        };
453
454        struct TraversalData
455        { 
456                VspKdNode *mNode;
457                AxisAlignedBox3 mBox;
458                int mDepth;
459                //float mPriority;
460       
461                TraversalData() {}
462
463                TraversalData(VspKdNode *n, const float p):
464                mNode(n)//, mPriority(p)
465                {}
466
467                TraversalData(VspKdNode *n,     const AxisAlignedBox3 &b, const int d):
468                mNode(n), mBox(b), mDepth(d) {}
469   
470                // comparator for the priority queue
471                /*struct less_priority : public binary_function<const TraversalData, const TraversalData, bool>
472                {
473                        bool operator()(const TraversalData a, const TraversalData b) {                 
474                        return a.mPriority < b.mPriority;               }       };*/
475
476                //    ~TraversalData() {}
477                //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
478   
479        friend bool operator<(const TraversalData &a, const TraversalData &b)
480                {
481                        // return a.node->queries.size() < b.node->queries.size();
482                        VspKdLeaf *leafa = (VspKdLeaf *) a.mNode;
483                        VspKdLeaf *leafb = (VspKdLeaf *) b.mNode;
484#if 0
485                        return
486                                leafa->rays.size() * a.mBox.GetVolume()
487                                <
488                                leafb->rays.size() * b.mBox.GetVolume();
489#endif
490#if 1
491                        return
492                                leafa->GetPvsSize() * a.mBox.GetVolume()
493                                <
494                                leafb->GetPvsSize() * b.mBox.GetVolume();
495#endif
496#if 0
497                        return
498                                leafa->GetPvsSize()
499                                <
500                                leafb->GetPvsSize();
501#endif
502#if 0
503                        return
504                                leafa->GetPvsSize() / (float)(leafa->rays.size() + Limits::Small())
505                                >
506                                leafb->GetPvsSize() / (float)(leafb->rays.size() + Limits::Small());
507#endif
508#if 0
509                        return
510                                leafa->GetPvsSize() * (float)leafa->rays.size()
511                                <
512                                leafb->GetPvsSize() * (float)leafb->rays.size();
513#endif
514                }
515        };
516 
517        /** Simplified data for ray traversal only.
518        */
519        struct RayTraversalData
520        {
521                RayInfo mRayData;
522                VspKdNode *mNode;
523
524                RayTraversalData() {}
525         
526                RayTraversalData(VspKdNode *n, const RayInfo &data):
527                mRayData(data), mNode(n) {}
528        };
529       
530        struct LineTraversalData
531        {
532                VspKdNode *mNode;
533                Vector3 mExitPoint;
534               
535                float mMaxT;
536   
537                LineTraversalData () {}
538                LineTraversalData (VspKdNode *n,
539                                                                  const Vector3 &p,
540                                                                  const float maxt):
541                mNode(n), mExitPoint(p), mMaxT(maxt) {}
542        };
543
544public:
545
546        VspKdTree();
547        virtual ~VspKdTree();
548
549        virtual void Construct(const VssRayContainer &rays,
550                                                   AxisAlignedBox3 *forcedBoundingBox = NULL);
551
552        /** Returns bounding box of the specified node.
553        */
554        AxisAlignedBox3 GetBBox(VspKdNode *node) const;
555
556        const VspKdStatistics &GetStatistics() const;
557
558        /** Get the root of the tree.
559        */
560        VspKdNode *GetRoot() const;
561
562        /** Returns average PVS size in tree.
563        */
564        float GetAvgPvsSize();
565
566        /** Returns memory usage in MB.
567        */
568        float GetMemUsage() const;
569        //?
570        float GetRayMemUsage() const;
571
572        /** Collects leaves of this tree.
573        */
574        void CollectLeaves(vector<VspKdLeaf *> &leaves) const;
575
576        /** Merges view cells created with this tree according to
577                some (global) cost heuristics.
578        */
579        int MergeViewCells(const VssRayContainer &rays);
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 using shuffling, i.e., border leaves
608                of two view cells are exchanged if the resulting view cells
609                are tested to be "better" than the old ones.
610                @returns number of refined view cells
611        */
612        int RefineViewCells(const VssRayContainer &rays);
613
614        /** Collects candidates for the merge in the merge queue.
615        */
616        void CollectMergeCandidates();
617
618        /** Collapses the tree with respect to the view cell partition.
619        */
620        void CollapseTree();
621
622protected:
623
624        /** Collapses the tree with respect to the view cell partition.
625                @returns node of type leaf if the node could be collapsed,
626                this node otherwise
627        */
628        VspKdNode *CollapseTree(VspKdNode *node);
629        // incremental construction
630        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
631
632        virtual void AddRays(VssRayContainer &add);
633
634        VspKdNode *Locate(const Vector3 &v);
635       
636        VspKdNode *SubdivideNode(VspKdLeaf *leaf,
637                                                                 const AxisAlignedBox3 &box,
638                                                                 AxisAlignedBox3 &backBox,
639                                                                 AxisAlignedBox3 &frontBox);
640       
641        VspKdNode *Subdivide(const TraversalData &tdata);
642       
643        int SelectPlane(VspKdLeaf *leaf,
644                                        const AxisAlignedBox3 &box,
645                                        float &position,
646                                        int &raysBack,
647                                        int &raysFront,
648                                        int &pvsBack,
649                                        int &pvsFront);
650
651        void SortSplitCandidates(VspKdLeaf *node,
652                                                         const int axis);       
653 
654        float BestCostRatioHeuristic(VspKdLeaf *node,
655                                                                 const AxisAlignedBox3 &box,
656                                                                 int &axis,
657                                                                 float &position,
658                                                                 int &raysBack,
659                                                                 int &raysFront,
660                                                                 int &pvsBack,
661                                                                 int &pvsFront);
662
663        float BestCostRatioRegular(VspKdLeaf *node,
664                                                           const AxisAlignedBox3 &box,
665                                                           int &axis,
666                                                           float &position,
667                                                           int &raysBack,
668                                                           int &raysFront,
669                                                           int &pvsBack,
670                                                           int &pvsFront);
671       
672        float EvalCostRatio(VspKdLeaf *node,
673                                                const AxisAlignedBox3 &box,
674                                                const int axis,
675                                                const float position,
676                                                int &raysBack,
677                                                int &raysFront,
678                                                int &pvsBack,
679                                                int &pvsFront);
680
681
682        VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
683                                                                  const float SAThreshold);
684
685        void RemoveRay(VssRay *ray,
686                                   vector<VspKdLeaf *> *affectedLeaves,
687                                   const bool removeAllScheduledRays);
688
689        void AddRay(VssRay *ray);
690       
691        void TraverseInternalNode(RayTraversalData &data,
692                                                         stack<RayTraversalData> &tstack);
693
694        void EvaluateLeafStats(const TraversalData &data);
695
696
697        int     GetRootPvsSize() const;
698       
699        int     GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
700
701        void GetRayContributionStatistics(float &minRayContribution,
702                                                                          float &maxRayContribution,
703                                                                          float &avgRayContribution);
704
705        int GenerateRays(const float ratioPerLeaf,
706                                         SimpleRayContainer &rays);
707
708        /** Collapses this subtree and releases the memory.
709                @returns number of collapsed rays.
710        */
711        int CollapseSubtree(VspKdNode *sroot, const int time);
712       
713        int ReleaseMemory(const int time);
714
715        bool TerminationCriteriaMet(const VspKdLeaf *leaf,
716                                                                const AxisAlignedBox3 &box) const;
717
718        /** Computes PVS size of this node given a global ray set.
719                @returns PVS size of the intersection of this node bounding box with the rays.
720        */
721        int ComputePvsSize(VspKdNode *node,
722                                           const RayInfoContainer &globalRays) const;
723
724
725        /** Generates view cell for this leaf taking the ray contributions.
726        */
727        void GenerateViewCell(VspKdLeaf *leaf);
728
729        /** Merges view cells of the two leaves.
730        */
731        bool MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2);
732       
733        /** Helper function revalidating the view cell leaf list after merge.
734        */
735        void RepairVcLeafLists();
736
737        /** Shuffles the leaves, i.e., tests if exchanging
738                the view cells the leaves belong to helps in improving the view cells.
739        */
740        bool ShuffleLeaves(VspKdLeaf *leaf1, VspKdLeaf *leaf2) const;
741
742        /** Shuffles, i.e. takes border leaf from view cell 1 and adds it
743                to view cell 2.
744        */
745        void ShuffleLeaf(VspKdLeaf *leaf,
746                                         VspKdViewCell *vc1,
747                                         VspKdViewCell *vc2) const;
748protected:
749       
750
751        /////////////////////////////
752        // The core pointer
753        VspKdNode *mRoot;
754 
755        /////////////////////////////
756        // Basic properties
757
758        // total number of nodes of the tree
759        int mNumNodes;
760       
761        // axis aligned bounding box of the scene
762        AxisAlignedBox3 mBox;
763
764        // epsilon used for the construction
765        float mEpsilon;
766
767        // ratio between traversal and intersection costs
768        float mCtDivCi;
769       
770        // type of the splitting to use for the tree construction
771        enum {ESplitRegular, ESplitHeuristic};
772        int splitType;
773       
774        // maximum alovable memory in MB
775        float mMaxTotalMemory;
776
777        // maximum alovable memory for static kd tree in MB
778        float mMaxStaticMemory;
779
780        // this is used during the construction depending
781        // on the type of the tree and queries...
782        float mMaxMemory;
783
784        // minimal acess time for collapse
785        int mAccessTimeThreshold;
786
787        // minimal depth at which to perform collapse
788        int mMinCollapseDepth;
789       
790        // reusable array of split candidates
791        vector<SortableEntry> *mSplitCandidates;
792       
793        ViewCellsManager *mViewCellsManager;
794
795        priority_queue<MergeCandidate> mMergeQueue;
796
797
798        /////////////////////////////
799        // Construction parameters
800
801        /// max depth of the tree
802        int mTermMaxDepth;
803        /// minimal ratio of the volume of the cell and the query volume
804        float mTermMinSize;
805        /// minimal pvs per node to still get subdivided
806        int mTermMinPvs;
807        /// minimal ray number per node to still get subdivided
808        int mTermMinRays;
809        /// maximal acceptable cost ratio to continue subdivision
810        float mTermMaxCostRatio;
811        /// maximal contribution per ray to subdivide the node
812        float mTermMaxRayContribution;
813        /// tolerance value indicating how often the max cost ratio can be failed
814        int mTermMissTolerance;
815
816        /// maximal numbers of view cells
817        int mMaxViewCells;
818
819        /// maximal cost ratio of a merge
820        float mMergeMaxCostRatio;
821       
822        /// minimal number of view cells
823        int mMergeMinViewCells;
824
825        /// if only the "driving axis", i.e., the axis with the biggest extent
826        /// should be used for subdivision
827        bool mOnlyDrivingAxis;
828
829        /////////////////////////////
830        VspKdStatistics mStat; 
831};
832
833
834#endif // __VSP_KDTREE_H__
835
Note: See TracBrowser for help on using the repository browser.