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

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