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

Revision 462, 16.5 KB checked in by mattausch, 19 years ago (diff)

worked on vsp kd view cells

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