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

Revision 489, 20.9 KB checked in by mattausch, 19 years ago (diff)

valid view point regions working now for bsp view cells (crit: maxpvs)

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
425        /** Sorts split candidates for surface area heuristics for axis aligned splits.
426                @param polys the input for choosing split candidates
427                @param axis the current split axis
428                @param splitCandidates returns sorted list of split candidates
429        */
430        void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
431
432        /** Computes best cost for axis aligned planes.
433        */
434        float BestCostRatioHeuristics(const RayInfoContainer &rays,
435                                                                  const AxisAlignedBox3 &box,
436                                                                  const int pvsSize,
437                                                                  const int &axis,
438                                                                  float &position);
439
440        /** Selects an axis aligned split plane.
441                Returns true if split is valied
442        */
443        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
444
445        /** Subdivides the rays into front and back rays according to the split plane.
446               
447                @param plane the split plane
448                @param rays contains the rays to be split. The rays are
449                           distributed into front and back rays.
450                @param frontRays returns rays on the front side of the plane
451                @param backRays returns rays on the back side of the plane
452               
453                @returns the number of splits
454        */
455        int SplitRays(const Plane3 &plane,
456                                  RayInfoContainer &rays,
457                              RayInfoContainer &frontRays,
458                                  RayInfoContainer &backRays);
459
460
461        /** Extracts the split planes representing the space bounded by node n.
462        */
463        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
464
465        /** Adds the object to the pvs of the front and back leaf with a given classification.
466
467                @param obj the object to be added
468                @param cf the ray classification regarding the split plane
469                @param frontPvs returns the PVS of the front partition
470                @param backPvs returns the PVS of the back partition
471       
472        */
473        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
474       
475        /** Computes PVS size induced by the rays.
476        */
477        int ComputePvsSize(const RayInfoContainer &rays) const;
478
479        /** Returns true if tree can be terminated.
480        */
481        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
482
483        /** Computes accumulated ray lenght of this rays.
484        */
485        float AccumulatedRayLength(const RayInfoContainer &rays) const;
486
487        /** Splits polygons with respect to the split plane.
488
489                @param plane the split plane
490                @param polys the polygons to be split. the polygons are consumed and
491                           distributed to the containers frontPolys, backPolys, coincident.
492                @param frontPolys returns the polygons in the front of the split plane
493                @param backPolys returns the polygons in the back of the split plane
494                @param coincident returns the polygons coincident to the split plane
495
496                @returns the number of splits   
497        */
498        int SplitPolygons(const Plane3 &plane,
499                                          PolygonContainer &polys,
500                                          PolygonContainer &frontPolys,
501                                          PolygonContainer &backPolys,
502                                          PolygonContainer &coincident) const;
503
504        /** Adds ray sample contributions to the PVS.
505                @param sampleContributions the number contributions of the samples
506                @param contributingSampels the number of contributing rays
507               
508        */
509        void AddToPvs(BspLeaf *leaf,
510                                  const RayInfoContainer &rays,
511                                  int &sampleContributions,
512                                  int &contributingSamples);
513
514
515        /** Collects candidates for the merge in the merge queue.
516                @returns number of leaves in queue
517        */
518        int CollectMergeCandidates();
519        /** Collects candidates for the merge in the merge queue.
520                @returns number of leaves in queue
521        */
522        int CollectMergeCandidates(const VssRayContainer &rays);
523
524        /** Take 3 ray endpoints, where two are minimum and one a maximum
525                point or the other way round.
526        */
527        Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;
528
529        /** Take plane normal as plane normal and the midpoint of the ray.
530                PROBLEM: does not resemble any point where visibility is
531                likely to change
532        */
533        Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;
534
535        /** Fit the plane between the two lines so that the plane
536                has equal shortest distance to both lines.
537        */
538        Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;
539 
540        /** Shuffles, i.e. takes border leaf from view cell 1 and adds it
541                to view cell 2.
542        */
543        void ShuffleLeaf(BspLeaf *leaf,
544                                         BspViewCell *vc1,
545                                         BspViewCell *vc2) const;
546
547        /**
548                Checks if this traversal data corresponds to
549                a valid view space region.
550        */
551        bool CheckValid(const VspBspTraversalData &data) const;
552
553        /** Propagates valid flag up the tree.
554        */
555        void PropagateUpValidity(BspNode *node);
556
557        /** Creates or returns view cell corresponding to
558                the space outside the valid view space.
559        */
560        BspViewCell *GetOrCreateOutOfBoundsCell();
561
562        /// Pointer to the root of the tree
563        BspNode *mRoot;
564               
565        BspTreeStatistics mStat;
566
567        /// Strategies for choosing next split plane.
568        enum {NO_STRATEGY = 0,
569                  RANDOM_POLYGON = 1,
570                  AXIS_ALIGNED = 2,
571                  LEAST_RAY_SPLITS = 256,
572                  BALANCED_RAYS = 512,
573                  PVS = 1024
574                };
575
576        /// box around the whole view domain
577        AxisAlignedBox3 mBox;
578
579        /// minimal number of rays before subdivision termination
580        int mTermMinRays;
581        /// maximal possible depth
582        int mTermMaxDepth;
583        /// mininum area
584        float mTermMinArea;
585        /// mininum PVS
586        int mTermMinPvs;
587
588        /// minimal number of rays for axis aligned split
589        int mTermMinRaysForAxisAligned;
590        /// minimal number of objects for axis aligned split
591        int mTermMinObjectsForAxisAligned;
592        /// maximal contribution per ray
593        float mTermMaxRayContribution;
594        /// minimal accumulated ray length
595        float mTermMinAccRayLength;
596
597        /// strategy to get the best split plane
598        int mSplitPlaneStrategy;
599        /// number of candidates evaluated for the next split plane
600        int mMaxPolyCandidates;
601        /// number of candidates for split planes evaluated using the rays
602        int mMaxRayCandidates;
603        /// balancing factor for PVS criterium
604        float mCtDivCi;
605
606        //-- axis aligned split criteria
607        float mAxisAlignedCtDivCi;
608        /// spezifies the split border of the axis aligned split
609        float mAxisAlignedSplitBorder;
610
611        /// maximal acceptable cost ratio
612        float mTermMaxCostRatio;
613        /// tolerance value indicating how often the max cost ratio can be failed
614        int mTermMissTolerance;
615
616        //-- factors guiding the split plane heuristics
617        float mLeastRaySplitsFactor;
618        float mBalancedRaysFactor;
619        float mPvsFactor;
620
621        /// if area or accumulated ray lenght should be used for PVS heuristics
622        bool mPvsUseArea;
623        /// tolerance for polygon split
624        float mEpsilon;
625        /// maximal number of test rays used to evaluate candidate split plane
626        int mMaxTests;
627        /// normalizes different bsp split plane criteria
628        float mCostNormalizer;
629        /// maximal number of view cells
630        int mMaxViewCells;
631        /// minimal number of view cells
632        int mMergeMinViewCells;
633        /// maximal cost ratio for the merge
634        float mMergeMaxCostRatio;
635
636        // if rays should be stored in leaves
637        bool mStoreRays;
638       
639        /// if only driving axis should be used for split
640        bool mOnlyDrivingAxis;
641
642        ViewCellsManager *mViewCellsManager;
643
644        vector<SortableEntry> *mSplitCandidates;
645
646
647        typedef priority_queue<BspMergeCandidate> MergeQueue;
648
649        MergeQueue mMergeQueue;
650        /// if rays should be used to collect merge candidates
651        bool mUseRaysForMerge;
652        /// maximal allowed pvs so that view cell is valid
653        int mMaxPvs;
654
655        /// View cell corresponding to the space outside the valid view space
656        BspViewCell *mOutOfBoundsCell;
657
658private:
659       
660        static const float sLeastRaySplitsTable[5];
661        /** Evaluates split plane classification with respect to the plane's
662                contribution for balanced rays.
663        */
664        static const float sBalancedRaysTable[5];
665
666        /// Generates unique ids for PVS criterium
667        static void GenerateUniqueIdsForPvs();
668
669        //-- unique ids for PVS criterium
670        static int sFrontId;
671        static int sBackId;
672        static int sFrontAndBackId;
673};
674
675/**
676        Candidate for leaf merging based on priority.
677*/
678class BspMergeCandidate
679
680public:
681
682        BspMergeCandidate(BspLeaf *l1, BspLeaf *l2);
683
684        /** If this merge pair is still valid.
685        */
686        bool Valid() const;
687
688        /** Sets this merge candidate to be valid.
689        */
690        void SetValid();
691
692        friend bool operator<(const BspMergeCandidate &leafa, const BspMergeCandidate &leafb)
693        {
694                return leafb.GetMergeCost() < leafa.GetMergeCost();
695        }
696
697        void SetLeaf1(BspLeaf *l);
698        void SetLeaf2(BspLeaf *l);
699
700        BspLeaf *GetLeaf1();
701        BspLeaf *GetLeaf2();
702
703        /** Merge cost of this candidate pair.
704        */
705        float GetMergeCost() const;
706
707        /** Returns cost of leaf 1.
708        */
709        float GetLeaf1Cost() const;
710        /** Returns cost of leaf 2.
711        */
712        float GetLeaf2Cost() const;
713
714        /// maximal pvs size
715        static int sMaxPvsSize;
716        /// overall cost used to normalize cost ratio
717        static float sOverallCost;
718
719protected:
720
721        /** Cost of a view cell.
722        */
723        float GetCost(ViewCell *vc) const;
724        /** Evaluates the merge costs of the leaves.
725        */
726        void EvalMergeCost();
727
728        int mLeaf1Id;
729        int mLeaf2Id;
730
731        float mMergeCost;
732       
733        BspLeaf *mLeaf1;
734        BspLeaf *mLeaf2;
735};
736
737
738class MergeStatistics: public StatisticsBase
739{
740public:
741       
742        int merged;
743        int siblings;
744        int candidates;
745        int nodes;
746
747        int accTreeDist;
748        int maxTreeDist;
749       
750        Real collectTime;
751        Real mergeTime;
752
753        // Constructor
754        MergeStatistics()
755        {
756                Reset();
757        }
758       
759        double AvgTreeDist() const {return (double)accTreeDist / (double)merged;};
760
761        void Reset()
762        {
763                nodes = 0;
764                merged = 0;
765                siblings = 0;
766                candidates = 0;
767       
768                accTreeDist = 0;
769                maxTreeDist = 0;
770
771                collectTime = 0;
772                mergeTime = 0;
773        }
774
775        void Print(ostream &app) const;
776
777        friend ostream &operator<<(ostream &s, const MergeStatistics &stat)
778        {
779                stat.Print(s);
780                return s;
781        }
782};
783
784#endif
Note: See TracBrowser for help on using the repository browser.