source: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h @ 491

Revision 491, 21.2 KB checked in by mattausch, 18 years ago (diff)
Line 
1#ifndef _VspBspTree_H__
2#define _VspBspTree_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
13class ViewCell;
14//class BspViewCell;
15class Plane3;
16class VspBspTree; 
17class BspInterior;
18class BspNode;
19class AxisAlignedBox3;
20class Ray;
21class ViewCellsStatistics;
22class ViewCellsManager;
23class BspMergeCandidate;
24struct BspRay;
25
26
27/**
28        This is a view space partitioning specialised BSPtree. 
29        There are no polygon splits, but we split the sample rays.
30        The candidates for the next split plane are evaluated only
31        by checking the sampled visibility information.
32        The polygons are employed merely as candidates for the next split planes.
33*/
34class VspBspTree
35{
36public:
37       
38        /** Additional data which is passed down the BSP tree during traversal.
39        */
40        struct VspBspTraversalData
41        { 
42                /// the current node
43                BspNode *mNode;
44                /// polygonal data for splitting
45                PolygonContainer *mPolygons;
46                /// current depth
47                int mDepth;
48                /// rays piercing this node
49                RayInfoContainer *mRays;
50                /// area of current node
51                float mArea;
52                /// geometry of node as induced by planes
53                BspNodeGeometry *mGeometry;
54                /// pvs size
55                int mPvs;
56                /// how often this branch has missed the max-cost ratio
57                int mMaxCostMisses;
58
59
60                /** Returns average ray contribution.
61                */
62                float GetAvgRayContribution() const
63                {
64                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
65                }
66
67
68                VspBspTraversalData():
69                mNode(NULL),
70                mPolygons(NULL),
71                mDepth(0),
72                mRays(NULL),
73                mPvs(0),
74                mArea(0.0),
75                mGeometry(NULL),
76                mMaxCostMisses(0)
77                {}
78               
79                VspBspTraversalData(BspNode *node,
80                                                        PolygonContainer *polys,
81                                                        const int depth,
82                                                        RayInfoContainer *rays,
83                                                        int pvs,
84                                                        float area,
85                                                        BspNodeGeometry *geom):
86                mNode(node),
87                mPolygons(polys),
88                mDepth(depth),
89                mRays(rays),
90                mPvs(pvs),
91                mArea(area),
92                mGeometry(geom),
93                mMaxCostMisses(0)
94                {}
95
96                VspBspTraversalData(PolygonContainer *polys,
97                                                        const int depth,
98                                                        RayInfoContainer *rays,
99                                                        BspNodeGeometry *geom):
100                mNode(NULL),
101                mPolygons(polys),
102                mDepth(depth),
103                mRays(rays),
104                mPvs(0),
105                mArea(0),
106                mGeometry(geom),
107                mMaxCostMisses(0)
108                {}
109
110                /** Returns cost of the traversal data.
111                */
112                float GetCost() const
113                {
114#if 1
115                        return mPvs * mArea;
116#endif
117#if 0
118                        return (float)(mPvs * (int)mRays->size());
119#endif
120#if 0
121                        return (float)mPvs;
122#endif
123#if 0
124                        return mArea * (float)mRays->size();
125#endif
126                }
127
128                // deletes contents and sets them to NULL
129                void Clear()
130                {
131                        DEL_PTR(mPolygons);
132                        DEL_PTR(mRays);
133                        DEL_PTR(mGeometry);
134                }
135
136                friend bool operator<(const VspBspTraversalData &a, const VspBspTraversalData &b)
137                {
138                        return a.GetCost() < b.GetCost();
139                }
140    };
141       
142        typedef std::priority_queue<VspBspTraversalData> VspBspTraversalStack;
143        //typedef std::stack<VspBspTraversalData> VspBspTraversalStack;
144
145        /** Default constructor creating an empty tree.
146        */
147        VspBspTree();
148
149        /** Default destructor.
150        */
151        ~VspBspTree();
152
153        /** Returns BSP Tree statistics.
154        */
155        const BspTreeStatistics &GetStatistics() const;
156 
157
158        /** Constructs the tree from a given set of rays.
159                @param sampleRays the set of sample rays the construction is based on
160                @param viewCells if not NULL, new view cells are
161                created in the leafs and stored in the container
162        */
163        void Construct(const VssRayContainer &sampleRays,
164                                   AxisAlignedBox3 *forcedBoundingBox);
165
166        /** Returns list of BSP leaves.
167        */
168        void CollectLeaves(vector<BspLeaf *> &leaves) const;
169
170        /** Returns box which bounds the whole tree.
171        */
172        AxisAlignedBox3 GetBoundingBox()const;
173
174        /** Returns root of BSP tree.
175        */
176        BspNode *GetRoot() const;
177
178        /** Exports VspBsp tree to file.
179        */
180        bool Export(const string filename);
181
182        /** Collects the leaf view cells of the tree
183                @param viewCells returns the view cells
184        */
185        void CollectViewCells(ViewCellContainer &viewCells) const;
186
187        /** A ray is cast possible intersecting the tree.
188                @param the ray that is cast.
189                @returns the number of intersections with objects stored in the tree.
190        */
191        int CastRay(Ray &ray);
192
193        /// bsp tree construction types
194        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
195
196        /** finds neighbouring leaves of this tree node.
197        */
198        int FindNeighbors(BspNode *n,
199                                          vector<BspLeaf *> &neighbors,
200                                          const bool onlyUnmailed) const;
201
202        /** Constructs geometry associated with the half space intersections
203                leading to this node.
204        */
205        void ConstructGeometry(BspNode *n, PolygonContainer &cell) const;
206
207        /** Constructs geometry associated with the half space intersections
208                leading to this node.
209        */
210        void ConstructGeometry(BspViewCell *vc, PolygonContainer &cell) const;
211
212        /** Construct geometry and stores it in a geometry node container.
213        */
214        void ConstructGeometry(BspNode *n, BspNodeGeometry &cell) const;
215
216        /** Returns random leaf of BSP tree.
217                @param halfspace defines the halfspace from which the leaf is taken.
218        */
219        BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
220
221        /** Returns random leaf of BSP tree.
222                @param onlyUnmailed if only unmailed leaves should be returned.
223        */
224        BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
225
226        /** Returns epsilon of this tree.
227        */
228        float GetEpsilon() const;
229
230        /** Casts line segment into the tree.
231                @param origin the origin of the line segment
232                @param termination the end point of the line segment
233                @returns view cells intersecting the line segment.
234        */
235    int CastLineSegment(const Vector3 &origin,
236                                                const Vector3 &termination,
237                                                ViewCellContainer &viewcells);
238
239               
240        /** Sets pointer to view cells manager.
241        */
242        void SetViewCellsManager(ViewCellsManager *vcm);
243
244        /** Returns distance from node 1 to node 2.
245        */
246        int TreeDistance(BspNode *n1, BspNode *n2) const;
247
248        /** Merges view cells according to some cost heuristics.
249        */
250        int MergeViewCells(const VssRayContainer &rays);
251       
252        /** Refines view cells using shuffling, i.e., border leaves
253                of two view cells are exchanged if the resulting view cells
254                are tested to be "better" than the old ones.
255                @returns number of refined view cells
256        */
257        int RefineViewCells(const VssRayContainer &rays);
258
259        /** Collapses the tree with respect to the view cell partition,
260                i.e. leaves having the same view cell are collapsed.
261                @returns node of type leaf if the node could be collapsed,
262                this node otherwise
263        */
264        BspNode *CollapseTree(BspNode *node);
265
266        /** Constructs bsp rays for post processing and visualization.
267        */
268        void ConstructBspRays(vector<BspRay *> &bspRays,
269                                                  const VssRayContainer &rays);
270       
271        /** Merge view cells of leaves l1 and l2.
272        */
273        bool MergeViewCells(BspLeaf *l1, BspLeaf *l2) const;
274
275        /** Returns true if this view point is in a valid view space,
276                false otherwise.
277        */
278        bool ViewPointValid(const Vector3 &viewPoint) const;
279
280        /** Returns the view cell corresponding to
281                the space outside the valid view space.
282        */
283        BspViewCell *GetOutOfBoundsCell() const;
284
285protected:
286
287        // --------------------------------------------------------------
288        // For sorting objects
289        // --------------------------------------------------------------
290        struct SortableEntry
291        {
292                enum EType
293                {
294                        ERayMin,
295                        ERayMax
296                };
297
298                int type;
299                float value;
300                VssRay *ray;
301 
302                SortableEntry() {}
303                SortableEntry(const int t, const float v, VssRay *r):type(t),
304                                          value(v), ray(r)
305                {
306                }
307               
308                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
309                {
310                        return a.value < b.value;
311                }
312        };
313
314        /** Shuffles the leaves, i.e., tests if exchanging
315                the leaves helps in improving the view cells.
316        */
317        bool ShuffleLeaves(BspLeaf *leaf1, BspLeaf *leaf2) const;
318
319        /** Helper function revalidating the view cell leaf list after merge.
320        */
321        void RepairVcLeafLists();
322
323        /** Evaluates tree stats in the BSP tree leafs.
324        */
325        void EvaluateLeafStats(const VspBspTraversalData &data);
326
327        /** Subdivides node with respect to the traversal data.
328            @param tStack current traversal stack
329                @param tData traversal data also holding node to be subdivided
330                @returns new root of the subtree
331        */
332        BspNode *Subdivide(VspBspTraversalStack &tStack,
333                                           VspBspTraversalData &tData);
334
335        /** Constructs the tree from the given traversal data.
336                @param polys stores set of polygons on which subdivision may be based
337                @param rays storesset of rays on which subdivision may be based
338        */
339        void Construct(const PolygonContainer &polys, RayInfoContainer *rays);
340
341        /** Selects the best possible splitting plane.
342                @param plane returns the split plane
343                @param leaf the leaf to be split
344                @param polys the polygon list on which the split decition is based
345                @param rays ray container on which selection may be based
346                @note the polygons can be reordered in the process
347                @returns true if the cost of the split is under maxCostRatio
348
349        */
350        bool SelectPlane(Plane3 &plane,
351                                         BspLeaf *leaf,
352                                         VspBspTraversalData &data);
353       
354        /** Strategies where the effect of the split plane is tested
355            on all input rays.
356
357                @returns the cost of the candidate split plane
358        */
359        float SplitPlaneCost(const Plane3 &candidatePlane,
360                                                 const VspBspTraversalData &data) const;
361
362
363        /** Subdivide leaf.
364                @param leaf the leaf to be subdivided
365               
366                @param polys the polygons to be split
367                @param frontPolys returns the polygons in front of the split plane
368                @param backPolys returns the polygons in the back of the split plane
369               
370                @param rays the polygons to be filtered
371                @param frontRays returns the polygons in front of the split plane
372                @param backRays returns the polygons in the back of the split plane
373
374                @returns the root of the subdivision
375        */
376
377        BspNode *SubdivideNode(VspBspTraversalData &tData,
378                                                   VspBspTraversalData &frontData,
379                                                   VspBspTraversalData &backData,
380                                                   PolygonContainer &coincident);
381
382        /** Selects the split plane in order to construct a tree with
383                certain characteristics (e.g., balanced tree, least splits,
384                2.5d aligned)
385                @param bestPlane returns the split plane
386                @param polygons container of polygons
387                @param rays bundle of rays on which the split can be based
388
389                @returns true if the overall cost is under maxCostRatio
390        */
391        bool SelectPlaneHeuristics(Plane3 &bestPlane,
392                                                           BspLeaf *leaf,
393                                                           VspBspTraversalData &data);
394
395        /** Extracts the meshes of the objects and adds them to polygons.
396                Adds object aabb to the aabb of the tree.
397                @param maxPolys the maximal number of objects to be stored as polygons
398                @returns the number of polygons
399        */
400        int AddToPolygonSoup(const ObjectContainer &objects,
401                                                 PolygonContainer &polys,
402                                                 int maxObjects = 0);
403
404        /** Extracts the meshes of the view cells and and adds them to polygons.
405                Adds view cell aabb to the aabb of the tree.
406                @param maxPolys the maximal number of objects to be stored as polygons
407                @returns the number of polygons
408        */
409        int AddToPolygonSoup(const ViewCellContainer &viewCells,
410                                                 PolygonContainer &polys,
411                                                 int maxObjects = 0);
412
413        /** Extract polygons of this mesh and add to polygon container.
414                @param mesh the mesh that drives the polygon construction
415                @param parent the parent intersectable this polygon is constructed from
416                @returns number of polygons
417        */
418        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
419
420        /** Selects a plane axis aligned.
421        */
422        float SelectAxisAlignedPlane(Plane3 &plane,
423                                                                 const VspBspTraversalData &tData,
424                                                                 int &bestAxis);
425
426        /** Sorts split candidates for surface area heuristics for axis aligned splits.
427                @param polys the input for choosing split candidates
428                @param axis the current split axis
429                @param splitCandidates returns sorted list of split candidates
430        */
431        void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
432
433        /** Computes best cost for axis aligned planes.
434        */
435        float BestCostRatioHeuristics(const RayInfoContainer &rays,
436                                                                  const AxisAlignedBox3 &box,
437                                                                  const int pvsSize,
438                                                                  const int &axis,
439                                                                  float &position);
440
441        /** Evaluates cost ratio for axis aligned splits.
442        */
443        float EvalCostRatio(const VspBspTraversalData &tData,
444                                                const AxisAlignedBox3 &box,
445                                                const int axis,
446                                                const float position,
447                                                int &raysBack,
448                                                int &raysFront,
449                                                int &pvsBack,
450                                                int &pvsFront);
451
452        /** Selects an axis aligned split plane.
453                @Returns true if split is valied
454        */
455        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
456
457        /** Subdivides the rays into front and back rays according to the split plane.
458               
459                @param plane the split plane
460                @param rays contains the rays to be split. The rays are
461                           distributed into front and back rays.
462                @param frontRays returns rays on the front side of the plane
463                @param backRays returns rays on the back side of the plane
464               
465                @returns the number of splits
466        */
467        int SplitRays(const Plane3 &plane,
468                                  RayInfoContainer &rays,
469                              RayInfoContainer &frontRays,
470                                  RayInfoContainer &backRays);
471
472
473        /** Extracts the split planes representing the space bounded by node n.
474        */
475        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
476
477        /** Adds the object to the pvs of the front and back leaf with a given classification.
478
479                @param obj the object to be added
480                @param cf the ray classification regarding the split plane
481                @param frontPvs returns the PVS of the front partition
482                @param backPvs returns the PVS of the back partition
483       
484        */
485        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
486       
487        /** Computes PVS size induced by the rays.
488        */
489        int ComputePvsSize(const RayInfoContainer &rays) const;
490
491        /** Returns true if tree can be terminated.
492        */
493        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
494
495        /** Computes accumulated ray lenght of this rays.
496        */
497        float AccumulatedRayLength(const RayInfoContainer &rays) const;
498
499        /** Splits polygons with respect to the split plane.
500
501                @param plane the split plane
502                @param polys the polygons to be split. the polygons are consumed and
503                           distributed to the containers frontPolys, backPolys, coincident.
504                @param frontPolys returns the polygons in the front of the split plane
505                @param backPolys returns the polygons in the back of the split plane
506                @param coincident returns the polygons coincident to the split plane
507
508                @returns the number of splits   
509        */
510        int SplitPolygons(const Plane3 &plane,
511                                          PolygonContainer &polys,
512                                          PolygonContainer &frontPolys,
513                                          PolygonContainer &backPolys,
514                                          PolygonContainer &coincident) const;
515
516        /** Adds ray sample contributions to the PVS.
517                @param sampleContributions the number contributions of the samples
518                @param contributingSampels the number of contributing rays
519               
520        */
521        void AddToPvs(BspLeaf *leaf,
522                                  const RayInfoContainer &rays,
523                                  int &sampleContributions,
524                                  int &contributingSamples);
525
526
527        /** Collects candidates for the merge in the merge queue.
528                @returns number of leaves in queue
529        */
530        int CollectMergeCandidates();
531        /** Collects candidates for the merge in the merge queue.
532                @returns number of leaves in queue
533        */
534        int CollectMergeCandidates(const VssRayContainer &rays);
535
536        /** Take 3 ray endpoints, where two are minimum and one a maximum
537                point or the other way round.
538        */
539        Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;
540
541        /** Take plane normal as plane normal and the midpoint of the ray.
542                PROBLEM: does not resemble any point where visibility is
543                likely to change
544        */
545        Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;
546
547        /** Fit the plane between the two lines so that the plane
548                has equal shortest distance to both lines.
549        */
550        Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;
551 
552        /** Shuffles, i.e. takes border leaf from view cell 1 and adds it
553                to view cell 2.
554        */
555        void ShuffleLeaf(BspLeaf *leaf,
556                                         BspViewCell *vc1,
557                                         BspViewCell *vc2) const;
558
559        /**
560                Checks if this traversal data corresponds to
561                a valid view space region.
562        */
563        bool CheckValid(const VspBspTraversalData &data) const;
564
565        /** Propagates valid flag up the tree.
566        */
567        void PropagateUpValidity(BspNode *node);
568
569        /** Creates or returns view cell corresponding to
570                the space outside the valid view space.
571        */
572        BspViewCell *GetOrCreateOutOfBoundsCell();
573
574        /// Pointer to the root of the tree
575        BspNode *mRoot;
576               
577        BspTreeStatistics mStat;
578
579        /// Strategies for choosing next split plane.
580        enum {NO_STRATEGY = 0,
581                  RANDOM_POLYGON = 1,
582                  AXIS_ALIGNED = 2,
583                  LEAST_RAY_SPLITS = 256,
584                  BALANCED_RAYS = 512,
585                  PVS = 1024
586                };
587
588        /// box around the whole view domain
589        AxisAlignedBox3 mBox;
590
591        /// minimal number of rays before subdivision termination
592        int mTermMinRays;
593        /// maximal possible depth
594        int mTermMaxDepth;
595        /// mininum area
596        float mTermMinArea;
597        /// mininum PVS
598        int mTermMinPvs;
599
600        /// minimal number of rays for axis aligned split
601        int mTermMinRaysForAxisAligned;
602        /// minimal number of objects for axis aligned split
603        int mTermMinObjectsForAxisAligned;
604        /// maximal contribution per ray
605        float mTermMaxRayContribution;
606        /// minimal accumulated ray length
607        float mTermMinAccRayLength;
608
609        /// strategy to get the best split plane
610        int mSplitPlaneStrategy;
611        /// number of candidates evaluated for the next split plane
612        int mMaxPolyCandidates;
613        /// number of candidates for split planes evaluated using the rays
614        int mMaxRayCandidates;
615        /// balancing factor for PVS criterium
616        float mCtDivCi;
617
618        //-- axis aligned split criteria
619        float mAxisAlignedCtDivCi;
620        /// spezifies the split border of the axis aligned split
621        float mAxisAlignedSplitBorder;
622
623        /// maximal acceptable cost ratio
624        float mTermMaxCostRatio;
625        /// tolerance value indicating how often the max cost ratio can be failed
626        int mTermMissTolerance;
627
628        //-- factors guiding the split plane heuristics
629        float mLeastRaySplitsFactor;
630        float mBalancedRaysFactor;
631        float mPvsFactor;
632
633        /// if area or accumulated ray lenght should be used for PVS heuristics
634        bool mPvsUseArea;
635        /// tolerance for polygon split
636        float mEpsilon;
637        /// maximal number of test rays used to evaluate candidate split plane
638        int mMaxTests;
639        /// normalizes different bsp split plane criteria
640        float mCostNormalizer;
641        /// maximal number of view cells
642        int mMaxViewCells;
643        /// minimal number of view cells
644        int mMergeMinViewCells;
645        /// maximal cost ratio for the merge
646        float mMergeMaxCostRatio;
647
648        // if rays should be stored in leaves
649        bool mStoreRays;
650       
651        /// if only driving axis should be used for split
652        bool mOnlyDrivingAxis;
653
654        ViewCellsManager *mViewCellsManager;
655
656        vector<SortableEntry> *mSplitCandidates;
657
658
659        typedef priority_queue<BspMergeCandidate> MergeQueue;
660
661        MergeQueue mMergeQueue;
662        /// if rays should be used to collect merge candidates
663        bool mUseRaysForMerge;
664        /// maximal allowed pvs so that view cell is valid
665        int mMaxPvs;
666
667        /// View cell corresponding to the space outside the valid view space
668        BspViewCell *mOutOfBoundsCell;
669
670private:
671       
672        static const float sLeastRaySplitsTable[5];
673        /** Evaluates split plane classification with respect to the plane's
674                contribution for balanced rays.
675        */
676        static const float sBalancedRaysTable[5];
677
678        /// Generates unique ids for PVS criterium
679        static void GenerateUniqueIdsForPvs();
680
681        //-- unique ids for PVS criterium
682        static int sFrontId;
683        static int sBackId;
684        static int sFrontAndBackId;
685};
686
687/**
688        Candidate for leaf merging based on priority.
689*/
690class BspMergeCandidate
691
692public:
693
694        BspMergeCandidate(BspLeaf *l1, BspLeaf *l2);
695
696        /** If this merge pair is still valid.
697        */
698        bool Valid() const;
699
700        /** Sets this merge candidate to be valid.
701        */
702        void SetValid();
703
704        friend bool operator<(const BspMergeCandidate &leafa, const BspMergeCandidate &leafb)
705        {
706                return leafb.GetMergeCost() < leafa.GetMergeCost();
707        }
708
709        void SetLeaf1(BspLeaf *l);
710        void SetLeaf2(BspLeaf *l);
711
712        BspLeaf *GetLeaf1();
713        BspLeaf *GetLeaf2();
714
715        /** Merge cost of this candidate pair.
716        */
717        float GetMergeCost() const;
718
719        /** Returns cost of leaf 1.
720        */
721        float GetLeaf1Cost() const;
722        /** Returns cost of leaf 2.
723        */
724        float GetLeaf2Cost() const;
725
726        /// maximal pvs size
727        static int sMaxPvsSize;
728        /// overall cost used to normalize cost ratio
729        static float sOverallCost;
730
731protected:
732
733        /** Cost of a view cell.
734        */
735        float GetCost(ViewCell *vc) const;
736        /** Evaluates the merge costs of the leaves.
737        */
738        void EvalMergeCost();
739
740        int mLeaf1Id;
741        int mLeaf2Id;
742
743        float mMergeCost;
744       
745        BspLeaf *mLeaf1;
746        BspLeaf *mLeaf2;
747};
748
749
750class MergeStatistics: public StatisticsBase
751{
752public:
753       
754        int merged;
755        int siblings;
756        int candidates;
757        int nodes;
758
759        int accTreeDist;
760        int maxTreeDist;
761       
762        Real collectTime;
763        Real mergeTime;
764
765        // Constructor
766        MergeStatistics()
767        {
768                Reset();
769        }
770       
771        double AvgTreeDist() const {return (double)accTreeDist / (double)merged;};
772
773        void Reset()
774        {
775                nodes = 0;
776                merged = 0;
777                siblings = 0;
778                candidates = 0;
779       
780                accTreeDist = 0;
781                maxTreeDist = 0;
782
783                collectTime = 0;
784                mergeTime = 0;
785        }
786
787        void Print(ostream &app) const;
788
789        friend ostream &operator<<(ostream &s, const MergeStatistics &stat)
790        {
791                stat.Print(s);
792                return s;
793        }
794};
795
796#endif
Note: See TracBrowser for help on using the repository browser.