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

Revision 319, 16.2 KB checked in by mattausch, 19 years ago (diff)

changed the from rays construction (not finished yet)

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               
257                BspTraversalData():
258                mNode(NULL),
259                mPolygons(NULL),
260                mDepth(0),
261                mViewCell(NULL)
262                {}
263               
264                BspTraversalData(BspNode *node,
265                                                 PolygonContainer *polys,
266                                                 const int depth,
267                                                 ViewCell *viewCell):
268                mNode(node),
269                mPolygons(polys),
270                mDepth(depth),
271                mViewCell(viewCell)
272                {}
273    };
274
275        typedef std::stack<BspTraversalData> BspTraversalStack;
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 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 the tree from the given list of polygons.
305                @param viewCells if not NULL, new view cells are
306                created in the leafs and stored in the conatainer
307        */
308        void Construct(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
309       
310        /** Constructs the tree from a list of scene geometry and a
311                given bundle of rays.
312                @param objects list of objects
313                @param rays the bundle of sample rays
314                @param viewCells if not NULL, new view cells are
315                created in the leafs and stored in the conatainer
316        */
317        void Construct(const ObjectContainer &objects,
318                                   const RayContainer &rays,
319                                   ViewCellContainer *viewCells = NULL);
320
321        /** Returns list of BSP leaves.
322        */
323        void CollectLeaves(vector<BspLeaf *> &leaves);
324
325        /** Returns box which bounds the whole tree.
326        */
327        AxisAlignedBox3 GetBoundingBox()const;
328
329        /** Returns root of BSP tree.
330        */
331        BspNode *GetRoot() const;
332
333        /** If the view cell polygons are stored in the nodes.
334        */
335        bool StorePolys() const;
336
337        /** Exports Bsp tree to file.
338        */
339        bool Export(const string filename);
340
341        void CollectViewCells(BspNode *n, ViewCellContainer &viewCells);
342
343        /** A ray is cast possible intersecting the tree.
344                @param the ray that is cast.
345                @returns the number of intersections with objects stored in the tree.
346        */
347        int CastRay(Ray &ray);
348
349        /// bsp tree construction types
350        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_RAYS};
351
352protected:
353       
354        // --------------------------------------------------------------
355        // For sorting objects
356        // --------------------------------------------------------------
357        struct SortableEntry
358        {
359                enum {POLY_MIN, POLY_MAX};
360   
361                int type;
362                float value;
363                Polygon3 *poly;
364                SortableEntry() {}
365                SortableEntry(const int t, const float v, Polygon3 *poly):
366                type(t), value(v), poly(poly) {}
367               
368                bool operator<(const SortableEntry &b) const
369                {
370                        return value < b.value;
371                } 
372        };
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
381        /** Evaluates tree stats in the BSP tree leafs.
382        */
383        void EvaluateLeafStats(const BspTraversalData &data);
384
385        /** Subdivides node with respect to the traversal data.
386            @param tStack current traversal stack
387                @param tData traversal data also holding node to be subdivided
388                @returns new root of the subtree
389        */
390        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData);
391
392        /** Selects the best possible splitting plane.
393                @param leaf the leaf to be split
394                @param polys the polygon list on which the split decition is based
395                @Returns the split plane
396        */
397        Plane3 SelectPlane(BspLeaf *leaf,
398                                           PolygonContainer &polys);
399
400        /** Filters next view cell down the tree and inserts it into the appropriate leaves
401                (i.e., possibly more than one leaf).
402        */
403        void InsertViewCell(ViewCell *viewCell);
404        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
405                then further subdivided.
406                @param viewCellContainer if not null, a new viewcell is created and stored in the container
407        */
408        void InsertPolygons(PolygonContainer *polys, ViewCellContainer *viewCells = NULL);
409
410        /** Subdivide leaf.
411                @param leaf the leaf to be subdivided
412                @param polys the input polygons
413                @param frontPolys returns the polygons in the front of the split plane
414                @param backPolys returns the polygons in the back of the split plane
415                @param coincident returns the polygons coincident to the split plane
416                @returns the root of the subdivision
417        */
418        BspInterior *SubdivideNode(BspLeaf *leaf,
419                                                           PolygonContainer &polys,
420                                                           PolygonContainer &frontPolys,
421                                                           PolygonContainer &backPolys,
422                                                           PolygonContainer &coincident);
423
424        /** Filters polygons down the tree.
425                @param node the current BSP node
426                @param polys the polygons to be filtered
427                @param frontPolys returns the polygons in front of the split plane
428                @param backPolys returns the polygons in the back of the split plane
429        */
430        void FilterPolygons(BspInterior *node,
431                                                PolygonContainer *polys,
432                                                PolygonContainer *frontPolys,
433                                                PolygonContainer *backPolys);
434
435        /** Selects the split plane in order to construct a tree with
436                certain characteristics (e.g., balanced tree, least splits,
437                2.5d aligned)
438                @param polygons container of polygons
439                @param maxTests the maximal number of candidate tests
440        */
441        Plane3 SelectPlaneHeuristics(PolygonContainer &polys,
442                                                                const int maxTests);
443
444        /** Extracts the meshes of the objects and adds them to polygons.
445                Adds object aabb to the aabb of the tree.
446                @param maxPolys the maximal number of objects to be stored as polygons
447                @returns the number of polygons
448        */
449        int AddToPolygonSoup(const ObjectContainer &objects,
450                                                 PolygonContainer &polys,
451                                                 int maxObjects = 0);
452
453        /** Extracts the meshes of the view cells and and adds them to polygons.
454                Adds view cell aabb to the aabb of the tree.
455                @param maxPolys the maximal number of objects to be stored as polygons
456                @returns the number of polygons
457        */
458        int AddToPolygonSoup(const ViewCellContainer &viewCells,
459                                                 PolygonContainer &polys,
460                                                 int maxObjects = 0);
461
462        /** Extract polygons of this mesh and add to polygon container.
463                @param mesh the mesh that drives the polygon construction
464                @param parent the parent intersectable this polygon is constructed from
465                @returns number of polygons
466        */
467        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
468
469        /** returns next candidate index and reorders polygons so no candidate is chosen two times
470                @param the current candidate index
471                @param max the range of candidates
472        */
473        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
474
475        /** Helper function which extracts a view cell on the front and the back
476                of the split plane.
477                @param backViewCell returns view cell on the back of the split plane
478                @param frontViewCell returns a view cell on the front of the split plane
479                @param coincident container of polygons coincident to the split plane
480                @param splitPlane the split plane which decides about back and front
481                @param extractBack if a back view cell is extracted
482                @param extractFront if a front view cell is extracted
483        */
484        void ExtractViewCells(ViewCell **backViewCell,
485                                                  ViewCell **frontViewCell,
486                                                  const PolygonContainer &coincident,
487                                                  const Plane3 splitPlane,
488                                                  const bool extractBack,
489                                                  const bool extractFront) const;
490       
491        /** Computes best cost ratio for the suface area heuristics for axis aligned
492                splits. This heuristics minimizes the cost for ray traversal.
493                @param polys the polygons guiding the ratio computation
494                @param box the bounding box of the leaf
495                @param axis the current split axis
496                @param position returns the split position
497                @param objectsBack the number of objects in the back of the split plane
498                @param objectsFront the number of objects in the front of the split plane
499        */
500        float BestCostRatio(const PolygonContainer &polys,
501                                                const AxisAlignedBox3 &box,
502                                                const int axis,
503                                                float &position,
504                                                int &objectsBack,
505                                                int &objectsFront) const;
506       
507        /** Sorts split candidates for surface area heuristics for axis aligned splits.
508                @param polys the input for choosing split candidates
509                @param axis the current split axis
510                @param splitCandidates returns sorted list of split candidates
511        */
512        void SortSplitCandidates(const PolygonContainer &polys,
513                                                         const int axis,
514                                                         vector<SortableEntry> &splitCandidates) const;
515
516        /// Pointer to the root of the tree
517        BspNode *mRoot;
518
519        /// Pointer to the root cell of the viewspace
520        // ViewCell *mRootCell;
521               
522        BspTreeStatistics mStat;
523
524        /// Strategies for choosing next split plane.
525        enum {NO_STRATEGY = 0,
526                  NEXT_POLYGON = 1,
527                  AXIS_ALIGNED = 2,
528                  LEAST_SPLITS = 4,
529                  BALANCED_POLYS = 8,
530                  BALANCED_VIEW_CELLS = 16,
531                  LARGEST_POLY_AREA = 32,
532                  VERTICAL_AXIS = 64,
533                  BLOCKED_RAYS = 128
534                };
535
536        /// box around the whole view domain
537        AxisAlignedBox3 mBox;
538
539        /// if polygons should be stored in the tree
540        bool mStoreSplitPolys;
541
542        /// view cell corresponding to unbounded space
543        ViewCell *mRootCell;
544
545public:
546        /// Parses the environment and stores the global BSP tree parameters
547        static void ParseEnvironment();
548
549        /// maximal number of polygons where tree construction is terminated
550        static int sTermMaxPolygons;
551        /// maximal possible depth
552        static int sTermMaxDepth;
553        /// strategy to get the best split plane
554        static int sSplitPlaneStrategy;
555        /// number of candidates evaluated for the next split plane
556        static int sMaxCandidates;
557        /// BSP tree construction method
558        static int sConstructionMethod;
559        /// maximal number of polygons where we do axis aligned splits
560        static int sTermMaxPolysForAxisAligned;
561
562        static float sCt_div_ci;
563        static float sSplitBorder;
564        static float sMaxCostRatio;
565
566        // factors to guid the split plane heuristics
567        static float sLeastSplitsFactor;
568        static float sBalancedPolysFactor;
569        static float sBalancedViewCellsFactor;
570        static float sVerticalSplitsFactor;
571        static float sLargestPolyAreaFactor;
572        static float sBlockedRaysFactor;
573
574private:
575        /** Evaluates split plane classification with respect to the plane's
576                contribution for a balanced tree.
577        */
578        static float sLeastSplitsTable[4];
579        /** Evaluates split plane classification with respect to the plane's
580                contribution for a minimum number splits in the tree.
581        */
582        static float sBalancedPolysTable[4];
583};
584
585//}; // GtpVisibilityPreprocessor
586
587#endif
Note: See TracBrowser for help on using the repository browser.