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

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