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

Revision 2895, 15.8 KB checked in by mattausch, 16 years ago (diff)
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//#include "SceneEntity.h"
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 BvhLoader;
32        friend class mygreaterdistance;
33
34public:
35
36        /** visibility related options
37        */
38        struct VisibilityInfo
39        {
40                VisibilityInfo() { Reset(); }           
41                /** Reset the visibility info.
42                */
43                void Reset();
44
45                /// if the node is visible
46                bool mIsVisible;
47                /// frame id until this node is assumed to stay visible
48                int mAssumedVisibleFrameId;
49                /// the frame when this node was last touched during traversal
50                int mLastVisitedFrame;
51                /// #times this node was invisible (only valid if the node actually is invisible)
52                int mTimesInvisible;
53                /// if the node is view frustum culled
54                bool mIsFrustumCulled;
55                /// if the node is newly processed with no prior history available
56                bool mIsNew;
57                /// the frame this node was last queried
58                int mLastQueriedFrame;
59        };
60
61        /** Constructor taking the parent node.
62        */
63        BvhNode(BvhNode *parent);
64        /** Returns true if this node is a leaf.
65        */
66        //virtual bool IsPseudoLeaf() = 0;
67        /** Virtual destructor doing nothing.
68        */
69        virtual ~BvhNode();
70        /** Depth of this node in the tree.
71        */
72        inline int GetDepth() const {return mDepth;}
73        /** Returns parent of this bvh node, NULL if it is root.
74        */
75        inline BvhNode *GetParent() {return mParent;}
76        /** Number of leaves in the subtree induced by this node.
77        */
78        inline int GetNumLeaves() const {return mNumLeaves;}
79        /** Reset the status of this node.
80        */
81        virtual void ResetVisibility();
82
83        virtual bool IsLeaf() const = 0;
84
85        bool IsVirtualLeaf() const { return mIsVirtualLeaf; }
86
87
88        ////////////////
89        //-- visibility culling related functions
90
91        inline int GetLastVisitedFrame() const;
92
93        inline void SetLastVisitedFrame(int lastVisited);
94        /** If this node is considered visible.
95        */
96        inline bool IsVisible() const;
97        /** Set visibility flag of the node.
98        */
99        inline void SetVisible(bool visible);
100        /** The frame id until this node is assumed visible
101        */
102        inline void SetAssumedVisibleFrameId(int t);
103        /** See set.
104        */
105        inline int GetAssumedVisibleFrameId() const;
106        /** Increases the #times this node was
107                successfully tested invisible.
108        */
109        inline void IncTimesTestedInvisible();
110       
111        inline int GetTimesTestedInvisible() const;
112        inline void SetTimesTestedInvisible(int t);
113       
114        inline int GetTurnedVisibleFrame() const;
115        inline void SetTurnedVisibleFrame(int turnedVisibleFrame);
116
117        inline int GetLastQueriedFrame() const;
118        inline void SetLastQueriedFrame(int lastTested);
119       
120        inline bool IsViewFrustumCulled() const;
121        inline void SetViewFrustumCulled(bool frustumCulled);
122
123        inline bool IsNew() const;
124        inline void SetIsNew(bool isNew);
125
126
127        /** Returns the bounding box of this node.
128        */
129        inline const AxisAlignedBox3 &GetBox() { return mBox; }
130        /** Return index of this node.
131        */
132        inline int GetId() const { return mId; }
133        /** See get
134        */
135        inline void SetId(int id) { mId = id; }
136
137
138        //////////
139        //-- rendering
140       
141        /** Returns the frame in which this node was last rendered.
142        */
143        inline int GetLastRenderedFrame() const;
144        /** See get.
145        */
146        inline void SetLastRenderedFrame(int lastRenderedFrame);
147        /** Does this node contain renderable geometry?
148        */
149        inline bool Empty() const;
150        /** Counts #geometry stored in the subtree.
151        */
152        inline int CountPrimitives() const;
153
154        static void SetCurrentState(int _state) { sCurrentState = _state; }
155
156
157protected:
158
159        /// the depth of this node
160        unsigned char mDepth;
161        /// the split axis
162        char mAxis;
163        /// the parent node
164        BvhNode *mParent;
165
166
167        //////////////
168        //-- these members define the current state
169
170        /// stores the visibility related info
171        VisibilityInfo mVisibility[NUM_STATES];
172
173        /////////
174        //-- used for view frustum culling
175
176        int mPlaneMask[NUM_STATES];
177        int mPreferredPlane[NUM_STATES];
178
179        // the current state
180        static int sCurrentState;
181
182
183        ////////////////////
184
185
186        ////////////
187        //-- rendering related options
188       
189        /// when the node was last rendered
190        int mLastRenderedFrame;
191        /// #leaves under this node
192        int mNumLeaves;
193       
194        // Indices to first and last triangle in the triangle array
195        // assumes the triangle are placed in continuous chunk of memory
196        // however this need not be a global array!
197       
198        /// the index of the first triangle
199        int mFirst;
200        /// the index of the last triangle
201        int mLast;
202
203        /// the bounding boxes of these nodes are queries instead of the current node
204        int mTestNodesIdx;
205        /// the number of tighter bounding volumes used for this node
206        int mNumTestNodes;
207        /// used for efficient element array rendering
208        int mIndicesPtr;
209
210        /// Area of this node
211        float mArea;
212        /// distance to the camera
213        float mDistance;
214        /// the index of this node
215        unsigned int mId;
216        /// the bounding box
217        AxisAlignedBox3 mBox;
218        /// if this node is a virtual leaf
219        bool mIsVirtualLeaf;
220        /** This marks the maximal depth where a virtual leaf can be defined.
221            From this point on it makes no sense to traverse down further, as all
222                nodes below contain the same geometry, so no further refinement of visibility
223                can be archieved. All nodes below this point can merely used to define the
224                tighter bounds.
225        */
226        bool mIsMaxDepthForVirtualLeaf;
227};
228
229
230
231/////////////////
232//-- public inline functions
233
234
235int BvhNode::GetLastVisitedFrame() const
236{
237        return mVisibility[sCurrentState].mLastVisitedFrame;
238}
239
240
241void BvhNode::SetLastVisitedFrame(const int lastVisited)
242{
243        mVisibility[sCurrentState].mLastVisitedFrame = lastVisited;
244}
245
246
247bool BvhNode::IsVisible() const
248{
249        return mVisibility[sCurrentState].mIsVisible;
250}
251
252
253void BvhNode::SetVisible(bool visible)
254{
255        mVisibility[sCurrentState].mIsVisible = visible;
256}
257
258
259void BvhNode::IncTimesTestedInvisible()
260{
261        ++ mVisibility[sCurrentState].mTimesInvisible;
262}
263
264
265int BvhNode::GetTimesTestedInvisible() const
266{
267        return mVisibility[sCurrentState].mTimesInvisible;
268}
269
270
271void BvhNode::SetTimesTestedInvisible(int t)
272{
273        mVisibility[sCurrentState].mTimesInvisible = t;
274}
275
276
277bool BvhNode::IsViewFrustumCulled() const
278{
279        return mVisibility[sCurrentState].mIsFrustumCulled;
280}
281
282
283void BvhNode::SetViewFrustumCulled(bool frustumCulled)
284{
285        mVisibility[sCurrentState].mIsFrustumCulled = frustumCulled;
286}
287
288
289bool BvhNode::IsNew() const
290{
291        return mVisibility[sCurrentState].mIsNew;
292}
293
294
295void BvhNode::SetIsNew(bool isNew)
296{
297        mVisibility[sCurrentState].mIsNew = isNew;
298}
299
300
301void BvhNode::SetAssumedVisibleFrameId(int t)
302{
303        mVisibility[sCurrentState].mAssumedVisibleFrameId = t;
304}
305
306
307int BvhNode::GetAssumedVisibleFrameId() const
308{
309        return mVisibility[sCurrentState].mAssumedVisibleFrameId;
310}
311
312
313int BvhNode::GetLastQueriedFrame() const
314{
315        return mVisibility[sCurrentState].mLastQueriedFrame;
316}
317
318
319void BvhNode::SetLastQueriedFrame(int lastTested)
320{
321        mVisibility[sCurrentState].mLastQueriedFrame = lastTested;
322}
323
324int BvhNode::GetLastRenderedFrame() const
325{
326        return mLastRenderedFrame;
327}
328       
329
330void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
331{
332        mLastRenderedFrame = lastRenderedFrame;
333}
334       
335       
336bool BvhNode::Empty() const
337{
338        return mFirst == -1;
339}
340
341
342int BvhNode::CountPrimitives() const
343{
344        return mLast - mFirst + 1;
345}
346
347
348
349
350
351/** Internal node of the bv hierarchy.
352*/
353class BvhInterior: public BvhNode
354{
355        friend class Bvh;
356        friend class BvhLoader;
357
358public:
359
360        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
361        {}
362        virtual bool IsLeaf() const { return false; }
363        /** Back child.
364        */
365        inline BvhNode *GetBack() { return mBack; }
366        /** Front child.
367        */
368        inline BvhNode *GetFront() { return mFront; }
369        /** Recursivly delete hierarchy.
370        */
371        virtual ~BvhInterior();
372
373protected:
374
375        BvhNode *mBack;
376        BvhNode *mFront;
377};
378
379
380class BvhLeaf: public BvhNode
381{
382        friend class Bvh;
383        friend class BvhLoader;
384
385public:
386
387        BvhLeaf(BvhNode *parent): BvhNode(parent)
388        {}
389
390        ~BvhLeaf();
391
392        virtual bool IsLeaf() const { return true; }
393};
394
395
396/**     This class implements the compare operator for the priority queue.
397        a lower distance has a higher value in the queue
398*/
399class mygreaterdistance
400{
401public:
402        bool operator() (BvhNode *v1, BvhNode *v2) const
403    {
404                return (v1->mDistance > v2->mDistance);
405    }
406};
407
408typedef std::priority_queue<BvhNode *, std::vector<BvhNode *>, mygreaterdistance> TraversalQueue;
409
410
411/** Class representing a bounding volume hierarchy.
412*/
413class Bvh
414{
415        friend class BvhLoader;
416
417        /** Bvh properties
418        */
419        struct BvhStats
420        {
421                BvhStats():
422                mInteriorSA(0),
423                mLeafSA(0),
424                mInteriorVol(0),
425                mLeafVol(0),
426                mTriangles(0),
427                mTriangleRatio(0),
428                mGeometryRatio(0),
429                mMaxGeometry(0),
430                mMaxTriangles(0)
431                {}
432               
433                float mInteriorSA;
434                float mLeafSA;
435                float mInteriorVol;
436                float mLeafVol;
437               
438                int mTriangles;
439
440                float mTriangleRatio;
441                float mGeometryRatio;
442
443                int mMaxGeometry;
444                int mMaxTriangles;
445        };
446
447public:
448
449        /** Destructor.
450        */
451        ~Bvh();
452        /** Returns number of bvh nodes.
453        */
454        inline int GetNumNodes() const { return mNumNodes; }
455        /** Returns number of bvh leaves.
456        */
457        inline int GetNumLeaves() const { return mNumNodes / 2 + 1;}
458        /** Returns number of 'virtual' nodes in the hierarchy, i.e.
459                the number of nodes actually used for traversal.
460        */
461        int GetNumVirtualNodes() const  { return mNumVirtualNodes; }
462        /** Returns number of bvh leaves.
463        */
464        inline int GetNumVirtualLeaves() const { return mNumVirtualNodes / 2 + 1;}
465        /** Returns root node of the bvh.
466        */
467        BvhNode *GetRoot() { return mRoot; }
468        /** Sets the scene camera
469        */
470        void SetCamera(Camera * camera) { mCamera = camera; }
471
472        ///////////////
473        //-- functions collecting nodes based on some criteria
474
475        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
476        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
477        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
478        /** Collect only the virtual leaves.
479        */
480        void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
481
482
483        //////////////////////
484
485        /** Returns geometry by reference (faster).
486        */
487        SceneEntity **GetGeometry(BvhNode *node, int &size);
488
489
490        /////////////
491        //-- Rendering related options
492
493        /** Renders the bounds of this node
494            (the box of the node or the tigher bounds of some subnodes).
495        */
496        void RenderBounds(BvhNode *node, RenderState *state, bool useTightBounds);
497        /** Renders bounding boxes of the collection of nodes.
498                @returns #rendered boxes
499        */
500        int RenderBounds(const BvhNodeContainer &nodes, RenderState *state, bool useTightBounds);
501        /** Returns the bounding box of this bvh.
502        */
503        inline const AxisAlignedBox3 &GetBox() { return mBox; }
504
505
506        //////////////
507        //-- Traversal related options
508
509        /** Pulls up visible classification.
510        */
511        void MakeParentsVisible(BvhNode *node);
512        /** Does the view frustum culling for this node with respect to the previous culls
513                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
514        */
515        int     IsWithinViewFrustum(BvhNode *node);
516        /** Sets frame dependent values
517        */
518        void InitFrame();
519        /** This gives the orthogonal distance from the viewpoint to the nearest bounding box vertex
520                note that negative values can appear because culling is done only afterwards
521        */
522        void CalcDistance(BvhNode *node) const;
523        /** Returns the stored distance.
524        */
525        float GetDistance(BvhNode *node) const  { return node->mDistance; }
526        /** Pulls up the last visited classification in the bvh.
527        */
528        void PullUpLastVisited(BvhNode *node, int frameId) const;
529        /** Resets the node classifications in the tree.
530        */
531        void ResetNodeClassifications();
532        /** Helper function that renders the bounding boxes of the leaves as
533                wireframes for visualization purpose.
534        */
535        //void RenderBoundingBoxesForViz(int mode);
536        /** Count triangles the node contains.
537        */
538        int CountTriangles(BvhNode *node) const;
539        /** Returns area of the the node.
540        */
541        float GetArea(BvhNode *node) const;
542        /** Compute unique ids for the nodes.
543        */
544        void ComputeIds();
545        /** Assign virtual leaves based on specified number of triangles per leaf.
546        */
547        void SetVirtualLeaves(int numTriangles);
548       
549
550        ////////
551        //-- functions influencing tighter bounds
552
553
554        /** Sets maximal depth for taking the bounding boxes to test the
555                visibility of a node.
556                Deeper => the bounds adapt more to the geometry.
557        */
558        void SetMaxDepthForTestingChildren(int maxDepth);
559
560        void SetAreaRatioThresholdForTestingChildren(float ratio);
561
562
563        ////////////////////////////
564
565        /** Returns stats.
566        */
567        const BvhStats &GetBvhStats() const { return mBvhStats; }
568        /** Render wireframe bvh for visualization purpose.
569        */
570        void RenderBoundsForViz(BvhNode *node, RenderState *state, bool useTightBounds);
571
572
573protected:
574
575        ////////////////////
576
577        /** protected constructor: do nothing.
578        */
579        Bvh();
580        /** Protected constructor taking scene geometry into account
581        */
582        const Bvh(const SceneEntityContainer &entities);
583        /** Called by the constructor. Initializes important members.
584        */
585        void Init();
586
587        /////////////
588
589        void ComputeBvhStats();
590        void PrintBvhStats() const;
591
592
593        //////////
594        //-- Helper methods for bounding box rendering in immediate and vbo mode.
595       
596        void PrepareVertices();
597
598        int PrepareBoundsWithDrawArrays(const BvhNodeContainer &nodes);
599        void RenderBoundsWithDrawArrays(int numNodes, RenderState *state);
600
601        /** Create the indices that each node needs to use vbo rendering.
602        */
603        void CreateIndices();
604        /** Create the list of nodes whose bounding boxes are tested instead of the
605                bounding box of the node itself.
606        */
607        bool CreateNodeRenderList(BvhNode *node);
608        /** Recursivly updates indices so we can
609                render also interior nodes without traversing hierarchy
610        */
611        void UpdateInteriors(BvhNode *node);
612        /** Recomputes the boundaries of the nodes.
613            This function is always called if some boundary options are changed.
614        */
615        void RecomputeBounds();
616        /** Does some postprocessing on the nodes.
617        */
618        void PostProcess();
619        /** Helper method that updates the number of leaves in the subtree under
620                this node.
621        */
622        void UpdateNumLeaves(BvhNode *node) const;
623        /** Frustum tests the ith plane.
624        */
625        inline bool TestPlane(BvhNode *node, int i, bool &bIntersect);
626        /** Renders a bounding box in immediate mode.
627        */
628        void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
629
630
631
632        ////////////////////////
633       
634        /// the bounding box of the bvh
635        AxisAlignedBox3 mBox;
636        /// the root of the hierarchy
637        BvhNode *mRoot;
638        /// pointers to the geometry associated with this node
639        SceneEntity **mGeometry;
640        /// #of entities
641        size_t mGeometrySize;
642
643        /// the current camera
644        Camera *mCamera;
645
646
647        ////////////////
648        //-- tigher bounds termination criteria
649
650        /** maximal depth from which children are fetched for
651                testing instead of the current node
652        */
653        int mMaxDepthForTestingChildren;
654        /// threshold for computing tighter bounds
655        float mAreaRatioThreshold;
656       
657       
658        ////////////////
659        //-- statistics
660
661        BvhStats mBvhStats;
662        /// the overall number of nodes
663        int mNumNodes;
664        /// the number of "virtual" (=actually used) nodes
665        int mNumVirtualNodes;
666
667
668        ////////////
669        //-- rendering stuff
670
671        /// these proxy nodes are tested instead of the current node
672        BvhNodeContainer mTestNodes;
673        /// the indices used for vbo index buffering
674        unsigned int *mTestIndices;
675        /// a pointer to the end of the indices array
676        int mCurrentIndicesPtr;
677        /// the vbo id
678        unsigned int mVboId;
679        /// a vertex array used if working with indexed arrays (without vbo)
680        Vector3 *mVertices;
681        /// indices used for draw array rendering
682        unsigned int *mIndices;
683};
684
685}
686
687#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.