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

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