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

Revision 332, 17.3 KB checked in by mattausch, 19 years ago (diff)

fixed bug when asigning bsp root
subdivision termination criterium based on rays

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