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

Revision 487, 20.6 KB checked in by mattausch, 19 years ago (diff)

fixed bug in raycasting
added valid view point regions, get view point only from valid regions

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