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

Revision 344, 18.4 KB checked in by mattausch, 19 years ago (diff)
Line 
1#ifndef _ViewCellBsp_H__
2#define _ViewCellBsp_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include <stack>
7
8class ViewCell;
9class Plane3;
10class BspTree; 
11class BspInterior;
12class Polygon3;
13class AxisAlignedBox3;
14class Ray;
15
16struct BspRayTraversalData
17{
18    BspNode *mNode;
19    Vector3 mExitPoint;
20    float mMaxT;
21   
22    BspRayTraversalData() {}
23
24    BspRayTraversalData(BspNode *n, const Vector3 &extp, const float maxt):
25    mNode(n), mExitPoint(extp), mMaxT(maxt)
26        {}
27};
28
29class BspTreeStatistics
30{
31public:
32  // total number of nodes
33  int nodes;
34  // number of splits
35  int splits;
36  // totals number of rays
37  int rays;
38  // maximal reached depth
39  int maxDepth;
40  // minimal depth
41  int minDepth;
42  // max depth nodes
43  int maxDepthNodes;
44  // max number of rays per node
45  int maxObjectRefs;
46   // accumulated depth (used to compute average)
47  int accumDepth;
48  // number of initial polygons
49  int polys;
50  /// number of view cells different to the view cell representing unbounded space.
51  int viewCells;
52  /// 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        /** Merges view cells based on some criteria
351            E.g., empty view cells can pe purged, view cells which have
352                a very similar PVS can be merged to one larger view cell farther up
353                in the BSP tree.
354                @returns the number of merged view cells
355        */
356        int MergeViewCells();
357
358        /** Set to true if new view cells shall be generated in each leaf.
359        */
360        void SetGenerateViewCells(int generateViewCells);
361
362        /// bsp tree construction types
363        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_RAYS};
364
365        /** Returns statistics.
366        */
367        BspTreeStatistics &GetStat();
368
369protected:
370
371        // --------------------------------------------------------------
372        // For sorting objects
373        // --------------------------------------------------------------
374        struct SortableEntry
375        {
376                enum {POLY_MIN, POLY_MAX};
377   
378                int type;
379                float value;
380                Polygon3 *poly;
381                SortableEntry() {}
382                SortableEntry(const int t, const float v, Polygon3 *poly):
383                type(t), value(v), poly(poly) {}
384               
385                bool operator<(const SortableEntry &b) const
386                {
387                        return value < b.value;
388                } 
389        };
390
391        BspNode *MergeNodes(BspInterior *node);
392
393        bool MergeNecessary(BspLeaf *front, BspLeaf *back) const;
394
395        /** Evaluates tree stats in the BSP tree leafs.
396        */
397        void EvaluateLeafStats(const BspTraversalData &data);
398
399        /** Subdivides node with respect to the traversal data.
400            @param tStack current traversal stack
401                @param tData traversal data also holding node to be subdivided
402                @returns new root of the subtree
403        */
404        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData);
405
406        /** Constructs the tree from the given list of polygons and rays.
407                @param polys stores set of polygons on which subdivision may be based
408                @param rays storesset of rays on which subdivision may be based
409        */
410        void Construct(PolygonContainer *polys, RayContainer *rays);
411
412        /** Selects the best possible splitting plane.
413                @param leaf the leaf to be split
414                @param polys the polygon list on which the split decition is based
415                @param rays ray container on which selection may be based
416                @note the polygons can be reordered in the process
417                @returns the split plane
418        */
419        Plane3 SelectPlane(BspLeaf *leaf,
420                                           PolygonContainer &polys,
421                                           const RayContainer &ray);
422
423        /** Evaluates the contribution of the candidate split plane.
424               
425                @param canditatePlane the candidate split plane
426                @param polys the polygons the split can be based on
427                @param rays the rays the split can be based on
428                @returns the cost of the candidate split plane
429        */
430        float SplitPlaneCost(const Plane3 &candidatePlane,
431                                                 const PolygonContainer &polys,                                                 
432                                                 const RayContainer &rays) const;
433
434        /** Strategies where the effect of the split plane is tested
435            on all input rays.
436                @returns the cost of the candidate split plane
437        */
438        float SplitPlaneCost(const Plane3 &candidatePlane,
439                                                 const PolygonContainer &polys) const;
440
441        /** Strategies where the effect of the split plane is tested
442            on all input polygons.
443                @returns the cost of the candidate split plane
444        */
445        float SplitPlaneCost(const Plane3 &candidatePlane,
446                                                 const RayContainer &polys) const;
447
448        /** Filters next view cell down the tree and inserts it into the appropriate leaves
449                (i.e., possibly more than one leaf).
450        */
451        void InsertViewCell(ViewCell *viewCell);
452        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
453                then further subdivided.
454        */
455        void InsertPolygons(PolygonContainer *polys);
456
457        /** Subdivide leaf.
458                @param leaf the leaf to be subdivided
459               
460                @param polys the polygons to be split
461                @param frontPolys returns the polygons in front of the split plane
462                @param backPolys returns the polygons in the back of the split plane
463               
464                @param rays the polygons to be filtered
465                @param frontRays returns the polygons in front of the split plane
466                @param backRays returns the polygons in the back of the split plane
467
468                @returns the root of the subdivision
469        */
470        BspInterior *SubdivideNode(BspLeaf *leaf,
471                                                           PolygonContainer &polys,
472                                                           PolygonContainer &frontPolys,
473                                                           PolygonContainer &backPolys,
474                                                           PolygonContainer &coincident,
475                                                           RayContainer &rays,
476                                                           RayContainer &backRays,
477                                                           RayContainer &frontRays);
478
479        /** Filters polygons down the tree.
480                @param node the current BSP node
481                @param polys the polygons to be filtered
482                @param frontPolys returns the polygons in front of the split plane
483                @param backPolys returns the polygons in the back of the split plane
484        */
485        void FilterPolygons(BspInterior *node,
486                                                PolygonContainer *polys,
487                                                PolygonContainer *frontPolys,
488                                                PolygonContainer *backPolys);
489
490        /** Selects the split plane in order to construct a tree with
491                certain characteristics (e.g., balanced tree, least splits,
492                2.5d aligned)
493                @param polygons container of polygons
494                @param rays bundle of rays on which the split can be based
495                @param maxTests the maximal number of candidate tests
496        */
497        Plane3 SelectPlaneHeuristics(PolygonContainer &polys,
498                                                                 const RayContainer &rays,
499                                                                 const int maxTests);
500
501        /** Extracts the meshes of the objects and adds them to polygons.
502                Adds object aabb to the aabb of the tree.
503                @param maxPolys the maximal number of objects to be stored as polygons
504                @returns the number of polygons
505        */
506        int AddToPolygonSoup(const ObjectContainer &objects,
507                                                 PolygonContainer &polys,
508                                                 int maxObjects = 0);
509
510        /** Extracts the meshes of the view cells and and adds them to polygons.
511                Adds view cell aabb to the aabb of the tree.
512                @param maxPolys the maximal number of objects to be stored as polygons
513                @returns the number of polygons
514        */
515        int AddToPolygonSoup(const ViewCellContainer &viewCells,
516                                                 PolygonContainer &polys,
517                                                 int maxObjects = 0);
518
519        /** Extract polygons of this mesh and add to polygon container.
520                @param mesh the mesh that drives the polygon construction
521                @param parent the parent intersectable this polygon is constructed from
522                @returns number of polygons
523        */
524        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
525
526        /** returns next candidate index and reorders polygons so no candidate is chosen two times
527                @param the current candidate index
528                @param max the range of candidates
529        */
530        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
531
532        /** Helper function which extracts a view cell on the front and the back
533                of the split plane.
534                @param backViewCell returns view cell on the back of the split plane
535                @param frontViewCell returns a view cell on the front of the split plane
536                @param coincident container of polygons coincident to the split plane
537                @param splitPlane the split plane which decides about back and front
538                @param extractBack if a back view cell is extracted
539                @param extractFront if a front view cell is extracted
540        */
541        void ExtractViewCells(ViewCell **backViewCell,
542                                                  ViewCell **frontViewCell,
543                                                  const PolygonContainer &coincident,
544                                                  const Plane3 splitPlane,
545                                                  const bool extractBack,
546                                                  const bool extractFront) const;
547       
548        /** Computes best cost ratio for the suface area heuristics for axis aligned
549                splits. This heuristics minimizes the cost for ray traversal.
550                @param polys the polygons guiding the ratio computation
551                @param box the bounding box of the leaf
552                @param axis the current split axis
553                @param position returns the split position
554                @param objectsBack the number of objects in the back of the split plane
555                @param objectsFront the number of objects in the front of the split plane
556        */
557        float BestCostRatio(const PolygonContainer &polys,
558                                                const AxisAlignedBox3 &box,
559                                                const int axis,
560                                                float &position,
561                                                int &objectsBack,
562                                                int &objectsFront) const;
563       
564        /** Sorts split candidates for surface area heuristics for axis aligned splits.
565                @param polys the input for choosing split candidates
566                @param axis the current split axis
567                @param splitCandidates returns sorted list of split candidates
568        */
569        void SortSplitCandidates(const PolygonContainer &polys,
570                                                         const int axis,
571                                                         vector<SortableEntry> &splitCandidates) const;
572
573        /// Pointer to the root of the tree
574        BspNode *mRoot;
575
576        /// Pointer to the root cell of the viewspace
577        // ViewCell *mRootCell;
578               
579        BspTreeStatistics mStat;
580
581        /// Strategies for choosing next split plane.
582        enum {NO_STRATEGY = 0,
583                  RANDOM_POLYGON = 1,
584                  AXIS_ALIGNED = 2,
585                  LEAST_SPLITS = 4,
586                  BALANCED_POLYS = 8,
587                  BALANCED_VIEW_CELLS = 16,
588                  LARGEST_POLY_AREA = 32,
589                  VERTICAL_AXIS = 64,
590                  BLOCKED_RAYS = 128,
591                  LEAST_RAY_SPLITS = 256,
592                  BALANCED_RAYS = 512
593                };
594
595        /// box around the whole view domain
596        AxisAlignedBox3 mBox;
597
598        /// view cell corresponding to unbounded space
599        ViewCell *mRootCell;
600        /// should view cells be stored or generated in the leaves?
601        bool mGenerateViewCells;
602
603public:
604        /// Parses the environment and stores the global BSP tree parameters
605        static void ParseEnvironment();
606
607        /// maximal number of polygons before subdivision termination
608        static int sTermMaxPolygons;
609        /// maximal number of rays before subdivision termination
610        static int sTermMaxRays;
611        /// maximal possible depth
612        static int sTermMaxDepth;
613        /// strategy to get the best split plane
614        static int sSplitPlaneStrategy;
615        /// number of candidates evaluated for the next split plane
616        static int sMaxCandidates;
617        /// BSP tree construction method
618        static int sConstructionMethod;
619        /// maximal number of polygons where we do axis aligned splits
620        static int sTermMaxPolysForAxisAligned;
621
622        /// axis aligned split criteria
623        static float sCt_div_ci;
624        static float sSplitBorder;
625        static float sMaxCostRatio;
626
627        // factors guiding the split plane heuristics
628        static float sLeastSplitsFactor;
629        static float sBalancedPolysFactor;
630        static float sBalancedViewCellsFactor;
631        static float sVerticalSplitsFactor;
632        static float sLargestPolyAreaFactor;
633        static float sBlockedRaysFactor;
634        static float sLeastRaySplitsFactor;
635        static float sBalancedRaysFactor;
636
637        /// if polygons should be stored in the tree
638        static bool sStoreSplitPolys;
639
640private:
641        /** Evaluates split plane classification with respect to the plane's
642                contribution for a balanced tree.
643        */
644        static float sLeastSplitsTable[4];
645        /** Evaluates split plane classification with respect to the plane's
646                contribution for a minimum number splits in the tree.
647        */
648        static float sBalancedTreeTable[4];
649};
650
651//}; // GtpVisibilityPreprocessor
652
653#endif
Note: See TracBrowser for help on using the repository browser.