source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h @ 352

Revision 352, 19.2 KB checked in by mattausch, 19 years ago (diff)
RevLine 
[221]1#ifndef _ViewCellBsp_H__
2#define _ViewCellBsp_H__
3
4#include "Mesh.h"
[224]5#include "Containers.h"
[233]6#include <stack>
[224]7
[221]8class ViewCell;
9class Plane3;
[224]10class BspTree; 
[221]11class BspInterior;
[235]12class Polygon3;
[242]13class AxisAlignedBox3;
[260]14class Ray;
[221]15
[241]16struct BspRayTraversalData
17{
18    BspNode *mNode;
19    Vector3 mExitPoint;
20    float mMaxT;
21   
22    BspRayTraversalData() {}
23
[313]24    BspRayTraversalData(BspNode *n, const Vector3 &extp, const float maxt):
25    mNode(n), mExitPoint(extp), mMaxT(maxt)
[241]26        {}
27};
28
[322]29class BspTreeStatistics
[234]30{
31public:
32  // total number of nodes
33  int nodes;
[235]34  // number of splits
35  int splits;
[234]36  // totals number of rays
37  int rays;
[235]38  // maximal reached depth
39  int maxDepth;
[265]40  // minimal depth
41  int minDepth;
[234]42  // max depth nodes
43  int maxDepthNodes;
44  // max number of rays per node
45  int maxObjectRefs;
[322]46   // accumulated depth (used to compute average)
[265]47  int accumDepth;
48  // number of initial polygons
49  int polys;
[322]50  /// number of view cells different to the view cell representing unbounded space.
51  int viewCells;
[332]52  /// size of the VPS
53  int pvs;
54  /// samples contributing to pvs
55  int contributingSamples;
[350]56   /// sample contributions to pvs
57  int sampleContributions;
58
[234]59  // Constructor
60  BspTreeStatistics()
61  {
[235]62          Reset();
[234]63  }
64
65  int Nodes() const {return nodes;}
[263]66  int Interior() const { return nodes / 2; }
67  int Leaves() const { return (nodes / 2) + 1; }
[271]68  double AvgDepth() const { return accumDepth / (double)Leaves();}; // TODO: computation wrong
[265]69 
[234]70  void Reset()
71  {
72          nodes = 0;
[235]73          splits = 0;
[234]74      maxDepthNodes = 0;
[265]75          maxDepth = 0;
76          minDepth = 99999;
77          polys = 0;
78          accumDepth = 0;
[322]79          viewCells = 0;
[332]80          pvs = 0;
81          contributingSamples = 0;
[350]82          sampleContributions = 0;
[234]83  }
84
85  void
86  Print(ostream &app) const;
87
88  friend ostream &operator<<(ostream &s, const BspTreeStatistics &stat) {
89    stat.Print(s);
90    return s;
91  }
92 
93};
94
[233]95/**
96    BspNode abstract class serving for interior and leaf node implementation
97*/
98class BspNode
99{
100        friend BspTree;
[221]101
[233]102public:
[235]103        BspNode();
[264]104        virtual ~BspNode();
[235]105        BspNode(BspInterior *parent);
106
[233]107        /** Determines whether this node is a leaf or not
108        @return true if leaf
109        */
110        virtual bool IsLeaf() const = 0;
[221]111
[233]112        /** Determines whether this node is a root
113        @return true if root
114        */
115        virtual bool IsRoot() const;
[221]116
[233]117        /** Returns parent node.
118        */
119        BspInterior *GetParent();
[235]120        /** Sets parent node.
121        */
122        void SetParent(BspInterior *parent);
123
[264]124        /** Returns pointer to polygons.
125        */
[260]126        PolygonContainer *GetPolygons();
[286]127        /** Stores polygons in node or discards them according to storePolys.
[263]128        */
[264]129        void ProcessPolygons(PolygonContainer *polys, const bool storePolys);
[263]130
[286]131//int mViewCellIdx;
132protected:
[221]133
[233]134        /// parent of this node
135        BspInterior *mParent;
[260]136
[264]137        /// store polygons created during BSP splits
138        PolygonContainer *mPolygons;
[233]139};
[221]140
[233]141/** BSP interior node implementation
142*/
143class BspInterior : public BspNode
144{
[297]145        friend BspTree;
[233]146public:
147        /** Standard contructor taking split plane as argument.
148        */
[263]149        BspInterior(const Plane3 &plane);
[233]150        /** @return false since it is an interior node
151        */
152        bool IsLeaf() const;
[222]153
[233]154        BspNode *GetBack();
155        BspNode *GetFront();
[221]156
[233]157        Plane3 *GetPlane();
[221]158
[233]159        void ReplaceChildLink(BspNode *oldChild, BspNode *newChild);
160        void SetupChildLinks(BspNode *b, BspNode *f);
[225]161
[318]162        /** Splits polygons with respect to the split plane.
163                @param polys the polygons to be split. the polygons are consumed and
164                           distributed to the containers frontPolys, backPolys, coincident.
[233]165                @param frontPolys returns the polygons in the front of the split plane
166                @param backPolys returns the polygons in the back of the split plane
[289]167                @param coincident returns the polygons coincident to the split plane
168                @param storePolys if the polygons should be stored in the node
[328]169                @returns the number of splits   
[233]170        */
[328]171        int SplitPolygons(PolygonContainer &polys,
172                                          PolygonContainer &frontPolys,
173                                          PolygonContainer &backPolys,
174                                          PolygonContainer &coincident,
[349]175                                          const bool storePolys = false);
[225]176
[286]177        /** Stores polygon in node or discards them according to storePolys.
178                @param polys the polygons
179                @param storePolys if the polygons should be stored or discarded
180        */
[289]181        void ProcessPolygon(Polygon3 **poly, const bool storePolys);
[286]182
[237]183        friend ostream &operator<<(ostream &s, const BspInterior &A)
184        {
185                return s << A.mPlane;
186        }
187
[349]188protected:
[328]189
[233]190        /// Splitting plane corresponding to this node
191        Plane3 mPlane;
192        /// back node
193        BspNode *mBack;
194        /// front node
195        BspNode *mFront;
196};
[225]197
[237]198/** BSP leaf node implementation.
199*/
[233]200class BspLeaf : public BspNode
201{
[260]202        friend BspTree;
203
[233]204public:
[263]205        BspLeaf();
206        BspLeaf(ViewCell *viewCell);
207        BspLeaf(BspInterior *parent);
[264]208        BspLeaf(BspInterior *parent, ViewCell *viewCell);
[225]209
[260]210        /** @return true since it is an interior node
211        */
[233]212        bool IsLeaf() const;
[260]213        /** Returns pointer from view cell.
214        */
[233]215        ViewCell *GetViewCell();
[260]216        /** Sets pointer to view cell.
217        */
218        void SetViewCell(ViewCell *viewCell);
[225]219
[332]220        /** Generates new view cell and adds rays to the PVS.
[350]221                @param sampleContributions the number contributions of the sampels
222                @param contributingSampels the number of contributing rays
[352]223                @param storeRays if ray set should be stored in view cell
[331]224        */
[350]225        void BspLeaf::GenerateViewCell(const RayContainer &rays,
226                                                           int &sampleContributions,
[352]227                                                           int &contributingSamples,
228                                                           const bool storeRays = false);
[331]229
[233]230protected:
[225]231
[313]232        /// if NULL this does not correspond to feasible viewcell
[233]233        ViewCell *mViewCell;
234};
[225]235
[310]236/** Implementation of the view cell BSP tree.
237*/
[233]238class BspTree
239{
240public:
241               
242        /** Additional data which is passed down the BSP tree during traversal.
243        */
244        struct BspTraversalData
245        { 
246                /// the current node
247                BspNode *mNode;
248                /// polygonal data for splitting
[238]249                PolygonContainer *mPolygons;
[233]250                /// current depth
251                int mDepth;
[289]252                /// the view cell associated with this subdivsion
253                ViewCell *mViewCell;
[325]254                /// rays piercing this node
255                RayContainer *mRays;
256
[318]257                BspTraversalData():
258                mNode(NULL),
259                mPolygons(NULL),
260                mDepth(0),
[325]261                mViewCell(NULL),
262                mRays(NULL)
[318]263                {}
[233]264               
[318]265                BspTraversalData(BspNode *node,
266                                                 PolygonContainer *polys,
267                                                 const int depth,
[325]268                                                 ViewCell *viewCell,
[328]269                                                 RayContainer *rays):
[318]270                mNode(node),
271                mPolygons(polys),
272                mDepth(depth),
[325]273                mViewCell(viewCell),
274                mRays(rays)
[318]275                {}
[233]276    };
[329]277       
[233]278        typedef std::stack<BspTraversalData> BspTraversalStack;
279
[235]280        /** Default constructor creating an empty tree.
[297]281                @param viewCell view cell corresponding to unbounded space
[233]282        */
[297]283        BspTree(ViewCell *viewCell);
[233]284
285        ~BspTree();
286
[235]287        const BspTreeStatistics &GetStatistics() const;
288 
[303]289        /** Constructs tree using the given list of view cells.
[289]290            For this type of construction we filter all view cells down the
291                tree. If there is no polygon left, the last split plane
[303]292            decides inside or outside of the viewcell. A pointer to the
293                appropriate view cell is stored within each leaf.
294                Many leafs can point to the same viewcell.
295        */
[332]296        void Construct(const ViewCellContainer &viewCells);
[303]297
298        /** Constructs tree using the given list of objects.
[319]299            @note the objects are not taken as view cells, but the view cells are
300                constructed from the subdivision: Each leaf is taken as one viewcell.
[303]301                @param objects list of objects
302        */
[332]303        void Construct(const ObjectContainer &objects);
[235]304
[331]305        /** Constructs the tree from a given set of rays.
306                @param sampleRays the set of sample rays the construction is based on
[319]307                @param viewCells if not NULL, new view cells are
308                created in the leafs and stored in the conatainer
309        */
[332]310        void Construct(const RayContainer &sampleRays);
[260]311
[319]312        /** Returns list of BSP leaves.
313        */
[240]314        void CollectLeaves(vector<BspLeaf *> &leaves);
315
[242]316        /** Returns box which bounds the whole tree.
317        */
318        AxisAlignedBox3 GetBoundingBox()const;
319
320        /** Returns root of BSP tree.
321        */
322        BspNode *GetRoot() const;
323
[262]324        /** Exports Bsp tree to file.
325        */
326        bool Export(const string filename);
327
[332]328        /** Collects the leaf view cells of the tree
329                @param viewCells returns the view cells
330        */
331        void CollectViewCells(ViewCellContainer &viewCells) const;
[308]332
333        /** A ray is cast possible intersecting the tree.
334                @param the ray that is cast.
335                @returns the number of intersections with objects stored in the tree.
336        */
337        int CastRay(Ray &ray);
338
[341]339        /** Merges view cells based on some criteria
340            E.g., empty view cells can pe purged, view cells which have
341                a very similar PVS can be merged to one larger view cell farther up
342                in the BSP tree.
[338]343                @returns the number of merged view cells
[332]344        */
[342]345        int MergeViewCells();
[338]346
347        /** Set to true if new view cells shall be generated in each leaf.
348        */
[332]349        void SetGenerateViewCells(int generateViewCells);
350
[310]351        /// bsp tree construction types
352        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_RAYS};
353
[332]354        /** Returns statistics.
355        */
356        BspTreeStatistics &GetStat();
357
[233]358protected:
[342]359
[303]360        // --------------------------------------------------------------
361        // For sorting objects
362        // --------------------------------------------------------------
363        struct SortableEntry
364        {
365                enum {POLY_MIN, POLY_MAX};
366   
367                int type;
368                float value;
369                Polygon3 *poly;
370                SortableEntry() {}
371                SortableEntry(const int t, const float v, Polygon3 *poly):
372                type(t), value(v), poly(poly) {}
373               
374                bool operator<(const SortableEntry &b) const
375                {
376                        return value < b.value;
377                } 
[302]378        };
379
[352]380        /** Merges view cells of leafs.
381        */
382        void MergeLeafs(BspLeaf *front, BspLeaf *back) const;
[238]383
384        /** Evaluates tree stats in the BSP tree leafs.
385        */
[235]386        void EvaluateLeafStats(const BspTraversalData &data);
387
388        /** Subdivides node with respect to the traversal data.
389            @param tStack current traversal stack
390                @param tData traversal data also holding node to be subdivided
[239]391                @returns new root of the subtree
[233]392        */
[308]393        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData);
[233]394
[332]395        /** Constructs the tree from the given list of polygons and rays.
396                @param polys stores set of polygons on which subdivision may be based
397                @param rays storesset of rays on which subdivision may be based
[327]398        */
[332]399        void Construct(PolygonContainer *polys, RayContainer *rays);
[327]400
[319]401        /** Selects the best possible splitting plane.
[302]402                @param leaf the leaf to be split
[263]403                @param polys the polygon list on which the split decition is based
[325]404                @param rays ray container on which selection may be based
[335]405                @note the polygons can be reordered in the process
406                @returns the split plane
[233]407        */
[318]408        Plane3 SelectPlane(BspLeaf *leaf,
[325]409                                           PolygonContainer &polys,
410                                           const RayContainer &ray);
[303]411
[327]412        /** Evaluates the contribution of the candidate split plane.
[335]413               
414                @param canditatePlane the candidate split plane
415                @param polys the polygons the split can be based on
416                @param rays the rays the split can be based on
[327]417                @returns the cost of the candidate split plane
418        */
[335]419        float SplitPlaneCost(const Plane3 &candidatePlane,
420                                                 const PolygonContainer &polys,                                                 
421                                                 const RayContainer &rays) const;
[327]422
[335]423        /** Strategies where the effect of the split plane is tested
424            on all input rays.
425                @returns the cost of the candidate split plane
426        */
427        float SplitPlaneCost(const Plane3 &candidatePlane,
428                                                 const PolygonContainer &polys) const;
429
430        /** Strategies where the effect of the split plane is tested
431            on all input polygons.
432                @returns the cost of the candidate split plane
433        */
434        float SplitPlaneCost(const Plane3 &candidatePlane,
435                                                 const RayContainer &polys) const;
436
[303]437        /** Filters next view cell down the tree and inserts it into the appropriate leaves
438                (i.e., possibly more than one leaf).
439        */
[289]440        void InsertViewCell(ViewCell *viewCell);
[303]441        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
442                then further subdivided.
443        */
[332]444        void InsertPolygons(PolygonContainer *polys);
[303]445
446        /** Subdivide leaf.
447                @param leaf the leaf to be subdivided
[329]448               
449                @param polys the polygons to be split
450                @param frontPolys returns the polygons in front of the split plane
451                @param backPolys returns the polygons in the back of the split plane
452               
453                @param rays the polygons to be filtered
454                @param frontRays returns the polygons in front of the split plane
455                @param backRays returns the polygons in the back of the split plane
456
[303]457                @returns the root of the subdivision
458        */
459        BspInterior *SubdivideNode(BspLeaf *leaf,
[329]460                                                           PolygonContainer &polys,
461                                                           PolygonContainer &frontPolys,
462                                                           PolygonContainer &backPolys,
463                                                           PolygonContainer &coincident,
464                                                           RayContainer &rays,
[349]465                                                           RayContainer &frontRays,
466                                                            RayContainer &backRays);
[221]467
[233]468        /** Filters polygons down the tree.
469                @param node the current BSP node
470                @param polys the polygons to be filtered
471                @param frontPolys returns the polygons in front of the split plane
472                @param backPolys returns the polygons in the back of the split plane
473        */
[319]474        void FilterPolygons(BspInterior *node,
475                                                PolygonContainer *polys,
476                                                PolygonContainer *frontPolys,
477                                                PolygonContainer *backPolys);
[224]478
[318]479        /** Selects the split plane in order to construct a tree with
480                certain characteristics (e.g., balanced tree, least splits,
481                2.5d aligned)
[238]482                @param polygons container of polygons
[325]483                @param rays bundle of rays on which the split can be based
[238]484                @param maxTests the maximal number of candidate tests
485        */
[318]486        Plane3 SelectPlaneHeuristics(PolygonContainer &polys,
[325]487                                                                 const RayContainer &rays,
488                                                                 const int maxTests);
[238]489
[318]490        /** Extracts the meshes of the objects and adds them to polygons.
[260]491                Adds object aabb to the aabb of the tree.
[241]492                @param maxPolys the maximal number of objects to be stored as polygons
[265]493                @returns the number of polygons
[233]494        */
[318]495        int AddToPolygonSoup(const ObjectContainer &objects,
496                                                 PolygonContainer &polys,
497                                                 int maxObjects = 0);
498
499        /** Extracts the meshes of the view cells and and adds them to polygons.
[260]500                Adds view cell aabb to the aabb of the tree.
501                @param maxPolys the maximal number of objects to be stored as polygons
[265]502                @returns the number of polygons
[260]503        */
[318]504        int AddToPolygonSoup(const ViewCellContainer &viewCells,
505                                                 PolygonContainer &polys,
506                                                 int maxObjects = 0);
[224]507
[265]508        /** Extract polygons of this mesh and add to polygon container.
[286]509                @param mesh the mesh that drives the polygon construction
510                @param parent the parent intersectable this polygon is constructed from
[265]511                @returns number of polygons
[235]512        */
[312]513        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
[233]514
[305]515        /** returns next candidate index and reorders polygons so no candidate is chosen two times
[304]516                @param the current candidate index
[295]517                @param max the range of candidates
518        */
[305]519        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
[295]520
[297]521        /** Helper function which extracts a view cell on the front and the back
522                of the split plane.
523                @param backViewCell returns view cell on the back of the split plane
524                @param frontViewCell returns a view cell on the front of the split plane
525                @param coincident container of polygons coincident to the split plane
526                @param splitPlane the split plane which decides about back and front
527                @param extractBack if a back view cell is extracted
[313]528                @param extractFront if a front view cell is extracted
[297]529        */
530        void ExtractViewCells(ViewCell **backViewCell,
531                                                  ViewCell **frontViewCell,
532                                                  const PolygonContainer &coincident,
533                                                  const Plane3 splitPlane,
[313]534                                                  const bool extractBack,
535                                                  const bool extractFront) const;
[297]536       
[302]537        /** Computes best cost ratio for the suface area heuristics for axis aligned
538                splits. This heuristics minimizes the cost for ray traversal.
539                @param polys the polygons guiding the ratio computation
540                @param box the bounding box of the leaf
541                @param axis the current split axis
542                @param position returns the split position
543                @param objectsBack the number of objects in the back of the split plane
544                @param objectsFront the number of objects in the front of the split plane
545        */
546        float BestCostRatio(const PolygonContainer &polys,
547                                                const AxisAlignedBox3 &box,
548                                                const int axis,
549                                                float &position,
550                                                int &objectsBack,
551                                                int &objectsFront) const;
552       
553        /** Sorts split candidates for surface area heuristics for axis aligned splits.
554                @param polys the input for choosing split candidates
555                @param axis the current split axis
556                @param splitCandidates returns sorted list of split candidates
557        */
558        void SortSplitCandidates(const PolygonContainer &polys,
559                                                         const int axis,
560                                                         vector<SortableEntry> &splitCandidates) const;
561
[349]562        /** Selects an axis aligned split plane.
563                Returns true if split is valied
564        */
565        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
566
[350]567        /** Bounds ray and returns minT and maxT.
568                @returns true if ray hits BSP tree bounding box
569        */
570        bool BoundRay(const Ray &ray, float &minT, float &maxT) const;
571
572        /** Subdivides the rays into front and back rays according to the split plane.
573               
574                @param plane the split plane
575                @param rays contains the rays to be split. The rays are
576                           distributed into front and back rays.
577                @param frontRays returns rays on the front side of the plane
578                @param backRays returns rays on the back side of the plane
579               
580                @returns the number of splits
581        */
582        int SplitRays(const Plane3 &plane,
583                                  RayContainer &rays,
584                              RayContainer &frontRays,
585                                  RayContainer &backRays);
586
[233]587        /// Pointer to the root of the tree
588        BspNode *mRoot;
[237]589
[233]590        /// Pointer to the root cell of the viewspace
591        // ViewCell *mRootCell;
[237]592               
[235]593        BspTreeStatistics mStat;
[234]594
[237]595        /// Strategies for choosing next split plane.
[297]596        enum {NO_STRATEGY = 0,
[321]597                  RANDOM_POLYGON = 1,
[297]598                  AXIS_ALIGNED = 2,
599                  LEAST_SPLITS = 4,
600                  BALANCED_POLYS = 8,
601                  BALANCED_VIEW_CELLS = 16,
602                  LARGEST_POLY_AREA = 32,
[319]603                  VERTICAL_AXIS = 64,
[332]604                  BLOCKED_RAYS = 128,
605                  LEAST_RAY_SPLITS = 256,
606                  BALANCED_RAYS = 512
[297]607                };
[236]608
[241]609        /// box around the whole view domain
610        AxisAlignedBox3 mBox;
611
[297]612        /// view cell corresponding to unbounded space
[313]613        ViewCell *mRootCell;
[350]614
[344]615        /// should view cells be stored or generated in the leaves?
[332]616        bool mGenerateViewCells;
617
[350]618        /// if rays should be stored that are piercing this view cell
619        bool mStorePiercingRays;
620
[235]621public:
622        /// Parses the environment and stores the global BSP tree parameters
623        static void ParseEnvironment();
624
[332]625        /// maximal number of polygons before subdivision termination
[235]626        static int sTermMaxPolygons;
[332]627        /// maximal number of rays before subdivision termination
628        static int sTermMaxRays;
[235]629        /// maximal possible depth
630        static int sTermMaxDepth;
[238]631        /// strategy to get the best split plane
[236]632        static int sSplitPlaneStrategy;
[238]633        /// number of candidates evaluated for the next split plane
634        static int sMaxCandidates;
[263]635        /// BSP tree construction method
636        static int sConstructionMethod;
[297]637        /// maximal number of polygons where we do axis aligned splits
638        static int sTermMaxPolysForAxisAligned;
[263]639
[332]640        /// axis aligned split criteria
[303]641        static float sCt_div_ci;
[302]642        static float sSplitBorder;
643        static float sMaxCostRatio;
644
[332]645        // factors guiding the split plane heuristics
[296]646        static float sLeastSplitsFactor;
[297]647        static float sBalancedPolysFactor;
648        static float sBalancedViewCellsFactor;
649        static float sVerticalSplitsFactor;
[306]650        static float sLargestPolyAreaFactor;
[319]651        static float sBlockedRaysFactor;
[332]652        static float sLeastRaySplitsFactor;
653        static float sBalancedRaysFactor;
654
[321]655        /// if polygons should be stored in the tree
656        static bool sStoreSplitPolys;
[319]657
[263]658private:
659        /** Evaluates split plane classification with respect to the plane's
660                contribution for a balanced tree.
661        */
[349]662        static float sLeastPolySplitsTable[4];
[263]663        /** Evaluates split plane classification with respect to the plane's
664                contribution for a minimum number splits in the tree.
665        */
[349]666        static float sBalancedPolysTable[4];
667        /** Evaluates split plane classification with respect to the plane's
668                contribution for a minimum number of ray splits.
669        */
670        static float sLeastRaySplitsTable[5];
671        /** Evaluates split plane classification with respect to the plane's
672                contribution for balanced rays.
673        */
674        static float sBalancedRaysTable[5];
675
[233]676};
677
[221]678//}; // GtpVisibilityPreprocessor
679
680#endif
Note: See TracBrowser for help on using the repository browser.