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

Revision 1345, 19.0 KB checked in by mattausch, 18 years ago (diff)

started with global objects sorting for bvh split heuristics

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