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

Revision 2894, 15.3 KB checked in by mattausch, 16 years ago (diff)

shadow mapping almost working (but ulgy!!)

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        /** Depth of this node in the tree.
68        */
69        inline int GetDepth() const {return mDepth;}
70        /** Returns parent of this bvh node, NULL if it is root.
71        */
72        inline BvhNode *GetParent() {return mParent;}
73        /** Number of leaves in the subtree induced by this node.
74        */
75        inline int GetNumLeaves() const {return mNumLeaves;}
76        /** Reset the status of this node.
77        */
78        virtual void ResetVisibility();
79
80        virtual bool IsLeaf() const = 0;
81
82        bool IsVirtualLeaf() const { return mIsVirtualLeaf; }
83
84
85        ////////////////
86        //-- visibility culling related functions
87
88        inline int GetLastVisitedFrame() const;
89
90        inline void SetLastVisitedFrame(int lastVisited);
91        /** If this node is considered visible.
92        */
93        inline bool IsVisible() const;
94        /** Set visibility flag of the node.
95        */
96        inline void SetVisible(bool visible);
97        /** The frame id until this node is assumed visible
98        */
99        inline void SetAssumedVisibleFrameId(int t);
100        /** See set.
101        */
102        inline int GetAssumedVisibleFrameId() const;
103        /** Increases the #times this node was
104                successfully tested invisible.
105        */
106        inline void IncTimesTestedInvisible();
107       
108        inline int GetTimesTestedInvisible() const;
109        inline void SetTimesTestedInvisible(int t);
110       
111        inline int GetTurnedVisibleFrame() const;
112        inline void SetTurnedVisibleFrame(int turnedVisibleFrame);
113
114        inline int GetLastQueriedFrame() const;
115        inline void SetLastQueriedFrame(int lastTested);
116       
117        inline bool IsViewFrustumCulled() const;
118        inline void SetViewFrustumCulled(bool frustumCulled);
119
120        inline bool IsNew() const;
121        inline void SetIsNew(bool isNew);
122
123
124        /** Returns the bounding box of this node.
125        */
126        inline const AxisAlignedBox3 &GetBox() { return mBox; }
127        /** Return index of this node.
128        */
129        inline int GetId() const { return mId; }
130        /** See get
131        */
132        inline void SetId(int id) { mId = id; }
133
134
135        //////////
136        //-- rendering
137       
138        /** Returns the frame in which this node was last rendered.
139        */
140        inline int GetLastRenderedFrame() const;
141        /** See get.
142        */
143        inline void SetLastRenderedFrame(int lastRenderedFrame);
144        /** Does this node contain renderable geometry?
145        */
146        inline bool Empty() const;
147        /** Counts #geometry stored in the subtree.
148        */
149        inline int CountPrimitives() const;
150
151
152protected:
153
154        /////////////
155       
156        /// the depth of this node
157        unsigned char mDepth;
158        /// the split axis
159        char mAxis;
160        /// the parent node
161        BvhNode *mParent;
162        /// stores the visibility related info
163        VisibilityInfo mVisibility;
164
165        /////////
166        //-- used for view frustum culling
167
168        int mPlaneMask;
169        int mPreferredPlane;
170
171
172        ////////////
173        //-- rendering related options
174       
175        /// when the node was last rendered
176        int mLastRenderedFrame;
177        /// #leaves under this node
178        int mNumLeaves;
179       
180        // Indices to first and last triangle in the triangle array
181        // assumes the triangle are placed in continuous chunk of memory
182        // however this need not be a global array!
183       
184        /// the index of the first triangle
185        int mFirst;
186        /// the index of the last triangle
187        int mLast;
188
189        /// the bounding boxes of these nodes are queries instead of the current node
190        int mTestNodesIdx;
191        /// the number of tighter bounding volumes used for this node
192        int mNumTestNodes;
193        /// used for efficient element array rendering
194        int mIndicesPtr;
195
196        /// Area of this node
197        float mArea;
198        /// distance to the camera
199        float mDistance;
200        /// the index of this node
201        unsigned int mId;
202        /// the bounding box
203        AxisAlignedBox3 mBox;
204        /// if this node is a virtual leaf
205        bool mIsVirtualLeaf;
206        /** This marks the maximal depth where a virtual leaf can be defined.
207            From this point on it makes no sense to traverse down further, as all
208                nodes below contain the same geometry, so no further refinement of visibility
209                can be archieved. All nodes below this point can merely used to define the
210                tighter bounds.
211        */
212        bool mIsMaxDepthForVirtualLeaf;
213};
214
215
216
217/////////////////
218//-- public inline functions
219
220
221int BvhNode::GetLastVisitedFrame() const
222{
223        return mVisibility.mLastVisitedFrame;
224}
225
226
227void BvhNode::SetLastVisitedFrame(const int lastVisited)
228{
229        mVisibility.mLastVisitedFrame = lastVisited;
230}
231
232
233bool BvhNode::IsVisible() const
234{
235        return mVisibility.mIsVisible;
236}
237
238
239void BvhNode::SetVisible(bool visible)
240{
241        mVisibility.mIsVisible = visible;
242}
243
244
245void BvhNode::IncTimesTestedInvisible()
246{
247        ++ mVisibility.mTimesInvisible;
248}
249
250
251int BvhNode::GetTimesTestedInvisible() const
252{
253        return mVisibility.mTimesInvisible;
254}
255
256
257void BvhNode::SetTimesTestedInvisible(int t)
258{
259        mVisibility.mTimesInvisible = t;
260}
261
262
263bool BvhNode::IsViewFrustumCulled() const
264{
265        return mVisibility.mIsFrustumCulled;
266}
267
268
269void BvhNode::SetViewFrustumCulled(bool frustumCulled)
270{
271        mVisibility.mIsFrustumCulled = frustumCulled;
272}
273
274
275bool BvhNode::IsNew() const
276{
277        return mVisibility.mIsNew;
278}
279
280
281void BvhNode::SetIsNew(bool isNew)
282{
283        mVisibility.mIsNew = isNew;
284}
285
286
287int BvhNode::GetLastRenderedFrame() const
288{
289        return mLastRenderedFrame;
290}
291       
292
293void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
294{
295        mLastRenderedFrame = lastRenderedFrame;
296}
297       
298       
299bool BvhNode::Empty() const
300{
301        return mFirst == -1;
302}
303
304
305int BvhNode::CountPrimitives() const
306{
307        return mLast - mFirst + 1;
308}
309
310
311void BvhNode::SetAssumedVisibleFrameId(int t)
312{
313        mVisibility.mAssumedVisibleFrameId = t;
314}
315
316
317int BvhNode::GetAssumedVisibleFrameId() const
318{
319        return mVisibility.mAssumedVisibleFrameId;
320}
321
322
323int BvhNode::GetLastQueriedFrame() const
324{
325        return mVisibility.mLastQueriedFrame;
326}
327
328
329void BvhNode::SetLastQueriedFrame(int lastTested)
330{
331        mVisibility.mLastQueriedFrame = lastTested;
332}
333
334
335
336/** Internal node of the bv hierarchy.
337*/
338class BvhInterior: public BvhNode
339{
340        friend class Bvh;
341        friend class BvhLoader;
342
343public:
344
345        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
346        {}
347        virtual bool IsLeaf() const { return false; }
348        /** Back child.
349        */
350        inline BvhNode *GetBack() { return mBack; }
351        /** Front child.
352        */
353        inline BvhNode *GetFront() { return mFront; }
354        /** Recursivly delete hierarchy.
355        */
356        virtual ~BvhInterior();
357
358protected:
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 number of 'virtual' nodes in the hierarchy, i.e.
444                the number of nodes actually used for traversal.
445        */
446        int GetNumVirtualNodes() const  { return mNumVirtualNodes; }
447        /** Returns number of bvh leaves.
448        */
449        inline int GetNumVirtualLeaves() const { return mNumVirtualNodes / 2 + 1;}
450        /** Returns root node of the bvh.
451        */
452        BvhNode *GetRoot() { return mRoot; }
453        /** Sets the scene camera
454        */
455        void SetCamera(Camera * camera) { mCamera = camera; }
456
457        ///////////////
458        //-- functions collecting nodes based on some criteria
459
460        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
461        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
462        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
463        /** Collect only the virtual leaves.
464        */
465        void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
466
467
468        //////////////////////
469
470        /** Returns geometry by reference (faster).
471        */
472        SceneEntity **GetGeometry(BvhNode *node, int &size);
473
474
475        /////////////
476        //-- Rendering related options
477
478        /** Renders the bounds of this node
479            (the box of the node or the tigher bounds of some subnodes).
480        */
481        void RenderBounds(BvhNode *node, RenderState *state, bool useTightBounds);
482        /** Renders bounding boxes of the collection of nodes.
483                @returns #rendered boxes
484        */
485        int RenderBounds(const BvhNodeContainer &nodes, RenderState *state, bool useTightBounds);
486        /** Returns the bounding box of this bvh.
487        */
488        inline const AxisAlignedBox3 &GetBox() { return mBox; }
489
490
491        //////////////
492        //-- Traversal related options
493
494        /** Pulls up visible classification.
495        */
496        void MakeParentsVisible(BvhNode *node);
497        /** Does the view frustum culling for this node with respect to the previous culls
498                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
499        */
500        int     IsWithinViewFrustum(BvhNode *node);
501        /** Sets frame dependent values
502        */
503        void InitFrame();
504        /** This gives the orthogonal distance from the viewpoint to the nearest bounding box vertex
505                note that negative values can appear because culling is done only afterwards
506        */
507        void CalcDistance(BvhNode *node) const;
508        /** Returns the stored distance.
509        */
510        float GetDistance(BvhNode *node) const  { return node->mDistance; }
511        /** Pulls up the last visited classification in the bvh.
512        */
513        void PullUpLastVisited(BvhNode *node, int frameId) const;
514        /** Resets the node classifications in the tree.
515        */
516        void ResetNodeClassifications();
517        /** Helper function that renders the bounding boxes of the leaves as
518                wireframes for visualization purpose.
519        */
520        //void RenderBoundingBoxesForViz(int mode);
521        /** Count triangles the node contains.
522        */
523        int CountTriangles(BvhNode *node) const;
524        /** Returns area of the the node.
525        */
526        float GetArea(BvhNode *node) const;
527        /** Compute unique ids for the nodes.
528        */
529        void ComputeIds();
530        /** Assign virtual leaves based on specified number of triangles per leaf.
531        */
532        void SetVirtualLeaves(int numTriangles);
533       
534
535        ////////
536        //-- functions influencing tighter bounds
537
538
539        /** Sets maximal depth for taking the bounding boxes to test the
540                visibility of a node.
541                Deeper => the bounds adapt more to the geometry.
542        */
543        void SetMaxDepthForTestingChildren(int maxDepth);
544
545        void SetAreaRatioThresholdForTestingChildren(float ratio);
546
547
548        ////////////////////////////
549
550        /** Returns stats.
551        */
552        const BvhStats &GetBvhStats() const { return mBvhStats; }
553        /** Render wireframe bvh for visualization purpose.
554        */
555        void RenderBoundsForViz(BvhNode *node, RenderState *state, bool useTightBounds);
556
557
558protected:
559
560        ////////////////////
561
562        /** protected constructor: do nothing.
563        */
564        Bvh();
565        /** Protected constructor taking scene geometry into account
566        */
567        const Bvh(const SceneEntityContainer &entities);
568        /** Called by the constructor. Initializes important members.
569        */
570        void Init();
571
572        /////////////
573
574        void ComputeBvhStats();
575        void PrintBvhStats() const;
576
577
578        //////////
579        //-- Helper methods for bounding box rendering in immediate and vbo mode.
580       
581        void PrepareVertices();
582
583        int PrepareBoundsWithDrawArrays(const BvhNodeContainer &nodes);
584        void RenderBoundsWithDrawArrays(int numNodes, RenderState *state);
585
586        /** Create the indices that each node needs to use vbo rendering.
587        */
588        void CreateIndices();
589        /** Create the list of nodes whose bounding boxes are tested instead of the
590                bounding box of the node itself.
591        */
592        bool CreateNodeRenderList(BvhNode *node);
593        /** Recursivly updates indices so we can
594                render also interior nodes without traversing hierarchy
595        */
596        void UpdateInteriors(BvhNode *node);
597        /** Recomputes the boundaries of the nodes.
598            This function is always called if some boundary options are changed.
599        */
600        void RecomputeBounds();
601        /** Does some postprocessing on the nodes.
602        */
603        void PostProcess();
604        /** Helper method that updates the number of leaves in the subtree under
605                this node.
606        */
607        void UpdateNumLeaves(BvhNode *node) const;
608        /** Frustum tests the ith plane.
609        */
610        inline bool TestPlane(BvhNode *node, int i, bool &bIntersect);
611        /** Renders a bounding box in immediate mode.
612        */
613        void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
614
615
616
617        ////////////////////////
618       
619        /// the bounding box of the bvh
620        AxisAlignedBox3 mBox;
621        /// the root of the hierarchy
622        BvhNode *mRoot;
623        /// pointers to the geometry associated with this node
624        SceneEntity **mGeometry;
625        /// #of entities
626        size_t mGeometrySize;
627
628        /// the current camera
629        Camera *mCamera;
630
631
632        ////////////////
633        //-- tigher bounds termination criteria
634
635        /** maximal depth from which children are fetched for
636                testing instead of the current node
637        */
638        int mMaxDepthForTestingChildren;
639        /// threshold for computing tighter bounds
640        float mAreaRatioThreshold;
641       
642       
643        ////////////////
644        //-- statistics
645
646        BvhStats mBvhStats;
647        /// the overall number of nodes
648        int mNumNodes;
649        /// the number of "virtual" (=actually used) nodes
650        int mNumVirtualNodes;
651
652
653        ////////////
654        //-- rendering stuff
655
656        /// these proxy nodes are tested instead of the current node
657        BvhNodeContainer mTestNodes;
658        /// the indices used for vbo index buffering
659        unsigned int *mTestIndices;
660        /// a pointer to the end of the indices array
661        int mCurrentIndicesPtr;
662        /// the vbo id
663        unsigned int mVboId;
664        /// a vertex array used if working with indexed arrays (without vbo)
665        Vector3 *mVertices;
666        /// indices used for draw array rendering
667        unsigned int *mIndices;
668};
669
670}
671
672#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.