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

Revision 332, 17.3 KB checked in by mattausch, 19 years ago (diff)

fixed bug when asigning bsp root
subdivision termination criterium based on rays

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