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

Revision 2897, 15.8 KB checked in by mattausch, 16 years ago (diff)

improved shadow mapping

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