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

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