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

Revision 297, 14.2 KB checked in by mattausch, 19 years ago (diff)

added bsp split plane criteria

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
247/** Implementation of the ViewCell BSP tree. */
248class BspTree
249{
250public:
251               
252        /** Additional data which is passed down the BSP tree during traversal.
253        */
254        struct BspTraversalData
255        { 
256                /// the current node
257                BspNode *mNode;
258                /// polygonal data for splitting
259                PolygonContainer *mPolygons;
260                /// current depth
261                int mDepth;
262                /// the view cell associated with this subdivsion
263                ViewCell *mViewCell;
264                /// if the node is an inside or outside node with respect to the parent plane
265                //bool mIsInside;
266                BspTraversalData() {}
267               
268                BspTraversalData(BspNode *node, PolygonContainer *polys, const int depth, ViewCell *viewCell):
269                mNode(node), mPolygons(polys), mDepth(depth), mViewCell(viewCell) {}
270    };
271
272        typedef std::stack<BspTraversalData> BspTraversalStack;
273
274        /// BSP tree construction type
275        enum {VIEW_CELLS, SCENE_GEOMETRY, RAYS};
276
277        /** Default constructor creating an empty tree.
278                @param viewCell view cell corresponding to unbounded space
279        */
280        BspTree(ViewCell *viewCell);
281
282        ~BspTree();
283
284        const BspTreeStatistics &GetStatistics() const;
285 
286        /** Constructs tree using the given list of view cells.
287            For this type of construction we filter all view cells down the
288                tree. If there is no polygon left, the last split plane
289            decides inside or outside of the viewcell. A pointer to the
290                appropriate view cell is stored within each leaf.
291                Many leafs can point to the same viewcell.
292        */
293        void Construct(const ViewCellContainer &viewCells);
294
295        /** Constructs tree using the given list of objects.
296            Note that the objects are not taken as view cells, but the view cells are
297                constructed from the subdivision: Each leaf is taken as one viewcell;
298
299                @param objects list of objects
300                @returns list of view cells.
301        */
302        void Construct(const ObjectContainer &objects, ViewCellContainer *viewCells);
303
304        /** Constructs tree using the given number of rays
305            @param objects list of objects
306                @returns list of view cells.
307        */
308        void Construct(const RayContainer &rays, ViewCellContainer *viewCells);
309
310        int CollectLeafPvs();
311
312        void CollectLeaves(vector<BspLeaf *> &leaves);
313
314        /** Returns box which bounds the whole tree.
315        */
316        AxisAlignedBox3 GetBoundingBox()const;
317
318        /** Returns root of BSP tree.
319        */
320        BspNode *GetRoot() const;
321
322        /** If the view cell polygons are stored in the nodes.
323        */
324        bool StorePolys() const;
325
326        /** Exports Bsp tree to file.
327        */
328        bool Export(const string filename);
329
330        //static bool displayDebug;
331protected:
332       
333        /** Constructs the tree from the given list of polygons.
334                @param viewCells if not NULL, new view cells are
335                created in the leafs and stored in the conatainer
336        */
337        void Construct(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
338
339        /** Evaluates the contribution of the candidate split plane.
340                @returns the cost of the candidate split plane
341        */
342        float EvalSplitPlane(const PolygonContainer &polys, const Plane3 &candidatePlane) const;
343
344        /** Evaluates tree stats in the BSP tree leafs.
345        */
346        void EvaluateLeafStats(const BspTraversalData &data);
347
348        /** Subdivides node with respect to the traversal data.
349            @param tStack current traversal stack
350                @param tData traversal data also holding node to be subdivided
351                @param viewCellContainer if not null, a new viewcell is created and stored in the container
352                @returns new root of the subtree
353        */
354        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData, ViewCellContainer *viewCells = NULL);
355
356        /** Selects a splitting plane.
357                @param polys the polygon list on which the split decition is based
358        */
359        Plane3 SelectPlane(const PolygonContainer &polys) const;
360
361        /** Filters next view cell down the tree and inserts it into the appropriate leaves
362                (i.e., possibly more than one leaf).
363        */
364        void InsertViewCell(ViewCell *viewCell);
365        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
366                then further subdivided.
367                @param viewCellContainer if not null, a new viewcell is created and stored in the container
368        */
369        void InsertPolygons(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
370
371        /** Subdivide leaf.
372                @param leaf the leaf to be subdivided
373                @param polys the input polygons
374                @param frontPolys returns the polygons in the front of the split plane
375                @param backPolys returns the polygons in the back of the split plane
376                @param coincident returns the polygons coincident to the split plane
377                @returns the root of the subdivision
378        */
379        BspInterior *SubdivideNode(BspLeaf *leaf,
380                                                           PolygonContainer *polys,
381                                                           PolygonContainer *frontPolys,
382                                                           PolygonContainer *backPolys,
383                                                           PolygonContainer *coincident);
384
385        /** Filters polygons down the tree.
386                @param node the current BSP node
387                @param polys the polygons to be filtered
388                @param frontPolys returns the polygons in front of the split plane
389                @param backPolys returns the polygons in the back of the split plane
390        */
391        void FilterPolygons(BspInterior *node, PolygonContainer *polys,
392                                                PolygonContainer *frontPolys, PolygonContainer *backPolys);
393
394        /** Selects the split plane in order to get a balanced tree.
395                @param polygons container of polygons
396                @param maxTests the maximal number of candidate tests
397        */
398        Plane3 SelectPlaneHeuristics(const PolygonContainer &polys, const int maxTests) const;
399
400        /** Extracts the meshes of the objects and copies them into the mesh.
401                Adds object aabb to the aabb of the tree.
402                @param maxPolys the maximal number of objects to be stored as polygons
403                @returns the number of polygons
404        */
405        int Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects = 0);
406        /** Extracts the meshes of the view cells and copies them into the mesh.
407                Adds view cell aabb to the aabb of the tree.
408                @param maxPolys the maximal number of objects to be stored as polygons
409                @returns the number of polygons
410        */
411        int Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects = 0);
412
413        /** Extract polygons of this mesh and add to polygon container.
414                @param mesh the mesh that drives the polygon construction
415                @param parent the parent intersectable this polygon is constructed from
416                @returns number of polygons
417        */
418        int AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys, Intersectable *parent = NULL);
419
420        /** A ray is cast possible intersecting the tree.
421                @param the ray that is cast.
422                @returns the number of intersections with objects stored in the tree.
423        */
424        int CastRay(Ray &ray);
425
426        /** returns next candidate index
427                @param max the range of candidates
428        */
429        inline int GetNextCandidateIdx(const int max) const;
430
431        /** Helper function which extracts a view cell on the front and the back
432                of the split plane.
433                @param backViewCell returns view cell on the back of the split plane
434                @param frontViewCell returns a view cell on the front of the split plane
435                @param coincident container of polygons coincident to the split plane
436                @param splitPlane the split plane which decides about back and front
437                @param extractFront if a front view cell is extracted
438                @param extractBack if a back view cell is extracted
439        */
440        void ExtractViewCells(ViewCell **backViewCell,
441                                                  ViewCell **frontViewCell,
442                                                  const PolygonContainer &coincident,
443                                                  const Plane3 splitPlane,
444                                                  const bool extractFront,
445                                                  const bool extractBack) const;
446       
447        /// Pointer to the root of the tree
448        BspNode *mRoot;
449
450        /// Pointer to the root cell of the viewspace
451        // ViewCell *mRootCell;
452               
453        BspTreeStatistics mStat;
454
455        /// Strategies for choosing next split plane.
456        enum {NO_STRATEGY = 0,
457                  NEXT_POLYGON = 1,
458                  AXIS_ALIGNED = 2,
459                  LEAST_SPLITS = 4,
460                  BALANCED_POLYS = 8,
461                  BALANCED_VIEW_CELLS = 16,
462                  LARGEST_POLY_AREA = 32,
463                  VERTICAL_AXIS = 64
464                };
465
466        /// box around the whole view domain
467        AxisAlignedBox3 mBox;
468
469        /// if polygons should be stored in the tree
470        bool mStorePolys;
471
472        /// view cell corresponding to unbounded space
473        ViewCell *mViewCell;
474
475public:
476        /// Parses the environment and stores the global BSP tree parameters
477        static void ParseEnvironment();
478
479        /// maximal number of polygons where tree construction is terminated
480        static int sTermMaxPolygons;
481        /// maximal possible depth
482        static int sTermMaxDepth;
483        /// strategy to get the best split plane
484        static int sSplitPlaneStrategy;
485        /// number of candidates evaluated for the next split plane
486        static int sMaxCandidates;
487        /// BSP tree construction method
488        static int sConstructionMethod;
489        /// maximal number of polygons where we do axis aligned splits
490        static int sTermMaxPolysForAxisAligned;
491
492        // factors to guid the split plane heuristics
493        static float sLeastSplitsFactor;
494        static float sBalancedPolysFactor;
495        static float sBalancedViewCellsFactor;
496        static float sVerticalSplitsFactor;
497       
498private:
499        /** Evaluates split plane classification with respect to the plane's
500                contribution for a balanced tree.
501        */
502        static float sLeastSplitsTable[4];
503        /** Evaluates split plane classification with respect to the plane's
504                contribution for a minimum number splits in the tree.
505        */
506        static float sBalancedPolysTable[4];
507};
508
509//}; // GtpVisibilityPreprocessor
510
511#endif
Note: See TracBrowser for help on using the repository browser.