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

Line 
1#ifndef _ViewCellBsp_H__
2#define _ViewCellBsp_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include <stack>
7
8class ViewCell;
9class Plane3;
10//class Mesh;
11class BspTree; 
12class BspInterior;
13class Polygon3;
14class AxisAlignedBox3;
15class Ray;
16
17//namespace GtpVisibilityPreprocessor {
18
19/** Container storing a soup of polygons used during BSP tree construction
20*/
21typedef vector<Polygon3 *> PolygonContainer;
22typedef vector<Ray *> RayContainer;
23
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
37class BspTreeStatistics // TODO: should have common superclass with KdTreeStatistics
38{
39public:
40  // total number of nodes
41  int nodes;
42  // number of splits
43  int splits;
44  // totals number of rays
45  int rays;
46  // maximal reached depth
47  int maxDepth;
48  // minimal depth
49  int minDepth;
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;
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
75  // Constructor
76  BspTreeStatistics()
77  {
78          Reset();
79  }
80
81  int Nodes() const {return nodes;}
82  int Interior() const { return nodes / 2; }
83  int Leaves() const { return (nodes / 2) + 1; }
84  double AvgDepth() const { return accumDepth / (double)Leaves();}; // TODO: computation wrong
85 
86  void Reset()
87  {
88          nodes = 0;
89          splits = 0;
90          rays = queryDomains = 0;
91          rayRefs = rayRefsNonZeroQuery = objectRefs = 0;
92          zeroQueryNodes = 0;
93      maxDepthNodes = 0;
94
95          maxObjectRefs = 0;
96          addedRayRefs = removedRayRefs = 0;
97          maxDepth = 0;
98          minDepth = 99999;
99          polys = 0;
100          accumDepth = 0;
101          viewCellLeaves = 0;
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
114/**
115    BspNode abstract class serving for interior and leaf node implementation
116*/
117class BspNode
118{
119        friend BspTree;
120
121public:
122        BspNode();
123        virtual ~BspNode();
124        BspNode(BspInterior *parent);
125
126        /** Determines whether this node is a leaf or not
127        @return true if leaf
128        */
129        virtual bool IsLeaf() const = 0;
130
131        /** Determines whether this node is a root
132        @return true if root
133        */
134        virtual bool IsRoot() const;
135
136        /** Returns parent node.
137        */
138        BspInterior *GetParent();
139        /** Sets parent node.
140        */
141        void SetParent(BspInterior *parent);
142
143        /** Returns pointer to polygons.
144        */
145        PolygonContainer *GetPolygons();
146        /** Stores polygons in node or discards them according to storePolys.
147        */
148        void ProcessPolygons(PolygonContainer *polys, const bool storePolys);
149
150//int mViewCellIdx;
151protected:
152
153        /// parent of this node
154        BspInterior *mParent;
155
156        /// store polygons created during BSP splits
157        PolygonContainer *mPolygons;
158};
159
160/** BSP interior node implementation
161*/
162class BspInterior : public BspNode
163{
164        friend BspTree;
165public:
166        /** Standard contructor taking split plane as argument.
167        */
168        BspInterior(const Plane3 &plane);
169        /** @return false since it is an interior node
170        */
171        bool IsLeaf() const;
172
173        BspNode *GetBack();
174        BspNode *GetFront();
175
176        Plane3 *GetPlane();
177
178        void ReplaceChildLink(BspNode *oldChild, BspNode *newChild);
179        void SetupChildLinks(BspNode *b, BspNode *f);
180
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
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
188        */
189        void SplitPolygons(PolygonContainer *polys,
190                                           PolygonContainer *frontPolys,
191                                           PolygonContainer *backPolys,
192                                           PolygonContainer *coincident,
193                                           int &splits,
194                                           bool storePolys = false);
195
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        */
200        void ProcessPolygon(Polygon3 **poly, const bool storePolys);
201
202        friend ostream &operator<<(ostream &s, const BspInterior &A)
203        {
204                return s << A.mPlane;
205        }
206
207protected:     
208       
209        /// Splitting plane corresponding to this node
210        Plane3 mPlane;
211        /// back node
212        BspNode *mBack;
213        /// front node
214        BspNode *mFront;
215};
216
217/** BSP leaf node implementation.
218*/
219class BspLeaf : public BspNode
220{
221        friend BspTree;
222
223public:
224        BspLeaf();
225        BspLeaf(ViewCell *viewCell);
226        BspLeaf(BspInterior *parent);
227        BspLeaf(BspInterior *parent, ViewCell *viewCell);
228
229        /** @return true since it is an interior node
230        */
231        bool IsLeaf() const;
232        /** Returns pointer from view cell.
233        */
234        ViewCell *GetViewCell();
235        /** Sets pointer to view cell.
236        */
237        void SetViewCell(ViewCell *viewCell);
238
239protected:
240
241        /// polygonal representation of this viewcell
242        /// if NULL this note does not correspond to feasible viewcell
243        ViewCell *mViewCell;
244};
245
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
258                PolygonContainer *mPolygons;
259                /// current depth
260                int mDepth;
261                /// the view cell associated with this subdivsion
262                ViewCell *mViewCell;
263                /// if the node is an inside or outside node with respect to the parent plane
264                //bool mIsInside;
265                BspTraversalData() {}
266               
267                BspTraversalData(BspNode *node, PolygonContainer *polys, const int depth, ViewCell *viewCell):
268                mNode(node), mPolygons(polys), mDepth(depth), mViewCell(viewCell) {}
269    };
270
271        typedef std::stack<BspTraversalData> BspTraversalStack;
272
273        /// BSP tree construction type
274        enum {VIEW_CELLS, SCENE_GEOMETRY, RAYS};
275
276        /** Default constructor creating an empty tree.
277                @param viewCell view cell corresponding to unbounded space
278        */
279        BspTree(ViewCell *viewCell);
280
281        ~BspTree();
282
283        const BspTreeStatistics &GetStatistics() const;
284 
285        /** Constructs tree using the given list of view cells.
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.
290                Many leafs can point to the same viewcell.
291        */
292        void Construct(const ViewCellContainer &viewCells);
293
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
298                @param objects list of objects
299                @returns list of view cells.
300        */
301        void Construct(const ObjectContainer &objects, ViewCellContainer *viewCells);
302
303        /** Constructs tree using the given number of rays
304            @param objects list of objects
305                @returns list of view cells.
306        */
307        void Construct(const RayContainer &rays, ViewCellContainer *viewCells);
308
309        int CollectLeafPvs();
310
311        void CollectLeaves(vector<BspLeaf *> &leaves);
312
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
321        /** If the view cell polygons are stored in the nodes.
322        */
323        bool StorePolys() const;
324
325        /** Exports Bsp tree to file.
326        */
327        bool Export(const string filename);
328
329        //static bool displayDebug;
330protected:
331       
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
352        /** Constructs the tree from the given list of polygons.
353                @param viewCells if not NULL, new view cells are
354                created in the leafs and stored in the conatainer
355        */
356        void Construct(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
357
358        /** Evaluates the contribution of the candidate split plane.
359                @returns the cost of the candidate split plane
360        */
361        float EvalSplitPlane(const PolygonContainer &polys, const Plane3 &candidatePlane) const;
362
363        /** Evaluates tree stats in the BSP tree leafs.
364        */
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
370                @param viewCellContainer if not null, a new viewcell is created and stored in the container
371                @returns new root of the subtree
372        */
373        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData, ViewCellContainer *viewCells = NULL);
374
375        /** Selects a splitting plane.
376                @param leaf the leaf to be split
377                @param polys the polygon list on which the split decition is based
378        */
379        Plane3 SelectPlane(BspLeaf *leaf, const PolygonContainer &polys) const;
380
381        /** Filters next view cell down the tree and inserts it into the appropriate leaves
382                (i.e., possibly more than one leaf).
383        */
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
391        /** Subdivide leaf.
392                @param leaf the leaf to be subdivided
393                @param polys the input polygons
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
397                @returns the root of the subdivision
398        */
399        BspInterior *SubdivideNode(BspLeaf *leaf,
400                                                           PolygonContainer *polys,
401                                                           PolygonContainer *frontPolys,
402                                                           PolygonContainer *backPolys,
403                                                           PolygonContainer *coincident);
404
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        */
411        void FilterPolygons(BspInterior *node, PolygonContainer *polys,
412                                                PolygonContainer *frontPolys, PolygonContainer *backPolys);
413
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        */
418        Plane3 SelectPlaneHeuristics(const PolygonContainer &polys, const int maxTests) const;
419
420        /** Extracts the meshes of the objects and copies them into the mesh.
421                Adds object aabb to the aabb of the tree.
422                @param maxPolys the maximal number of objects to be stored as polygons
423                @returns the number of polygons
424        */
425        int Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects = 0);
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
429                @returns the number of polygons
430        */
431        int Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects = 0);
432
433        /** Extract polygons of this mesh and add to polygon container.
434                @param mesh the mesh that drives the polygon construction
435                @param parent the parent intersectable this polygon is constructed from
436                @returns number of polygons
437        */
438        int AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys, Intersectable *parent = NULL);
439
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
446        /** returns next candidate index
447                @param max the range of candidates
448        */
449        inline int GetNextCandidateIdx(const int max) const;
450
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       
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
492        /// Pointer to the root of the tree
493        BspNode *mRoot;
494
495        /// Pointer to the root cell of the viewspace
496        // ViewCell *mRootCell;
497               
498        BspTreeStatistics mStat;
499
500        /// Strategies for choosing next split plane.
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                };
510
511        /// box around the whole view domain
512        AxisAlignedBox3 mBox;
513
514        /// if polygons should be stored in the tree
515        bool mStorePolys;
516
517        /// view cell corresponding to unbounded space
518        ViewCell *mViewCell;
519
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;
528        /// strategy to get the best split plane
529        static int sSplitPlaneStrategy;
530        /// number of candidates evaluated for the next split plane
531        static int sMaxCandidates;
532        /// BSP tree construction method
533        static int sConstructionMethod;
534        /// maximal number of polygons where we do axis aligned splits
535        static int sTermMaxPolysForAxisAligned;
536
537        static float sCt_div_ci;
538        static float sSplitBorder;
539        static float sMaxCostRatio;
540
541        // factors to guid the split plane heuristics
542        static float sLeastSplitsFactor;
543        static float sBalancedPolysFactor;
544        static float sBalancedViewCellsFactor;
545        static float sVerticalSplitsFactor;
546       
547private:
548        /** Evaluates split plane classification with respect to the plane's
549                contribution for a balanced tree.
550        */
551        static float sLeastSplitsTable[4];
552        /** Evaluates split plane classification with respect to the plane's
553                contribution for a minimum number splits in the tree.
554        */
555        static float sBalancedPolysTable[4];
556};
557
558//}; // GtpVisibilityPreprocessor
559
560#endif
Note: See TracBrowser for help on using the repository browser.