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

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