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

Revision 362, 21.1 KB checked in by mattausch, 19 years ago (diff)

added post merging bsp view cells
fixed bug at per ray subdivision

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