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

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
36class VspKdLeaf;
37class ViewCellsManager;
38class VspKdViewCell;
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        /// 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;
94};
95
96
97
98/**
99        Static statistics for vsp kd-tree search
100*/
101class VspKdStatistics:  public StatisticsBase
102{
103public: 
104        // total number of nodes
105        int nodes;
106        // number of splits along each of the axes
107        int splits[3];
108        // totals number of rays
109        int rays;
110        // initial size of the pvs
111        int initialPvsSize;
112        // total number of query domains
113        int queryDomains;
114        // total number of ray references
115        int rayRefs;
116
117        // max depth nodes
118        int maxDepthNodes;
119        // max depth nodes
120        int minPvsNodes;
121        // nodes with minimum PVS
122        int minRaysNodes;
123        // max ray contribution nodes
124        int maxRayContribNodes;
125        // max depth nodes
126        int minSizeNodes;
127       
128        // max number of rays per node
129        int maxRayRefs;
130        // maximal PVS size / leaf
131        int maxPvsSize;
132
133        // number of dynamically added ray refs
134        int addedRayRefs;
135        // number of dynamically removed ray refs
136        int removedRayRefs;
137 
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; }
144
145        void Reset()
146        {
147                nodes = 0;
148
149                for (int i=0; i<3; i++)
150                        splits[i] = 0;
151
152                rays = queryDomains = 0;
153                rayRefs = 0;
154               
155                maxDepthNodes = 0;
156                minPvsNodes = 0;
157                minRaysNodes = 0;
158                maxRayContribNodes = 0;
159                minSizeNodes = 0;
160
161                maxRayRefs = 0;
162                addedRayRefs = removedRayRefs = 0;
163               
164                initialPvsSize = 0;
165                maxPvsSize = 0;
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        } 
174};
175
176
177class VspKdInterior;
178
179
180/** Abstract superclass of Vsp-Kd-Tree nodes.
181*/
182class VspKdNode
183{
184public:
185
186        friend class VspKdTree;
187
188        enum {EInterior, ELeaf};
189
190        /** Constructs new interior node from the parent node.
191        */
192        inline VspKdNode(VspKdInterior *p);
193
194        /** Destroys this node and the subtree.
195        */
196        virtual ~VspKdNode();
197
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;
209
210        /** Returns time needed to access this node.
211        */
212        virtual int GetAccessTime(); // NOTE: don't really know how it is used!
213
214        /** Returns parent node.
215        */
216        VspKdInterior *GetParent() const;
217
218        /** Sets parent node.
219        */
220        void SetParent(VspKdInterior *p);
221
222protected:
223        /////////////////////////////////
224        // The actual data goes here
225 
226        /// link to the parent
227        VspKdInterior *mParent;
228
229        enum {SPLIT_X = 0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
230 
231        /// splitting axis
232        char mAxis;
233       
234        /// depth
235        unsigned char mDepth;
236};
237
238// --------------------------------------------------------------
239// KD-tree node - interior node
240// --------------------------------------------------------------
241class VspKdInterior: public VspKdNode
242{
243public:
244        friend class VspKdTree;
245
246        /** Constructs new interior node from parent node.
247        */
248        VspKdInterior(VspKdInterior *p);
249                       
250        virtual int GetAccessTime();
251       
252        virtual int Type() const;
253 
254        virtual ~VspKdInterior();
255   
256        virtual void Print(ostream &s) const;
257
258        /** Returns back child.
259        */
260        inline VspKdNode *GetBack() const;
261        /** Returns front child.
262        */
263        inline VspKdNode *GetFront() const;
264
265protected:
266
267        /** Sets pointers to back child and front child.
268        */
269        void SetupChildLinks(VspKdNode *b, VspKdNode *f);
270
271        /** Replaces the pointer to oldChild with a pointer to newChild.
272        */
273        void ReplaceChildLink(VspKdNode *oldChild, VspKdNode *newChild);
274 
275        /** Computes intersection of the ray with the node boundaries.
276        */
277        int ComputeRayIntersection(const RayInfo &rayData, float &t);
278
279        // plane in local modelling coordinates
280        float mPosition;
281
282        // pointers to children
283        VspKdNode *mBack;
284        VspKdNode *mFront;
285
286        // the bbox of the node
287        AxisAlignedBox3 mBox;
288
289        // data for caching
290        long mAccesses;
291        long mLastAccessTime;
292};
293
294
295// --------------------------------------------------------------
296// KD-tree node - leaf node
297// --------------------------------------------------------------
298class VspKdLeaf: public VspKdNode
299{
300public:
301        friend class VspKdTree;
302
303        /** Constructs leaf from parent node.
304                @param p the parent node
305                @param nRays preallocates memory to store this number of rays
306        */
307        VspKdLeaf(VspKdInterior *p,     const int nRays);
308       
309        virtual ~VspKdLeaf();
310
311        virtual int Type() const; 
312
313        virtual void Print(ostream &s) const;
314 
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;
323
324        /** If PVS is not valid, this function recomputes the leaf
325                PVS as induced by the rays.
326        */
327        void UpdatePvsSize();
328
329        /** Returns stored rays.
330        */
331        RayInfoContainer &GetRays();
332
333        /** Returns rays into this ray container.
334        */
335        void GetRays(VssRayContainer &rays);
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;
342
343        /** Extracts PVS from ray set.
344        */
345        void ExtractPvs(ObjectContainer &objects) const;
346
347        //-- mailing options
348        void Mail();
349
350        bool Mailed() const;
351 
352        /** Returns true if mail equals the leaf mail box.
353        */
354        bool Mailed(const int mail) const;
355
356        void SetViewCell(VspKdViewCell *viewCell);
357
358        /** Returns mail box of this leaf.
359        */
360        int GetMailbox() const;
361
362        /** Returns view cell associated with this leaf.
363        */
364        VspKdViewCell *GetViewCell();
365
366        ////////////////////////////////////////////
367       
368        static void NewMail();
369
370        static int sMailId;
371
372
373protected:
374
375        /** Manually sets PVS size.
376                @param s the PVS size
377        */
378        void SetPvsSize(const int s);
379
380        int mMailbox;
381 
382        RayInfoContainer mRays;
383       
384        /// true if mPvsSize is valid => PVS does not have to be updated
385        bool mValidPvs;
386
387        /// the view cell associated with this leaf
388        VspKdViewCell *mViewCell;
389
390private:
391        /// stores PVS size so we have to evaluate PVS size only once
392        int mPvsSize;
393};
394
395
396
397// ---------------------------------------------------------------
398// Main LSDS search class
399// ---------------------------------------------------------------
400class VspKdTree
401{
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
429        struct TraversalData
430        { 
431                VspKdNode *mNode;
432                AxisAlignedBox3 mBox;
433                int mDepth;
434                //float mPriority;
435       
436                TraversalData() {}
437
438                TraversalData(VspKdNode *n, const float p):
439                mNode(n)//, mPriority(p)
440                {}
441
442                TraversalData(VspKdNode *n,     const AxisAlignedBox3 &b, const int d):
443                mNode(n), mBox(b), mDepth(d) {}
444   
445                // comparator for the priority queue
446                /*struct less_priority : public binary_function<const TraversalData, const TraversalData, bool>
447                {
448                        bool operator()(const TraversalData a, const TraversalData b) {                 
449                        return a.mPriority < b.mPriority;               }       };*/
450
451                //    ~TraversalData() {}
452                //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
453   
454                friend bool operator<(const TraversalData &a, const TraversalData &b)
455                {
456                        // return a.node->queries.size() < b.node->queries.size();
457                        VspKdLeaf *leafa = (VspKdLeaf *) a.mNode;
458                        VspKdLeaf *leafb = (VspKdLeaf *) b.mNode;
459#if 0
460                        return
461                                leafa->rays.size()*a.mBox.GetVolume()
462                                <
463                                leafb->rays.size()*b.mBox.GetVolume();
464#endif
465#if 1
466                        return
467                                leafa->GetPvsSize()*a.mBox.GetVolume()
468                                <
469                                leafb->GetPvsSize()*b.mBox.GetVolume();
470#endif
471#if 0
472                        return
473                                leafa->GetPvsSize()
474                                <
475                                leafb->GetPvsSize();
476#endif
477#if 0
478                        return
479                                leafa->GetPvsSize() / (float)(leafa->rays.size() + Limits::Small())
480                                >
481                                leafb->GetPvsSize() / (float)(leafb->rays.size() + Limits::Small());
482#endif
483#if 0
484                        return
485                                leafa->GetPvsSize() * (float)leafa->rays.size()
486                                <
487                                leafb->GetPvsSize() * (float)leafb->rays.size();
488#endif
489    }
490  };
491 
492  /** Simplified data for ray traversal only.
493  */
494  struct RayTraversalData
495  {
496          RayInfo mRayData;
497          VspKdNode *mNode;
498     
499          RayTraversalData() {}
500         
501          RayTraversalData(VspKdNode *n, const RayInfo &data):
502          mRayData(data), mNode(n) {}
503  };
504       
505public:
506
507        VspKdTree();
508        virtual ~VspKdTree();
509
510        virtual void Construct(const VssRayContainer &rays,
511                                                   AxisAlignedBox3 *forcedBoundingBox = NULL);
512
513        /** Returns bounding box of the specified node.
514        */
515        AxisAlignedBox3 GetBBox(VspKdNode *node) const;
516
517        const VspKdStatistics &GetStatistics() const;
518
519        /** Get the root of the tree.
520        */
521        VspKdNode *GetRoot() const;
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
533        /** Collects leaves of this tree.
534        */
535        void CollectLeaves(vector<VspKdLeaf *> &leaves) const;
536
537        /** Merges leaves of this tree according to some criteria.
538        */
539        int MergeLeaves();
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        */
546        int FindNeighbors(VspKdLeaf *n,
547                                          vector<VspKdLeaf *> &neighbors,
548                                          bool onlyUnmailed);
549
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
569protected:
570
571        // incremental construction
572        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
573
574        virtual void AddRays(VssRayContainer &add);
575
576        VspKdNode *Locate(const Vector3 &v);
577       
578        VspKdNode *SubdivideNode(VspKdLeaf *leaf,
579                                                                 const AxisAlignedBox3 &box,
580                                                                 AxisAlignedBox3 &backBox,
581                                                                 AxisAlignedBox3 &frontBox);
582       
583        VspKdNode *Subdivide(const TraversalData &tdata);
584       
585        int SelectPlane(VspKdLeaf *leaf,
586                                        const AxisAlignedBox3 &box,
587                                        float &position,
588                                        int &raysBack,
589                                        int &raysFront,
590                                        int &pvsBack,
591                                        int &pvsFront);
592
593        void SortSplitCandidates(VspKdLeaf *node,
594                                                         const int axis);       
595 
596        float BestCostRatioHeuristic(VspKdLeaf *node,
597                                                                 int &axis,
598                                                                 float &position,
599                                                                 int &raysBack,
600                                                                 int &raysFront,
601                                                                 int &pvsBack,
602                                                                 int &pvsFront);
603
604        float BestCostRatioRegular(VspKdLeaf *node,
605                                                           int &axis,
606                                                           float &position,
607                                                           int &raysBack,
608                                                           int &raysFront,
609                                                           int &pvsBack,
610                                                           int &pvsFront);
611       
612        float EvalCostRatio(VspKdLeaf *node,
613                                                const int axis,
614                                                const float position,
615                                                int &raysBack,
616                                                int &raysFront,
617                                                int &pvsBack,
618                                                int &pvsFront);
619
620
621        VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
622                                                                  const float SAThreshold);
623
624        void RemoveRay(VssRay *ray,
625                                   vector<VspKdLeaf *> *affectedLeaves,
626                                   const bool removeAllScheduledRays);
627
628        void AddRay(VssRay *ray);
629       
630        void TraverseInternalNode(RayTraversalData &data,
631                                                         stack<RayTraversalData> &tstack);
632
633        void EvaluateLeafStats(const TraversalData &data);
634
635
636        int     GetRootPvsSize() const;
637       
638        int     GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
639
640        void GetRayContributionStatistics(float &minRayContribution,
641                                                                          float &maxRayContribution,
642                                                                          float &avgRayContribution);
643
644        int GenerateRays(const float ratioPerLeaf,
645                                         SimpleRayContainer &rays);
646
647        /** Collapses this subtree and releases the memory.
648                @returns number of collapsed rays.
649        */
650        int CollapseSubtree(VspKdNode *sroot, const int time);
651       
652        int ReleaseMemory(const int time);
653
654        bool TerminationCriteriaMet(const VspKdLeaf *leaf,
655                                                                const AxisAlignedBox3 &box) const;
656
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        */
660        int ComputePvsSize(VspKdNode *node,
661                                           const RayInfoContainer &globalRays) const;
662
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       
673protected:
674       
675
676        /////////////////////////////
677        // The core pointer
678        VspKdNode *mRoot;
679 
680        /////////////////////////////
681        // Basic properties
682
683        // total number of nodes of the tree
684        int mNumNodes;
685       
686        // axis aligned bounding box of the scene
687        AxisAlignedBox3 mBox;
688
689        // epsilon used for the construction
690        float mEpsilon;
691
692        // ratio between traversal and intersection costs
693        float mCtDivCi;
694       
695        // type of the splitting to use for the tree construction
696        enum {ESplitRegular, ESplitHeuristic};
697        int splitType;
698       
699        // maximum alovable memory in MB
700        float mMaxTotalMemory;
701
702        // maximum alovable memory for static kd tree in MB
703        float mMaxStaticMemory;
704
705        // this is used during the construction depending
706        // on the type of the tree and queries...
707        float mMaxMemory;
708
709        // minimal acess time for collapse
710        int mAccessTimeThreshold;
711
712        // minimal depth at which to perform collapse
713        int mMinCollapseDepth;
714       
715        // reusable array of split candidates
716        vector<SortableEntry> *mSplitCandidates;
717       
718        ViewCellsManager *mViewCellsManager;
719
720        /// maximal cost ratio of a merge
721        float mMaxCostRatio;
722
723        /////////////////////////////
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
744        /// if only the "driving axis", i.e., the axis with the biggest extent
745        /// should be used for subdivision
746        bool mOnlyDrivingAxis;
747
748        /// maximal numbers of view cells
749        int mMaxViewCells;
750
751        /////////////////////////////
752        VspKdStatistics mStat; 
753};
754
755
756#endif // __VSP_KDTREE_H__
757
Note: See TracBrowser for help on using the repository browser.