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

Revision 473, 18.0 KB checked in by mattausch, 19 years ago (diff)

worked on new features,
removed Random Bug (took only 32000 values),
removed bug when choosing new candidates (totally wrong)
introduced new candidate plane method
implemented priority queue for vsp bsp

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.