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

Revision 2746, 20.0 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#if TOIMPLEMENT
7
8#include "Bounds.h"
9#include "PerfTimer.h"
10#include "NV_RenderPredictorRenderAction.h"
11#include "VisibilityPredictor.h"
12#include "HierarchyNode.h"
13#include "FlexibleHeap.h"
14
15
16////////
17// Forward declarations
18
19class Scene;
20class Node;
21class Camera;
22class Box;
23class BvhLeaf;
24class BvhNode;
25class TriangleBvh;
26
27
28
29/** A node in the bv hierarchy.
30*/
31class BvhNode: public RenderableHierarchyNode, public Heapable
32{
33        friend class Bvh;
34
35public:
36
37        /** visibility related options
38        */
39        struct VisibilityInfo
40        {
41                VisibilityInfo() { Reset(); }           
42                /** Reset the visibility info.
43                */
44                void Reset();
45
46
47                /// if the node is visible
48                bool mIsVisible;
49                /// if all the leaves are visible
50                bool mIsFullyVisible;
51               
52                /// #pixels this node was visible for the last test
53                int mVisiblePixels;             
54                /// #frames this node is assumed to stay visible
55                int mAssumedVisibleFrames;
56                /// #frames this node is assumed to stay visible
57                int mRemainingVisibleFrames;
58               
59                /// the frame in which the node was last tested visible
60                int mLastTestedVisibleFrame;
61                /// the frame when this node was last touched during traversal
62                int mLastVisitedFrame;
63                /// frame id when the node turned visible
64                int mTurnedVisibleFrame;
65                /// when was the node last tested
66                int mLastTestedFrame;
67
68                /// #times this node was invisible (only valid if the node actually is invisible)
69                int mTimesInvisible;
70                /// #times this node was tested
71                int mTimesTested;
72                /// #times this node was tested
73                int mTimesChangedClassification;
74                /// The ratio of classification changes / tests
75                float mAvgChangedClassification;
76               
77                /// if the node is view frustum culled
78                bool mIsFrustumCulled;
79
80                bool mIsNew;
81        };
82
83        /** Constructor taking the parent node.
84        */
85        BvhNode(BvhNode *parent);
86       
87        /** Returns true if this node is a leaf.
88        */
89        //virtual bool IsPseudoLeaf() = 0;
90        /** Virtual destructor doing nothing.
91        */
92        virtual ~BvhNode();
93        /** Returns unique id for this node.
94        */
95        inline int GetId() {return mId;}
96        /** Depth of this node in the tree.
97        */
98        inline int GetDepth() const {return (int)mDepth;}
99        /** Returns parent of this bvh node, NULL if it is root.
100        */
101        inline BvhNode *GetParent() {return mParent;}
102        /** Number of leaves in the subtree induced by this node.
103        */
104        inline int GetNumLeaves() const {return mNumLeaves;}
105        /** Box used for visualization.
106        */
107        Box *GetOrCreateVizBox();
108        /** Reset the status of this node.
109        */
110        virtual void ResetVisibility();
111
112        virtual int GetType() { return BVH_NODE; }
113
114
115        /////////////////////
116        //-- visibility culling related functions
117
118        inline int GetLastVisitedFrame() const;
119
120        inline void SetLastVisitedFrame(const int lastVisited);
121        /** If this node is considered visible.
122        */
123        inline bool IsVisible() const;
124        /** Set visibility flag of the node.
125        */
126        inline void SetVisible(const bool visible);
127        /** The assumed visible time span of this node.
128        */
129        inline void SetAssumedVisibleFrames(const int t);
130        /** See set.
131        */
132        inline int GetAssumedVisibleFrames() const;
133        /** The time span this node remains visible.
134        */
135        inline void SetRemainingVisibleFrames(const int t);
136        /** See set.
137        */
138        inline int GetRemainingVisibleFrames() const;
139        /** Decrease the time this node is considered visible.
140        */
141        inline void DecRemainingVisibleFrames();
142        /** Returns the frame id when this node was tested
143                visible.
144        */
145        inline void SetLastTestedVisibleFrame(const int t);
146        /** See set.
147        */
148        inline int GetLastTestedVisibleFrame() const;
149        /** Increases the #times this node was
150                successfully tested invisible.
151        */
152        inline void IncTimesInvisible();
153        /** If the subtree induced by this node
154                is fully visible.
155        */
156        inline bool IsFullyVisible();
157
158        inline int GetTimesInvisible() const;
159        inline void SetTimesInvisible(const int t);
160       
161        inline int GetTurnedVisibleFrame() const;
162        inline void SetTurnedVisibleFrame(const int turnedVisibleFrame);
163
164        inline int GetLastTestedFrame();
165        inline void SetLastTestedFrame(const int lastTested);
166
167        inline void SetVisiblePixels(const int pixels);
168        inline int GetVisiblePixels();
169
170        inline void IncTimesTested();
171        inline void IncTimesChangedClassficiation();
172
173        inline int GetTimesTested();
174        inline int GetTimesChangedClassification();
175       
176        inline bool IsViewFrustumCulled() const;
177        inline void SetViewFrustumCulled(const bool frustumCulled);
178
179        inline bool IsNew() const;
180        inline void SetIsNew(const bool isNew);
181
182
183        //////////
184        //-- rendering
185       
186        /** Returns the frame in which this node was last rendered.
187        */
188        inline int GetLastRenderedFrame() const;
189        /** See get.
190        */
191        inline void SetLastRenderedFrame(int lastRenderedFrame);
192       
193       
194        /** Does this node contain renderable geometry?
195        */
196        inline bool Empty() const;
197        /** Counts #geometry stored in the subtree.
198        */
199        inline int CountPrimitives() const;
200
201
202        ///////////////
203        //-- public stuff
204
205        /// Visibility measurements for the period this node was visible
206        VisibilityMeasurementBuffer mMeasurements;
207        /// some flags
208        int mFlags;
209
210        //int mNumFailedTests;
211
212protected:
213
214        /** Marks the subtree induced by this node
215                as fully visible.
216        */
217        inline void SetFullyVisible(const bool visible);
218
219
220        /////////////
221
222        /// the depth of this node
223        unsigned char mDepth;
224        /// the split axis
225        char mAxis;
226        /// the parent node
227        BvhNode *mParent;
228       
229        /// stores the visibility related parameters
230        VisibilityInfo mVisibility;
231
232        /////////
233        // used for view frustum culling
234
235        int mPlaneMask;
236        int mPreferredPlane;
237
238
239        ////////////
240        //-- rendering related options
241       
242        /// when the node was last rendered
243        int mLastRenderedFrame;
244        /// #leaves under this node
245        int mNumLeaves;
246       
247        // Indices to first and last triangle in the triangle array
248        // assumes the traingle are placed in continuous chunk of memory
249        // however this need not be a global array!
250       
251        /// the index of the first triangle
252        int mFirst;
253        /// the index of the last triangle
254        int mLast;
255
256        /// these nodes can be tested instead of the current node
257        int mTestNodesIdx;
258        int mNumTestNodes;
259        int mIndicesPtr;
260
261        /// Area of this node
262        float mArea;
263};
264
265
266/////////////////
267//-- public inline functions
268
269int BvhNode::GetLastVisitedFrame() const
270{
271        return mVisibility.mLastVisitedFrame;
272}
273
274
275void BvhNode::SetLastVisitedFrame(const int lastVisited)
276{
277        mVisibility.mLastVisitedFrame = lastVisited;
278}
279
280
281bool BvhNode::IsVisible() const
282{
283        return mVisibility.mIsVisible;
284}
285
286
287void BvhNode::SetVisible(const bool visible)
288{
289        mVisibility.mIsVisible = visible;
290}
291
292
293void BvhNode::SetLastTestedVisibleFrame(const int t)
294{
295        mVisibility.mLastTestedVisibleFrame = t;
296}
297
298
299int BvhNode::GetLastTestedVisibleFrame() const
300{
301        return mVisibility.mLastTestedVisibleFrame;
302}
303
304
305void BvhNode::IncTimesInvisible()
306{
307        ++ mVisibility.mTimesInvisible;
308}
309
310
311bool BvhNode::IsFullyVisible()
312{
313        return mVisibility.mIsFullyVisible;
314}
315
316
317int BvhNode::GetTimesInvisible() const
318{
319        return mVisibility.mTimesInvisible;
320}
321
322
323void BvhNode::SetTimesInvisible(const int t)
324{
325        mVisibility.mTimesInvisible = t;
326}
327
328
329int BvhNode::GetTurnedVisibleFrame() const
330{
331        return mVisibility.mTurnedVisibleFrame;
332}
333
334
335void BvhNode::SetTurnedVisibleFrame(const int turnedVisibleFrame)
336{
337        mVisibility.mTurnedVisibleFrame = turnedVisibleFrame;
338}
339
340
341int BvhNode::GetLastTestedFrame()
342{
343        return mVisibility.mLastTestedFrame;
344}
345
346
347void BvhNode::SetLastTestedFrame(const int lastTested)
348{
349        mVisibility.mLastTestedFrame = lastTested;
350}
351
352
353void BvhNode::SetVisiblePixels(const int pixels)
354{
355        mVisibility.mVisiblePixels = pixels;
356}
357
358
359int BvhNode::GetVisiblePixels()
360{
361        return mVisibility.mVisiblePixels;
362}
363
364
365void BvhNode::IncTimesTested()
366{
367        ++ mVisibility.mTimesTested;
368}
369
370
371void BvhNode::IncTimesChangedClassficiation()
372{
373        ++ mVisibility.mTimesChangedClassification;
374}
375
376
377int BvhNode::GetTimesTested()
378{
379        return mVisibility.mTimesTested;
380}
381
382
383int BvhNode::GetTimesChangedClassification()
384{
385        return mVisibility.mTimesChangedClassification;
386}
387
388
389bool BvhNode::IsViewFrustumCulled() const
390{
391        return mVisibility.mIsFrustumCulled;
392}
393
394
395void BvhNode::SetViewFrustumCulled(const bool frustumCulled)
396{
397        mVisibility.mIsFrustumCulled = frustumCulled;
398}
399
400
401bool BvhNode::IsNew() const
402{
403        return mVisibility.mIsNew;
404}
405
406
407void BvhNode::SetIsNew(const bool isNew)
408{
409        mVisibility.mIsNew = isNew;
410}
411
412
413int BvhNode::GetLastRenderedFrame() const
414{
415        return mLastRenderedFrame;
416}
417       
418
419void BvhNode::SetLastRenderedFrame(int lastRenderedFrame)
420{
421        mLastRenderedFrame = lastRenderedFrame;
422}
423       
424       
425bool BvhNode::Empty() const
426{
427        return mFirst == -1;
428}
429
430
431int BvhNode::CountPrimitives() const
432{
433        return mLast - mFirst + 1;
434}
435
436
437void BvhNode::SetAssumedVisibleFrames(const int t)
438{
439        mVisibility.mAssumedVisibleFrames = t;
440}
441
442
443int BvhNode::GetAssumedVisibleFrames() const
444{
445        return mVisibility.mAssumedVisibleFrames;
446}
447
448
449void BvhNode::SetRemainingVisibleFrames(const int t)
450{
451        mVisibility.mRemainingVisibleFrames = t;
452}
453
454
455int BvhNode::GetRemainingVisibleFrames() const
456{
457        return mVisibility.mRemainingVisibleFrames;
458}
459
460
461void BvhNode::DecRemainingVisibleFrames()
462{
463        -- mVisibility.mRemainingVisibleFrames;
464}
465
466
467
468/** Internal node of the bv hierarchy.
469*/
470class BvhInterior: public BvhNode
471{
472friend class Bvh;
473
474public:
475        BvhInterior(BvhNode *parent): mBack(NULL), mFront(NULL), BvhNode(parent)
476        {}
477        virtual bool IsLeaf() {return false;}
478        /** Back child.
479        */
480        inline BvhNode *GetBack() { return mBack;}
481        /** Front child.
482        */
483        inline BvhNode *GetFront() { return mFront;}
484        /** recursivly delete tree.
485        */
486        virtual ~BvhInterior() { if (mBack) delete mBack; if (mFront) delete mFront;}
487        /** Returns split axis of this interior node.
488        */
489        inline int GetAxis() {return (int)mAxis;}
490        /** Returns position of the split axis.
491        */
492        inline float GetPosition() {return (float)mPosition;}
493
494
495protected:
496
497        /// the position of the split plane
498        float mPosition;
499       
500        BvhNode *mBack;
501        BvhNode *mFront;
502};
503
504
505class BvhLeaf: public BvhNode
506{
507friend class Bvh;
508
509public:
510
511        BvhLeaf(BvhNode *parent): BvhNode(parent), mTriangleBvh(NULL)
512        {}
513
514        ~BvhLeaf();
515
516        virtual bool IsLeaf() { return true; }
517};
518
519
520struct NodeGeometry
521{
522        virtual AxisAlignedBox3 GetBoundingBox() = 0;
523};
524
525
526struct ObjectGeometry
527{
528        virtual AxisAlignedBox3 GetBoundingBox() = 0;
529};
530
531
532struct TriangleGeometry
533{
534        virtual AxisAlignedBox3 GetBoundingBox() = 0;
535};
536
537
538/** Class representing a bounding volume hierarchy.
539*/
540class Bvh
541{
542        /** Bvh properties
543        */
544        struct BvhStats
545        {
546                BvhStats():
547                mInteriorSA(0),
548                mLeafSA(0),
549                mInteriorVol(0),
550                mLeafVol(0),
551                mBoundsInteriorSA(0),
552                mBoundsLeafSA(0),
553                mBoundsInteriorVol(0),
554                mBoundsLeafVol(0),
555                mBoundsLeavesCount(0),
556                mTriangles(0),
557                mTriangleRatio(0),
558                mGeometryRatio(0),
559                mMaxGeometry(0),
560                mMaxTriangles(0)
561                {}
562               
563                float mInteriorSA;
564                float mLeafSA;
565                float mInteriorVol;
566                float mLeafVol;
567                float mBoundsInteriorSA;
568                float mBoundsLeafSA;
569                float mBoundsInteriorVol;
570                float mBoundsLeafVol;
571                int mBoundsLeavesCount;
572                int mTriangles;
573
574                float mTriangleRatio;
575                float mGeometryRatio;
576
577                int mMaxGeometry;
578                int mMaxTriangles;
579        };
580
581public:
582
583        /** Returns number of bvh nodes.
584        */
585        inline int GetNumNodes() const {return mNumNodes;}
586        /** Returns number of bvh leaves.
587        */
588        inline int GetNumLeaves() const {return mNumNodes / 2 + 1;}
589        /** Constructs the bounding volume hierarchy.
590        */
591        void Construct();
592        /** Returns root node of the bvh.
593        */
594        BvhNode *GetRoot() {return mRoot;}
595        /** Counts the triangle in this leaf.
596        */
597        int CountTriangles(BvhLeaf *leaf) const;
598
599
600        //////////////////////
601
602        /** Returns geometry by reference (faster).
603        */
604        NodeGeometry **GetGeometry(BvhNode *node, int &size);
605
606
607        /////////////
608        //-- Rendering related options
609
610        /** Renders the bounding box of this node (Or the tigher bounding boxes of some subnodes).
611        */
612        void RenderBoundingBox(BvhNode *node);
613        /** Renders bounding boxes of the collection of nodes.
614                @returns #rendered boxes
615        */
616        int RenderBoundingBoxes(const BvhNodeContainer &nodes);
617
618
619
620        //////////////
621        //-- Traversal related options
622
623        /** Pulls up visible classification.
624        */
625        void MakeParentsVisible(BvhNode *node);
626        /** Does the view frustum culling for this node with respect to the previous culls
627                @returns: 0 if completely outside, 1 if completely inside, -1 if intersecting (partly inside),
628        */
629        int     IsWithinViewFrustum(BvhNode *node);
630        /** sets frame dependent values.
631        */
632        void InitFrame(Camera *camera, const int currentFrameId, Viewer *viewer);
633        /** this gives the orthogonal distance from the viewpoint to the nearest BBox-Vertex
634                note that negative values can appear because culling is done only afterwards
635        */
636        float CalcDistance(BvhNode *node) const;
637        /** Sets maximal depth for taking the bounding boxes to test the
638                visibility of a node. The deeper the more the box fits to the geometry.
639        */
640        void SetMaxDepthForTestingChildren(const int maxDepth);
641        /** Resize the visibility buffers of the bvh nodes.
642        */
643        void ResizeVisibilityBuffers(const int size);
644
645       
646        /** Pulls up the fully visible classification in the bvh.
647        */
648        void UpdateFullVisibility(BvhNode *node) const;
649        /** Pulls up the last visited classification in the bvh.
650        */
651        void PullUpLastVisited(BvhNode *node, const int frameId) const;
652        /** Resets the node classifications in the tree.
653        */
654        void ResetNodeClassifications();
655        /** Helper function that renders the bounding boxes of the leaves as
656                wireframes for visualization purpose.
657        */
658        void RenderBoundingBoxesForViz(const int mode);
659        /** Returns squared min distance to the view point.
660        */
661        float GetSquareDistance(BvhNode *node) const;
662        /** Count triangles the node contains.
663        */
664        int CountTriangles(BvhNode *node) const;
665        /** Returns area of the geometry contained in the node.
666        */
667        float GetGeometryArea(BvhNode *node) const;
668
669
670        ////////////
671        //-- functions that change the boundaries of the nodes
672
673        void SetUseTighterBoundsForTests(bool tighterBoundsForTests);
674
675        void SetAreaRatioThresholdForTestingChildren(const float ratio);
676
677        void SetVolRatioThresholdForTestingChildren(const float ratio);
678        /** Returns depth of bvh hierarchy.
679        */
680        float GetAvgDepth() const;
681
682
683        const BvhStats &GetBvhStats() const {return mBvhStats;}
684
685        void SetCollectTighterBoundsWithMaxLevel(bool t);
686
687
688        /////////////
689        //-- timers
690
691        mutable PerfTimer timeSetup;
692        mutable PerfTimer timeIssueDrawElements;
693        mutable PerfTimer timeViewFrustumCulling;
694        mutable PerfTimer timeDistance;
695
696        //////////////
697
698        static unsigned int sCurrentVboId;
699       
700
701protected:
702
703        /** Small struct representing a frustum.
704        */
705        struct Frustum
706        {
707                /// the 6 clip planes
708                float mClipPlane[6][4];
709        };
710       
711
712
713        ////////////////////
714
715        /** Constructor taking the geometry and a pointer to the current render action.
716        */
717        Bvh(const GeometryVector &geometry,
718                DistanceSortedRenderAction *const renderer);
719        /** protected constructor: do nothing.
720        */
721        Bvh(): mCamera(NULL), mFrameId(-1), mVertices(NULL), mRenderer(NULL) {}
722        /** Destructor.
723        */
724        ~Bvh();
725
726
727
728        //-- sorting functions
729
730        /** The method of subdividing objects into halves in some axis using spatial median
731        */
732        int     SortTrianglesSpatialMedian(BvhLeaf *leaf, const int axis);
733        /** The method of subdividing objects into halves in some axis
734                using object median.
735        */
736        int     SortTrianglesObjectMedian(BvhLeaf *leaf, const int axis, float &pos);
737        /** sort triangles along the axis with respect to the splitting plane
738                given by axis/position return index of the first tiangles belong
739                to the front of the splitting plane.
740        */
741        int     SortTriangles(BvhLeaf *leaf, const int axis, const float position);
742        /** sort triangles by their area.
743        */
744        int SortTrianglesSurfaceArea(BvhLeaf *leaf, const float sa);
745
746
747        /////////////
748
749
750        /** Subdivides the current leaf.
751        */
752        BvhNode *SubdivideLeaf(BvhLeaf *leaf, const int parentAxis);   
753        /** select splitting plane using SAH - returns the position of the splitting plane.
754        */
755        float SelectPlaneSah(BvhLeaf *leaf, int &axis, float &minCost);
756        /** evaluate the SAH cost of a particulkar splitting plane
757        */
758        float EvaluateSahCost(BvhLeaf *leaf, const int axis, const float position);
759
760        void ComputeBvhStats();
761        void PrintBvhStats() const;
762
763        /** Update children nodes recursively.
764        */
765        void UpdateBoxes(BvhNode *node);
766        /** Update box for a leaf node
767        */
768        void UpdateLeafBox(BvhLeaf *leaf);
769        /** Returns true if termination criteria met.
770        */
771        bool TerminationCriteriaMet(BvhLeaf *leaf) const;
772        /** Compute unique ids for the bvh nodes.
773        */
774        void ComputeIds();
775        /** Helper method that updates the number of leaves in the subtree under
776                this node.
777        */
778        void UpdateNumLeaves(BvhNode *node) const;
779
780
781        //////////
782        //-- Helper methods for bounding box rendering in immediate and vbo mode.
783       
784        void PrepareVertices();
785
786        int PrepareBoundingBoxesWithDrawArrays(const BvhNodeContainer &nodes);
787        void RenderBoundingBoxesWithDrawArrays(const int numNodes);
788
789        int RenderBoundingBoxesImmediate(const BvhNodeContainer &nodes);
790        /** Renders a bounding box in immediate mode using index restart
791                and restarts the strip only if wished.
792        */
793        void RenderBoundingBoxImmediate(const BoundingBox &box, const bool restartStrip);
794        /** Create the indices that each node needs to use vbo rendering.
795        */
796        void CreateIndices();
797        /** Create the list of nodes whose bounding boxes are tested instead of the
798                bounding box of the node itself.
799        */
800        bool CreateNodeRenderList(BvhNode *node);
801        /** Recursivly updates indices so we can
802                render also interior nodes without traversing hierarchy
803        */
804        void UpdateInteriors(BvhNode *node);
805        /** Recomputes the boundaries of the nodes. This function is always called if
806                some boundary options are changed.
807        */
808        void RecomputeBounds();
809        /** Does some postprocessing on the leaves.
810                @returns #leaves that were chosen for tighter bounds.
811        */
812        int PostProcessLeaves(BvhLeafContainer &leaves);
813
814        bool CreateTighterBoundsForLeaf(BvhLeaf *leaf, Point3f *triangles, const int triangleCount);
815
816        Point3f *CollectTriangles(BvhLeaf *leaf, int &triangleCount);
817
818        int     IsWithinViewFrustumLocal(BvhNode *node);
819
820        int     IsWithinViewFrustum(const BoundingBox &box, const int planeMask, const int preferredPlane);
821        /** Compute screen space projection of a bounding box.
822        */
823        float ComputeScreenSpaceProjection(const BoundingBox &box) const;
824
825        float GetMinSquareDistance(const BoundingBox &box) const;
826        /** Computes the area of the triangles in a leaf.
827        */
828        float ComputeGeometryArea(BvhLeaf *leaf, Point3f *triangles, const int triangleCount) const;
829
830
831       
832        ////////////////////////
833
834        /// the root of the hierarchy
835        BvhNode *mRoot;
836        /// pointers to the geometry associated with this node
837        NodeGeometry **mGeometry;
838        /// #of entities of geometry
839        size_t mGeometrySize;
840
841
842        /////////
843        //-- termination criteria
844
845        int mMaxGeometry;
846        int mMaxTriangles;
847        int mSplitType;
848        int mNumNodes;
849        int mMaxDepth;
850        float mMinArea;
851
852        ////////////////
853
854
855        /// these values are valid for all nodes
856        char mClipPlaneAABBVertexIndices[6][2];
857        /// the current view frustum
858        Frustum mFrustum;
859        /// the current camera
860        Camera *mCamera;
861        // current frame id
862        int mFrameId;
863        /// a vertex array used if working with indexed arrays (without vbo)
864        Point3f *mVertices;
865        /// indices used for draw array rendering
866        unsigned int *mIndices;
867
868        /** maximal depth from which children are fetched for
869                testing instead of the current node
870        */
871        int mMaxDepthForTestingChildren;
872
873        float mAreaRatioThreshold;
874        float mVolRatioThreshold;
875
876        /// pointer to the renderaction
877        DistanceSortedRenderAction *const mRenderer;
878
879        BvhStats mBvhStats;
880
881        HierarchyNodeContainer mTestNodes;
882       
883        unsigned int *mTestIndices;
884
885        /// a pointer to the end of the indices array
886        int mCurrentIndicesPtr;
887
888        float mScale;
889
890        float mAvgDepth;
891
892        Vector3f mNearPlane;
893        float mNearPlaneD;
894};
895
896#endif
897#endif // __BVH_H
Note: See TracBrowser for help on using the repository browser.