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

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