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

Revision 318, 16.8 KB checked in by mattausch, 19 years ago (diff)

VisibilityInfo?: query sort operators as templates
X3dExporter: Fixed polygon wire frame, bsp splits, and bsp split planes visualization
ViewCellBsp?: Added rays to split criteria (not finished yet)
OgreOctreeSceneManager?: fixed error (mNumOctants instead of mNumOctrees)

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