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

Revision 350, 19.2 KB checked in by mattausch, 19 years ago (diff)

ray merge started

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