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

Revision 590, 20.0 KB checked in by mattausch, 18 years ago (diff)

implemented some code for merge history loading

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