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

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