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

Revision 302, 15.8 KB checked in by mattausch, 19 years ago (diff)

added surface area heuristic for bsp

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;
10//class Mesh;
[224]11class BspTree; 
[221]12class BspInterior;
[235]13class Polygon3;
[242]14class AxisAlignedBox3;
[260]15class Ray;
[221]16
[242]17//namespace GtpVisibilityPreprocessor {
18
[238]19/** Container storing a soup of polygons used during BSP tree construction
[235]20*/
[260]21typedef vector<Polygon3 *> PolygonContainer;
22typedef vector<Ray *> RayContainer;
[224]23
[241]24struct BspRayTraversalData
25{
26    BspNode *mNode;
27    Vector3 mExitPoint;
28    float mMaxT;
29   
30    BspRayTraversalData() {}
31
32    BspRayTraversalData(BspNode *n, const Vector3 &p, const float maxt):
33    mNode(n), mExitPoint(p), mMaxT(maxt)
34        {}
35};
36
[234]37class BspTreeStatistics // TODO: should have common superclass with KdTreeStatistics
38{
39public:
40  // total number of nodes
41  int nodes;
[235]42  // number of splits
43  int splits;
[234]44  // totals number of rays
45  int rays;
[235]46  // maximal reached depth
47  int maxDepth;
[265]48  // minimal depth
49  int minDepth;
[234]50  // total number of query domains
51  int queryDomains;
52  // total number of ray references
53  int rayRefs;
54  // refs in non empty leafs
55  int rayRefsNonZeroQuery;
56  // total number of query references
57  int objectRefs;
58  // nodes with zero queries
59  int zeroQueryNodes;
60  // max depth nodes
61  int maxDepthNodes;
62  // max number of rays per node
63  int maxObjectRefs;
64  // number of dynamically added ray refs
65  int addedRayRefs;
66  // number of dynamically removed ray refs
67  int removedRayRefs;
[265]68  // accumulated depth (used to compute average)
69  int accumDepth;
70  // number of initial polygons
71  int polys;
72  /// number of view cells in leaf
73  int viewCellLeaves;
74
[234]75  // Constructor
76  BspTreeStatistics()
77  {
[235]78          Reset();
[234]79  }
80
81  int Nodes() const {return nodes;}
[263]82  int Interior() const { return nodes / 2; }
83  int Leaves() const { return (nodes / 2) + 1; }
[271]84  double AvgDepth() const { return accumDepth / (double)Leaves();}; // TODO: computation wrong
[265]85 
[234]86  void Reset()
87  {
88          nodes = 0;
[235]89          splits = 0;
[234]90          rays = queryDomains = 0;
91          rayRefs = rayRefsNonZeroQuery = objectRefs = 0;
92          zeroQueryNodes = 0;
93      maxDepthNodes = 0;
[265]94
[234]95          maxObjectRefs = 0;
96          addedRayRefs = removedRayRefs = 0;
[265]97          maxDepth = 0;
98          minDepth = 99999;
99          polys = 0;
100          accumDepth = 0;
101          viewCellLeaves = 0;
[234]102  }
103
104  void
105  Print(ostream &app) const;
106
107  friend ostream &operator<<(ostream &s, const BspTreeStatistics &stat) {
108    stat.Print(s);
109    return s;
110  }
111 
112};
113
[233]114/**
115    BspNode abstract class serving for interior and leaf node implementation
116*/
117class BspNode
118{
119        friend BspTree;
[221]120
[233]121public:
[235]122        BspNode();
[264]123        virtual ~BspNode();
[235]124        BspNode(BspInterior *parent);
125
[233]126        /** Determines whether this node is a leaf or not
127        @return true if leaf
128        */
129        virtual bool IsLeaf() const = 0;
[221]130
[233]131        /** Determines whether this node is a root
132        @return true if root
133        */
134        virtual bool IsRoot() const;
[221]135
[233]136        /** Returns parent node.
137        */
138        BspInterior *GetParent();
[235]139        /** Sets parent node.
140        */
141        void SetParent(BspInterior *parent);
142
[264]143        /** Returns pointer to polygons.
144        */
[260]145        PolygonContainer *GetPolygons();
[286]146        /** Stores polygons in node or discards them according to storePolys.
[263]147        */
[264]148        void ProcessPolygons(PolygonContainer *polys, const bool storePolys);
[263]149
[286]150//int mViewCellIdx;
151protected:
[221]152
[233]153        /// parent of this node
154        BspInterior *mParent;
[260]155
[264]156        /// store polygons created during BSP splits
157        PolygonContainer *mPolygons;
[233]158};
[221]159
[233]160/** BSP interior node implementation
161*/
162class BspInterior : public BspNode
163{
[297]164        friend BspTree;
[233]165public:
166        /** Standard contructor taking split plane as argument.
167        */
[263]168        BspInterior(const Plane3 &plane);
[233]169        /** @return false since it is an interior node
170        */
171        bool IsLeaf() const;
[222]172
[233]173        BspNode *GetBack();
174        BspNode *GetFront();
[221]175
[233]176        Plane3 *GetPlane();
[221]177
[233]178        void ReplaceChildLink(BspNode *oldChild, BspNode *newChild);
179        void SetupChildLinks(BspNode *b, BspNode *f);
[225]180
[233]181        /** Splits polygons.
182                @param polys the polygons to be split
183                @param frontPolys returns the polygons in the front of the split plane
184                @param backPolys returns the polygons in the back of the split plane
[289]185                @param coincident returns the polygons coincident to the split plane
186                @param splits returns the splits number of splits       
187                @param storePolys if the polygons should be stored in the node
[233]188        */
[289]189        void SplitPolygons(PolygonContainer *polys,
190                                           PolygonContainer *frontPolys,
191                                           PolygonContainer *backPolys,
192                                           PolygonContainer *coincident,
193                                           int &splits,
194                                           bool storePolys = false);
[225]195
[286]196        /** Stores polygon in node or discards them according to storePolys.
197                @param polys the polygons
198                @param storePolys if the polygons should be stored or discarded
199        */
[289]200        void ProcessPolygon(Polygon3 **poly, const bool storePolys);
[286]201
[237]202        friend ostream &operator<<(ostream &s, const BspInterior &A)
203        {
204                return s << A.mPlane;
205        }
206
[286]207protected:     
[233]208       
209        /// Splitting plane corresponding to this node
210        Plane3 mPlane;
211        /// back node
212        BspNode *mBack;
213        /// front node
214        BspNode *mFront;
215};
[225]216
[237]217/** BSP leaf node implementation.
218*/
[233]219class BspLeaf : public BspNode
220{
[260]221        friend BspTree;
222
[233]223public:
[263]224        BspLeaf();
225        BspLeaf(ViewCell *viewCell);
226        BspLeaf(BspInterior *parent);
[264]227        BspLeaf(BspInterior *parent, ViewCell *viewCell);
[225]228
[260]229        /** @return true since it is an interior node
230        */
[233]231        bool IsLeaf() const;
[260]232        /** Returns pointer from view cell.
233        */
[233]234        ViewCell *GetViewCell();
[260]235        /** Sets pointer to view cell.
236        */
237        void SetViewCell(ViewCell *viewCell);
[225]238
[233]239protected:
[225]240
[233]241        /// polygonal representation of this viewcell
242        /// if NULL this note does not correspond to feasible viewcell
243        ViewCell *mViewCell;
244};
[225]245
[233]246/** Implementation of the ViewCell BSP tree. */
247class BspTree
248{
249public:
250               
251        /** Additional data which is passed down the BSP tree during traversal.
252        */
253        struct BspTraversalData
254        { 
255                /// the current node
256                BspNode *mNode;
257                /// polygonal data for splitting
[238]258                PolygonContainer *mPolygons;
[233]259                /// current depth
260                int mDepth;
[289]261                /// the view cell associated with this subdivsion
262                ViewCell *mViewCell;
[264]263                /// if the node is an inside or outside node with respect to the parent plane
[286]264                //bool mIsInside;
[233]265                BspTraversalData() {}
266               
[289]267                BspTraversalData(BspNode *node, PolygonContainer *polys, const int depth, ViewCell *viewCell):
268                mNode(node), mPolygons(polys), mDepth(depth), mViewCell(viewCell) {}
[233]269    };
270
271        typedef std::stack<BspTraversalData> BspTraversalStack;
272
[235]273        /// BSP tree construction type
[263]274        enum {VIEW_CELLS, SCENE_GEOMETRY, RAYS};
[235]275
276        /** Default constructor creating an empty tree.
[297]277                @param viewCell view cell corresponding to unbounded space
[233]278        */
[297]279        BspTree(ViewCell *viewCell);
[233]280
281        ~BspTree();
282
[235]283        const BspTreeStatistics &GetStatistics() const;
284 
[260]285        /** Constructs tree using the given list of view cells.
[289]286            For this type of construction we filter all view cells down the
287                tree. If there is no polygon left, the last split plane
288            decides inside or outside of the viewcell. A pointer to the
289                appropriate view cell is stored within each leaf.
[235]290                Many leafs can point to the same viewcell.
291        */
292        void Construct(const ViewCellContainer &viewCells);
293
[260]294        /** Constructs tree using the given list of objects.
295            Note that the objects are not taken as view cells, but the view cells are
296                constructed from the subdivision: Each leaf is taken as one viewcell;
297
[235]298                @param objects list of objects
[260]299                @returns list of view cells.
[235]300        */
[261]301        void Construct(const ObjectContainer &objects, ViewCellContainer *viewCells);
[235]302
[260]303        /** Constructs tree using the given number of rays
304            @param objects list of objects
305                @returns list of view cells.
306        */
[261]307        void Construct(const RayContainer &rays, ViewCellContainer *viewCells);
[260]308
[242]309        int CollectLeafPvs();
[235]310
[240]311        void CollectLeaves(vector<BspLeaf *> &leaves);
312
[242]313        /** Returns box which bounds the whole tree.
314        */
315        AxisAlignedBox3 GetBoundingBox()const;
316
317        /** Returns root of BSP tree.
318        */
319        BspNode *GetRoot() const;
320
[260]321        /** If the view cell polygons are stored in the nodes.
322        */
323        bool StorePolys() const;
324
[262]325        /** Exports Bsp tree to file.
326        */
327        bool Export(const string filename);
328
[289]329        //static bool displayDebug;
[233]330protected:
[238]331       
[302]332        // --------------------------------------------------------------
333        // For sorting objects
334        // --------------------------------------------------------------
335        struct SortableEntry
336        {
337                enum {POLY_MIN, POLY_MAX};
338   
339                int type;
340                float value;
341                Polygon3 *poly;
342                SortableEntry() {}
343                SortableEntry(const int t, const float v, Polygon3 *poly):
344                type(t), value(v), poly(poly) {}
345               
346                bool operator<(const SortableEntry &b) const
347                {
348                        return value < b.value;
349                } 
350        };
351
[260]352        /** Constructs the tree from the given list of polygons.
[265]353                @param viewCells if not NULL, new view cells are
354                created in the leafs and stored in the conatainer
[260]355        */
[265]356        void Construct(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
[260]357
[238]358        /** Evaluates the contribution of the candidate split plane.
[294]359                @returns the cost of the candidate split plane
[238]360        */
[295]361        float EvalSplitPlane(const PolygonContainer &polys, const Plane3 &candidatePlane) const;
[238]362
363        /** Evaluates tree stats in the BSP tree leafs.
364        */
[235]365        void EvaluateLeafStats(const BspTraversalData &data);
366
367        /** Subdivides node with respect to the traversal data.
368            @param tStack current traversal stack
369                @param tData traversal data also holding node to be subdivided
[286]370                @param viewCellContainer if not null, a new viewcell is created and stored in the container
[239]371                @returns new root of the subtree
[233]372        */
[286]373        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData, ViewCellContainer *viewCells = NULL);
[233]374
[235]375        /** Selects a splitting plane.
[302]376                @param leaf the leaf to be split
[263]377                @param polys the polygon list on which the split decition is based
[233]378        */
[302]379        Plane3 SelectPlane(BspLeaf *leaf, const PolygonContainer &polys) const;
[224]380
[289]381        /** Filters next view cell down the tree and inserts it into the appropriate leaves
[233]382                (i.e., possibly more than one leaf).
383        */
[289]384        void InsertViewCell(ViewCell *viewCell);
385        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
386                then further subdivided.
387                @param viewCellContainer if not null, a new viewcell is created and stored in the container
388        */
389        void InsertPolygons(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
390
[235]391        /** Subdivide leaf.
[233]392                @param leaf the leaf to be subdivided
393                @param polys the input polygons
[289]394                @param frontPolys returns the polygons in the front of the split plane
395                @param backPolys returns the polygons in the back of the split plane
396                @param coincident returns the polygons coincident to the split plane
[264]397                @returns the root of the subdivision
[233]398        */
[264]399        BspInterior *SubdivideNode(BspLeaf *leaf,
400                                                           PolygonContainer *polys,
401                                                           PolygonContainer *frontPolys,
[289]402                                                           PolygonContainer *backPolys,
403                                                           PolygonContainer *coincident);
[221]404
[233]405        /** Filters polygons down the tree.
406                @param node the current BSP node
407                @param polys the polygons to be filtered
408                @param frontPolys returns the polygons in front of the split plane
409                @param backPolys returns the polygons in the back of the split plane
410        */
[238]411        void FilterPolygons(BspInterior *node, PolygonContainer *polys,
412                                                PolygonContainer *frontPolys, PolygonContainer *backPolys);
[224]413
[238]414        /** Selects the split plane in order to get a balanced tree.
415                @param polygons container of polygons
416                @param maxTests the maximal number of candidate tests
417        */
[295]418        Plane3 SelectPlaneHeuristics(const PolygonContainer &polys, const int maxTests) const;
[238]419
[260]420        /** Extracts the meshes of the objects and copies them into the mesh.
421                Adds object aabb to the aabb of the tree.
[241]422                @param maxPolys the maximal number of objects to be stored as polygons
[265]423                @returns the number of polygons
[233]424        */
[267]425        int Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects = 0);
[260]426        /** Extracts the meshes of the view cells and copies them into the mesh.
427                Adds view cell aabb to the aabb of the tree.
428                @param maxPolys the maximal number of objects to be stored as polygons
[265]429                @returns the number of polygons
[260]430        */
[267]431        int Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects = 0);
[224]432
[265]433        /** Extract polygons of this mesh and add to polygon container.
[286]434                @param mesh the mesh that drives the polygon construction
435                @param parent the parent intersectable this polygon is constructed from
[265]436                @returns number of polygons
[235]437        */
[286]438        int AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys, Intersectable *parent = NULL);
[233]439
[241]440        /** A ray is cast possible intersecting the tree.
441                @param the ray that is cast.
442                @returns the number of intersections with objects stored in the tree.
443        */
444        int CastRay(Ray &ray);
445
[295]446        /** returns next candidate index
447                @param max the range of candidates
448        */
449        inline int GetNextCandidateIdx(const int max) const;
450
[297]451        /** Helper function which extracts a view cell on the front and the back
452                of the split plane.
453                @param backViewCell returns view cell on the back of the split plane
454                @param frontViewCell returns a view cell on the front of the split plane
455                @param coincident container of polygons coincident to the split plane
456                @param splitPlane the split plane which decides about back and front
457                @param extractFront if a front view cell is extracted
458                @param extractBack if a back view cell is extracted
459        */
460        void ExtractViewCells(ViewCell **backViewCell,
461                                                  ViewCell **frontViewCell,
462                                                  const PolygonContainer &coincident,
463                                                  const Plane3 splitPlane,
464                                                  const bool extractFront,
465                                                  const bool extractBack) const;
466       
[302]467        /** Computes best cost ratio for the suface area heuristics for axis aligned
468                splits. This heuristics minimizes the cost for ray traversal.
469                @param polys the polygons guiding the ratio computation
470                @param box the bounding box of the leaf
471                @param axis the current split axis
472                @param position returns the split position
473                @param objectsBack the number of objects in the back of the split plane
474                @param objectsFront the number of objects in the front of the split plane
475        */
476        float BestCostRatio(const PolygonContainer &polys,
477                                                const AxisAlignedBox3 &box,
478                                                const int axis,
479                                                float &position,
480                                                int &objectsBack,
481                                                int &objectsFront) const;
482       
483        /** Sorts split candidates for surface area heuristics for axis aligned splits.
484                @param polys the input for choosing split candidates
485                @param axis the current split axis
486                @param splitCandidates returns sorted list of split candidates
487        */
488        void SortSplitCandidates(const PolygonContainer &polys,
489                                                         const int axis,
490                                                         vector<SortableEntry> &splitCandidates) const;
491
[233]492        /// Pointer to the root of the tree
493        BspNode *mRoot;
[237]494
[233]495        /// Pointer to the root cell of the viewspace
496        // ViewCell *mRootCell;
[237]497               
[235]498        BspTreeStatistics mStat;
[234]499
[237]500        /// Strategies for choosing next split plane.
[297]501        enum {NO_STRATEGY = 0,
502                  NEXT_POLYGON = 1,
503                  AXIS_ALIGNED = 2,
504                  LEAST_SPLITS = 4,
505                  BALANCED_POLYS = 8,
506                  BALANCED_VIEW_CELLS = 16,
507                  LARGEST_POLY_AREA = 32,
508                  VERTICAL_AXIS = 64
509                };
[236]510
[241]511        /// box around the whole view domain
512        AxisAlignedBox3 mBox;
513
[260]514        /// if polygons should be stored in the tree
515        bool mStorePolys;
516
[297]517        /// view cell corresponding to unbounded space
518        ViewCell *mViewCell;
[295]519
[235]520public:
521        /// Parses the environment and stores the global BSP tree parameters
522        static void ParseEnvironment();
523
524        /// maximal number of polygons where tree construction is terminated
525        static int sTermMaxPolygons;
526        /// maximal possible depth
527        static int sTermMaxDepth;
[238]528        /// strategy to get the best split plane
[236]529        static int sSplitPlaneStrategy;
[238]530        /// number of candidates evaluated for the next split plane
531        static int sMaxCandidates;
[263]532        /// BSP tree construction method
533        static int sConstructionMethod;
[297]534        /// maximal number of polygons where we do axis aligned splits
535        static int sTermMaxPolysForAxisAligned;
[263]536
[302]537        static float sCt_div_ci;
538        static float sSplitBorder;
539        static float sMaxCostRatio;
540
[297]541        // factors to guid the split plane heuristics
[296]542        static float sLeastSplitsFactor;
[297]543        static float sBalancedPolysFactor;
544        static float sBalancedViewCellsFactor;
545        static float sVerticalSplitsFactor;
546       
[263]547private:
548        /** Evaluates split plane classification with respect to the plane's
549                contribution for a balanced tree.
550        */
[294]551        static float sLeastSplitsTable[4];
[263]552        /** Evaluates split plane classification with respect to the plane's
553                contribution for a minimum number splits in the tree.
554        */
[297]555        static float sBalancedPolysTable[4];
[233]556};
557
[221]558//}; // GtpVisibilityPreprocessor
559
560#endif
Note: See TracBrowser for help on using the repository browser.