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

Revision 3059, 17.2 KB checked in by mattausch, 16 years ago (diff)

working on dynamic objects

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
10
11
12namespace CHCDemoEngine
13{
14
15// the number of visibility states
16#define NUM_STATES 2
17
18////////
19//-- Forward declarations
20
21class SceneEntity;
22class Camera;
23class RenderState;
24
25
26/** A node in the bv hierarchy.
27*/
28class BvhNode
29{
30        friend class Bvh;
31        friend class BvhLoader;
32        friend class mygreaterdistance;
33
34public:
35
36        /** visibility related options
37        */
38        struct VisibilityInfo
39        {
40                VisibilityInfo() { Reset(); }           
41                /** Reset the visibility info.
42                */
43                void Reset();
44
45                /// if the node is visible
46                bool mIsVisible;
47                /// frame id until this node is assumed to stay visible
48                int mAssumedVisibleFrameId;
49                /// the frame when this node was last touched during traversal
50                int mLastVisitedFrame;
51                /// #times this node was invisible (only valid if the node actually is invisible)
52                int mTimesInvisible;
53                /// if the node is view frustum culled
54                bool mIsFrustumCulled;
55                /// if the node is newly processed with no prior history available
56                bool mIsNew;
57                /// the frame this node was last queried
58                int mLastQueriedFrame;
59        };
60
61        /** Constructor taking the parent node.
62        */
63        BvhNode(BvhNode *parent);
64        /** Returns true if this node is a leaf.
65        */
66        //virtual bool IsPseudoLeaf() = 0;
67        /** Virtual destructor doing nothing.
68        */
69        virtual ~BvhNode();
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        /** Returns the stored distance to the near plane.
88        */
89        float GetDistance() const  { return mDistance; }
90
91
92        ////////////////
93        //-- visibility culling related functions
94
95        inline int GetLastVisitedFrame() const;
96
97        inline void SetLastVisitedFrame(int lastVisited);
98        /** If this node is considered visible.
99        */
100        inline bool IsVisible() const;
101        /** Set visibility flag of the node.
102        */
103        inline void SetVisible(bool visible);
104        /** The frame id until this node is assumed visible
105        */
106        inline void SetAssumedVisibleFrameId(int t);
107        /** See set.
108        */
109        inline int GetAssumedVisibleFrameId() const;
110        /** Increases the #times this node was
111                successfully tested invisible.
112        */
113        inline void IncTimesTestedInvisible();
114       
115        inline int GetTimesTestedInvisible() const;
116        inline void SetTimesTestedInvisible(int t);
117       
118        inline int GetTurnedVisibleFrame() const;
119        inline void SetTurnedVisibleFrame(int turnedVisibleFrame);
120
121        inline int GetLastQueriedFrame() const;
122        inline void SetLastQueriedFrame(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        /** This is an imporantent function once you have one or more
158                view point changes within a frame (e.g., camera view and shadow view for
159                shadow mapping), because each camera needs its own state in
160                order to not break temporal coherency.
161        */
162        static void SetCurrentState(int _state) { sCurrentState = _state; }
163
164
165protected:
166
167        /// the depth of this node
168        unsigned char mDepth;
169        /// the split axis
170        char mAxis;
171        /// the parent node
172        BvhNode *mParent;
173
174
175        //////////////
176        //-- members that define the current state. There is one state for each camera
177
178        /// the currently used state
179        static int sCurrentState;
180
181        /// stores the visibility related info
182        VisibilityInfo mVisibility[NUM_STATES];
183       
184        // members used to speed up view frustum culling
185        /// masks out planes of the frustum that do not have to be tested against
186        int mPlaneMask[NUM_STATES];
187        /// the plane that is usually responsible for culling this node.
188        /** if our educated guess was right, we save up to 5 comparisons.
189        */
190        int mPreferredPlane[NUM_STATES];
191        /// when the node was last rendered
192        int mLastRenderedFrame[NUM_STATES];
193
194        ////////////////////
195
196
197        /// #leaves under this node
198        int mNumLeaves;
199
200
201        ////////////
202        //-- rendering related options
203       
204       
205        // Indices to first and last triangle in the triangle array
206        // assumes the triangle are placed in continuous chunk of memory
207        // however this need not be a global array!
208       
209        /// the index of the first triangle
210        int mFirst;
211        /// the index of the last triangle
212        int mLast;
213
214        /// the bounding boxes of these nodes are queries instead of the current node
215        int mTestNodesIdx;
216        /// the number of tighter bounding volumes used for this node
217        int mNumTestNodes;
218        /// used for efficient element array rendering
219        int mIndicesPtr;
220
221        /// Area of this node
222        float mArea;
223        /// distance to the camera
224        float mDistance;
225        /// the index of this node
226        unsigned int mId;
227        /// the bounding box
228        AxisAlignedBox3 mBox;
229        /// if this node is a virtual leaf
230        bool mIsVirtualLeaf;
231        /** This marks the maximal depth where a virtual leaf can be defined.
232            From this point on it makes no sense to traverse down further, as all
233                nodes below contain the same geometry, so no further refinement of visibility
234                can be archieved. All nodes below this point can merely used to define the
235                tighter bounds.
236        */
237        bool mIsMaxDepthForVirtualLeaf;
238};
239
240
241
242/////////////////
243//-- public inline functions
244
245
246int BvhNode::GetLastVisitedFrame() const
247{
248        return mVisibility[sCurrentState].mLastVisitedFrame;
249}
250
251
252void BvhNode::SetLastVisitedFrame(const int lastVisited)
253{
254        mVisibility[sCurrentState].mLastVisitedFrame = lastVisited;
255}
256
257
258bool BvhNode::IsVisible() const
259{
260        return mVisibility[sCurrentState].mIsVisible;
261}
262
263
264void BvhNode::SetVisible(bool visible)
265{
266        mVisibility[sCurrentState].mIsVisible = visible;
267}
268
269
270void BvhNode::IncTimesTestedInvisible()
271{
272        ++ mVisibility[sCurrentState].mTimesInvisible;
273}
274
275
276int BvhNode::GetTimesTestedInvisible() const
277{
278        return mVisibility[sCurrentState].mTimesInvisible;
279}
280
281
282void BvhNode::SetTimesTestedInvisible(int t)
283{
284        mVisibility[sCurrentState].mTimesInvisible = t;
285}
286
287
288bool BvhNode::IsViewFrustumCulled() const
289{
290        return mVisibility[sCurrentState].mIsFrustumCulled;
291}
292
293
294void BvhNode::SetViewFrustumCulled(bool frustumCulled)
295{
296        mVisibility[sCurrentState].mIsFrustumCulled = frustumCulled;
297}
298
299
300bool BvhNode::IsNew() const
301{
302        return mVisibility[sCurrentState].mIsNew;
303}
304
305
306void BvhNode::SetIsNew(bool isNew)
307{
308        mVisibility[sCurrentState].mIsNew = isNew;
309}
310
311
312void BvhNode::SetAssumedVisibleFrameId(int t)
313{
314        mVisibility[sCurrentState].mAssumedVisibleFrameId = t;
315}
316
317
318int BvhNode::GetAssumedVisibleFrameId() const
319{
320        return mVisibility[sCurrentState].mAssumedVisibleFrameId;
321}
322
323
324int BvhNode::GetLastQueriedFrame() const
325{
326        return mVisibility[sCurrentState].mLastQueriedFrame;
327}
328
329
330void BvhNode::SetLastQueriedFrame(int lastTested)
331{
332        mVisibility[sCurrentState].mLastQueriedFrame = lastTested;
333}
334
335
336int BvhNode::GetLastRenderedFrame() const
337{
338        return mLastRenderedFrame[sCurrentState];
339}
340       
341
342void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
343{
344        mLastRenderedFrame[sCurrentState] = lastRenderedFrame;
345}
346       
347       
348bool BvhNode::Empty() const
349{
350        return (mFirst == -1);
351}
352
353
354int BvhNode::CountPrimitives() const
355{
356        return mLast - mFirst + 1;
357}
358
359
360
361
362
363/** Internal node of the bv hierarchy.
364*/
365class BvhInterior: public BvhNode
366{
367        friend class Bvh;
368        friend class BvhLoader;
369
370public:
371
372        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
373        {}
374        virtual bool IsLeaf() const { return false; }
375        /** Back child.
376        */
377        inline BvhNode *GetBack() { return mBack; }
378        /** Front child.
379        */
380        inline BvhNode *GetFront() { return mFront; }
381        /** Recursivly delete hierarchy.
382        */
383        virtual ~BvhInterior();
384
385protected:
386
387        BvhNode *mBack;
388        BvhNode *mFront;
389};
390
391
392class BvhLeaf: public BvhNode
393{
394        friend class Bvh;
395        friend class BvhLoader;
396
397public:
398
399        BvhLeaf(BvhNode *parent): BvhNode(parent)
400        {}
401
402        ~BvhLeaf();
403
404        virtual bool IsLeaf() const { return true; }
405};
406
407
408/**     This class implements the compare operator for the priority queue.
409        a lower distance has a higher value in the queue
410*/
411class mygreaterdistance
412{
413public:
414        bool operator() (BvhNode *v1, BvhNode *v2) const
415    {
416                return (v1->GetDistance() > v2->GetDistance());
417    }
418};
419
420typedef std::priority_queue<BvhNode *, std::vector<BvhNode *>, mygreaterdistance> TraversalQueue;
421
422
423/** Class representing a bounding volume hierarchy.
424*/
425class Bvh
426{
427        friend class BvhLoader;
428
429        /** Bvh properties
430        */
431        struct BvhStats
432        {
433                BvhStats():
434                mInteriorSA(0),
435                mLeafSA(0),
436                mInteriorVol(0),
437                mLeafVol(0),
438                mTriangles(0),
439                mTriangleRatio(0),
440                mGeometryRatio(0),
441                mMaxGeometry(0),
442                mMaxTriangles(0)
443                {}
444               
445                float mInteriorSA;
446                float mLeafSA;
447                float mInteriorVol;
448                float mLeafVol;
449               
450                int mTriangles;
451
452                float mTriangleRatio;
453                float mGeometryRatio;
454
455                int mMaxGeometry;
456                int mMaxTriangles;
457        };
458
459public:
460
461        /** Destructor.
462        */
463        ~Bvh();
464        /** Returns number of bvh nodes.
465        */
466        inline int GetNumNodes() const { return mNumNodes; }
467        /** Returns number of bvh leaves.
468        */
469        inline int GetNumLeaves() const { return mNumNodes / 2 + 1;}
470        /** Returns number of 'virtual' nodes in the hierarchy, i.e.
471                the number of nodes actually used for traversal.
472        */
473        int GetNumVirtualNodes() const  { return mNumVirtualNodes; }
474        /** Returns number of bvh leaves.
475        */
476        inline int GetNumVirtualLeaves() const { return mNumVirtualNodes / 2 + 1;}
477        /** Returns root node of the bvh.
478        */
479        BvhNode *GetRoot() { return mRoot; }
480        /** Sets the scene camera
481        */
482        //void SetCamera(Camera * camera) { mCamera = camera; }
483
484        ///////////////
485        //-- functions collecting nodes based on some criteria
486
487        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes, int depth);
488        void CollectNodes(BvhNode *node, BvhNodeContainer &nodes);
489        void CollectLeaves(BvhNode *node, BvhLeafContainer &leaves);
490        /** Collect only the virtual leaves.
491        */
492        void CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves);
493
494
495        //////////////////////
496
497        /** Returns geometry by reference (faster).
498        */
499        SceneEntity **GetGeometry(BvhNode *node, int &size) const;
500
501
502        /////////////
503        //-- Rendering related options
504
505        /** Renders the bounds of this node
506            (the box of the node or the tigher bounds of some subnodes).
507        */
508        void RenderBounds(BvhNode *node, RenderState *state, bool useTightBounds);
509        /** Renders bounding boxes of the collection of nodes.
510                @returns #rendered boxes
511        */
512        int RenderBounds(const BvhNodeContainer &nodes, RenderState *state, bool useTightBounds);
513        /** Returns the bounding box of this bvh.
514        */
515        inline const AxisAlignedBox3 &GetBox() { return mBox; }
516
517
518        //////////////
519        //-- Traversal related options
520
521        /** Pulls up visible classification.
522        */
523        void MakeParentsVisible(BvhNode *node);
524        /** Does the view frustum culling for this node with respect to the previous culls
525                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
526        */
527        int     IsWithinViewFrustum(BvhNode *node);
528        /** Sets frame dependent values
529        */
530        void InitFrame(Camera *camera);
531        /** Stores the orthogonal distance from the viewpoint to a point on the node.
532                We choose the the nearest bounding box vertex .
533                Note that negative values can appear because culling is done only afterwards
534        */
535        void UpdateDistance(BvhNode *node) const;
536        /** Returns the maximum distance from the near plane to this node.
537        */
538        float CalcMaxDistance(BvhNode *node) const;
539        /** Pulls up the last visited classification in the bvh.
540        */
541        void PullUpLastVisited(BvhNode *node, int frameId) const;
542        /** Resets the node classifications in the tree.
543        */
544        void ResetNodeClassifications();
545        /** Helper function that renders the bounding boxes of the leaves as
546                wireframes for visualization purpose.
547        */
548        //void RenderBoundingBoxesForViz(int mode);
549        /** Count triangles the node contains.
550        */
551        int CountTriangles(BvhNode *node) const;
552        /** Returns area of the the node.
553        */
554        float GetArea(BvhNode *node) const;
555        /** Compute unique ids for the nodes.
556        */
557        void ComputeIds();
558        /** Assign virtual leaves based on specified number of triangles per leaf.
559        */
560        void SetVirtualLeaves(int numTriangles);
561       
562
563        ////////
564        //-- functions influencing tighter bounds
565
566
567        /** Sets maximal depth for taking the bounding boxes to test the
568                visibility of a node.
569                Deeper => the bounds adapt more to the geometry.
570        */
571        void SetMaxDepthForTestingChildren(int maxDepth);
572
573        void SetAreaRatioThresholdForTestingChildren(float ratio);
574
575
576        ////////////////////////////
577
578        /** Returns stats.
579        */
580        const BvhStats &GetBvhStats() const { return mBvhStats; }
581        /** Render wireframe bvh for visualization purpose.
582        */
583        void RenderBoundsForViz(BvhNode *node, RenderState *state, bool useTightBounds);
584
585
586protected:
587
588        ////////////////////
589
590        /** protected constructor: do nothing.
591        */
592        Bvh();
593        /** Protected constructor taking scene geometry into account
594        */
595        const Bvh(const SceneEntityContainer &entities);
596        /** Called by the constructor. Initializes important members.
597        */
598        void Init();
599
600        /////////////
601
602        void ComputeBvhStats();
603        void PrintBvhStats() const;
604
605
606        //////////
607        //-- Helper methods for bounding box rendering in immediate and vbo mode.
608       
609        void PrepareVertices();
610
611        int PrepareBoundsWithDrawArrays(const BvhNodeContainer &nodes);
612        void RenderBoundsWithDrawArrays(int numNodes, RenderState *state);
613
614        /** Create the indices that each node needs to use vbo rendering.
615        */
616        void CreateIndices();
617        /** Create the list of nodes whose bounding boxes are tested instead of the
618                bounding box of the node itself.
619        */
620        bool CreateNodeRenderList(BvhNode *node);
621        /** Recursivly updates indices so we can
622                render also interior nodes without traversing hierarchy
623        */
624        void UpdateInteriors(BvhNode *node);
625        /** Recomputes the boundaries of the nodes.
626            This function is always called if some boundary options are changed.
627        */
628        void RecomputeBounds();
629        /** Does some postprocessing on the nodes.
630        */
631        void PostProcess();
632        /** Helper method that updates the number of leaves in the subtree under
633                this node.
634        */
635        void UpdateNumLeaves(BvhNode *node) const;
636        /** Frustum tests the ith plane.
637        */
638        inline bool TestPlane(BvhNode *node, int i, bool &bIntersect);
639        /** Renders a bounding box in immediate mode.
640        */
641        void RenderBoundingBoxImmediate(const AxisAlignedBox3 &box);
642
643
644        /////////////////////////////
645
646        int SortTriangles(BvhLeaf *leaf,
647                              int axis,
648                                          float position,
649                                          SceneEntityContainer &entities);
650
651        int SortTrianglesSpatialMedian(BvhLeaf *leaf,
652                                           int axis,
653                                                                   SceneEntityContainer &entities);
654
655        BvhNode *SubdivideLeaf(BvhLeaf *leaf,
656                                   int parentAxis,
657                                                   SceneEntityContainer &entities);
658
659        /** Recompute the dynamic branch of the hierarchy.
660        */
661        void UpdateDynamicBranch();
662
663        inline bool TerminationCriteriaMet(BvhLeaf *leaf) const;
664
665
666        ////////////////////////
667       
668        /// the bounding box of the bvh
669        AxisAlignedBox3 mBox;
670        /// the root of the hierarchy
671        BvhNode *mRoot;
672        /// pointers to the geometry associated with this node
673        SceneEntity **mGeometry;
674        /// #of entities
675        size_t mGeometrySize;
676
677
678        ////////////////
679        //-- tigher bounds termination criteria
680
681        /** maximal depth from which children are fetched for
682                testing instead of the current node
683        */
684        int mMaxDepthForTestingChildren;
685        /// threshold for computing tighter bounds
686        float mAreaRatioThreshold;
687       
688       
689        ////////////////
690        //-- statistics
691
692        BvhStats mBvhStats;
693        /// the overall number of nodes
694        int mNumNodes;
695        /// the number of "virtual" (=actually used) nodes
696        int mNumVirtualNodes;
697
698
699        ////////////
700        //-- rendering stuff
701
702        /// these proxy nodes are tested instead of the current node
703        BvhNodeContainer mTestNodes;
704        /// the indices used for vbo index buffering
705        unsigned int *mTestIndices;
706        /// a pointer to the end of the indices array
707        int mCurrentIndicesPtr;
708        /// the vbo id
709        unsigned int mVboId;
710        /// a vertex array used if working with indexed arrays (without vbo)
711        Vector3 *mVertices;
712        /// indices used for draw array rendering
713        unsigned int *mIndices;
714
715
716        ///////////
717        //-- termination criteria for dynamic branch
718
719        int mMaxDepthForDynamicBranch;
720
721        SceneEntityContainer mDynamicEntities;
722};
723
724}
725
726#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.