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

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