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

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