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

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