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

Revision 482, 18.1 KB checked in by mattausch, 19 years ago (diff)

added visualizations

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