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

Revision 580, 19.9 KB checked in by mattausch, 18 years ago (diff)

implemented variance
started implementing merge history

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