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

Revision 445, 19.2 KB checked in by mattausch, 19 years ago (diff)

Added VspBspTree? functionality:
This is a view space partitioning specialised BSPtree.
There are no polygon splits, but we split the sample rays.
The candidates for the next split plane are evaluated only
by checking the sampled visibility information.
The polygons are employed merely as candidates for the next split planes.

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
12class ViewCell;
13class BspViewCell;
14class Plane3;
15class VspBspTree; 
16class VspBspInterior;
17class VspBspNode;
18class AxisAlignedBox3;
19class Ray;
20
21class VspBspNodeGeometry
22{
23public:
24        VspBspNodeGeometry()
25        {}; 
26
27        ~VspBspNodeGeometry();
28
29        float GetArea() const;
30       
31        /** Computes new cell based on the old cell definition and a new split plane
32                @param side indicates which side of the halfspace
33        */
34        void SplitGeometry(VspBspNodeGeometry &front,
35                                           VspBspNodeGeometry &back,
36                                           const VspBspTree &tree,
37                                           const Plane3 &splitPlane) const;
38
39        Polygon3 *SplitPolygon(Polygon3 *poly, const VspBspTree &tree) const;
40
41        PolygonContainer mPolys;
42};
43
44/** Data structure used for optimized ray casting.
45*/
46struct VspBspRayTraversalData
47{
48    VspBspNode *mNode;
49    Vector3 mExitPoint;
50    float mMaxT;
51   
52    VspBspRayTraversalData() {}
53
54    VspBspRayTraversalData(VspBspNode *n, const Vector3 &extp, const float maxt):
55    mNode(n), mExitPoint(extp), mMaxT(maxt)
56        {}
57};
58
59class VspBspTreeStatistics: public StatisticsBase
60{
61public:
62        // total number of nodes
63        int nodes;
64        // number of splits
65        int splits;
66        // totals number of rays
67        int rays;
68        // maximal reached depth
69        int maxDepth;
70        // minimal depth
71        int minDepth;
72       
73        // max depth nodes
74        int maxDepthNodes;
75        // minimum depth nodes
76        int minDepthNodes;
77        // max depth nodes
78        int minPvsNodes;
79        // nodes with minimum PVS
80        int minRaysNodes;
81        // max ray contribution nodes
82        int maxRayContribNodes;
83        // minimum area nodes
84        int minAreaNodes;
85
86        // max number of rays per node
87        int maxObjectRefs;
88        // accumulated depth (used to compute average)
89        int accumDepth;
90        // number of initial polygons
91        int polys;
92        /// samples contributing to pvs
93        int contributingSamples;
94        /// sample contributions to pvs
95        int sampleContributions;
96        /// largest pvs
97        int largestPvs;
98
99        // Constructor
100        VspBspTreeStatistics()
101        {
102                Reset();
103        }
104
105        int Nodes() const {return nodes;}
106        int Interior() const { return nodes / 2; }
107        int Leaves() const { return (nodes / 2) + 1; }
108       
109        // TODO: computation wrong
110        double AvgDepth() const { return accumDepth / (double)Leaves();};
111 
112        void Reset()
113        {
114                nodes = 0;
115                splits = 0;
116               
117                maxDepth = 0;
118                minDepth = 99999;
119                polys = 0;
120                accumDepth = 0;
121       
122                maxDepthNodes = 0;
123                minPvsNodes = 0;
124                minRaysNodes = 0;
125                maxRayContribNodes = 0;
126                minAreaNodes = 0;
127
128                contributingSamples = 0;
129                sampleContributions = 0;
130        }
131
132        void Print(ostream &app) const;
133
134        friend ostream &operator<<(ostream &s, const VspBspTreeStatistics &stat)
135        {
136                stat.Print(s);
137                return s;
138        }
139};
140
141class VspBspViewCellsStatistics: public StatisticsBase
142{
143public:
144
145        /// number of view cells
146        int viewCells;
147
148        /// size of the PVS
149        int pvs;
150 
151        /// largest PVS of all view cells
152        int maxPvs;
153
154        /// smallest PVS of all view cells
155        int minPvs;
156
157        /// view cells with empty PVS
158        int emptyPvs;
159
160        /// number of bsp leaves covering the view space
161        int bspLeaves;
162
163        /// largest number of leaves covered by one view cell 
164        int maxVspBspLeaves;
165
166    // Constructor
167        VspBspViewCellsStatistics()
168        {
169                Reset();
170        }
171
172        double AvgVspBspLeaves() const {return (double)bspLeaves / (double)viewCells;};
173        double AvgPvs() const {return (double)pvs / (double)viewCells;};
174 
175        void Reset()
176        {
177                viewCells = 0; 
178                pvs = 0; 
179                maxPvs = 0;
180
181                minPvs = 999999;
182                emptyPvs = 0;
183                bspLeaves = 0;
184                maxVspBspLeaves = 0;
185        }
186
187        void Print(ostream &app) const;
188
189        friend ostream &operator<<(ostream &s, const VspBspViewCellsStatistics &stat)
190        {
191                stat.Print(s);
192                return s;
193        } 
194};
195
196/**
197    VspBspNode abstract class serving for interior and leaf node implementation
198*/
199class VspBspNode
200{
201        friend class VspBspTree;
202
203public:
204        VspBspNode();
205        virtual ~VspBspNode(){};
206        VspBspNode(VspBspInterior *parent);
207
208        /** Determines whether this node is a leaf or not
209        @return true if leaf
210        */
211        virtual bool IsLeaf() const = 0;
212
213        /** Determines whether this node is a root
214        @return true if root
215        */
216        virtual bool IsRoot() const;
217
218        /** Returns parent node.
219        */
220        VspBspInterior *GetParent();
221
222        /** Sets parent node.
223        */
224        void SetParent(VspBspInterior *parent);
225
226       
227        static int sMailId;
228        int mMailbox;
229 
230        void Mail() { mMailbox = sMailId; }
231        static void NewMail() { ++ sMailId; }
232        bool Mailed() const { return mMailbox == sMailId; }
233
234protected:
235
236        /// parent of this node
237        VspBspInterior *mParent;
238};
239
240/** BSP interior node implementation
241*/
242class VspBspInterior : public VspBspNode
243{
244        friend class VspBspTree;
245public:
246        /** Standard contructor taking split plane as argument.
247        */
248        VspBspInterior(const Plane3 &plane);
249        ~VspBspInterior();
250        /** @return false since it is an interior node
251        */
252        bool IsLeaf() const;
253
254        VspBspNode *GetBack();
255        VspBspNode *GetFront();
256
257        Plane3 *GetPlane();
258
259        void ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild);
260        void SetupChildLinks(VspBspNode *b, VspBspNode *f);
261
262        /** Splits polygons with respect to the split plane.
263                @param polys the polygons to be split. the polygons are consumed and
264                           distributed to the containers frontPolys, backPolys, coincident.
265                @param frontPolys returns the polygons in the front of the split plane
266                @param backPolys returns the polygons in the back of the split plane
267                @param coincident returns the polygons coincident to the split plane
268
269                @returns the number of splits   
270        */
271        int SplitPolygons(PolygonContainer &polys,
272                                          PolygonContainer &frontPolys,
273                                          PolygonContainer &backPolys,
274                                          PolygonContainer &coincident);
275
276        friend ostream &operator<<(ostream &s, const VspBspInterior &A)
277        {
278                return s << A.mPlane;
279        }
280
281protected:
282
283        /// Splitting plane corresponding to this node
284        Plane3 mPlane;
285        /// back node
286        VspBspNode *mBack;
287        /// front node
288        VspBspNode *mFront;
289};
290
291/** BSP leaf node implementation.
292*/
293class VspBspLeaf : public VspBspNode
294{
295        friend class VspBspTree;
296
297public:
298        VspBspLeaf();
299        VspBspLeaf(BspViewCell *viewCell);
300        VspBspLeaf(VspBspInterior *parent);
301        VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell);
302
303        /** @return true since it is an interior node
304        */
305        bool IsLeaf() const;
306       
307        /** Returns pointer of view cell.
308        */
309        BspViewCell *GetViewCell() const;
310
311        /** Sets pointer to view cell.
312        */
313        void SetViewCell(BspViewCell *viewCell);
314
315        /** Adds ray sample contributions to the PVS.
316                @param sampleContributions the number contributions of the samples
317                @param contributingSampels the number of contributing rays
318               
319        */
320        void AddToPvs(const RayInfoContainer &rays,
321                                  int &sampleContributions,
322                                  int &contributingSamples,
323                                  bool storeLeavesWithRays = false);
324
325protected:
326
327        /// if NULL this does not correspond to feasible viewcell
328        BspViewCell *mViewCell;
329};
330
331/**
332        This is a view space partitioning specialised BSPtree. 
333        There are no polygon splits, but we split the sample rays.
334        The candidates for the next split plane are evaluated only
335        by checking the sampled visibility information.
336        The polygons are employed merely as candidates for the next split planes.
337*/
338class VspBspTree
339{
340public:
341       
342        /** Additional data which is passed down the BSP tree during traversal.
343        */
344        struct VspBspTraversalData
345        { 
346                /// the current node
347                VspBspNode *mNode;
348                /// polygonal data for splitting
349                PolygonContainer *mPolygons;
350                /// current depth
351                int mDepth;
352                /// the view cell associated with this subdivsion
353                ViewCell *mViewCell;
354                /// rays piercing this node
355                RayInfoContainer *mRays;
356                /// area of current node
357                float mArea;
358                /// geometry of current node induced by split planes
359                VspBspNodeGeometry *mGeometry;
360
361                /// pvs size
362                int mPvs;
363               
364                /** Returns average ray contribution.
365                */
366                float GetAvgRayContribution() const
367                {
368                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
369                }
370
371
372                VspBspTraversalData():
373                mNode(NULL),
374                mPolygons(NULL),
375                mDepth(0),
376                mViewCell(NULL),
377                mRays(NULL),
378                mPvs(0),
379                mArea(0.0),
380                mGeometry(NULL)
381                {}
382               
383                VspBspTraversalData(VspBspNode *node,
384                                                 PolygonContainer *polys,
385                                                 const int depth,
386                                                 ViewCell *viewCell,
387                                                 RayInfoContainer *rays,
388                                                 int pvs,
389                                                 float area,
390                                                 VspBspNodeGeometry *cell):
391                mNode(node),
392                mPolygons(polys),
393                mDepth(depth),
394                mViewCell(viewCell),
395                mRays(rays),
396                mPvs(pvs),
397                mArea(area),
398                mGeometry(cell)
399                {}
400    };
401       
402        typedef std::stack<VspBspTraversalData> VspBspTraversalStack;
403
404        /** Default constructor creating an empty tree.
405        */
406        VspBspTree();
407
408        ~VspBspTree();
409
410        const VspBspTreeStatistics &GetStatistics() const;
411 
412
413        /** Constructs the tree from a given set of rays.
414                @param sampleRays the set of sample rays the construction is based on
415                @param viewCells if not NULL, new view cells are
416                created in the leafs and stored in the container
417        */
418        void Construct(const VssRayContainer &sampleRays);
419
420        /** Returns list of BSP leaves.
421        */
422        void CollectLeaves(vector<VspBspLeaf *> &leaves) const;
423
424        /** Returns box which bounds the whole tree.
425        */
426        AxisAlignedBox3 GetBoundingBox()const;
427
428        /** Returns root of BSP tree.
429        */
430        VspBspNode *GetRoot() const;
431
432        /** Exports VspBsp tree to file.
433        */
434        bool Export(const string filename);
435
436        /** Collects the leaf view cells of the tree
437                @param viewCells returns the view cells
438        */
439        void CollectViewCells(ViewCellContainer &viewCells) const;
440
441        /** A ray is cast possible intersecting the tree.
442                @param the ray that is cast.
443                @returns the number of intersections with objects stored in the tree.
444        */
445        int CastRay(Ray &ray);
446
447        /// bsp tree construction types
448        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
449
450        /** Returns statistics.
451        */
452        VspBspTreeStatistics &GetStat();
453
454        /** finds neighbouring leaves of this tree node.
455        */
456        int FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors,
457                                          const bool onlyUnmailed) const;
458
459        /** Constructs geometry associated with the half space intersections
460                leading to this node.
461        */
462        void ConstructGeometry(VspBspNode *n, PolygonContainer &cell) const;
463
464        /** Constructs geometry associated with the half space intersections
465                leading to this node.
466        */
467        void ConstructGeometry(BspViewCell *vc, PolygonContainer &cell) const;
468
469        /** Construct geometry and stores it in a geometry node container.
470        */
471        void ConstructGeometry(VspBspNode *n, VspBspNodeGeometry &cell) const;
472
473        /** Returns random leaf of BSP tree.
474                @param halfspace defines the halfspace from which the leaf is taken.
475        */
476        VspBspLeaf *GetRandomLeaf(const Plane3 &halfspace);
477
478        /** Returns random leaf of BSP tree.
479                @param onlyUnmailed if only unmailed leaves should be returned.
480        */
481        VspBspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
482
483        /** Traverses tree and counts all view cells as well as their PVS size.
484        */
485        void EvaluateViewCellsStats(VspBspViewCellsStatistics &stat) const;
486
487
488        /** Returns view cell corresponding to unbounded space.
489        */
490        BspViewCell *GetRootCell() const;
491
492protected:
493
494        // --------------------------------------------------------------
495        // For sorting objects
496        // --------------------------------------------------------------
497        struct SortableEntry
498        {
499                enum {POLY_MIN, POLY_MAX};
500   
501                int type;
502                float value;
503                Polygon3 *poly;
504                SortableEntry() {}
505                SortableEntry(const int t, const float v, Polygon3 *poly):
506                type(t), value(v), poly(poly) {}
507               
508                bool operator<(const SortableEntry &b) const
509                {
510                        return value < b.value;
511                } 
512        };
513
514        /** Evaluates tree stats in the BSP tree leafs.
515        */
516        void EvaluateLeafStats(const VspBspTraversalData &data);
517
518        /** Subdivides node with respect to the traversal data.
519            @param tStack current traversal stack
520                @param tData traversal data also holding node to be subdivided
521                @returns new root of the subtree
522        */
523        VspBspNode *Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData);
524
525        /** Constructs the tree from the given list of polygons and rays.
526                @param polys stores set of polygons on which subdivision may be based
527                @param rays storesset of rays on which subdivision may be based
528        */
529        void Construct(PolygonContainer *polys, RayInfoContainer *rays);
530
531        /** Selects the best possible splitting plane.
532                @param leaf the leaf to be split
533                @param polys the polygon list on which the split decition is based
534                @param rays ray container on which selection may be based
535                @note the polygons can be reordered in the process
536                @returns the split plane
537        */
538        Plane3 SelectPlane(VspBspLeaf *leaf,
539                                           VspBspTraversalData &data);
540
541       
542        /** Strategies where the effect of the split plane is tested
543            on all input rays.
544
545                @returns the cost of the candidate split plane
546        */
547        float SplitPlaneCost(const Plane3 &candidatePlane,
548                                                 const VspBspTraversalData &data);
549
550
551
552        /** Subdivide leaf.
553                @param leaf the leaf to be subdivided
554               
555                @param polys the polygons to be split
556                @param frontPolys returns the polygons in front of the split plane
557                @param backPolys returns the polygons in the back of the split plane
558               
559                @param rays the polygons to be filtered
560                @param frontRays returns the polygons in front of the split plane
561                @param backRays returns the polygons in the back of the split plane
562
563                @returns the root of the subdivision
564        */
565
566        VspBspInterior *SubdivideNode(VspBspTraversalData &tData,
567                                                           VspBspTraversalData &frontData,
568                                                           VspBspTraversalData &backData,
569                                                           PolygonContainer &coincident);
570
571        /** Selects the split plane in order to construct a tree with
572                certain characteristics (e.g., balanced tree, least splits,
573                2.5d aligned)
574                @param polygons container of polygons
575                @param rays bundle of rays on which the split can be based
576        */
577        Plane3 SelectPlaneHeuristics(VspBspLeaf *leaf,
578                                                                 VspBspTraversalData &data);
579
580        /** Extracts the meshes of the objects and adds them to polygons.
581                Adds object aabb to the aabb of the tree.
582                @param maxPolys the maximal number of objects to be stored as polygons
583                @returns the number of polygons
584        */
585        int AddToPolygonSoup(const ObjectContainer &objects,
586                                                 PolygonContainer &polys,
587                                                 int maxObjects = 0);
588
589        /** Extracts the meshes of the view cells and and adds them to polygons.
590                Adds view cell aabb to the aabb of the tree.
591                @param maxPolys the maximal number of objects to be stored as polygons
592                @returns the number of polygons
593        */
594        int AddToPolygonSoup(const ViewCellContainer &viewCells,
595                                                 PolygonContainer &polys,
596                                                 int maxObjects = 0);
597
598        /** Extract polygons of this mesh and add to polygon container.
599                @param mesh the mesh that drives the polygon construction
600                @param parent the parent intersectable this polygon is constructed from
601                @returns number of polygons
602        */
603        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
604
605        /** returns next candidate index and reorders polygons so no candidate is chosen two times
606                @param the current candidate index
607                @param max the range of candidates
608        */
609        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
610       
611        /** Computes best cost ratio for the suface area heuristics for axis aligned
612                splits. This heuristics minimizes the cost for ray traversal.
613                @param polys the polygons guiding the ratio computation
614                @param box the bounding box of the leaf
615                @param axis the current split axis
616                @param position returns the split position
617                @param objectsBack the number of objects in the back of the split plane
618                @param objectsFront the number of objects in the front of the split plane
619        */
620        float BestCostRatio(const PolygonContainer &polys,
621                                                const AxisAlignedBox3 &box,
622                                                const int axis,
623                                                float &position,
624                                                int &objectsBack,
625                                                int &objectsFront) const;
626       
627        /** Sorts split candidates for surface area heuristics for axis aligned splits.
628                @param polys the input for choosing split candidates
629                @param axis the current split axis
630                @param splitCandidates returns sorted list of split candidates
631        */
632        void SortSplitCandidates(const PolygonContainer &polys,
633                                                         const int axis,
634                                                         vector<SortableEntry> &splitCandidates) const;
635
636        /** Selects an axis aligned split plane.
637                Returns true if split is valied
638        */
639        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
640
641        /** Bounds ray and returns minT and maxT.
642                @returns true if ray hits BSP tree bounding box
643        */
644        bool BoundRay(const Ray &ray, float &minT, float &maxT) const;
645
646        /** Subdivides the rays into front and back rays according to the split plane.
647               
648                @param plane the split plane
649                @param rays contains the rays to be split. The rays are
650                           distributed into front and back rays.
651                @param frontRays returns rays on the front side of the plane
652                @param backRays returns rays on the back side of the plane
653               
654                @returns the number of splits
655        */
656        int SplitRays(const Plane3 &plane,
657                                  RayInfoContainer &rays,
658                              RayInfoContainer &frontRays,
659                                  RayInfoContainer &backRays);
660
661
662        /** Extracts the split planes representing the space bounded by node n.
663        */
664        void ExtractHalfSpaces(VspBspNode *n, vector<Plane3> &halfSpaces) const;
665
666        /** Adds the object to the pvs of the front and back leaf with a given classification.
667
668                @param obj the object to be added
669                @param cf the ray classification regarding the split plane
670                @param frontPvs returns the PVS of the front partition
671                @param backPvs returns the PVS of the back partition
672       
673        */
674        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
675       
676        /** Computes PVS size induced by the rays.
677        */
678        int ComputePvsSize(const RayInfoContainer &rays) const;
679
680        /** Returns true if tree can be terminated.
681        */
682        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
683
684        /** Computes accumulated ray lenght of this rays.
685        */
686        float AccumulatedRayLength(const RayInfoContainer &rays) const;
687
688
689
690        /// Pointer to the root of the tree
691        VspBspNode *mRoot;
692               
693        VspBspTreeStatistics mStat;
694
695        /// Strategies for choosing next split plane.
696        enum {NO_STRATEGY = 0,
697                  RANDOM_POLYGON = 1,
698                  AXIS_ALIGNED = 2,
699                  LEAST_RAY_SPLITS = 256,
700                  BALANCED_RAYS = 512,
701                  PVS = 1024
702                };
703
704        /// box around the whole view domain
705        AxisAlignedBox3 mBox;
706
707        /// view cell corresponding to unbounded space
708        BspViewCell *mRootCell;
709
710        /// minimal number of rays before subdivision termination
711        int mTermMinRays;
712        /// maximal possible depth
713        int mTermMaxDepth;
714        /// mininum area
715        float mTermMinArea;
716        /// mininum PVS
717        int mTermMinPvs;
718
719        /// minimal number of rays for axis aligned split
720        int mTermMinRaysForAxisAligned;
721        /// minimal number of objects for axis aligned split
722        int mTermMinObjectsForAxisAligned;
723        /// maximal contribution per ray
724        float mTermMaxRayContribution;
725        /// minimal accumulated ray length
726        float mTermMinAccRayLength;
727
728
729        /// strategy to get the best split plane
730        int mSplitPlaneStrategy;
731        /// number of candidates evaluated for the next split plane
732        int mMaxPolyCandidates;
733        /// number of candidates for split planes evaluated using the rays
734        int mMaxRayCandidates;
735        /// balancing factor for PVS criterium
736        float mCtDivCi;
737
738        //-- axis aligned split criteria
739        float mAaCtDivCi;
740        float mSplitBorder;
741        float mMaxCostRatio;
742
743        //-- factors guiding the split plane heuristics
744        float mLeastRaySplitsFactor;
745        float mBalancedRaysFactor;
746        float mPvsFactor;
747
748        /// if area or accumulated ray lenght should be used for PVS heuristics
749        bool mPvsUseArea;
750
751private:
752       
753        static const float sLeastRaySplitsTable[5];
754        /** Evaluates split plane classification with respect to the plane's
755                contribution for balanced rays.
756        */
757        static const float sBalancedRaysTable[5];
758
759        /// Generates unique ids for PVS criterium
760        static void GenerateUniqueIdsForPvs();
761
762        //-- unique ids for PVS criterium
763        static int sFrontId;
764        static int sBackId;
765        static int sFrontAndBackId;
766};
767
768#endif
Note: See TracBrowser for help on using the repository browser.