source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.h @ 3282

Revision 3282, 21.0 KB checked in by mattausch, 15 years ago (diff)

probably found export error

Line 
1// This file has been written by Jiri Bittner, October 2006
2
3#ifndef __BVH_H
4#define __BVH_H
5
6#include "common.h"
7#include "Vector3.h"
8#include "AxisAlignedBox3.h"
9
10
11
12namespace CHCDemoEngine
13{
14
15// the number of visibility states
16#define NUM_STATES 2
17
18////////
19//-- Forward declarations
20
21class SceneEntity;
22class Camera;
23class RenderState;
24
25
26/** A node in the bv hierarchy.
27*/
28class BvhNode
29{
30        friend class Bvh;
31        friend class BvhFactory;
32        friend class BvhExporter;
33        friend class BvhConstructor;
34
35public:
36
37        /** visibility related options
38        */
39        struct VisibilityInfo
40        {
41                VisibilityInfo() { Reset(); }           
42                /** Reset the visibility info.
43                */
44                void Reset();
45
46                /// if the node is visible
47                bool mIsVisible;
48                /// frame id until this node is assumed to stay visible
49                int mAssumedVisibleFrameId;
50                /// the frame when this node was last touched during traversal
51                int mLastVisitedFrame;
52                /// #times this node was invisible (only valid if the node actually is invisible)
53                int mTimesInvisible;
54                /// if the node is view frustum culled
55                bool mIsFrustumCulled;
56                /// if the node is newly processed with no prior history available
57                bool mIsNew;
58                /// the frame this node was last queried
59                int mLastQueriedFrame;
60        };
61
62        /** Constructor taking the parent node.
63        */
64        BvhNode(BvhNode *parent);
65        /** Virtual destructor doing nothing.
66        */
67        virtual ~BvhNode();
68        /** Reset the status of this node.
69        */
70        virtual void ResetVisibility();
71        /** Returns true if this node is a leaf.
72        */
73        virtual bool IsLeaf() const = 0;
74        /** Depth of this node in the tree.
75        */
76        inline int GetDepth() const;
77        /** Returns parent of this bvh node, NULL if it is root.
78        */
79        inline BvhNode *GetParent();
80        /** Number of leaves in the subtree induced by this node.
81        */
82        inline int GetNumLeaves() const;
83        /** Returns true if this node is a "virtual" leaf,
84                i.e., the node is handled as a leaf during traversal.
85        */
86        inline bool IsVirtualLeaf() const;
87        /** Returns the stored distance to the near plane.
88        */
89        inline float GetDistance() const;
90        /** Returns id of the first scene entity in the node.
91        */
92        inline int GetFirstEntity() const;
93        /** Returns id of the last scene entity in the node.
94        */
95        inline int GetLastEntity() const;
96
97
98        ////////////////
99        //-- visibility culling related functions
100
101        inline int GetLastVisitedFrame() const;
102
103        inline void SetLastVisitedFrame(int lastVisited);
104        /** If this node is considered visible.
105        */
106        inline bool IsVisible() const;
107        /** Set visibility flag of the node.
108        */
109        inline void SetVisible(bool visible);
110        /** The frame id until this node is assumed visible
111        */
112        inline void SetAssumedVisibleFrameId(int t);
113        /** See set.
114        */
115        inline int GetAssumedVisibleFrameId() const;
116        /** Increases the #times this node was
117                successfully tested invisible.
118        */
119        inline void IncTimesTestedInvisible();
120       
121        inline int GetTimesTestedInvisible() const;
122        inline void SetTimesTestedInvisible(int t);
123       
124        inline int GetTurnedVisibleFrame() const;
125        inline void SetTurnedVisibleFrame(int turnedVisibleFrame);
126
127        inline int GetLastQueriedFrame() const;
128        inline void SetLastQueriedFrame(int lastTested);
129       
130        inline bool IsViewFrustumCulled() const;
131        inline void SetViewFrustumCulled(bool frustumCulled);
132
133        inline bool IsNew() const;
134        inline void SetIsNew(bool isNew);
135
136
137        /** Returns the bounding box of this node.
138        */
139        inline const AxisAlignedBox3 &GetBox() const;
140        /** Return index of this node.
141        */
142        inline int GetId() const;
143        /** See get
144        */
145        inline void SetId(int id);
146       
147
148        //////////
149        //-- rendering
150       
151        /** Returns the frame in which this node was last rendered.
152        */
153        inline int GetLastRenderedFrame() const;
154        /** See get.
155        */
156        inline void SetLastRenderedFrame(int lastRenderedFrame);
157        /** Does this node contain renderable geometry?
158        */
159        inline bool Empty() const;
160        /** Counts #geometry stored in the subtree.
161        */
162        inline int CountPrimitives() const;
163        /** This function is important in case you have more than one
164                view position within a frame (e.g., camera view and shadow view for
165                shadow mapping), because each camera needs its own state in
166                order to not break temporal coherency.
167        */
168        inline static void SetCurrentState(int _state);
169
170
171protected:
172
173        /// the depth of this node
174        unsigned char mDepth;
175        /// the split axis
176        char mAxis;
177        /// the parent node
178        BvhNode *mParent;
179
180
181        //////////////
182        //-- members definig the current visibility state (one state per camera)
183
184        /// the currently used state
185        static int sCurrentState;
186
187        /// stores the visibility related info
188        VisibilityInfo mVisibility[NUM_STATES];
189        /// when the node was last rendered
190        int mLastRenderedFrame[NUM_STATES];
191
192
193        ///////////////
194        //-- members that help to speed up view frustum culling
195
196        /// masks out planes of the frustum that do not have to be tested against
197        int mPlaneMask[NUM_STATES];
198        /// the plane that is usually responsible for culling this node.
199        /** if our educated guess was right, we save up to 5 comparisons.
200        */
201        int mPreferredPlane[NUM_STATES];
202
203
204        ////////////////////
205
206
207        /// #leaves under this node
208        int mNumLeaves;
209        /// Area of this node
210        float mArea;
211        /// distance to the camera
212        float mDistance;
213        /// the index of this node
214        unsigned int mId;
215        /// the bounding box
216        AxisAlignedBox3 mBox;
217        /// if this node is a virtual leaf
218        bool mIsVirtualLeaf;
219        /** This marks the maximal depth where a virtual leaf can be defined.
220            From this point on it makes no sense to traverse down further, as all
221                nodes below contain the same geometry, so no further refinement of visibility
222                can be archieved. All nodes below this point can merely used to define the
223                tighter bounds.
224        */
225        bool mIsMaxDepthForVirtualLeaf;
226
227
228        ////////////
229        //-- rendering related options
230       
231        // Indices to first and last triangle in the triangle array
232        // assumes the triangle are placed in continuous chunk of memory
233        // however this need not be a global array!
234       
235        /// the index of the first triangle
236        int mFirst;
237        /// the index of the last triangle
238        int mLast;
239
240
241        ////////////////
242        //-- rendering related options
243
244        /// we  query the bounding boxes of the test nodes when testing this node
245        int mTestNodesIdx;
246        /// the number of these test nodes
247        int mNumTestNodes;
248        /// used for efficient element array rendering
249        int mIndicesPtr;
250};
251
252
253
254/** Internal node of the bv hierarchy.
255*/
256class BvhInterior: public BvhNode
257{
258        friend class Bvh;
259        friend class BvhFactory;
260        friend class BvhExporter;
261        friend class BvhConstructor;
262
263public:
264
265        BvhInterior(BvhNode *parent);
266       
267        virtual bool IsLeaf() const;
268        /** Back child.
269        */
270        inline BvhNode *GetBack();
271        /** Front child.
272        */
273        inline BvhNode *GetFront();
274        /** Recursivly delete hierarchy.
275        */
276        virtual ~BvhInterior();
277
278
279protected:
280
281        BvhNode *mBack;
282        BvhNode *mFront;
283};
284
285
286
287class BvhLeaf: public BvhNode
288{
289        friend class Bvh;
290        friend class BvhFactory;
291
292public:
293
294        BvhLeaf(BvhNode *parent);
295
296        ~BvhLeaf();
297
298        virtual bool IsLeaf() const;
299};
300
301
302/**     This class implements the compare operator for the priority queue.
303        a lower distance has a higher value in the queue
304*/
305class GtDistance
306{
307public:
308        bool operator() (BvhNode *v1, BvhNode *v2) const
309    {
310                return (v1->GetDistance() > v2->GetDistance());
311    }
312};
313
314
315typedef std::priority_queue<BvhNode *, std::vector<BvhNode *>, GtDistance> TraversalQueue;
316
317
318/** Class representing a bounding volume hierarchy.
319*/
320class Bvh
321{
322        friend class BvhFactory;
323        friend class BvhConstructor;
324        friend class BvhExporter;
325
326        /** Bvh properties
327        */
328        struct BvhStats
329        {
330                BvhStats() { Reset(); }
331
332                void Reset()
333                {
334                        mInteriorSA = .0f;
335                        mLeafSA = .0f;
336                        mInteriorVol = .0f;
337                        mLeafVol = .0f;
338                        mTriangleRatio = .0f;
339                        mGeometryRatio = .0f;
340
341                        mTriangles = 0;
342                        mLeaves = 0;
343                }
344
345                ///////////////////
346
347                float mInteriorSA;
348                float mLeafSA;
349                float mInteriorVol;
350                float mLeafVol;
351               
352                float mTriangleRatio;
353                float mGeometryRatio;
354
355                int mTriangles;
356                int mLeaves;
357        };
358
359public:
360
361        /** Destructor.
362        */
363        ~Bvh();
364        /** Returns number of bvh nodes.
365        */
366        inline int GetNumNodes() const;
367        /** Counts the number of nodes in this subtree
368        */
369        int CountNumNodes(BvhNode *node) const;
370        /** Counts the number of virtual nodes in this subtree
371        */
372        int CountNumVirtualNodes(BvhNode *node) const;
373
374        /** Returns number of bvh leaves.
375        */
376        inline int GetNumLeaves() const;
377        /** Returns number of 'virtual' nodes in the hierarchy, i.e.
378                the number of nodes actually used for traversal.
379        */
380        inline int GetNumVirtualNodes() const;
381        /** Returns number of bvh leaves.
382        */
383        inline int GetNumVirtualLeaves() const;
384        /** Returns root node of the bvh.
385        */
386        inline BvhNode *GetRoot();
387        /** Returns the static root node of the bvh.
388        */
389        inline BvhNode *GetStaticRoot();
390        /** Returns the dynamic root node of the bvh.
391        */
392        inline BvhNode *GetDynamicRoot();
393        /** Returns the bounding box of this bvh.
394        */
395        inline const AxisAlignedBox3 &GetBox() const;
396        /** Returns true if the current bvh node intersects the near plane.
397        */
398        bool IntersectsNearPlane(BvhNode *node) const;
399
400
401        ///////////////
402        //-- functions collecting nodes based on some criteria
403
404        /** Collect all child nodes in a given depth from the specified node.
405        */
406        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
407        /** Collect all child nodes.
408        */
409        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
410        /** Collect the "physical" leaves of the hierarchy
411        */
412        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
413        /** Collect only the virtual leaves (can be anywhere in the hierarchy).
414        */
415        void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
416
417
418        //////////////////////
419
420        /** Returns geometry by reference (faster).
421        */
422        SceneEntity **GetGeometry(BvhNode *node, int &size) const;
423
424
425        /////////////
426        //-- Rendering related options
427
428        /** Renders the bounds of this node
429            (the box of the node or the tigher bounds of some subnodes).
430        */
431        void RenderBounds(BvhNode *node, RenderState *state, bool useTightBounds);
432        /** Renders bounding boxes of the collection of nodes.
433                @returns #rendered boxes
434        */
435        int RenderBounds(const BvhNodeContainer &nodes, RenderState *state, bool useTightBounds);
436       
437
438
439        //////////////
440        //-- Traversal related options
441
442        /** Pulls up visible classification.
443        */
444        void MakeParentsVisible(BvhNode *node);
445        /** Does the view frustum culling for this node with respect to the previous culls
446                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
447        */
448        int     IsWithinViewFrustum(BvhNode *node);
449        /** Sets frame dependent values
450        */
451        void InitFrame(Camera *camera, RenderState *state);
452        /** Stores the orthogonal distance from the viewpoint to a point on the node.
453                We choose the the nearest bounding box vertex .
454                Note that negative values can appear because culling is done only afterwards
455        */
456        void UpdateDistance(BvhNode *node) const;
457        /** Returns the maximum distance from the near plane to this node.
458        */
459        float CalcMaxDistance(BvhNode *node) const;
460        /** Pulls up the last visited classification in the bvh.
461        */
462        void PullUpLastVisited(BvhNode *node, int frameId) const;
463        /** Resets the node classifications in the tree.
464        */
465        void ResetNodeClassifications();
466        /** Counts the number of triangles contained in this node.
467        */
468        int CountTriangles(BvhNode *node) const;
469        /** Returns area of the the node.
470        */
471        float GetArea(BvhNode *node) const;
472        /** Compute unique ids for the nodes.
473        */
474        void ComputeIds();
475        /** Assign virtual leaves based on specified number of triangles per leaf.
476                That means that we try to set the leaves at a point where we
477                have less than numTriangles triangles within this leaf and beyond.
478
479                Virtual leaves are nodes that are determined to be the leaves
480                of the hierarchy during render traversal. These nodes are not necessarily
481                the same as the real leaves of the hierarchy and can be anywhere
482                in the hierarchy.
483                Please refer to the article for more info about virtual leaves
484        */
485        void SetVirtualLeaves(int numTriangles);
486       
487
488        ////////////
489        //-- these functions determine the 'tightness' of the bounds that are used for querying
490
491
492        /** Sets maximal depth for taking the bounding boxes to test the
493                visibility of a node.
494                Deeper level means that the bounds adapt more to the geometry but
495                also that more boxes are rendered
496        */
497        void SetMaxDepthForTestingChildren(int maxDepth);
498        /** The ratio of area between node and subnodes where
499                testing the subnodes as proxy is still considered feasable
500        */
501        void SetAreaRatioThresholdForTestingChildren(float ratio);
502
503
504        ////////////////////////////
505
506        /** Returns statistics.
507        */
508        const BvhStats &GetBvhStats() const { return mBvhStats; }
509        /** Render wireframe bvh for visualization purpose.
510        */
511        void RenderBoundsForViz(BvhNode *node, RenderState *state, bool useTightBounds);
512
513       
514protected:
515
516        ////////////////////
517
518        /** protected constructor: do nothing.
519        */
520        Bvh();
521        /** Protected constructor taking scene geometry into account
522                Sets the static and dynamic objects for the hierarchy.
523        */
524        Bvh(const SceneEntityContainer &staticEntities,
525            const SceneEntityContainer &dynamicEntities);
526        /** Protected constructor taking scene geometry into account
527                Sets the static and dynamic objects for the hierarchy.
528        */
529        Bvh(const SceneEntityContainer &staticEntities,
530            const SceneEntityContainer &dynamicEntities,
531            int maxDepthForTestingChildren);
532        /** Called by the constructor. Initializes important members.
533        */
534        void Init();
535
536
537        /////////////
538        /** Traverse hierarchy and compute stats.
539        */
540        void ComputeBvhStats(BvhNode *root, BvhStats &bvhStats);
541        /** Output the bvh statistics.
542        */
543        void PrintBvhStats(const BvhStats &bvhStats, BvhNode *root) const;
544
545
546        //////////
547        //-- Helper methods for bounding box rendering in immediate and vbo mode.
548       
549        void PrepareVertices();
550        /** Prepare nodes for vbo rendering.
551        */
552        int PrepareBoundsWithDrawArrays(const BvhNodeContainer &nodes);
553        /** Render the nodes from the vbo prepared previously.
554        */
555        void RenderBoundsWithDrawArrays(int numNodes, RenderState *state);
556
557        /** Create the indices that each node needs to use vbo rendering.
558        */
559        void CreateIndices();
560        /** Create the list of nodes whose bounding boxes are tested instead of the
561                bounding box of the node itself.
562        */
563        bool CreateNodeRenderList(BvhNode *node);
564        /** Recursivly updates indices so we can
565                render also interior nodes without traversing hierarchy
566        */
567        void UpdateInteriors(BvhNode *node);
568        /** Recomputes the boundaries of the nodes.
569            This function is always called if some boundary options are changed.
570        */
571        void RecomputeBounds();
572        /** Does some postprocessing on the nodes.
573        */
574        void PostProcess();
575        /** Helper method that updates the number of leaves in the subtree under
576                this node.
577        */
578        void UpdateNumLeaves(BvhNode *node) const;
579        /** Frustum tests the ith plane.
580        */
581        inline bool TestPlane(BvhNode *node, int i, bool &bIntersect);
582        /** Renders a bounding box in immediate mode.
583        */
584        void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
585
586
587        /////////////////////////////
588        //-- functions used to construct the dynamic part of the hierarchy
589
590        int SortTriangles(BvhLeaf *leaf,
591                              int axis,
592                                          float position);
593
594        int SortTrianglesSpatialMedian(BvhLeaf *leaf,
595                                           int axis);
596
597        BvhNode *SubdivideLeaf(BvhLeaf *leaf,
598                                   int parentAxis);
599        /** Recompute the dynamic branch of the hierarchy.
600        */
601        void CreateDynamicBranch();
602
603        void UpdateBoundingBoxes(BvhNode *node);
604
605        inline bool TerminationCriteriaMet(BvhLeaf *leaf) const;
606
607        void ComputeMaxDepthForVirtualLeaves();
608
609        void CreateRoot();
610
611        void UpdateDynamicBounds(RenderState *state);
612
613
614        ////////////////////////
615       
616        /// the bounding box of the bvh
617        AxisAlignedBox3 mBox;
618        /// the root of the hierarchy
619        BvhInterior *mRoot;
620        /// the root of static part of the the hierarchy
621        BvhNode *mStaticRoot;
622        /// the root of dynamic part of the the hierarchy
623        BvhNode *mDynamicRoot;
624        /// pointers to the geometry associated with this node
625        SceneEntity **mGeometry;
626        /// #of entities
627        size_t mGeometrySize;
628        /// #of static entities
629        size_t mStaticGeometrySize;
630        /// #of dynamic entities
631        size_t mDynamicGeometrySize;
632
633
634        ////////////////
635        //-- tigher bounds termination criteria
636
637        /** maximal depth from which children are fetched for
638                testing instead of the current node
639        */
640        int mMaxDepthForTestingChildren;
641        /// threshold for computing tighter bounds
642        float mAreaRatioThreshold;
643       
644       
645        ////////////////
646        //-- statistics
647
648        BvhStats mBvhStats;
649        /// the overall number of nodes
650        int mNumNodes;
651        /// the number of "virtual" (=actually used) nodes
652        int mNumVirtualNodes;
653
654
655        ////////////
656        //-- rendering stuff
657
658        /// these proxy nodes are tested instead of the current node
659        BvhNodeContainer mTestNodes;
660        /// the indices used for vbo index buffering
661        unsigned int *mTestIndices;
662        /// a pointer to the end of the indices array
663        int mCurrentIndicesPtr;
664        /// the vbo id
665        unsigned int mVboId;
666        /// a vertex array used if working with indexed arrays (without vbo)
667        Vector3 *mVertices;
668        /// indices used for draw array rendering
669        unsigned int *mIndices;
670
671
672        ///////////
673        //-- termination criteria for dynamic branch
674
675        int mMaxDepthForDynamicBranch;
676
677        //SceneEntityContainer mDynamicEntities;
678};
679
680
681
682/////////////////
683//-- public inline functions
684
685
686inline int BvhNode::GetLastVisitedFrame() const
687{
688        return mVisibility[sCurrentState].mLastVisitedFrame;
689}
690
691
692inline void BvhNode::SetLastVisitedFrame(const int lastVisited)
693{
694        mVisibility[sCurrentState].mLastVisitedFrame = lastVisited;
695}
696
697
698inline bool BvhNode::IsVisible() const
699{
700        return mVisibility[sCurrentState].mIsVisible;
701}
702
703
704inline void BvhNode::SetVisible(bool visible)
705{
706        mVisibility[sCurrentState].mIsVisible = visible;
707}
708
709
710inline void BvhNode::IncTimesTestedInvisible()
711{
712        ++ mVisibility[sCurrentState].mTimesInvisible;
713}
714
715
716inline int BvhNode::GetTimesTestedInvisible() const
717{
718        return mVisibility[sCurrentState].mTimesInvisible;
719}
720
721
722inline void BvhNode::SetTimesTestedInvisible(int t)
723{
724        mVisibility[sCurrentState].mTimesInvisible = t;
725}
726
727
728inline bool BvhNode::IsViewFrustumCulled() const
729{
730        return mVisibility[sCurrentState].mIsFrustumCulled;
731}
732
733
734inline void BvhNode::SetViewFrustumCulled(bool frustumCulled)
735{
736        mVisibility[sCurrentState].mIsFrustumCulled = frustumCulled;
737}
738
739
740inline bool BvhNode::IsNew() const
741{
742        return mVisibility[sCurrentState].mIsNew;
743}
744
745
746inline void BvhNode::SetIsNew(bool isNew)
747{
748        mVisibility[sCurrentState].mIsNew = isNew;
749}
750
751
752inline void BvhNode::SetAssumedVisibleFrameId(int t)
753{
754        mVisibility[sCurrentState].mAssumedVisibleFrameId = t;
755}
756
757
758inline int BvhNode::GetAssumedVisibleFrameId() const
759{
760        return mVisibility[sCurrentState].mAssumedVisibleFrameId;
761}
762
763
764inline int BvhNode::GetLastQueriedFrame() const
765{
766        return mVisibility[sCurrentState].mLastQueriedFrame;
767}
768
769
770inline void BvhNode::SetLastQueriedFrame(int lastTested)
771{
772        mVisibility[sCurrentState].mLastQueriedFrame = lastTested;
773}
774
775
776inline int BvhNode::GetLastRenderedFrame() const
777{
778        return mLastRenderedFrame[sCurrentState];
779}
780       
781
782inline void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
783{
784        mLastRenderedFrame[sCurrentState] = lastRenderedFrame;
785}
786       
787       
788inline bool BvhNode::Empty() const
789{
790        return (mFirst == -1);
791}
792
793
794inline int BvhNode::CountPrimitives() const
795{
796        return mLast - mFirst + 1;
797}
798
799inline int BvhNode::GetDepth() const
800{
801        return mDepth;
802}
803
804
805inline BvhNode *BvhNode::GetParent()
806{
807        return mParent;
808}
809
810
811inline int BvhNode::GetNumLeaves() const
812{
813        return mNumLeaves;
814}
815
816
817inline bool BvhNode::IsVirtualLeaf() const
818{
819        return mIsVirtualLeaf;
820}
821
822
823inline float BvhNode::GetDistance() const
824{
825        return mDistance;
826}
827
828       
829inline const AxisAlignedBox3 &BvhNode::GetBox() const
830{
831        return mBox;
832}
833
834
835inline int BvhNode::GetId() const
836{
837        return mId;
838}
839
840
841inline void BvhNode::SetId(int id)
842{
843        mId = id;
844}
845
846
847inline void BvhNode::SetCurrentState(int _state)
848{
849        sCurrentState = _state;
850}
851
852
853inline int BvhNode::GetFirstEntity() const
854{
855        return mFirst;
856}
857
858
859inline int BvhNode::GetLastEntity() const
860{
861        return mLast;
862}
863
864
865inline BvhNode *BvhInterior::GetBack()
866{
867        return mBack;
868}
869
870
871inline BvhNode *BvhInterior::GetFront()
872{
873        return mFront;
874}
875
876
877
878//////////////////////////////
879
880       
881inline int Bvh::GetNumNodes() const
882{
883        return mNumNodes;
884}
885
886
887inline int Bvh::GetNumLeaves() const
888{
889        return mNumNodes / 2 + 1;
890}
891
892
893inline int Bvh::GetNumVirtualNodes() const 
894{
895        return mNumVirtualNodes;
896}
897
898
899inline int Bvh::GetNumVirtualLeaves() const
900{
901        return mNumVirtualNodes / 2 + 1;
902}
903
904
905inline BvhNode *Bvh::GetRoot()
906{
907        return mRoot;
908}
909
910
911inline BvhNode *Bvh::GetDynamicRoot()
912{
913        return mDynamicRoot;
914}
915
916
917inline BvhNode *Bvh::GetStaticRoot()
918{
919        return mStaticRoot;
920}
921
922
923inline const AxisAlignedBox3 &Bvh::GetBox() const
924{
925        return mBox;
926}
927
928
929}
930
931#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.