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

Revision 2771, 14.7 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                /// 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        };
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 frame id until this node is assumed visible
99        */
100        inline void SetAssumedVisibleFrameId(int t);
101        /** See set.
102        */
103        inline int GetAssumedVisibleFrameId() const;
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        /// if this node is a virtual leaf
210        bool mIsVirtualLeaf;
211        /** This marks the maximal depth where a virtual leaf can be defined.
212            From this point on it makes no sense to traverse down further, as all
213                nodes below contain the same geometry, so no further refinement of visibility
214                can be archieved. All nodes below this point can merely used to define the
215                tighter bounds.
216        */
217        bool mIsMaxDepthForVirtualLeaf;
218};
219
220
221/////////////////
222//-- public inline functions
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(const bool visible)
243{
244        mVisibility.mIsVisible = visible;
245}
246
247
248void BvhNode::IncTimesInvisible()
249{
250        ++ mVisibility.mTimesInvisible;
251}
252
253
254int BvhNode::GetTimesInvisible() const
255{
256        return mVisibility.mTimesInvisible;
257}
258
259
260void BvhNode::SetTimesInvisible(const 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(const 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(const 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
326/** Internal node of the bv hierarchy.
327*/
328class BvhInterior: public BvhNode
329{
330        friend class Bvh;
331        friend class BvhLoader;
332
333public:
334
335        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
336        {}
337        virtual bool IsLeaf() const { return false; }
338        /** Back child.
339        */
340        inline BvhNode *GetBack() { return mBack; }
341        /** Front child.
342        */
343        inline BvhNode *GetFront() { return mFront; }
344        /** recursivly delete tree.
345        */
346        virtual ~BvhInterior() { if (mBack) delete mBack; if (mFront) delete mFront;}
347        /** Returns split axis of this interior node.
348        */
349        //inline int GetAxis() { return (int)mAxis; }
350        /** Returns position of the split axis.
351        */
352        //inline float GetPosition() {return (float)mPosition;}
353
354
355protected:
356
357        /// the position of the split plane
358        //float mPosition;
359       
360        BvhNode *mBack;
361        BvhNode *mFront;
362};
363
364
365class BvhLeaf: public BvhNode
366{
367        friend class Bvh;
368        friend class BvhLoader;
369
370public:
371
372        BvhLeaf(BvhNode *parent): BvhNode(parent)
373        {}
374
375        ~BvhLeaf();
376
377        virtual bool IsLeaf() const { return true; }
378};
379
380
381/**     This class implements the compare operator for the priority queue.
382        a lower distance has a higher value in the queue
383*/
384class mygreaterdistance
385{
386public:
387        bool operator() (BvhNode *v1, BvhNode *v2) const
388    {
389                return (v1->mDistance > v2->mDistance);
390    }
391};
392
393typedef std::priority_queue<BvhNode *, std::vector<BvhNode *>, mygreaterdistance> TraversalQueue;
394
395
396/** Class representing a bounding volume hierarchy.
397*/
398class Bvh
399{
400        friend class BvhLoader;
401
402        /** Bvh properties
403        */
404        struct BvhStats
405        {
406                BvhStats():
407                mInteriorSA(0),
408                mLeafSA(0),
409                mInteriorVol(0),
410                mLeafVol(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               
423                int mTriangles;
424
425                float mTriangleRatio;
426                float mGeometryRatio;
427
428                int mMaxGeometry;
429                int mMaxTriangles;
430        };
431
432public:
433
434        /** Destructor.
435        */
436        ~Bvh();
437        /** Returns number of bvh nodes.
438        */
439        inline int GetNumNodes() const { return mNumNodes; }
440        /** Returns number of bvh leaves.
441        */
442        inline int GetNumLeaves() const { return mNumNodes / 2 + 1;}
443        /** Returns root node of the bvh.
444        */
445        BvhNode *GetRoot() { return mRoot; }
446        /** Counts the triangle in this leaf.
447        */
448        int CountTriangles(BvhLeaf *leaf) const;
449        /** Sets the scene camera
450        */
451        void SetCamera(Camera * camera) { mCamera = camera; }
452
453        ///////////////
454        //-- functions collecting nodes based on some criteria
455
456        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
457        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
458        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
459        /** Collect only the virtual leaves.
460        */
461        void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
462
463
464        //////////////////////
465
466        /** Returns geometry by reference (faster).
467        */
468        SceneEntity **GetGeometry(BvhNode *node, int &size);
469
470
471        /////////////
472        //-- Rendering related options
473
474        /** Renders the bounding box of this node (Or the tigher bounding boxes of some subnodes).
475        */
476        void RenderBoundingBox(BvhNode *node);
477        /** Renders bounding boxes of the collection of nodes.
478                @returns #rendered boxes
479        */
480        int RenderBoundingBoxes(const BvhNodeContainer &nodes);
481
482        /** Returns the bounding box of this bvh.
483        */
484        inline const AxisAlignedBox3 &GetBox() { return mBox; }
485
486
487        //////////////
488        //-- Traversal related options
489
490        /** Pulls up visible classification.
491        */
492        void MakeParentsVisible(BvhNode *node);
493        /** Does the view frustum culling for this node with respect to the previous culls
494                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
495        */
496        int     IsWithinViewFrustum(BvhNode *node);
497        /** Sets frame dependent values
498        */
499        void InitFrame();
500        /** This gives the orthogonal distance from the viewpoint to the nearest bounding box vertex
501                note that negative values can appear because culling is done only afterwards
502        */
503        void CalcDistance(BvhNode *node) const;
504        /** Returns the stored distance.
505        */
506        float GetDistance(BvhNode *node) const  { return node->mDistance; }
507        /** Pulls up the last visited classification in the bvh.
508        */
509        void PullUpLastVisited(BvhNode *node, int frameId) const;
510        /** Resets the node classifications in the tree.
511        */
512        void ResetNodeClassifications();
513        /** Helper function that renders the bounding boxes of the leaves as
514                wireframes for visualization purpose.
515        */
516        //void RenderBoundingBoxesForViz(int mode);
517        /** Count triangles the node contains.
518        */
519        int CountTriangles(BvhNode *node) const;
520        /** Returns area of the the node.
521        */
522        float GetArea(BvhNode *node) const;
523        /** Compute unique ids for the nodes.
524        */
525        void ComputeIds();
526        /** Assign virtual leaves based on specified number of triangles per leaf.
527        */
528        void SetVirtualLeaves(int numTriangles);
529
530        ////////
531        //-- functions influencing tighter bounds
532
533
534        /** Sets maximal depth for taking the bounding boxes to test the
535                visibility of a node.
536                Deeper => the bounds adapt more to the geometry.
537        */
538        void SetMaxDepthForTestingChildren(int maxDepth);
539
540        void SetAreaRatioThresholdForTestingChildren(float ratio);
541
542        /** Returns stats.
543        */
544        const BvhStats &GetBvhStats() const {return mBvhStats;}
545        /** Renders the geometry contained in this node.
546        */
547        int Render(BvhNode *node, RenderState *state);
548        /** Returns number of 'virtual' nodes in the hierarchy, i.e.
549                the number of nodes actually used for traversal.
550        */
551        int GetNumVirtualNodes() const  { return mNumVirtualNodes; }
552
553
554protected:
555
556        ////////////////////
557
558        /** protected constructor: do nothing.
559        */
560        Bvh();
561
562        /** Protected constructor taking scene geometry into account
563        */
564        const Bvh(const SceneEntityContainer &entities);
565       
566
567        /////////////
568
569        void ComputeBvhStats();
570        void PrintBvhStats() const;
571
572
573        //////////
574        //-- Helper methods for bounding box rendering in immediate and vbo mode.
575       
576        void PrepareVertices();
577
578        int PrepareBoundingBoxesWithDrawArrays(const BvhNodeContainer &nodes);
579        void RenderBoundingBoxesWithDrawArrays(int numNodes);
580
581        /** Create the indices that each node needs to use vbo rendering.
582        */
583        void CreateIndices();
584        /** Create the list of nodes whose bounding boxes are tested instead of the
585                bounding box of the node itself.
586        */
587        bool CreateNodeRenderList(BvhNode *node);
588        /** Recursivly updates indices so we can
589                render also interior nodes without traversing hierarchy
590        */
591        void UpdateInteriors(BvhNode *node);
592        /** Recomputes the boundaries of the nodes.
593            This function is always called if some boundary options are changed.
594        */
595        void RecomputeBounds();
596        /** Does some postprocessing on the nodes.
597        */
598        void PostProcess();
599        /** Helper method that updates the number of leaves in the subtree under
600                this node.
601        */
602        void UpdateNumLeaves(BvhNode *node) const;
603        /** Frustum tests the ith plane.
604        */
605        inline bool TestPlane(BvhNode *node, int i, bool &bIntersect);
606
607        void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
608
609
610
611        ////////////////////////
612
613        /// the root of the hierarchy
614        BvhNode *mRoot;
615        /// pointers to the geometry associated with this node
616        SceneEntity **mGeometry;
617        /// #of entities
618        size_t mGeometrySize;
619
620
621        ////////////////
622
623        /// the current camera
624        Camera *mCamera;
625        /// a vertex array used if working with indexed arrays (without vbo)
626        Vector3 *mVertices;
627        /// indices used for draw array rendering
628        unsigned int *mIndices;
629
630        /** maximal depth from which children are fetched for
631                testing instead of the current node
632        */
633        int mMaxDepthForTestingChildren;
634
635        float mAreaRatioThreshold;
636
637
638        BvhStats mBvhStats;
639
640        BvhNodeContainer mTestNodes;
641       
642        unsigned int *mTestIndices;
643        /// a pointer to the end of the indices array
644        int mCurrentIndicesPtr;
645
646        int mNumNodes;
647
648        /// the bounding box
649        AxisAlignedBox3 mBox;
650
651        int mNumVirtualNodes;
652
653        //////////////
654
655        static unsigned int sCurrentVboId;
656};
657
658}
659
660#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.