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

Revision 306, 15.9 KB checked in by mattausch, 19 years ago (diff)

fixed polygon area, eval candidate plane

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(PolygonContainer &polys, const Plane3 &candidatePlane);
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, PolygonContainer &polys);
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(PolygonContainer &polys, const int maxTests);
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);
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 and reorders polygons so no candidate is chosen two times
447                @param the current candidate index
448                @param max the range of candidates
449        */
450        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
451
452        /** Helper function which extracts a view cell on the front and the back
453                of the split plane.
454                @param backViewCell returns view cell on the back of the split plane
455                @param frontViewCell returns a view cell on the front of the split plane
456                @param coincident container of polygons coincident to the split plane
457                @param splitPlane the split plane which decides about back and front
458                @param extractFront if a front view cell is extracted
459                @param extractBack if a back view cell is extracted
460        */
461        void ExtractViewCells(ViewCell **backViewCell,
462                                                  ViewCell **frontViewCell,
463                                                  const PolygonContainer &coincident,
464                                                  const Plane3 splitPlane,
465                                                  const bool extractFront,
466                                                  const bool extractBack) const;
467       
468        /** Computes best cost ratio for the suface area heuristics for axis aligned
469                splits. This heuristics minimizes the cost for ray traversal.
470                @param polys the polygons guiding the ratio computation
471                @param box the bounding box of the leaf
472                @param axis the current split axis
473                @param position returns the split position
474                @param objectsBack the number of objects in the back of the split plane
475                @param objectsFront the number of objects in the front of the split plane
476        */
477        float BestCostRatio(const PolygonContainer &polys,
478                                                const AxisAlignedBox3 &box,
479                                                const int axis,
480                                                float &position,
481                                                int &objectsBack,
482                                                int &objectsFront) const;
483       
484        /** Sorts split candidates for surface area heuristics for axis aligned splits.
485                @param polys the input for choosing split candidates
486                @param axis the current split axis
487                @param splitCandidates returns sorted list of split candidates
488        */
489        void SortSplitCandidates(const PolygonContainer &polys,
490                                                         const int axis,
491                                                         vector<SortableEntry> &splitCandidates) const;
492
493        /// Pointer to the root of the tree
494        BspNode *mRoot;
495
496        /// Pointer to the root cell of the viewspace
497        // ViewCell *mRootCell;
498               
499        BspTreeStatistics mStat;
500
501        /// Strategies for choosing next split plane.
502        enum {NO_STRATEGY = 0,
503                  NEXT_POLYGON = 1,
504                  AXIS_ALIGNED = 2,
505                  LEAST_SPLITS = 4,
506                  BALANCED_POLYS = 8,
507                  BALANCED_VIEW_CELLS = 16,
508                  LARGEST_POLY_AREA = 32,
509                  VERTICAL_AXIS = 64
510                };
511
512        /// box around the whole view domain
513        AxisAlignedBox3 mBox;
514
515        /// if polygons should be stored in the tree
516        bool mStoreSplitPolys;
517
518        /// view cell corresponding to unbounded space
519        ViewCell *mViewCell;
520
521public:
522        /// Parses the environment and stores the global BSP tree parameters
523        static void ParseEnvironment();
524
525        /// maximal number of polygons where tree construction is terminated
526        static int sTermMaxPolygons;
527        /// maximal possible depth
528        static int sTermMaxDepth;
529        /// strategy to get the best split plane
530        static int sSplitPlaneStrategy;
531        /// number of candidates evaluated for the next split plane
532        static int sMaxCandidates;
533        /// BSP tree construction method
534        static int sConstructionMethod;
535        /// maximal number of polygons where we do axis aligned splits
536        static int sTermMaxPolysForAxisAligned;
537
538        static float sCt_div_ci;
539        static float sSplitBorder;
540        static float sMaxCostRatio;
541
542        // factors to guid the split plane heuristics
543        static float sLeastSplitsFactor;
544        static float sBalancedPolysFactor;
545        static float sBalancedViewCellsFactor;
546        static float sVerticalSplitsFactor;
547        static float sLargestPolyAreaFactor;
548       
549private:
550        /** Evaluates split plane classification with respect to the plane's
551                contribution for a balanced tree.
552        */
553        static float sLeastSplitsTable[4];
554        /** Evaluates split plane classification with respect to the plane's
555                contribution for a minimum number splits in the tree.
556        */
557        static float sBalancedPolysTable[4];
558};
559
560//}; // GtpVisibilityPreprocessor
561
562#endif
Note: See TracBrowser for help on using the repository browser.