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

Revision 1294, 18.7 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        /** Determines whether this node is a root
137                @return true if root
138        */
139        virtual bool IsRoot() const;
140
141        /** Returns parent node.
142        */
143        BvhInterior *GetParent();
144
145        /** Sets parent node.
146        */
147        void SetParent(BvhInterior *parent);
148
149        /** The bounding box specifies the node extent.
150        */
151        AxisAlignedBox3 GetBoundingBox() const
152        { return mBoundingBox; }
153
154
155        void SetBoundingBox(const AxisAlignedBox3 &boundingBox)
156        { mBoundingBox = boundingBox; }
157
158
159        /////////////////////////////////////
160        //-- mailing options
161       
162        static void NewMail(const int reserve = 1) {
163                sMailId += sReservedMailboxes;
164                sReservedMailboxes = reserve;
165        }
166       
167        void Mail() { mMailbox = sMailId; }
168        bool Mailed() const { return mMailbox == sMailId; }
169
170        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
171        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
172
173        int IncMail() { return ++ mMailbox - sMailId; }
174
175        static int sMailId;
176        int mMailbox;
177        static int sReservedMailboxes;
178
179        ///////////////////////////////////
180
181protected:
182       
183        /// the bounding box of the node
184        AxisAlignedBox3 mBoundingBox;
185
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
253public:
254
255        /// Rays piercing this leaf.
256        VssRayContainer mVssRays;
257       
258        /// objects
259        ObjectContainer mObjects;
260
261        /// universal counter
262        int mCounter;
263
264
265protected:
266
267        /// pointer to a split plane candidate splitting this leaf
268        SubdivisionCandidate *mSubdivisionCandidate;
269};
270
271
272typedef map<BvhNode *, BvhIntersectable *> BvhIntersectableMap;
273
274
275/** View Space Partitioning tree.
276*/
277class BvHierarchy
278{
279        friend class ViewCellsParseHandlers;
280        friend class HierarchyManager;
281
282public:
283       
284        /** Additional data which is passed down the BSP tree during traversal.
285        */
286        class BvhTraversalData
287        { 
288        public:
289               
290                BvhTraversalData():
291                mNode(NULL),
292                mDepth(0),
293                mProbability(0.0),
294                mMaxCostMisses(0),
295                mPriority(0),
296                mAxis(0)
297                {}
298               
299                BvhTraversalData(BvhLeaf *node,
300                                                 const int depth,
301                                                 const AxisAlignedBox3 &box,
302                                                 const float v):
303                mNode(node),
304                mDepth(depth),
305                mBoundingBox(box),
306                mProbability(v),
307                mMaxCostMisses(0),
308                mPriority(0),
309                mAxis(0)
310                {}
311
312
313                /** Returns cost of the traversal data.
314                */
315                float GetCost() const
316                {
317                        return mPriority;
318                }
319
320                /// deletes contents and sets them to NULL
321                void Clear()
322                {
323                        DEL_PTR(mNode);
324                }
325
326                /// the current node
327                BvhLeaf *mNode;
328                /// current depth
329                int mDepth;
330                /// the probability that this node is seen
331                float mProbability;
332                /// the bounding box of the node
333                AxisAlignedBox3 mBoundingBox;
334                /// how often this branch has missed the max-cost ratio
335                int mMaxCostMisses;
336                /// current axis
337                int mAxis;
338                /// current priority
339                float mPriority;
340
341
342                friend bool operator<(const BvhTraversalData &a, const BvhTraversalData &b)
343                {
344                        return a.GetCost() < b.GetCost();
345                }
346    };
347
348        /** Candidate for a view space split.
349        */
350        class BvhSubdivisionCandidate: public SubdivisionCandidate
351        { 
352        public:
353
354        BvhSubdivisionCandidate(const BvhTraversalData &tData): mParentData(tData)
355                {};
356
357                ~BvhSubdivisionCandidate() { mParentData.Clear(); }
358
359                int Type() const { return OBJECT_SPACE; }
360       
361                void EvalPriority()
362                {
363                        sBvHierarchy->EvalSubdivisionCandidate(*this); 
364                }
365
366                bool GlobalTerminationCriteriaMet() const
367                {
368                        return sBvHierarchy->GlobalTerminationCriteriaMet(mParentData);
369                }
370
371                BvhSubdivisionCandidate(
372                        const ObjectContainer &frontObjects,
373                        const ObjectContainer &backObjects,
374                        const BvhTraversalData &tData):
375                mFrontObjects(frontObjects), mBackObjects(backObjects), mParentData(tData)
376                {}
377
378               
379                static BvHierarchy *sBvHierarchy;
380
381                /// parent data
382                BvhTraversalData mParentData;
383                ObjectContainer mFrontObjects;
384                ObjectContainer mBackObjects;
385        };
386
387        /** Struct for traversing line segment.
388        */
389        struct LineTraversalData
390        {
391                BvhNode *mNode;
392                Vector3 mExitPoint;
393               
394                float mMaxT;
395   
396                LineTraversalData () {}
397                LineTraversalData (BvhNode *n, const Vector3 &p, const float maxt):
398                mNode(n), mExitPoint(p), mMaxT(maxt) {}
399        };
400
401
402        /** Default constructor creating an empty tree.
403        */
404        BvHierarchy();
405
406        /** Default destructor.
407        */
408        ~BvHierarchy();
409
410        /** Returns tree statistics.
411        */
412        const BvhStatistics &GetStatistics() const;
413 
414        /** Returns bounding box of the specified node.
415        */
416        AxisAlignedBox3 GetBoundingBox(BvhNode *node) const;
417
418        /** Reads parameters from environment singleton.
419        */
420        void ReadEnvironment();
421
422        /** Evaluates candidate for splitting.
423        */
424        void EvalSubdivisionCandidate(BvhSubdivisionCandidate &splitData);
425
426        /** Returns list of leaves with pvs smaller than
427                a certain threshold.
428                @param onlyUnmailed if only the unmailed leaves should be considered
429                @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited)
430        */
431        void CollectLeaves(vector<BvhLeaf *> &leaves) const;
432
433        /** Returns bounding box of the whole tree (= bbox of root node)
434        */
435        AxisAlignedBox3 GetBoundingBox()const;
436
437        /** Returns root of the view space partitioning tree.
438        */
439        BvhNode *GetRoot() const;
440
441        /** A ray is cast possible intersecting the tree.
442                @param the ray that is cast.
443                @returns the number of intersections with objects stored in the tree.
444        */
445        //int CastRay(Ray &ray);
446
447        /** finds neighbouring leaves of this tree node.
448        */
449        int FindNeighbors(BvhLeaf *n,
450                                          vector<BvhLeaf *> &neighbors,
451                                          const bool onlyUnmailed) const;
452
453        /** Returns random leaf of BSP tree.
454                @param halfspace defines the halfspace from which the leaf is taken.
455        */
456        BvhLeaf *GetRandomLeaf(const Plane3 &halfspace);
457
458        /** Returns random leaf of BSP tree.
459                @param onlyUnmailed if only unmailed leaves should be returned.
460        */
461        BvhLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
462
463        /** Casts line segment into the tree.
464                @param origin the origin of the line segment
465                @param termination the end point of the line segment
466                @returns view cells intersecting the line segment.
467        */
468    int CastLineSegment(const Vector3 &origin,
469                                                const Vector3 &termination,
470                                                ViewCellContainer &viewcells);
471               
472        /** Sets pointer to view cells manager.
473        */
474        void SetViewCellsManager(ViewCellsManager *vcm);
475
476        /** Writes tree to output stream
477        */
478        bool Export(OUT_STREAM &stream);
479
480        /** Returns or creates a new intersectable for use in a kd based pvs.
481                The OspTree is responsible for destruction of the intersectable.
482        */
483        BvhIntersectable *GetOrCreateBvhIntersectable(BvhNode *node);
484
485        /** Collects rays.
486        */
487        void CollectRays(const ObjectContainer &objects, VssRayContainer &rays) const;
488
489        /** Intersects box with the tree and returns the number of intersected boxes.
490                @returns number of view cells found
491        */
492        int ComputeBoxIntersections(
493                const AxisAlignedBox3 &box,
494                ViewCellContainer &viewCells) const;
495
496
497        /** Returns leaf the point pt lies in, starting from root.
498        */
499        BvhLeaf *GetLeaf(Intersectable *obj, BvhNode *root = NULL) const;
500
501        ViewCellsTree *GetViewCellsTree() const { return mViewCellsTree; }
502       
503        void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
504
505        /** Add the bvh leaf to the pvs of the view cell.
506        */
507        bool AddLeafToPvs(
508                BvhLeaf *leaf,
509                ViewCell *vc,
510                const float pdf,
511                float &contribution);
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        /** For sorting the objects during the heuristics
524        */
525        struct SortableEntry
526        {
527                Intersectable *mObject;
528                float mPos;
529
530                SortableEntry() {}
531
532                SortableEntry(Intersectable *obj, const float pos):
533                mObject(obj), mPos(pos)
534                {}
535
536                bool operator<(const SortableEntry &b) const
537                {
538                        return mPos < b.mPos;
539                }
540        };
541 
542        /** Evaluate balanced object partition.
543        */
544        float EvalLocalObjectPartition(
545                const BvhTraversalData &tData,
546                const int axis,
547                ObjectContainer &objectsFront,
548                ObjectContainer &objectsBack);
549
550        /** Computes priority of the traversal data and stores it in tData.
551        */
552        void EvalPriority(BvhTraversalData &tData) const;
553
554        /** Evaluates render cost of next split.
555        */
556        float EvalRenderCost(
557                const BvhTraversalData &tData,
558                const ObjectContainer &objectsLeft,
559                const ObjectContainer &objectsRight) const;
560
561        /** Evaluates tree stats in the BSP tree leafs.
562        */
563        void EvaluateLeafStats(const BvhTraversalData &data);
564
565        /** Subdivides node using a best split priority queue.
566            @param tQueue the best split priority queue
567                @param splitCandidate the candidate for the next split
568                @param globalCriteriaMet if the global termination criteria were already met
569                @returns new root of the subtree
570        */
571        BvhNode *Subdivide(
572                SplitQueue &tQueue,
573                SubdivisionCandidate *splitCandidate,
574                const bool globalCriteriaMet);
575       
576        /** Subdivides leaf.
577                @param leaf the leaf to be subdivided
578               
579                @param polys the polygons to be split
580                @param frontPolys returns the polygons in front of the split plane
581                @param backPolys returns the polygons in the back of the split plane
582               
583                @param rays the polygons to be filtered
584                @param frontRays returns the polygons in front of the split plane
585                @param backRays returns the polygons in the back of the split plane
586
587                @returns the root of the subdivision
588        */
589        BvhInterior *SubdivideNode(
590                const ObjectContainer &frontObjects,
591                const ObjectContainer &backObjects,
592                const BvhTraversalData &tData,
593                BvhTraversalData &frontData,
594                BvhTraversalData &backData);
595
596        /** Splits the objects for the next subdivision.
597                @returns cost for this split
598        */
599        float SelectObjectPartition(
600                const BvhTraversalData &tData,
601                ObjectContainer &frontObjects,
602                ObjectContainer &backObjects);
603       
604        /** Writes the node to disk
605                @note: should be implemented as visitor.
606        */
607        void ExportNode(BvhNode *node, OUT_STREAM &stream);
608
609        void ExportObjects(BvhLeaf *leaf, OUT_STREAM &stream);
610
611        /** Returns estimated memory usage of tree.
612        */
613        float GetMemUsage() const;
614
615        /** Creates new root of hierarchy.
616        */
617        void CreateRoot(const ObjectContainer &objects);
618
619        /////////////////////////////
620        // Helper functions for local cost heuristics
621
622       
623        /** Sorts split candidates for cost heuristics using axis aligned splits.
624                @param node the current node
625                @param axis the current split axis
626        */
627        void SortSubdivisionCandidates(
628                const BvhTraversalData &data,
629                const int axis);
630
631        /** Computes best cost for axis aligned planes.
632        */
633        float EvalLocalCostHeuristics(
634                const BvhTraversalData &tData,
635                const int axis,
636                ObjectContainer &objectsFront,
637                ObjectContainer &objectsFBack);
638
639        /** Evaluates the contribution to the front and back volume
640                when this object is changing sides in the bvs.
641
642                @param object the object
643                @param volLeft updates the left pvs
644                @param volPvs updates the right pvs
645        */
646        void EvalHeuristicsContribution(
647                Intersectable *obj,
648                float &volLeft,
649                float &volRight);
650
651        /** Prepares objects for the cost heuristics.
652                @returns sum of volume of associated view cells
653        */
654        float PrepareHeuristics(const BvhTraversalData &tData, const int axis);
655       
656
657        ////////////////////////////////////////////////
658
659
660        /** Prepares construction for vsp and osp trees.
661        */
662        AxisAlignedBox3 ComputeBoundingBox(
663                const ObjectContainer &objects,
664                const AxisAlignedBox3 *parentBox = NULL);
665
666        void CollectDirtyCandidates(
667                BvhSubdivisionCandidate *sc,
668                vector<SubdivisionCandidate *> &dirtyList);
669
670        /** Collect view cells which see this bvh leaf.
671        */
672        void CollectViewCells(
673                const ObjectContainer &objects,
674                ViewCellContainer &viewCells,
675                const bool setCounter = false) const;
676
677        /** Collects view cells which see an object.
678        */
679        void CollectViewCells(
680                Intersectable *object,
681                ViewCellContainer &viewCells,
682                const bool useMailBoxing,
683                const bool setCounter = false) const;
684
685        /** Rays will be clipped to the bounding box.
686        */
687        void PreprocessRays(
688                BvhLeaf *root,
689                const VssRayContainer &sampleRays,
690                RayInfoContainer &rays);
691
692        /** Print the subdivision stats in the subdivison log.
693        */
694        void PrintSubdivisionStats(const SubdivisionCandidate &tData);
695
696        void AddSubdivisionStats(
697                const int viewCells,
698                const float renderCostDecr,
699                const float totalRenderCost);
700
701        void AssociateObjectsWithRays(const VssRayContainer &rays);
702
703        bool IsObjectInLeaf(BvhLeaf *, Intersectable *object) const;
704
705        SubdivisionCandidate *PrepareConstruction(
706                const VssRayContainer &sampleRays,
707                const ObjectContainer &objects
708                );
709
710        float EvalViewCellsVolume(const ObjectContainer &objects) const;
711
712
713protected:
714       
715        /// pointer to the hierarchy of view cells
716        ViewCellsTree *mViewCellsTree;
717
718        VspTree *mVspTree;
719
720        /// The view cells manager
721        ViewCellsManager *mViewCellsManager;
722
723        /// candidates for placing split planes during cost heuristics
724        vector<SortableEntry> *mSubdivisionCandidates;
725
726        /// Pointer to the root of the tree
727        BvhNode *mRoot;
728               
729        /// Statistics for the object space partition
730        BvhStatistics mBvhStats;
731       
732        /// box around the whole view domain
733        AxisAlignedBox3 mBoundingBox;
734
735
736        //-- local termination
737
738        /// maximal possible depth
739        int mTermMaxDepth;
740        /// mininum probability
741        float mTermMinProbability;
742        /// minimal number of objects
743        int mTermMinObjects;
744        /// maximal contribution per ray
745        float mTermMaxRayContribution;
746        /// maximal acceptable cost ratio
747        float mTermMaxCostRatio;
748        /// tolerance value indicating how often the max cost ratio can be failed
749        int mTermMissTolerance;
750
751
752        //-- global criteria
753
754        float mTermMinGlobalCostRatio;
755        int mTermGlobalCostMissTolerance;
756        int mGlobalCostMisses;
757
758        /// maximal number of view cells
759        int mTermMaxLeaves;
760        /// maximal tree memory
761        float mMaxMemory;
762        /// the tree is out of memory
763        bool mOutOfMemory;
764
765
766        //-- split heuristics based parameters
767       
768        bool mUseCostHeuristics;
769        /// balancing factor for PVS criterium
770        float mCtDivCi;
771        /// if only driving axis should be used for split
772        bool mOnlyDrivingAxis;
773       
774        /// current time stamp (used for keeping split history)
775        int mTimeStamp;
776        // if rays should be stored in leaves
777        bool mStoreRays;
778
779        /// epsilon for geometric comparisons
780        float mEpsilon;
781
782        /// subdivision stats output file
783        ofstream  mSubdivisionStats;
784        /// keeps track of cost during subdivision
785        float mTotalCost;
786        /// keeps track of overall pvs size during subdivision
787        int mTotalPvsSize;
788        /// number of currenly generated view cells
789        int mCreatedLeaves;
790
791        /// represents min and max band for sweep
792        float mSplitBorder;
793
794        /// weight between render cost decrease and node render cost
795        float mRenderCostDecreaseWeight;
796
797        /// stores the kd node intersectables used for pvs
798        BvhIntersectableMap mBvhIntersectables;
799
800};
801
802}
803
804#endif
Note: See TracBrowser for help on using the repository browser.