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

Revision 485, 20.0 KB checked in by mattausch, 19 years ago (diff)

changed castlinesegment of vspbpstree
changed rayinfo ray classification for bsp tree
implemented shuffling

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       
272        /** Merge view cells of leaves l1 and l2.
273        */
274        bool MergeViewCells(BspLeaf *l1, BspLeaf *l2) const;
275
276protected:
277
278        // --------------------------------------------------------------
279        // For sorting objects
280        // --------------------------------------------------------------
281        struct SortableEntry
282        {
283                enum EType
284                {
285                        ERayMin,
286                        ERayMax
287                };
288
289                int type;
290                float value;
291                VssRay *ray;
292 
293                SortableEntry() {}
294                SortableEntry(const int t, const float v, VssRay *r):type(t),
295                                          value(v), ray(r)
296                {
297                }
298               
299                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
300                {
301                        return a.value < b.value;
302                }
303        };
304
305        /** Shuffles the leaves, i.e., tests if exchanging
306                the leaves helps in improving the view cells.
307        */
308        bool ShuffleLeaves(BspLeaf *leaf1, BspLeaf *leaf2) const;
309
310        /** Helper function revalidating the view cell leaf list after merge.
311        */
312        void RepairVcLeafLists();
313
314        /** Evaluates tree stats in the BSP tree leafs.
315        */
316        void EvaluateLeafStats(const VspBspTraversalData &data);
317
318        /** Subdivides node with respect to the traversal data.
319            @param tStack current traversal stack
320                @param tData traversal data also holding node to be subdivided
321                @returns new root of the subtree
322        */
323        BspNode *Subdivide(VspBspTraversalStack &tStack,
324                                           VspBspTraversalData &tData);
325
326        /** Constructs the tree from the given traversal data.
327                @param polys stores set of polygons on which subdivision may be based
328                @param rays storesset of rays on which subdivision may be based
329        */
330        void Construct(const PolygonContainer &polys, RayInfoContainer *rays);
331
332        /** Selects the best possible splitting plane.
333                @param plane returns the split plane
334                @param leaf the leaf to be split
335                @param polys the polygon list on which the split decition is based
336                @param rays ray container on which selection may be based
337                @note the polygons can be reordered in the process
338                @returns true if the cost of the split is under maxCostRatio
339
340        */
341        bool SelectPlane(Plane3 &plane,
342                                         BspLeaf *leaf,
343                                         VspBspTraversalData &data);
344       
345        /** Strategies where the effect of the split plane is tested
346            on all input rays.
347
348                @returns the cost of the candidate split plane
349        */
350        float SplitPlaneCost(const Plane3 &candidatePlane,
351                                                 const VspBspTraversalData &data) const;
352
353
354        /** Subdivide leaf.
355                @param leaf the leaf to be subdivided
356               
357                @param polys the polygons to be split
358                @param frontPolys returns the polygons in front of the split plane
359                @param backPolys returns the polygons in the back of the split plane
360               
361                @param rays the polygons to be filtered
362                @param frontRays returns the polygons in front of the split plane
363                @param backRays returns the polygons in the back of the split plane
364
365                @returns the root of the subdivision
366        */
367
368        BspNode *SubdivideNode(VspBspTraversalData &tData,
369                                                   VspBspTraversalData &frontData,
370                                                   VspBspTraversalData &backData,
371                                                   PolygonContainer &coincident);
372
373        /** Selects the split plane in order to construct a tree with
374                certain characteristics (e.g., balanced tree, least splits,
375                2.5d aligned)
376                @param bestPlane returns the split plane
377                @param polygons container of polygons
378                @param rays bundle of rays on which the split can be based
379
380                @returns true if the overall cost is under maxCostRatio
381        */
382        bool SelectPlaneHeuristics(Plane3 &bestPlane,
383                                                           BspLeaf *leaf,
384                                                           VspBspTraversalData &data);
385
386        /** Extracts the meshes of the objects and adds them to polygons.
387                Adds object aabb to the aabb of the tree.
388                @param maxPolys the maximal number of objects to be stored as polygons
389                @returns the number of polygons
390        */
391        int AddToPolygonSoup(const ObjectContainer &objects,
392                                                 PolygonContainer &polys,
393                                                 int maxObjects = 0);
394
395        /** Extracts the meshes of the view cells and and adds them to polygons.
396                Adds view cell 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 ViewCellContainer &viewCells,
401                                                 PolygonContainer &polys,
402                                                 int maxObjects = 0);
403
404        /** Extract polygons of this mesh and add to polygon container.
405                @param mesh the mesh that drives the polygon construction
406                @param parent the parent intersectable this polygon is constructed from
407                @returns number of polygons
408        */
409        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
410
411        /** Selects a plane axis aligned.
412        */
413        float SelectAxisAlignedPlane(Plane3 &plane,
414                                                                 const VspBspTraversalData &tData);
415
416        /** Sorts split candidates for surface area heuristics for axis aligned splits.
417                @param polys the input for choosing split candidates
418                @param axis the current split axis
419                @param splitCandidates returns sorted list of split candidates
420        */
421        void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
422
423        /** Computes best cost for axis aligned planes.
424        */
425        float BestCostRatioHeuristics(const RayInfoContainer &rays,
426                                                                  const AxisAlignedBox3 &box,
427                                                                  const int pvsSize,
428                                                                  const int &axis,
429                                                                  float &position);
430
431        /** Selects an axis aligned split plane.
432                Returns true if split is valied
433        */
434        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
435
436        /** Subdivides the rays into front and back rays according to the split plane.
437               
438                @param plane the split plane
439                @param rays contains the rays to be split. The rays are
440                           distributed into front and back rays.
441                @param frontRays returns rays on the front side of the plane
442                @param backRays returns rays on the back side of the plane
443               
444                @returns the number of splits
445        */
446        int SplitRays(const Plane3 &plane,
447                                  RayInfoContainer &rays,
448                              RayInfoContainer &frontRays,
449                                  RayInfoContainer &backRays);
450
451
452        /** Extracts the split planes representing the space bounded by node n.
453        */
454        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
455
456        /** Adds the object to the pvs of the front and back leaf with a given classification.
457
458                @param obj the object to be added
459                @param cf the ray classification regarding the split plane
460                @param frontPvs returns the PVS of the front partition
461                @param backPvs returns the PVS of the back partition
462       
463        */
464        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
465       
466        /** Computes PVS size induced by the rays.
467        */
468        int ComputePvsSize(const RayInfoContainer &rays) const;
469
470        /** Returns true if tree can be terminated.
471        */
472        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
473
474        /** Computes accumulated ray lenght of this rays.
475        */
476        float AccumulatedRayLength(const RayInfoContainer &rays) const;
477
478        /** Splits polygons with respect to the split plane.
479
480                @param plane the split plane
481                @param polys the polygons to be split. the polygons are consumed and
482                           distributed to the containers frontPolys, backPolys, coincident.
483                @param frontPolys returns the polygons in the front of the split plane
484                @param backPolys returns the polygons in the back of the split plane
485                @param coincident returns the polygons coincident to the split plane
486
487                @returns the number of splits   
488        */
489        int SplitPolygons(const Plane3 &plane,
490                                          PolygonContainer &polys,
491                                          PolygonContainer &frontPolys,
492                                          PolygonContainer &backPolys,
493                                          PolygonContainer &coincident) const;
494
495        /** Adds ray sample contributions to the PVS.
496                @param sampleContributions the number contributions of the samples
497                @param contributingSampels the number of contributing rays
498               
499        */
500        void AddToPvs(BspLeaf *leaf,
501                                  const RayInfoContainer &rays,
502                                  int &sampleContributions,
503                                  int &contributingSamples);
504
505
506        /** Collects candidates for the merge in the merge queue.
507                @returns number of leaves in queue
508        */
509        int CollectMergeCandidates();
510        /** Collects candidates for the merge in the merge queue.
511                @returns number of leaves in queue
512        */
513        int CollectMergeCandidates(const VssRayContainer &rays);
514
515        /** Take 3 ray endpoints, where two are minimum and one a maximum
516                point or the other way round.
517        */
518        Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;
519
520        /** Take plane normal as plane normal and the midpoint of the ray.
521                PROBLEM: does not resemble any point where visibility is
522                likely to change
523        */
524        Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;
525
526        /** Fit the plane between the two lines so that the plane
527                has equal shortest distance to both lines.
528        */
529        Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;
530 
531        void ShuffleLeaf(BspLeaf *leaf,
532                                         BspViewCell *vc1,
533                                         BspViewCell *vc2) const;
534
535        /// Pointer to the root of the tree
536        BspNode *mRoot;
537               
538        BspTreeStatistics mStat;
539
540        /// Strategies for choosing next split plane.
541        enum {NO_STRATEGY = 0,
542                  RANDOM_POLYGON = 1,
543                  AXIS_ALIGNED = 2,
544                  LEAST_RAY_SPLITS = 256,
545                  BALANCED_RAYS = 512,
546                  PVS = 1024
547                };
548
549        /// box around the whole view domain
550        AxisAlignedBox3 mBox;
551
552        /// minimal number of rays before subdivision termination
553        int mTermMinRays;
554        /// maximal possible depth
555        int mTermMaxDepth;
556        /// mininum area
557        float mTermMinArea;
558        /// mininum PVS
559        int mTermMinPvs;
560
561        /// minimal number of rays for axis aligned split
562        int mTermMinRaysForAxisAligned;
563        /// minimal number of objects for axis aligned split
564        int mTermMinObjectsForAxisAligned;
565        /// maximal contribution per ray
566        float mTermMaxRayContribution;
567        /// minimal accumulated ray length
568        float mTermMinAccRayLength;
569
570        /// strategy to get the best split plane
571        int mSplitPlaneStrategy;
572        /// number of candidates evaluated for the next split plane
573        int mMaxPolyCandidates;
574        /// number of candidates for split planes evaluated using the rays
575        int mMaxRayCandidates;
576        /// balancing factor for PVS criterium
577        float mCtDivCi;
578
579        //-- axis aligned split criteria
580        float mAxisAlignedCtDivCi;
581        /// spezifies the split border of the axis aligned split
582        float mAxisAlignedSplitBorder;
583
584        /// maximal acceptable cost ratio
585        float mTermMaxCostRatio;
586        /// tolerance value indicating how often the max cost ratio can be failed
587        int mTermMissTolerance;
588
589        //-- factors guiding the split plane heuristics
590        float mLeastRaySplitsFactor;
591        float mBalancedRaysFactor;
592        float mPvsFactor;
593
594        /// if area or accumulated ray lenght should be used for PVS heuristics
595        bool mPvsUseArea;
596        /// tolerance for polygon split
597        float mEpsilon;
598        /// maximal number of test rays used to evaluate candidate split plane
599        int mMaxTests;
600        /// normalizes different bsp split plane criteria
601        float mCostNormalizer;
602        /// maximal number of view cells
603        int mMaxViewCells;
604        /// minimal number of view cells
605        int mMergeMinViewCells;
606        /// maximal cost ratio for the merge
607        float mMergeMaxCostRatio;
608
609        // if rays should be stored in leaves
610        bool mStoreRays;
611       
612        /// if only driving axis should be used for split
613        bool mOnlyDrivingAxis;
614
615        ViewCellsManager *mViewCellsManager;
616
617        vector<SortableEntry> *mSplitCandidates;
618
619        typedef priority_queue<BspMergeCandidate> MergeQueue;
620        MergeQueue mMergeQueue;
621       
622        bool mUseRaysForMerge;
623
624private:
625       
626        static const float sLeastRaySplitsTable[5];
627        /** Evaluates split plane classification with respect to the plane's
628                contribution for balanced rays.
629        */
630        static const float sBalancedRaysTable[5];
631
632        /// Generates unique ids for PVS criterium
633        static void GenerateUniqueIdsForPvs();
634
635        //-- unique ids for PVS criterium
636        static int sFrontId;
637        static int sBackId;
638        static int sFrontAndBackId;
639};
640
641/**
642        Candidate for leaf merging based on priority.
643*/
644class BspMergeCandidate
645
646public:
647
648        BspMergeCandidate(BspLeaf *l1, BspLeaf *l2);
649
650        /** If this merge pair is still valid.
651        */
652        bool Valid() const;
653
654        /** Sets this merge candidate to be valid.
655        */
656        void SetValid();
657
658        friend bool operator<(const BspMergeCandidate &leafa, const BspMergeCandidate &leafb)
659        {
660                return leafb.GetMergeCost() < leafa.GetMergeCost();
661        }
662
663        void SetLeaf1(BspLeaf *l);
664        void SetLeaf2(BspLeaf *l);
665
666        BspLeaf *GetLeaf1();
667        BspLeaf *GetLeaf2();
668
669        /** Merge cost of this candidate pair.
670        */
671        float GetMergeCost() const;
672
673        /** Returns cost of leaf 1.
674        */
675        float GetLeaf1Cost() const;
676        /** Returns cost of leaf 2.
677        */
678        float GetLeaf2Cost() const;
679
680        /// maximal pvs size
681        static int sMaxPvsSize;
682        /// overall cost used to normalize cost ratio
683        static float sOverallCost;
684
685protected:
686
687        /** Cost of a view cell.
688        */
689        float GetCost(ViewCell *vc) const;
690        /** Evaluates the merge costs of the leaves.
691        */
692        void EvalMergeCost();
693
694        int mLeaf1Id;
695        int mLeaf2Id;
696
697        float mMergeCost;
698       
699        BspLeaf *mLeaf1;
700        BspLeaf *mLeaf2;
701};
702
703
704class MergeStatistics: public StatisticsBase
705{
706public:
707       
708        int merged;
709        int siblings;
710        int candidates;
711        int nodes;
712
713        int accTreeDist;
714        int maxTreeDist;
715       
716        Real collectTime;
717        Real mergeTime;
718
719        // Constructor
720        MergeStatistics()
721        {
722                Reset();
723        }
724       
725        double AvgTreeDist() const {return (double)accTreeDist / (double)merged;};
726
727        void Reset()
728        {
729                nodes = 0;
730                merged = 0;
731                siblings = 0;
732                candidates = 0;
733       
734                accTreeDist = 0;
735                maxTreeDist = 0;
736
737                collectTime = 0;
738                mergeTime = 0;
739        }
740
741        void Print(ostream &app) const;
742
743        friend ostream &operator<<(ostream &s, const MergeStatistics &stat)
744        {
745                stat.Print(s);
746                return s;
747        }
748};
749
750#endif
Note: See TracBrowser for help on using the repository browser.