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

Revision 469, 17.2 KB checked in by mattausch, 19 years ago (diff)

updated view cells, view cell manager. changed rendersimulator

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        /// 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
302        friend class VspKdTree;
303
304        /** Constructs leaf from parent node.
305                @param p the parent node
306                @param nRays preallocates memory to store this number of rays
307        */
308        VspKdLeaf(VspKdInterior *p,     const int nRays);
309       
310        virtual ~VspKdLeaf();
311
312        virtual int Type() const; 
313
314        virtual void Print(ostream &s) const;
315 
316        /** Adds a ray to the leaf ray container.
317        */
318        void AddRay(const RayInfo &data);
319        /** Returns size of the leaf PVS as induced by the rays
320                @note returns precomputed PVS size, which may not be valid
321                anymore. Run UpdatePvsSize to get a valid PVS.
322        */
323        int GetPvsSize() const;
324
325        /** If PVS is not valid, this function recomputes the leaf
326                PVS as induced by the rays.
327        */
328        void UpdatePvsSize();
329
330        /** Returns stored rays.
331        */
332        RayInfoContainer &GetRays();
333
334        /** Returns rays into this ray container.
335        */
336        void GetRays(VssRayContainer &rays);
337        /** Returns average contribution of a ray to the PVS
338        */
339        inline float GetAvgRayContribution() const;
340        /** Returns square of average contribution of a ray.
341        */
342        inline float GetSqrRayContribution() const;
343
344        /** Extracts PVS from ray set.
345        */
346        void ExtractPvs(ObjectContainer &objects) const;
347
348        //-- mailing options
349        void Mail();
350
351        bool Mailed() const;
352 
353        /** Returns true if mail equals the leaf mail box.
354        */
355        bool Mailed(const int mail) const;
356
357        void SetViewCell(VspKdViewCell *viewCell);
358
359        /** Returns mail box of this leaf.
360        */
361        int GetMailbox() const;
362
363        /** Returns view cell associated with this leaf.
364        */
365        VspKdViewCell *GetViewCell();
366
367        ////////////////////////////////////////////
368       
369        static void NewMail();
370
371        static int sMailId;
372
373
374protected:
375
376        /** Manually sets PVS size.
377                @param s the PVS size
378        */
379        void SetPvsSize(const int s);
380
381        int mMailbox;
382 
383        RayInfoContainer mRays;
384       
385        /// true if mPvsSize is valid => PVS does not have to be updated
386        bool mValidPvs;
387
388        /// the view cell associated with this leaf
389        VspKdViewCell *mViewCell;
390
391private:
392        /// stores PVS size so we have to evaluate PVS size only once
393        int mPvsSize;
394};
395
396
397
398// ---------------------------------------------------------------
399// Main LSDS search class
400// ---------------------------------------------------------------
401class VspKdTree
402{
403        // --------------------------------------------------------------
404        // For sorting rays
405        // -------------------------------------------------------------
406        struct SortableEntry
407        {
408                enum EType
409                {
410                        ERayMin,
411                        ERayMax
412                };
413
414                int type;
415                float value;
416                void *data;
417 
418                SortableEntry() {}
419                SortableEntry(const int t, const float v, void *d):type(t),
420                                          value(v), data(d)
421                {
422                }
423               
424                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
425                {
426                        return a.value < b.value;
427                }
428        };
429
430        struct TraversalData
431        { 
432                VspKdNode *mNode;
433                AxisAlignedBox3 mBox;
434                int mDepth;
435                //float mPriority;
436       
437                TraversalData() {}
438
439                TraversalData(VspKdNode *n, const float p):
440                mNode(n)//, mPriority(p)
441                {}
442
443                TraversalData(VspKdNode *n,     const AxisAlignedBox3 &b, const int d):
444                mNode(n), mBox(b), mDepth(d) {}
445   
446                // comparator for the priority queue
447                /*struct less_priority : public binary_function<const TraversalData, const TraversalData, bool>
448                {
449                        bool operator()(const TraversalData a, const TraversalData b) {                 
450                        return a.mPriority < b.mPriority;               }       };*/
451
452                //    ~TraversalData() {}
453                //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
454   
455                friend bool operator<(const TraversalData &a, const TraversalData &b)
456                {
457                        // return a.node->queries.size() < b.node->queries.size();
458                        VspKdLeaf *leafa = (VspKdLeaf *) a.mNode;
459                        VspKdLeaf *leafb = (VspKdLeaf *) b.mNode;
460#if 0
461                        return
462                                leafa->rays.size()*a.mBox.GetVolume()
463                                <
464                                leafb->rays.size()*b.mBox.GetVolume();
465#endif
466#if 1
467                        return
468                                leafa->GetPvsSize()*a.mBox.GetVolume()
469                                <
470                                leafb->GetPvsSize()*b.mBox.GetVolume();
471#endif
472#if 0
473                        return
474                                leafa->GetPvsSize()
475                                <
476                                leafb->GetPvsSize();
477#endif
478#if 0
479                        return
480                                leafa->GetPvsSize() / (float)(leafa->rays.size() + Limits::Small())
481                                >
482                                leafb->GetPvsSize() / (float)(leafb->rays.size() + Limits::Small());
483#endif
484#if 0
485                        return
486                                leafa->GetPvsSize() * (float)leafa->rays.size()
487                                <
488                                leafb->GetPvsSize() * (float)leafb->rays.size();
489#endif
490                }
491        };
492 
493        /** Simplified data for ray traversal only.
494        */
495        struct RayTraversalData
496        {
497                RayInfo mRayData;
498                VspKdNode *mNode;
499
500                RayTraversalData() {}
501         
502                RayTraversalData(VspKdNode *n, const RayInfo &data):
503                mRayData(data), mNode(n) {}
504        };
505       
506        struct LineSegmentTraversalData
507        {
508                VspKdNode *mNode;
509                Vector3 mExitPoint;
510               
511                float mMaxT;
512   
513                LineSegmentTraversalData () {}
514                LineSegmentTraversalData (VspKdNode *n,
515                                                                  const Vector3 &p,
516                                                                  const float maxt):
517                mNode(n), mExitPoint(p), mMaxT(maxt) {}
518        };
519
520public:
521
522        VspKdTree();
523        virtual ~VspKdTree();
524
525        virtual void Construct(const VssRayContainer &rays,
526                                                   AxisAlignedBox3 *forcedBoundingBox = NULL);
527
528        /** Returns bounding box of the specified node.
529        */
530        AxisAlignedBox3 GetBBox(VspKdNode *node) const;
531
532        const VspKdStatistics &GetStatistics() const;
533
534        /** Get the root of the tree.
535        */
536        VspKdNode *GetRoot() const;
537
538        /** Returns average PVS size in tree.
539        */
540        float GetAvgPvsSize();
541
542        /** Returns memory usage in MB.
543        */
544        float GetMemUsage() const;
545       
546        float GetRayMemUsage() const;
547
548        /** Collects leaves of this tree.
549        */
550        void CollectLeaves(vector<VspKdLeaf *> &leaves) const;
551
552        /** Merges leaves of this tree according to some criteria.
553        */
554        int MergeLeaves();
555
556        /** Finds neighbours of this node.
557                @param n the input node
558                @param neighbours the neighbors of the input node
559                @param onlyUnmailed if only unmailed neighbors are collected
560        */
561        int FindNeighbors(VspKdLeaf *n,
562                                          vector<VspKdLeaf *> &neighbors,
563                                          bool onlyUnmailed);
564
565       
566        /** Sets pointer to view cells manager.
567        */
568        void SetViewCellsManager(ViewCellsManager *vcm);
569
570        /** A ray is cast possible intersecting the tree.
571                @param the ray that is cast.
572                @returns the number of intersections with objects stored in the tree.
573        */
574        int CastLineSegment(const Vector3 &origin,
575                                                const Vector3 &termination,
576                                                vector<ViewCell *> &viewcells);
577
578        /** Collects view cells generated by this tree.
579        */
580        void CollectViewCells(ViewCellContainer &viewCells) const;
581
582        /** Traverses tree and counts all view cells as well as their PVS size.
583        */
584        void EvaluateViewCellsStats(ViewCellsStatistics &stat) const;
585
586protected:
587
588        // incremental construction
589        virtual void UpdateRays(VssRayContainer &remove, VssRayContainer &add);
590
591        virtual void AddRays(VssRayContainer &add);
592
593        VspKdNode *Locate(const Vector3 &v);
594       
595        VspKdNode *SubdivideNode(VspKdLeaf *leaf,
596                                                                 const AxisAlignedBox3 &box,
597                                                                 AxisAlignedBox3 &backBox,
598                                                                 AxisAlignedBox3 &frontBox);
599       
600        VspKdNode *Subdivide(const TraversalData &tdata);
601       
602        int SelectPlane(VspKdLeaf *leaf,
603                                        const AxisAlignedBox3 &box,
604                                        float &position,
605                                        int &raysBack,
606                                        int &raysFront,
607                                        int &pvsBack,
608                                        int &pvsFront);
609
610        void SortSplitCandidates(VspKdLeaf *node,
611                                                         const int axis);       
612 
613        float BestCostRatioHeuristic(VspKdLeaf *node,
614                                                                 int &axis,
615                                                                 float &position,
616                                                                 int &raysBack,
617                                                                 int &raysFront,
618                                                                 int &pvsBack,
619                                                                 int &pvsFront);
620
621        float BestCostRatioRegular(VspKdLeaf *node,
622                                                           int &axis,
623                                                           float &position,
624                                                           int &raysBack,
625                                                           int &raysFront,
626                                                           int &pvsBack,
627                                                           int &pvsFront);
628       
629        float EvalCostRatio(VspKdLeaf *node,
630                                                const int axis,
631                                                const float position,
632                                                int &raysBack,
633                                                int &raysFront,
634                                                int &pvsBack,
635                                                int &pvsFront);
636
637
638        VspKdNode * SubdivideLeaf(VspKdLeaf *leaf,
639                                                                  const float SAThreshold);
640
641        void RemoveRay(VssRay *ray,
642                                   vector<VspKdLeaf *> *affectedLeaves,
643                                   const bool removeAllScheduledRays);
644
645        void AddRay(VssRay *ray);
646       
647        void TraverseInternalNode(RayTraversalData &data,
648                                                         stack<RayTraversalData> &tstack);
649
650        void EvaluateLeafStats(const TraversalData &data);
651
652
653        int     GetRootPvsSize() const;
654       
655        int     GetPvsSize(VspKdNode *node, const AxisAlignedBox3 &box) const;
656
657        void GetRayContributionStatistics(float &minRayContribution,
658                                                                          float &maxRayContribution,
659                                                                          float &avgRayContribution);
660
661        int GenerateRays(const float ratioPerLeaf,
662                                         SimpleRayContainer &rays);
663
664        /** Collapses this subtree and releases the memory.
665                @returns number of collapsed rays.
666        */
667        int CollapseSubtree(VspKdNode *sroot, const int time);
668       
669        int ReleaseMemory(const int time);
670
671        bool TerminationCriteriaMet(const VspKdLeaf *leaf,
672                                                                const AxisAlignedBox3 &box) const;
673
674        /** Computes PVS size of this node given a global ray set.
675                @returns PVS size of the intersection of this node bounding box with the rays.
676        */
677        int ComputePvsSize(VspKdNode *node,
678                                           const RayInfoContainer &globalRays) const;
679
680
681        /** Generates view cell for this leaf taking the ray contributions.
682        */
683        void GenerateViewCell(VspKdLeaf *leaf);
684
685        /** Merges view cells of the two leaves.
686        */
687        bool MergeViewCells(VspKdLeaf *l1, VspKdLeaf *l2);
688
689        /** Collapses the tree with respect to the view cell partition.
690                @returns node of type leaf if the node could be collapsed, this node otherwise
691        */
692        VspKdNode *CollapseTree(VspKdNode *node);
693       
694        /** Helper function revalidating the view cell leaf list after merge.
695        */
696        void ValidateViewCellLeaves();
697
698protected:
699       
700
701        /////////////////////////////
702        // The core pointer
703        VspKdNode *mRoot;
704 
705        /////////////////////////////
706        // Basic properties
707
708        // total number of nodes of the tree
709        int mNumNodes;
710       
711        // axis aligned bounding box of the scene
712        AxisAlignedBox3 mBox;
713
714        // epsilon used for the construction
715        float mEpsilon;
716
717        // ratio between traversal and intersection costs
718        float mCtDivCi;
719       
720        // type of the splitting to use for the tree construction
721        enum {ESplitRegular, ESplitHeuristic};
722        int splitType;
723       
724        // maximum alovable memory in MB
725        float mMaxTotalMemory;
726
727        // maximum alovable memory for static kd tree in MB
728        float mMaxStaticMemory;
729
730        // this is used during the construction depending
731        // on the type of the tree and queries...
732        float mMaxMemory;
733
734        // minimal acess time for collapse
735        int mAccessTimeThreshold;
736
737        // minimal depth at which to perform collapse
738        int mMinCollapseDepth;
739       
740        // reusable array of split candidates
741        vector<SortableEntry> *mSplitCandidates;
742       
743        ViewCellsManager *mViewCellsManager;
744
745        /// maximal cost ratio of a merge
746        float mMaxCostRatio;
747
748        /////////////////////////////
749        // Construction parameters
750
751        /// max depth of the tree
752        int mTermMaxDepth;
753
754        /// minimal ratio of the volume of the cell and the query volume
755        float mTermMinSize;
756
757        /// minimal pvs per node to still get subdivided
758        int mTermMinPvs;
759
760        /// minimal ray number per node to still get subdivided
761        int mTermMinRays;
762       
763        /// maximal cost ration to subdivide a node
764        float mTermMaxCostRatio;
765       
766        /// maximal contribution per ray to subdivide the node
767        float mTermMaxRayContribution;
768
769        /// if only the "driving axis", i.e., the axis with the biggest extent
770        /// should be used for subdivision
771        bool mOnlyDrivingAxis;
772
773        /// maximal numbers of view cells
774        int mMaxViewCells;
775
776        /// minimal number of view cells
777        int mMinViewCells;
778
779        /////////////////////////////
780        VspKdStatistics mStat; 
781};
782
783
784#endif // __VSP_KDTREE_H__
785
Note: See TracBrowser for help on using the repository browser.