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

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