source: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h @ 1006

Revision 1006, 17.9 KB checked in by mattausch, 18 years ago (diff)

started viewspace-objectspace subdivision
removed memory leaks

Line 
1#ifndef _VspOspTree_H__
2#define _VspOspTree_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include "Polygon3.h"
7#include <stack>
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "ViewCellBsp.h"
12
13
14
15namespace GtpVisibilityPreprocessor {
16
17class ViewCellLeaf;
18//class BspViewCell;
19class Plane3;
20class VspBspTree; 
21class BspInterior;
22class BspNode;
23class AxisAlignedBox3;
24class Ray;
25class ViewCellsStatistics;
26class ViewCellsManager;
27class MergeCandidate;
28class Beam;
29class ViewCellsTree;
30class Environment;
31
32/**
33        This class implements a structure holding two different hierarchies,
34        one for object space partitioning and one for view space partitioning.
35
36        The object space and the view space are subdivided using a cost heuristics.
37        If an object space split or a view space split is chosen is also evaluated
38        based on the heuristics.
39       
40        The view space heuristics is evaluated by weighting and adding the pvss of the back and
41        front node of each specific split. unlike for the standalone method vspbsp tree,
42        the pvs of an object would not be the pvs of single object but that of all objects
43        which are contained in the same leaf of the object subdivision. This could be done
44        by storing the pointer to the object space partition parent, which would allow access to all children.
45        Another possibility is to include traced kd-cells in the ray casing process.
46
47        Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object.
48        the contribution to an object to the pvs is the number of view cells it can be seen from.
49
50
51        There is a potential efficiency problem involved in a sense that once a certain type
52        of split is chosen for view space / object space, the candidates for the next split of
53        object space / view space must be reevaluated.
54       
55*/
56class VspOspTree
57{
58        friend class ViewCellsParseHandlers;
59        friend class VspBspViewCellsManager;
60
61public:
62       
63        /** A definition for an axis aligned plane.
64        */
65        struct AxisAlignedPlane
66        {
67        public:
68                int mAxis;
69                float mPosition;
70        };
71
72        /** Additional data which is passed down the BSP tree during traversal.
73        */
74        class VspOspTraversalData
75        { 
76        public:
77                /// the current node
78                BspNode *mNode;
79                /// current depth
80                int mDepth;
81                /// rays piercing this node
82                RayInfoContainer *mRays;
83                /// the probability that this node contains view point
84                float mProbability;
85                /// the bounding box of the node
86                AxisAlignedBox3 mBoundingBox;
87                /// pvs size
88                int mPvs;
89                /// how often this branch has missed the max-cost ratio
90                int mMaxCostMisses;
91                // current axis
92                int mAxis;
93                // current priority
94                float mPriority;
95
96               
97                /** Returns average ray contribution.
98                */
99                float GetAvgRayContribution() const
100                {
101                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
102                }
103
104
105                VspOspTraversalData():
106                mNode(NULL),
107                mDepth(0),
108                mRays(NULL),
109                mPvs(0),
110                mProbability(0.0),
111                mMaxCostMisses(0),
112                mPriority(0),
113                mAxis(0)
114                {}
115               
116                VspOspTraversalData(BspNode *node,
117                                                        const int depth,
118                                                        RayInfoContainer *rays,
119                                                        const int pvs,
120                                                        const float p,
121                                                        const AxisAlignedBox3 &box):
122                mNode(node),
123                mDepth(depth),
124                mRays(rays),
125                mPvs(pvs),
126                mProbability(p),
127                mBoundingBox(box),
128                mMaxCostMisses(0),
129                mPriority(0),
130                mAxis(0)
131                {}
132
133                VspOspTraversalData(PolygonContainer *polys,
134                                                        const int depth,
135                                                        RayInfoContainer *rays,
136                                                        const AxisAlignedBox3 &box):
137                mNode(NULL),
138                mDepth(depth),
139                mRays(rays),
140                mPvs(0),
141                mProbability(0),
142                mMaxCostMisses(0),
143                mAxis(0),
144                mBoundingBox(box)
145                {}
146
147                /** Returns cost of the traversal data.
148                */
149                float GetCost() const
150                {
151                        //cout << mPriority << endl;
152                        return mPriority;
153                }
154
155                // deletes contents and sets them to NULL
156                void Clear()
157                {
158                        DEL_PTR(mRays);
159                }
160
161                friend bool operator<(const VspOspTraversalData &a, const VspOspTraversalData &b)
162                {
163                        return a.GetCost() < b.GetCost();
164                }
165    };
166       
167
168        typedef std::priority_queue<VspOspTraversalData> VspOspTraversalQueue;
169       
170       
171        struct VspOspSplitCandidate
172        { 
173                /// the current plane
174                AxisAlignedPlane mSplitPlane;
175                /// the number of misses of max cost ratio until this split
176                int mMaxCostMisses;
177                /// parent data
178                VspOspTraversalData mParentData;
179                /// cost of applying this split
180                float mRenderCost;
181
182                VspOspSplitCandidate(): mRenderCost(0)
183                {};
184
185                VspOspSplitCandidate(const AxisAlignedPlane &plane, const VspOspTraversalData &tData):
186                mSplitPlane(plane), mParentData(tData), mRenderCost(0)
187                {}
188
189                /** Returns cost of the traversal data.
190                */
191                float GetCost() const
192                {
193#if 1
194                        return mRenderCost;
195#endif
196#if 0
197                        return (float) (-mDepth); // for kd tree
198#endif
199                }
200
201                friend bool operator<(const VspOspSplitCandidate &a, const VspOspSplitCandidate &b)
202                {
203                        return a.GetCost() < b.GetCost();
204                }
205    };
206
207        typedef std::priority_queue<VspOspSplitCandidate> VspOspSplitQueue;
208
209        /** Default constructor creating an empty tree.
210        */
211        VspOspTree();
212
213        /** Default destructor.
214        */
215        ~VspOspTree();
216
217        /** Returns BSP Tree statistics.
218        */
219        const BspTreeStatistics &GetStatistics() const;
220 
221
222        /** Constructs the tree from a given set of rays.
223                @param sampleRays the set of sample rays the construction is based on
224                @param viewCells if not NULL, new view cells are
225                created in the leafs and stored in the container
226        */
227        void Construct(const VssRayContainer &sampleRays,
228                                   AxisAlignedBox3 *forcedBoundingBox);
229
230        /** Returns list of BSP leaves with pvs smaller than
231                a certain threshold.
232                @param onlyUnmailed if only the unmailed leaves should be considered
233                @param maxPvs the maximal pvs (-1 means unlimited)
234        */
235        void CollectLeaves(vector<BspLeaf *> &leaves,
236                                           const bool onlyUnmailed = false,
237                                           const int maxPvs = -1) const;
238
239        /** Returns box which bounds the whole tree.
240        */
241        AxisAlignedBox3 GetBoundingBox()const;
242
243        /** Returns root of BSP tree.
244        */
245        BspNode *GetRoot() const;
246
247        /** Collects the leaf view cells of the tree
248                @param viewCells returns the view cells
249        */
250        void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
251
252        /** A ray is cast possible intersecting the tree.
253                @param the ray that is cast.
254                @returns the number of intersections with objects stored in the tree.
255        */
256        int CastRay(Ray &ray);
257
258
259        /** finds neighbouring leaves of this tree node.
260        */
261        int FindNeighbors(BspNode *n,
262                                          vector<BspLeaf *> &neighbors,
263                                          const bool onlyUnmailed) const;
264
265        /** Returns random leaf of BSP tree.
266                @param halfspace defines the halfspace from which the leaf is taken.
267        */
268        BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
269
270        /** Returns random leaf of BSP tree.
271                @param onlyUnmailed if only unmailed leaves should be returned.
272        */
273        BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
274
275        /** Returns epsilon of this tree.
276        */
277        float GetEpsilon() const;
278
279        /** Casts line segment into the tree.
280                @param origin the origin of the line segment
281                @param termination the end point of the line segment
282                @returns view cells intersecting the line segment.
283        */
284    int CastLineSegment(const Vector3 &origin,
285                                                const Vector3 &termination,
286                                                ViewCellContainer &viewcells);
287
288               
289        /** Sets pointer to view cells manager.
290        */
291        void SetViewCellsManager(ViewCellsManager *vcm);
292
293        /** Returns distance from node 1 to node 2.
294        */
295        int TreeDistance(BspNode *n1, BspNode *n2) const;
296
297        /** Collapses the tree with respect to the view cell partition.
298                @returns number of collapsed nodes
299        */
300        int CollapseTree();
301
302        /** Returns view cell the current point is located in.
303                @param point the current view point
304                @param active if currently active view cells should be returned or
305                elementary view cell
306        */
307        ViewCell *GetViewCell(const Vector3 &point, const bool active = false);
308
309
310        /** Returns true if this view point is in a valid view space,
311                false otherwise.
312        */
313        bool ViewPointValid(const Vector3 &viewPoint) const;
314
315        /** Returns view cell corresponding to
316                the invalid view space.
317        */
318        BspViewCell *GetOutOfBoundsCell();
319
320        /** Writes tree to output stream
321        */
322#if ZIPPED_VIEWCELLS
323        bool Export(ogzstream &stream);
324#else
325        bool Export(ofstream &stream);
326#endif
327
328        /** Casts beam, i.e. a 5D frustum of rays, into tree.
329                Tests conservative using the bounding box of the nodes.
330                @returns number of view cells it intersected
331        */
332        int CastBeam(Beam &beam);
333
334        /** Finds approximate neighbours, i.e., finds correct neighbors
335                in most cases but sometimes more.
336        */
337        int FindApproximateNeighbors(BspNode *n,
338                                                             vector<BspLeaf *> &neighbors,
339                                                                 const bool onlyUnmailed) const;
340
341        /** Checks if tree validity-flags are right
342                with respect to view cell valitiy.
343                If not, marks subtree as invalid.
344        */
345        void ValidateTree();
346
347        /** Invalid view cells are added to the unbounded space
348        */
349        void CollapseViewCells();
350
351        /** Collects rays stored in the leaves.
352        */
353        void CollectRays(VssRayContainer &rays);
354
355        /** Intersects box with the tree and returns the number of intersected boxes.
356                @returns number of view cells found
357        */
358        int ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const;
359
360        // pointer to the hierarchy of view cells
361        ViewCellsTree *mViewCellsTree;
362
363
364protected:
365
366        // --------------------------------------------------------------
367        // For sorting objects
368        // --------------------------------------------------------------
369        struct SortableEntry
370        {
371                enum EType
372                {
373                        ERayMin,
374                        ERayMax
375                };
376
377                int type;
378                float value;
379                VssRay *ray;
380 
381                SortableEntry() {}
382                SortableEntry(const int t, const float v, VssRay *r):type(t),
383                                          value(v), ray(r)
384                {
385                }
386               
387                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
388                {
389                        return a.value < b.value;
390                }
391        };
392
393        /** faster evaluation of split plane cost for kd axis aligned cells.
394        */
395        float EvalSplitCost(const VspOspTraversalData &data,
396                                                const AxisAlignedBox3 &box,
397                                                const int axis,
398                                                const float &position,
399                                                float &pFront,
400                                                float &pBack) const;
401
402        /** Evaluates candidate for splitting.
403        */
404        void EvalSplitCandidate(VspOspTraversalData &tData, VspOspSplitCandidate &splitData);
405
406        /** Computes priority of the traversal data and stores it in tData.
407        */
408        void EvalPriority(VspOspTraversalData &tData) const;
409
410        /** Evaluates render cost decrease of next split.
411        */
412        float EvalRenderCostDecrease(const Plane3 &candidatePlane,
413                                                                 const VspOspTraversalData &data) const;
414
415        /** Constructs tree using the split priority queue.
416        */
417        void Construct(RayInfoContainer *rays);
418
419        /** Collects view cells in the subtree under root.
420        */
421        void CollectViewCells(BspNode *root,
422                                                  bool onlyValid,
423                                                  ViewCellContainer &viewCells,
424                                                  bool onlyUnmailed = false) const;
425
426        /** Returns view cell corresponding to
427                the invalid view space. If it does not exist, it is created.
428        */
429        BspViewCell *GetOrCreateOutOfBoundsCell();
430
431        /** Collapses the tree with respect to the view cell partition,
432                i.e. leaves having the same view cell are collapsed.
433                @param node the root of the subtree to be collapsed
434                @param collapsed returns the number of collapsed nodes
435                @returns node of type leaf if the node could be collapsed,
436                this node otherwise
437        */
438        BspNode *CollapseTree(BspNode *node, int &collapsed);
439
440        /** Helper function revalidating the view cell leaf list after merge.
441        */
442        void RepairViewCellsLeafLists();
443
444        /** Evaluates tree stats in the BSP tree leafs.
445        */
446        void EvaluateLeafStats(const VspOspTraversalData &data);
447
448        /** Subdivides node with respect to the traversal data.
449            @param tStack current traversal stack
450                @param tData traversal data also holding node to be subdivided
451                @returns new root of the subtree
452        */
453        BspNode *Subdivide(VspOspSplitQueue &tQueue,
454                                           VspOspSplitCandidate &splitCandidate);
455
456       
457        /** Subdivides leaf.
458                @param leaf the leaf to be subdivided
459               
460                @param polys the polygons to be split
461                @param frontPolys returns the polygons in front of the split plane
462                @param backPolys returns the polygons in the back of the split plane
463               
464                @param rays the polygons to be filtered
465                @param frontRays returns the polygons in front of the split plane
466                @param backRays returns the polygons in the back of the split plane
467
468                @returns the root of the subdivision
469        */
470
471        BspInterior *SubdivideNode(const Plane3 &splitPlane,
472                                                           VspOspTraversalData &tData,
473                                                           VspOspTraversalData &frontData,
474                               VspOspTraversalData &backData);
475
476        /** Selects an axis aligned for the next split.
477                @returns cost for this split
478        */
479        float SelectPlane(const VspOspTraversalData &tData,
480                                          AxisAlignedPlane &plane,
481                                          float &pFront,
482                                          float &pBack);
483
484        /** Sorts split candidates for surface area heuristics for axis aligned splits.
485                @param polys the input for choosing split candidates
486                @param axis the current split axis
487                @param splitCandidates returns sorted list of split candidates
488        */
489        void SortSplitCandidates(const RayInfoContainer &rays,
490                                                         const int axis,
491                                                         float minBand,
492                                                         float maxBand);
493
494        /** Computes best cost for axis aligned planes.
495        */
496        float BestCostRatioHeuristics(const RayInfoContainer &rays,
497                                                                  const AxisAlignedBox3 &box,
498                                                                  const int pvsSize,
499                                                                  const int axis,
500                                                                  float &position);
501
502        /** Subdivides the rays into front and back rays according to the split plane.
503               
504                @param plane the split plane
505                @param rays contains the rays to be split. The rays are
506                           distributed into front and back rays.
507                @param frontRays returns rays on the front side of the plane
508                @param backRays returns rays on the back side of the plane
509               
510                @returns the number of splits
511        */
512        int SplitRays(const Plane3 &plane,
513                                  RayInfoContainer &rays,
514                              RayInfoContainer &frontRays,
515                                  RayInfoContainer &backRays) const;
516
517        /** Adds the object to the pvs of the front and back leaf with a given classification.
518
519                @param obj the object to be added
520                @param cf the ray classification regarding the split plane
521                @param frontPvs returns the PVS of the front partition
522                @param backPvs returns the PVS of the back partition
523       
524        */
525        void AddObjToPvs(Intersectable *obj,
526                                         const int cf,
527                                         float &frontPvs,
528                                         float &backPvs,
529                                         float &totalPvs) const;
530       
531        /** Computes PVS size induced by the rays.
532        */
533        int ComputePvsSize(const RayInfoContainer &rays) const;
534
535        /** Returns true if tree can be terminated.
536        */
537        inline bool LocalTerminationCriteriaMet(const VspOspTraversalData &data) const;
538
539        /** Returns true if global tree can be terminated.
540        */
541        inline bool GlobalTerminationCriteriaMet(const VspOspTraversalData &data) const;
542
543        /** Adds ray sample contributions to the PVS.
544                @param sampleContributions the number contributions of the samples
545                @param contributingSampels the number of contributing rays
546               
547        */
548        void AddToPvs(BspLeaf *leaf,
549                                  const RayInfoContainer &rays,
550                                  float &sampleContributions,
551                                  int &contributingSamples);
552
553        /** Propagates valid flag up the tree.
554        */
555        void PropagateUpValidity(BspNode *node);
556
557        /** Writes the node to disk
558                @note: should be implemented as visitor.
559        */
560#if ZIPPED_VIEWCELLS
561        void ExportNode(BspNode *node, ogzstream &stream);
562#else
563        void ExportNode(BspNode *node, ofstream &stream);
564#endif
565
566        /** Returns estimated memory usage of tree.
567        */
568        float GetMemUsage() const;
569
570
571protected:
572
573        ViewCellsManager *mViewCellsManager;
574        vector<SortableEntry> *mSplitCandidates;
575
576        /// Pointer to the root of the tree
577        BspNode *mRoot;
578               
579        BspTreeStatistics mBspStats;
580       
581        /// View cell corresponding to the space outside the valid view space
582        BspViewCell *mOutOfBoundsCell;
583
584        /// box around the whole view domain
585        AxisAlignedBox3 mBox;
586
587
588
589        //-- local termination
590
591        /// minimal number of rays before subdivision termination
592        int mTermMinRays;
593        /// maximal possible depth
594        int mTermMaxDepth;
595        /// mininum probability
596        float mTermMinProbability;
597        /// mininum PVS
598        int mTermMinPvs;
599        /// maximal contribution per ray
600        float mTermMaxRayContribution;
601        /// maximal acceptable cost ratio
602        float mTermMaxCostRatio;
603        /// tolerance value indicating how often the max cost ratio can be failed
604        int mTermMissTolerance;
605
606
607        //-- global criteria
608        float mTermMinGlobalCostRatio;
609        int mTermGlobalCostMissTolerance;
610        int mGlobalCostMisses;
611
612        /// maximal number of view cells
613        int mMaxViewCells;
614        /// maximal tree memory
615        float mMaxMemory;
616        /// the tree is out of memory
617        bool mOutOfMemory;
618
619
620
621        //-- split heuristics based parameters
622       
623        bool mUseCostHeuristics;
624        /// balancing factor for PVS criterium
625        float mCtDivCi;
626        /// if only driving axis should be used for split
627        bool mOnlyDrivingAxis;
628        /// if random split axis should be used
629        bool mUseRandomAxis;
630        /// if vsp bsp tree should simulate octree
631        bool mCirculatingAxis;
632        /// minimal relative position where the split axis can be placed
633        float mMinBand;
634        /// maximal relative position where the split axis can be placed
635        float mMaxBand;
636
637
638        /// current time stamp (used for keeping split history)
639        int mTimeStamp;
640        // if rays should be stored in leaves
641        bool mStoreRays;
642
643        /// epsilon for geometric comparisons
644        float mEpsilon;
645
646        /// if we should use breath first priority for the splits
647        int mNodePriorityQueueType;
648
649        // priority queue strategy
650        enum {BREATH_FIRST, DEPTH_FIRST, COST_BASED};
651
652
653        /// subdivision stats output file
654        ofstream  mSubdivisionStats;
655        /// keeps track of cost during subdivision
656        float mTotalCost;
657        /// keeps track of overall pvs size during subdivision
658        int mTotalPvsSize;
659        /// number of currenly generated view cells
660        int mCreatedViewCells;
661
662private:
663
664        /// Generates unique ids for PVS criterium
665        static void GenerateUniqueIdsForPvs();
666
667        //-- unique ids for PVS criterium
668        static int sFrontId;
669        static int sBackId;
670        static int sFrontAndBackId;
671};
672
673}
674
675
676#endif
Note: See TracBrowser for help on using the repository browser.