source: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.h @ 2755

Revision 2755, 13.3 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 "Geometry.h"
7
8
9namespace CHCDemo
10{
11
12////////
13// Forward declarations
14
15class SceneEntity;
16class Camera;
17
18
19/** A node in the bv hierarchy.
20*/
21class BvhNode
22{
23        friend class Bvh;
24        friend class BvhLoader;
25        friend class myless;
26
27public:
28
29        /** visibility related options
30        */
31        struct VisibilityInfo
32        {
33                VisibilityInfo() { Reset(); }           
34                /** Reset the visibility info.
35                */
36                void Reset();
37
38                /// if the node is visible
39                bool mIsVisible;
40                /// #frames this node is assumed to stay visible
41                int mAssumedVisibleFrames;
42                /// the frame when this node was last touched during traversal
43                int mLastVisitedFrame;
44                /// #times this node was invisible (only valid if the node actually is invisible)
45                int mTimesInvisible;
46                /// if the node is view frustum culled
47                bool mIsFrustumCulled;
48                /// if the node is newly processed with no prior history available
49                bool mIsNew;
50        };
51
52        /** Constructor taking the parent node.
53        */
54        BvhNode(BvhNode *parent);
55        /** Returns true if this node is a leaf.
56        */
57        //virtual bool IsPseudoLeaf() = 0;
58        /** Virtual destructor doing nothing.
59        */
60        virtual ~BvhNode();
61        /** Returns unique id for this node.
62        */
63        //inline int GetId() {return mId;}
64        /** Depth of this node in the tree.
65        */
66        inline int GetDepth() const {return mDepth;}
67        /** Returns parent of this bvh node, NULL if it is root.
68        */
69        inline BvhNode *GetParent() {return mParent;}
70        /** Number of leaves in the subtree induced by this node.
71        */
72        inline int GetNumLeaves() const {return mNumLeaves;}
73        /** Reset the status of this node.
74        */
75        virtual void ResetVisibility();
76
77        virtual bool IsLeaf() = 0; //{ return BVH_NODE; }
78
79
80        ////////////////
81        //-- visibility culling related functions
82
83        inline int GetLastVisitedFrame() const;
84
85        inline void SetLastVisitedFrame(int lastVisited);
86        /** If this node is considered visible.
87        */
88        inline bool IsVisible() const;
89        /** Set visibility flag of the node.
90        */
91        inline void SetVisible(bool visible);
92        /** The assumed visible time span of this node.
93        */
94        inline void SetAssumedVisibleFrames(int t);
95        /** See set.
96        */
97        inline int GetAssumedVisibleFrames() const;
98        /** The time span this node remains visible.
99        */
100        inline void SetRemainingVisibleFrames(const int t);
101        /** Decrease the time this node is considered visible.
102        */
103        inline void DecAssumedVisibleFrames();
104        /** Increases the #times this node was
105                successfully tested invisible.
106        */
107        inline void IncTimesInvisible();
108       
109        inline int GetTimesInvisible() const;
110        inline void SetTimesInvisible(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        /// these nodes can be tested instead of the current node
193        int mTestNodesIdx;
194       
195        int mNumTestNodes;
196
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        /// indices used for draw array rendering
206        unsigned int *mIndices;
207        /// the bounding box
208        AxisAlignedBox3 mBox;
209
210};
211
212
213/////////////////
214//-- public inline functions
215
216int BvhNode::GetLastVisitedFrame() const
217{
218        return mVisibility.mLastVisitedFrame;
219}
220
221
222void BvhNode::SetLastVisitedFrame(const int lastVisited)
223{
224        mVisibility.mLastVisitedFrame = lastVisited;
225}
226
227
228bool BvhNode::IsVisible() const
229{
230        return mVisibility.mIsVisible;
231}
232
233
234void BvhNode::SetVisible(const bool visible)
235{
236        mVisibility.mIsVisible = visible;
237}
238
239
240void BvhNode::IncTimesInvisible()
241{
242        ++ mVisibility.mTimesInvisible;
243}
244
245
246int BvhNode::GetTimesInvisible() const
247{
248        return mVisibility.mTimesInvisible;
249}
250
251
252void BvhNode::SetTimesInvisible(const int t)
253{
254        mVisibility.mTimesInvisible = t;
255}
256
257
258bool BvhNode::IsViewFrustumCulled() const
259{
260        return mVisibility.mIsFrustumCulled;
261}
262
263
264void BvhNode::SetViewFrustumCulled(const bool frustumCulled)
265{
266        mVisibility.mIsFrustumCulled = frustumCulled;
267}
268
269
270bool BvhNode::IsNew() const
271{
272        return mVisibility.mIsNew;
273}
274
275
276void BvhNode::SetIsNew(const bool isNew)
277{
278        mVisibility.mIsNew = isNew;
279}
280
281
282int BvhNode::GetLastRenderedFrame() const
283{
284        return mLastRenderedFrame;
285}
286       
287
288void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
289{
290        mLastRenderedFrame = lastRenderedFrame;
291}
292       
293       
294bool BvhNode::Empty() const
295{
296        return mFirst == -1;
297}
298
299
300int BvhNode::CountPrimitives() const
301{
302        return mLast - mFirst + 1;
303}
304
305
306void BvhNode::SetAssumedVisibleFrames(const int t)
307{
308        mVisibility.mAssumedVisibleFrames = t;
309}
310
311
312int BvhNode::GetAssumedVisibleFrames() const
313{
314        return mVisibility.mAssumedVisibleFrames;
315}
316
317void BvhNode::DecAssumedVisibleFrames()
318{
319        -- mVisibility.mAssumedVisibleFrames;
320}
321
322
323/** Internal node of the bv hierarchy.
324*/
325class BvhInterior: public BvhNode
326{
327        friend class Bvh;
328        friend class BvhLoader;
329
330public:
331
332        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
333        {}
334        virtual bool IsLeaf() {return false;}
335        /** Back child.
336        */
337        inline BvhNode *GetBack() { return mBack;}
338        /** Front child.
339        */
340        inline BvhNode *GetFront() { return mFront;}
341        /** recursivly delete tree.
342        */
343        virtual ~BvhInterior() { if (mBack) delete mBack; if (mFront) delete mFront;}
344        /** Returns split axis of this interior node.
345        */
346        inline int GetAxis() { return (int)mAxis; }
347        /** Returns position of the split axis.
348        */
349        inline float GetPosition() {return (float)mPosition;}
350
351
352protected:
353
354        /// the position of the split plane
355        float mPosition;
356       
357        BvhNode *mBack;
358        BvhNode *mFront;
359};
360
361
362class BvhLeaf: public BvhNode
363{
364        friend class Bvh;
365        friend class BvhLoader;
366
367public:
368
369        BvhLeaf(BvhNode *parent): BvhNode(parent)
370        {}
371
372        ~BvhLeaf();
373
374        virtual bool IsLeaf() { return true; }
375};
376
377
378/**     This class implements the compare operator for the priority queue.
379        a lower distance has a higher value in the queue
380*/
381class myless
382{
383public:
384        bool operator() (BvhNode *v1, BvhNode *v2) const
385    {
386                return (v1->mDistance > v2->mDistance);
387    }
388};
389
390
391/** Class representing a bounding volume hierarchy.
392*/
393class Bvh
394{
395        friend class BvhLoader;
396
397        /** Bvh properties
398        */
399        struct BvhStats
400        {
401                BvhStats():
402                mInteriorSA(0),
403                mLeafSA(0),
404                mInteriorVol(0),
405                mLeafVol(0),
406                mBoundsInteriorSA(0),
407                mBoundsLeafSA(0),
408                mBoundsInteriorVol(0),
409                mBoundsLeafVol(0),
410                mBoundsLeavesCount(0),
411                mTriangles(0),
412                mTriangleRatio(0),
413                mGeometryRatio(0),
414                mMaxGeometry(0),
415                mMaxTriangles(0)
416                {}
417               
418                float mInteriorSA;
419                float mLeafSA;
420                float mInteriorVol;
421                float mLeafVol;
422                float mBoundsInteriorSA;
423                float mBoundsLeafSA;
424                float mBoundsInteriorVol;
425                float mBoundsLeafVol;
426                int mBoundsLeavesCount;
427                int mTriangles;
428
429                float mTriangleRatio;
430                float mGeometryRatio;
431
432                int mMaxGeometry;
433                int mMaxTriangles;
434        };
435
436public:
437
438        /** Returns number of bvh nodes.
439        */
440        inline int GetNumNodes() const {return mNumNodes;}
441        /** Returns number of bvh leaves.
442        */
443        inline int GetNumLeaves() const {return mNumNodes / 2 + 1;}
444        /** Returns root node of the bvh.
445        */
446        BvhNode *GetRoot() { return mRoot; }
447        /** Counts the triangle in this leaf.
448        */
449        int CountTriangles(BvhLeaf *leaf) const;
450
451
452        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
453        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
454        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
455
456
457        //////////////////////
458
459        /** Returns geometry by reference (faster).
460        */
461        SceneEntity **GetGeometry(BvhNode *node, int &size);
462
463
464        /////////////
465        //-- Rendering related options
466
467        /** Renders the bounding box of this node (Or the tigher bounding boxes of some subnodes).
468        */
469        void RenderBoundingBox(BvhNode *node);
470        /** Renders bounding boxes of the collection of nodes.
471                @returns #rendered boxes
472        */
473        int RenderBoundingBoxes(const BvhNodeContainer &nodes);
474
475
476
477        //////////////
478        //-- Traversal related options
479
480        /** Pulls up visible classification.
481        */
482        void MakeParentsVisible(BvhNode *node);
483        /** Does the view frustum culling for this node with respect to the previous culls
484                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
485        */
486        int     IsWithinViewFrustum(BvhNode *node);
487        /** Sets frame dependent values.
488        */
489        void InitFrame(Camera *camera, int currentFrameId);
490        /** This gives the orthogonal distance from the viewpoint to the nearest bounding box vertex
491                note that negative values can appear because culling is done only afterwards
492        */
493        float CalcDistance(BvhNode *node) const;
494        /** Pulls up the last visited classification in the bvh.
495        */
496        void PullUpLastVisited(BvhNode *node, int frameId) const;
497        /** Resets the node classifications in the tree.
498        */
499        void ResetNodeClassifications();
500        /** Helper function that renders the bounding boxes of the leaves as
501                wireframes for visualization purpose.
502        */
503        //void RenderBoundingBoxesForViz(int mode);
504        /** Count triangles the node contains.
505        */
506        int CountTriangles(BvhNode *node) const;
507        /** Returns area of the geometry contained in the node.
508        */
509        float GetGeometryArea(BvhNode *node) const;
510
511
512        ////////
513        //-- functions influencing tighter bounds
514
515
516        /** Sets maximal depth for taking the bounding boxes to test the
517                visibility of a node.
518                Deeper => the bounds adapt more to the geometry.
519        */
520        void SetMaxDepthForTestingChildren(int maxDepth);
521
522        void SetAreaRatioThresholdForTestingChildren(float ratio);
523
524        /** Returns stats.
525        */
526        const BvhStats &GetBvhStats() const {return mBvhStats;}
527       
528
529protected:
530
531        ////////////////////
532
533        /** protected constructor: do nothing.
534        */
535        Bvh();
536        /** Destructor.
537        */
538        ~Bvh();
539
540
541        /////////////
542
543        void ComputeBvhStats();
544        void PrintBvhStats() const;
545
546
547        //////////
548        //-- Helper methods for bounding box rendering in immediate and vbo mode.
549       
550        void PrepareVertices();
551
552        int PrepareBoundingBoxesWithDrawArrays(const BvhNodeContainer &nodes);
553        void RenderBoundingBoxesWithDrawArrays(int numNodes);
554
555        /** Create the indices that each node needs to use vbo rendering.
556        */
557        void CreateIndices();
558        /** Create the list of nodes whose bounding boxes are tested instead of the
559                bounding box of the node itself.
560        */
561        bool CreateNodeRenderList(BvhNode *node);
562        /** Recursivly updates indices so we can
563                render also interior nodes without traversing hierarchy
564        */
565        void UpdateInteriors(BvhNode *node);
566        /** Recomputes the boundaries of the nodes.
567            This function is always called if some boundary options are changed.
568        */
569        void RecomputeBounds();
570        /** Does some postprocessing on the leaves.
571                @returns #leaves that were chosen for tighter bounds.
572        */
573        int PostProcessLeaves(BvhLeafContainer &leaves);
574               
575       
576        ////////////////////////
577
578        /// the root of the hierarchy
579        BvhNode *mRoot;
580        /// pointers to the geometry associated with this node
581        SceneEntity **mGeometry;
582        /// #of entities
583        size_t mGeometrySize;
584
585
586        ////////////////
587
588        /// the current camera
589        Camera *mCamera;
590        // current frame id
591        int mFrameId;
592        /// a vertex array used if working with indexed arrays (without vbo)
593        Vector3 *mVertices;
594        /// indices used for draw array rendering
595        unsigned int *mIndices;
596
597        /** maximal depth from which children are fetched for
598                testing instead of the current node
599        */
600        int mMaxDepthForTestingChildren;
601
602        float mAreaRatioThreshold;
603
604
605        BvhStats mBvhStats;
606
607        BvhNodeContainer mTestNodes;
608       
609        unsigned int *mTestIndices;
610        /// a pointer to the end of the indices array
611        int mCurrentIndicesPtr;
612
613        int mNumNodes;
614
615
616        //////////////
617
618        static unsigned int sCurrentVboId;
619};
620
621}
622
623#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.