source: GTP/trunk/Lib/Vis/Preprocessing/src/BvHierarchy.h @ 1357

Revision 1357, 19.9 KB checked in by mattausch, 18 years ago (diff)

implemented the global version of the bounding volume construction

Line 
1#ifndef _BvHierarchy_H__
2#define _BvHierarchy_H__
3
4#include <stack>
5
6#include "Mesh.h"
7#include "Containers.h"
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "gzstream.h"
12#include "SubdivisionCandidate.h"
13#include "AxisAlignedBox3.h"
14#include "IntersectableWrapper.h"
15
16
17namespace GtpVisibilityPreprocessor {
18
19
20class ViewCellLeaf;
21class Plane3;
22class AxisAlignedBox3;
23class Ray;
24class ViewCellsStatistics;
25class ViewCellsManager;
26class MergeCandidate;
27class Beam;
28class ViewCellsTree;
29class Environment;
30class BvhInterior;
31class BvhLeaf;
32class BvhNode;
33class BvhIntersectable;
34class BvhTree;
35class VspTree;
36class ViewCellsContainer;
37
38
39/** View space partition statistics.
40*/
41class BvhStatistics: public StatisticsBase
42{
43public:
44        // total number of nodes
45        int nodes;
46        // number of splits
47        int splits;
48        // maximal reached depth
49        int maxDepth;
50        // minimal depth
51        int minDepth;
52        // max depth nodes
53        int maxDepthNodes;
54        // minimum depth nodes
55        int minDepthNodes;
56        // nodes with minimum objects
57        int minObjectsNodes;
58        // minimum area nodes
59        int minProbabilityNodes;
60        /// nodes termination because of max cost ratio;
61        int maxCostNodes;
62        // max number of rays per node
63        int maxObjectRefs;
64        /// number of invalid leaves
65        int invalidLeaves;
66        /// accumulated number of rays refs
67        //int accumRays;
68        // accumulated depth (used to compute average)
69        int accumDepth;
70        /// object references
71        int objectRefs;
72
73        // Constructor
74        BvhStatistics()
75        {
76                Reset();
77        }
78
79        int Nodes() const {return nodes;}
80        int Interior() const { return nodes / 2; }
81        int Leaves() const { return (nodes / 2) + 1; }
82       
83        // TODO: computation wrong
84        double AvgDepth() const
85        { return accumDepth / (double)Leaves(); }
86
87        void Reset()
88        {
89                nodes = 0;
90                splits = 0;
91               
92                maxDepth = 0;
93                minDepth = 99999;
94                accumDepth = 0;
95        maxDepthNodes = 0;
96                minObjectsNodes = 0;
97                minProbabilityNodes = 0;
98                maxCostNodes = 0;
99                invalidLeaves = 0;
100                maxObjectRefs = 0;
101                objectRefs = 0;
102        }
103
104        void Print(ostream &app) const;
105
106        friend ostream &operator<<(ostream &s, const BvhStatistics &stat)
107        {
108                stat.Print(s);
109                return s;
110        }
111};
112
113
114/**
115    VspNode abstract class serving for interior and leaf node implementation
116*/
117class BvhNode
118{
119public:
120       
121        // types of vsp nodes
122        enum {Interior, Leaf};
123
124        BvhNode();
125        BvhNode(const AxisAlignedBox3 &bbox);
126        BvhNode(const AxisAlignedBox3 &bbox, BvhInterior *parent);
127
128        virtual ~BvhNode(){};
129
130        /** Determines whether this node is a leaf or not
131                @return true if leaf
132        */
133        virtual bool IsLeaf() const = 0;
134
135        /** Determines whether this node is a root
136                @return true if root
137        */
138        virtual bool IsRoot() const;
139
140        /** Returns parent node.
141        */
142        BvhInterior *GetParent();
143
144        /** Sets parent node.
145        */
146        void SetParent(BvhInterior *parent);
147
148        /** The bounding box specifies the node extent.
149        */
150        inline
151        AxisAlignedBox3 GetBoundingBox() const
152        { return mBoundingBox; }
153
154
155        inline
156        void SetBoundingBox(const AxisAlignedBox3 &boundingBox)
157        { mBoundingBox = boundingBox; }
158
159
160        /////////////////////////////////////
161        //-- mailing options
162       
163        static void NewMail(const int reserve = 1) {
164                sMailId += sReservedMailboxes;
165                sReservedMailboxes = reserve;
166        }
167       
168        void Mail() { mMailbox = sMailId; }
169        bool Mailed() const { return mMailbox == sMailId; }
170
171        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
172        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
173
174        int IncMail() { return ++ mMailbox - sMailId; }
175
176        static int sMailId;
177        int mMailbox;
178        static int sReservedMailboxes;
179
180        ///////////////////////////////////
181
182protected:
183       
184        /// the bounding box of the node
185        AxisAlignedBox3 mBoundingBox;
186        /// parent of this node
187        BvhInterior *mParent;
188};
189
190
191/** BSP interior node implementation
192*/
193class BvhInterior: public BvhNode
194{
195public:
196        /** Standard contructor taking a bounding box as argument.
197        */
198        BvhInterior(const AxisAlignedBox3 &bbox);
199        BvhInterior(const AxisAlignedBox3 &bbox, BvhInterior *parent);
200
201        ~BvhInterior();
202        /** @return false since it is an interior node
203        */
204        bool IsLeaf() const;
205       
206        BvhNode *GetBack() { return mBack; }
207        BvhNode *GetFront() { return mFront; }
208
209        /** Replace front or back child with new child.
210        */
211        void ReplaceChildLink(BvhNode *oldChild, BvhNode *newChild);
212
213        /** Replace front and back child.
214        */
215        void SetupChildLinks(BvhNode *front, BvhNode *back);
216
217        friend ostream &operator<<(ostream &s, const BvhInterior &A)
218        {
219                return s << A.mBoundingBox;
220        }
221
222protected:
223
224        /// back node
225        BvhNode *mBack;
226        /// front node
227        BvhNode *mFront;
228};
229
230
231/** BSP leaf node implementation.
232*/
233class BvhLeaf: public BvhNode
234{
235public:
236        /** Standard contructor taking a bounding box as argument.
237        */
238        BvhLeaf(const AxisAlignedBox3 &bbox);
239        BvhLeaf(const AxisAlignedBox3 &bbox, BvhInterior *parent);
240        BvhLeaf(const AxisAlignedBox3 &bbox, BvhInterior *parent, const int numObjects);
241
242        ~BvhLeaf();
243
244        /** @return true since it is an interior node
245        */
246        bool IsLeaf() const;
247       
248        SubdivisionCandidate *GetSubdivisionCandidate()// const
249        {
250                return mSubdivisionCandidate;
251        }
252
253        void SetSubdivisionCandidate(SubdivisionCandidate *candidate)
254        {
255                mSubdivisionCandidate = candidate;
256        }
257
258public:
259
260        /// Rays piercing this leaf.
261        VssRayContainer mVssRays;
262        /// objects
263        ObjectContainer mObjects;
264        /// universal counter
265        int mCounter;
266
267protected:
268
269        /// pointer to a split plane candidate splitting this leaf
270        SubdivisionCandidate *mSubdivisionCandidate;
271};
272
273
274typedef map<BvhNode *, BvhIntersectable *> BvhIntersectableMap;
275
276
277/** View Space Partitioning tree.
278*/
279class BvHierarchy
280{
281        friend class ViewCellsParseHandlers;
282        friend class HierarchyManager;
283
284public:
285       
286        struct SortableEntry;
287        typedef vector<SortableEntry> SortableEntryContainer;
288
289        /** Additional data which is passed down the BSP tree during traversal.
290        */
291        class BvhTraversalData
292        { 
293        public:
294               
295                BvhTraversalData():
296                mNode(NULL),
297                mDepth(0),
298                mProbability(0.0),
299                mMaxCostMisses(0),
300                mAxis(0)
301                {
302                        mSortedObjects[0] = mSortedObjects[1] = mSortedObjects[2] = NULL;
303                }
304               
305                BvhTraversalData(BvhLeaf *node,
306                                                 const int depth,
307                                                 const AxisAlignedBox3 &box,
308                                                 const float v):
309                mNode(node),
310                mDepth(depth),
311                mBoundingBox(box),
312                mProbability(v),
313                mMaxCostMisses(0),
314                mAxis(0)
315                {
316                        mSortedObjects[0] = mSortedObjects[1] = mSortedObjects[2] = NULL;
317                }
318
319                /** Deletes contents and sets them to NULL.
320                */
321                void Clear()
322                {
323                        DEL_PTR(mNode);
324                        /*DEL_PTR(mSortedObjects[0]);
325                        DEL_PTR(mSortedObjects[1]);
326                        DEL_PTR(mSortedObjects[2]);*/
327                }
328
329                /// the current node
330                BvhLeaf *mNode;
331                /// current depth
332                int mDepth;
333                /// the probability that this node is seen
334                float mProbability;
335                /// the bounding box of the node
336                AxisAlignedBox3 mBoundingBox;
337                /// how often this branch has missed the max-cost ratio
338                int mMaxCostMisses;
339                /// current axis
340                int mAxis;
341                /// the sorted objects for the three dimensions
342                ObjectContainer *mSortedObjects[3];             
343    };
344
345
346        /** Candidate for a object space split.
347        */
348        class BvhSubdivisionCandidate: public SubdivisionCandidate
349        { 
350        public:
351
352        BvhSubdivisionCandidate(const BvhTraversalData &tData): mParentData(tData)
353                {};
354
355                ~BvhSubdivisionCandidate()
356                {
357                        mParentData.Clear();
358                }
359
360                int Type() const { return OBJECT_SPACE; }
361       
362                void EvalPriority()
363                {
364                        sBvHierarchy->EvalSubdivisionCandidate(*this); 
365                }
366
367                bool GlobalTerminationCriteriaMet() const
368                {
369                        return sBvHierarchy->GlobalTerminationCriteriaMet(mParentData);
370                }
371
372                BvhSubdivisionCandidate(
373                        const ObjectContainer &frontObjects,
374                        const ObjectContainer &backObjects,
375                        const BvhTraversalData &tData):
376                mFrontObjects(frontObjects), mBackObjects(backObjects), mParentData(tData)
377                {}
378
379                /// pointer to parent tree.
380                static BvHierarchy *sBvHierarchy;
381                /// parent data
382                BvhTraversalData mParentData;
383                /// the objects on the front of the potential split
384                ObjectContainer mFrontObjects;
385                /// the objects on the back of the potential split
386                ObjectContainer mBackObjects;
387        };
388
389        /** Struct for traversing line segment.
390        */
391        struct LineTraversalData
392        {
393                BvhNode *mNode;
394                Vector3 mExitPoint;
395               
396                float mMaxT;
397   
398                LineTraversalData () {}
399                LineTraversalData (BvhNode *n, const Vector3 &p, const float maxt):
400                mNode(n), mExitPoint(p), mMaxT(maxt) {}
401        };
402
403
404        /** Default constructor creating an empty tree.
405        */
406        BvHierarchy();
407
408        /** Default destructor.
409        */
410        ~BvHierarchy();
411
412        /** Returns tree statistics.
413        */
414        const BvhStatistics &GetStatistics() const;
415 
416        /** Returns bounding box of the specified node.
417        */
418        AxisAlignedBox3 GetBoundingBox(BvhNode *node) const;
419
420        /** Reads parameters from environment singleton.
421        */
422        void ReadEnvironment();
423
424        /** Evaluates candidate for splitting.
425        */
426        void EvalSubdivisionCandidate(BvhSubdivisionCandidate &splitData);
427
428        /** Returns list of leaves with pvs smaller than
429                a certain threshold.
430                @param onlyUnmailed if only the unmailed leaves should be considered
431                @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited)
432        */
433        void CollectLeaves(vector<BvhLeaf *> &leaves) const;
434
435        /** Returns bounding box of the whole tree (= bbox of root node)
436        */
437        AxisAlignedBox3 GetBoundingBox()const;
438
439        /** Returns root of the view space partitioning tree.
440        */
441        BvhNode *GetRoot() const;
442
443        /** A ray is cast possible intersecting the tree.
444                @param the ray that is cast.
445                @returns the number of intersections with objects stored in the tree.
446        */
447        //int CastRay(Ray &ray);
448
449        /** finds neighbouring leaves of this tree node.
450        */
451        int FindNeighbors(BvhLeaf *n,
452                                          vector<BvhLeaf *> &neighbors,
453                                          const bool onlyUnmailed) const;
454
455        /** Returns random leaf of BSP tree.
456                @param halfspace defines the halfspace from which the leaf is taken.
457        */
458        BvhLeaf *GetRandomLeaf(const Plane3 &halfspace);
459
460        /** Returns random leaf of BSP tree.
461                @param onlyUnmailed if only unmailed leaves should be returned.
462        */
463        BvhLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
464
465        /** Casts line segment into the tree.
466                @param origin the origin of the line segment
467                @param termination the end point of the line segment
468                @returns view cells intersecting the line segment.
469        */
470    int CastLineSegment(const Vector3 &origin,
471                                                const Vector3 &termination,
472                                                ViewCellContainer &viewcells);
473               
474        /** Sets pointer to view cells manager.
475        */
476        void SetViewCellsManager(ViewCellsManager *vcm);
477
478        /** Writes tree to output stream
479        */
480        bool Export(OUT_STREAM &stream);
481
482        /** Returns or creates a new intersectable for use in a kd based pvs.
483                The OspTree is responsible for destruction of the intersectable.
484        */
485        BvhIntersectable *GetOrCreateBvhIntersectable(BvhNode *node);
486
487        /** Collects rays.
488        */
489        void CollectRays(const ObjectContainer &objects, VssRayContainer &rays) const;
490
491        /** Intersects box with the tree and returns the number of intersected boxes.
492                @returns number of view cells found
493        */
494        int ComputeBoxIntersections(
495                const AxisAlignedBox3 &box,
496                ViewCellContainer &viewCells) const;
497
498
499        /** Returns leaf the point pt lies in, starting from root.
500        */
501        BvhLeaf *GetLeaf(Intersectable *obj, BvhNode *root = NULL) const;
502
503        ViewCellsTree *GetViewCellsTree() const { return mViewCellsTree; }
504       
505        void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
506
507        /** Add the bvh leaf to the pvs of the view cell.
508        */
509        bool AddLeafToPvs(
510                BvhLeaf *leaf,
511                ViewCell *vc,
512                const float pdf,
513                float &contribution);
514
515protected:
516
517        /** Returns true if tree can be terminated.
518        */
519        bool LocalTerminationCriteriaMet(const BvhTraversalData &data) const;
520
521        /** Returns true if global tree can be terminated.
522        */
523        bool GlobalTerminationCriteriaMet(const BvhTraversalData &data) const;
524
525        /** For sorting the objects during the heuristics
526        */
527        struct SortableEntry
528        {
529                Intersectable *mObject;
530                float mPos;
531
532                SortableEntry() {}
533
534                SortableEntry(Intersectable *obj, const float pos):
535                mObject(obj), mPos(pos)
536                {}
537
538                bool operator<(const SortableEntry &b) const
539                {
540                        return mPos < b.mPos;
541                }
542        };
543
544        /** Evaluate balanced object partition.
545        */
546        float EvalLocalObjectPartition(
547                const BvhTraversalData &tData,
548                const int axis,
549                ObjectContainer &objectsFront,
550                ObjectContainer &objectsBack);
551
552        float EvalSah(
553                const BvhTraversalData &tData,
554                const int axis,
555                ObjectContainer &objectsFront,
556                ObjectContainer &objectsBack);
557
558        /** Computes priority of the traversal data and stores it in tData.
559        */
560        void EvalPriority(BvhTraversalData &tData) const;
561
562        /** Evaluates render cost of next split.
563        */
564        float EvalRenderCost(
565                const BvhTraversalData &tData,
566                const ObjectContainer &objectsLeft,
567                const ObjectContainer &objectsRight) const;
568
569        /** Evaluates tree stats in the BSP tree leafs.
570        */
571        void EvaluateLeafStats(const BvhTraversalData &data);
572
573        /** Subdivides node using a best split priority queue.
574            @param tQueue the best split priority queue
575                @param splitCandidate the candidate for the next split
576                @param globalCriteriaMet if the global termination criteria were already met
577                @returns new root of the subtree
578        */
579        BvhNode *Subdivide(
580                SplitQueue &tQueue,
581                SubdivisionCandidate *splitCandidate,
582                const bool globalCriteriaMet);
583       
584        /** Subdivides leaf.
585                @param sc the subdivisionCandidate holding all necessary data for subdivision           
586               
587                @param frontData returns the traversal data for the front node
588                @param backData returns the traversal data for the back node
589
590                @returns the new interior node = the of the subdivision
591        */
592        BvhInterior *SubdivideNode(
593                const BvhSubdivisionCandidate &sc,
594                BvhTraversalData &frontData,
595                BvhTraversalData &backData);
596
597        /** Splits the objects for the next subdivision.
598                @returns cost for this split
599        */
600        float SelectObjectPartition(
601                const BvhTraversalData &tData,
602                ObjectContainer &frontObjects,
603                ObjectContainer &backObjects);
604       
605        /** Writes the node to disk
606                @note: should be implemented as visitor.
607        */
608        void ExportNode(BvhNode *node, OUT_STREAM &stream);
609
610        void ExportObjects(BvhLeaf *leaf, OUT_STREAM &stream);
611
612        /** Returns estimated memory usage of tree.
613        */
614        float GetMemUsage() const;
615
616        /** Creates new root of hierarchy.
617        */
618        void CreateRoot(const ObjectContainer &objects);
619
620        /////////////////////////////
621        // Helper functions for local cost heuristics
622
623       
624        /** Prepare split candidates for cost heuristics using axis aligned splits.
625                @param node the current node
626                @param axis the current split axis
627        */
628        void PrepareLocalSubdivisionCandidates(
629                const BvhTraversalData &tData,
630                const int axis);
631
632        static void CreateLocalSubdivisionCandidates(
633                const ObjectContainer &objects,
634                SortableEntryContainer **subdivisionCandidates,
635                const bool sort,
636                const int axis);
637
638        /** Computes object partition with the best cost according to the heurisics.
639                @param tData the traversal data
640                @param axis the split axis
641                @param objectsFront the objects in the front child bv
642                @param objectsBack the objects in the back child bv
643                @param backObjectsStart the iterator marking the position where the back objects begin
644
645                @returns relative cost (relative to parent cost)
646        */
647        float EvalLocalCostHeuristics(
648                const BvhTraversalData &tData,
649                const int axis,
650                ObjectContainer &objectsFront,
651                ObjectContainer &objectsBack);
652
653        /** Evaluates the contribution to the front and back volume
654                when this object is changing sides in the bvs.
655
656                @param object the object
657                @param volLeft updates the left pvs
658                @param volPvs updates the right pvs
659        */
660        void EvalHeuristicsContribution(
661                Intersectable *obj,
662                float &volLeft,
663                float &volRight);
664
665        /** Prepares objects for the cost heuristics.
666                @returns sum of volume of associated view cells
667        */
668        float PrepareHeuristics(const BvhTraversalData &tData, const int axis);
669       
670
671        ////////////////////////////////////////////////
672
673
674        /** Prepares construction for vsp and osp trees.
675        */
676        AxisAlignedBox3 ComputeBoundingBox(
677                const ObjectContainer &objects,
678                const AxisAlignedBox3 *parentBox = NULL);
679
680        void CollectDirtyCandidates(
681                BvhSubdivisionCandidate *sc,
682                vector<SubdivisionCandidate *> &dirtyList);
683
684        /** Collect view cells which see this bvh leaf.
685        */
686        void CollectViewCells(
687                const ObjectContainer &objects,
688                ViewCellContainer &viewCells,
689                const bool setCounter = false) const;
690
691        /** Collects view cells which see an object.
692        */
693        void CollectViewCells(
694                Intersectable *object,
695                ViewCellContainer &viewCells,
696                const bool useMailBoxing,
697                const bool setCounter = false) const;
698
699        /** Rays will be clipped to the bounding box.
700        */
701        void PreprocessRays(
702                BvhLeaf *root,
703                const VssRayContainer &sampleRays,
704                RayInfoContainer &rays);
705
706        /** Print the subdivision stats in the subdivison log.
707        */
708        void PrintSubdivisionStats(const SubdivisionCandidate &tData);
709
710        void AddSubdivisionStats(
711                const int viewCells,
712                const float renderCostDecr,
713                const float totalRenderCost);
714
715        void AssociateObjectsWithRays(const VssRayContainer &rays);
716
717        bool IsObjectInLeaf(BvhLeaf *, Intersectable *object) const;
718
719        SubdivisionCandidate *PrepareConstruction(
720                const VssRayContainer &sampleRays,
721                const ObjectContainer &objects
722                );
723
724        float EvalViewCellsVolume(const ObjectContainer &objects) const;
725
726        void CreateInitialSortedObjectList(BvhTraversalData &tData);
727
728        void AssignSortedObjects(
729                const BvhSubdivisionCandidate &sc,
730                BvhTraversalData &frontData,
731                BvhTraversalData &backData);
732
733
734protected:
735       
736        /// pre-sorted subdivision candidtes for all three directions.
737        vector<SortableEntry> *mGlobalSubdivisionCandidates[3];
738
739        /// pointer to the hierarchy of view cells
740        ViewCellsTree *mViewCellsTree;
741
742        VspTree *mVspTree;
743
744        /// The view cells manager
745        ViewCellsManager *mViewCellsManager;
746
747        /// candidates for placing split planes during cost heuristics
748        vector<SortableEntry> *mSubdivisionCandidates;
749
750        /// Pointer to the root of the tree
751        BvhNode *mRoot;
752               
753        /// Statistics for the object space partition
754        BvhStatistics mBvhStats;
755       
756        /// box around the whole view domain
757        AxisAlignedBox3 mBoundingBox;
758
759
760        ////////////////////////////////
761        //-- local termination criteria
762
763        /// maximal possible depth
764        int mTermMaxDepth;
765        /// mininum probability
766        float mTermMinProbability;
767        /// minimal number of objects
768        int mTermMinObjects;
769        /// maximal contribution per ray
770        float mTermMaxRayContribution;
771        /// maximal acceptable cost ratio
772        float mTermMaxCostRatio;
773        /// tolerance value indicating how often the max cost ratio can be failed
774        int mTermMissTolerance;
775
776
777        ////////////////////////////////////
778        //-- global termination criteria
779
780        float mTermMinGlobalCostRatio;
781        int mTermGlobalCostMissTolerance;
782        int mGlobalCostMisses;
783
784        /// maximal number of view cells
785        int mTermMaxLeaves;
786        /// maximal tree memory
787        float mMaxMemory;
788        /// the tree is out of memory
789        bool mOutOfMemory;
790
791
792        ////////////////////////////////////////
793        //-- split heuristics based parameters
794       
795        bool mUseCostHeuristics;
796        /// balancing factor for PVS criterium
797        float mCtDivCi;
798        /// if only driving axis should be used for split
799        bool mOnlyDrivingAxis;
800        /// current time stamp (used for keeping split history)
801        int mTimeStamp;
802        // if rays should be stored in leaves
803        bool mStoreRays;
804        // subdivision stats output file
805        ofstream  mSubdivisionStats;
806        /// keeps track of cost during subdivision
807        float mTotalCost;
808        /// keeps track of overall pvs size during subdivision
809        int mTotalPvsSize;
810        /// number of currenly generated view cells
811        int mCreatedLeaves;
812        /// represents min and max band for sweep
813        float mSplitBorder;
814        /// weight between render cost decrease and node render cost
815        float mRenderCostDecreaseWeight;
816        /// stores the kd node intersectables used for pvs
817        BvhIntersectableMap mBvhIntersectables;
818
819        bool mUseGlobalSorting;
820};
821
822}
823
824#endif
Note: See TracBrowser for help on using the repository browser.