source: trunk/VUT/GtpVisibilityPreprocessor/src/VspBspTree.h @ 443

Revision 443, 19.6 KB checked in by mattausch, 19 years ago (diff)
Line 
1#ifndef _VspBspTree_H__
2#define _VspBspTree_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include "Polygon3.h"
7#include <stack>
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11
12class ViewCell;
13class BspViewCell;
14class Plane3;
15class VspBspTree; 
16class VspBspInterior;
17class VspBspNode;
18class AxisAlignedBox3;
19class Ray;
20
21class VspBspNodeGeometry
22{
23public:
24        VspBspNodeGeometry()
25        {}; 
26
27        ~VspBspNodeGeometry();
28
29        float GetArea() const;
30       
31        /** Computes new cell based on the old cell definition and a new split plane
32                @param side indicates which side of the halfspace
33        */
34        void SplitGeometry(VspBspNodeGeometry &front,
35                                           VspBspNodeGeometry &back,
36                                           const VspBspTree &tree,
37                                           const Plane3 &splitPlane) const;
38
39        Polygon3 *SplitPolygon(Polygon3 *poly, const VspBspTree &tree) const;
40
41        PolygonContainer mPolys;
42};
43
44/** Data structure used for optimized ray casting.
45*/
46struct VspBspRayTraversalData
47{
48    VspBspNode *mNode;
49    Vector3 mExitPoint;
50    float mMaxT;
51   
52    VspBspRayTraversalData() {}
53
54    VspBspRayTraversalData(VspBspNode *n, const Vector3 &extp, const float maxt):
55    mNode(n), mExitPoint(extp), mMaxT(maxt)
56        {}
57};
58
59class VspBspTreeStatistics: public StatisticsBase
60{
61public:
62        // total number of nodes
63        int nodes;
64        // number of splits
65        int splits;
66        // totals number of rays
67        int rays;
68        // maximal reached depth
69        int maxDepth;
70        // minimal depth
71        int minDepth;
72       
73        // max depth nodes
74        int maxDepthNodes;
75        // minimum depth nodes
76        int minDepthNodes;
77        // max depth nodes
78        int minPvsNodes;
79        // nodes with minimum PVS
80        int minRaysNodes;
81        // max ray contribution nodes
82        int maxRayContribNodes;
83        // minimum area nodes
84        int minAreaNodes;
85
86        // max number of rays per node
87        int maxObjectRefs;
88        // accumulated depth (used to compute average)
89        int accumDepth;
90        // number of initial polygons
91        int polys;
92        /// samples contributing to pvs
93        int contributingSamples;
94        /// sample contributions to pvs
95        int sampleContributions;
96        /// largest pvs
97        int largestPvs;
98
99        // Constructor
100        VspBspTreeStatistics()
101        {
102                Reset();
103        }
104
105        int Nodes() const {return nodes;}
106        int Interior() const { return nodes / 2; }
107        int Leaves() const { return (nodes / 2) + 1; }
108       
109        // TODO: computation wrong
110        double AvgDepth() const { return accumDepth / (double)Leaves();};
111 
112        void Reset()
113        {
114                nodes = 0;
115                splits = 0;
116               
117                maxDepth = 0;
118                minDepth = 99999;
119                polys = 0;
120                accumDepth = 0;
121       
122                maxDepthNodes = 0;
123                minPvsNodes = 0;
124                minRaysNodes = 0;
125                maxRayContribNodes = 0;
126                minAreaNodes = 0;
127
128                contributingSamples = 0;
129                sampleContributions = 0;
130        }
131
132        void Print(ostream &app) const;
133
134        friend ostream &operator<<(ostream &s, const VspBspTreeStatistics &stat)
135        {
136                stat.Print(s);
137                return s;
138        }
139};
140
141class VspBspViewCellsStatistics: public StatisticsBase
142{
143public:
144
145        /// number of view cells
146        int viewCells;
147
148        /// size of the PVS
149        int pvs;
150 
151        /// largest PVS of all view cells
152        int maxPvs;
153
154        /// smallest PVS of all view cells
155        int minPvs;
156
157        /// view cells with empty PVS
158        int emptyPvs;
159
160        /// number of bsp leaves covering the view space
161        int bspLeaves;
162
163        /// largest number of leaves covered by one view cell 
164        int maxVspBspLeaves;
165
166    // Constructor
167        VspBspViewCellsStatistics()
168        {
169                Reset();
170        }
171
172        double AvgVspBspLeaves() const {return (double)bspLeaves / (double)viewCells;};
173        double AvgPvs() const {return (double)pvs / (double)viewCells;};
174 
175        void Reset()
176        {
177                viewCells = 0; 
178                pvs = 0; 
179                maxPvs = 0;
180
181                minPvs = 999999;
182                emptyPvs = 0;
183                bspLeaves = 0;
184                maxVspBspLeaves = 0;
185        }
186
187        void Print(ostream &app) const;
188
189        friend ostream &operator<<(ostream &s, const VspBspViewCellsStatistics &stat)
190        {
191                stat.Print(s);
192                return s;
193        } 
194};
195
196/**
197    VspBspNode abstract class serving for interior and leaf node implementation
198*/
199class VspBspNode
200{
201        friend class VspBspTree;
202
203public:
204        VspBspNode();
205        virtual ~VspBspNode(){};
206        VspBspNode(VspBspInterior *parent);
207
208        /** Determines whether this node is a leaf or not
209        @return true if leaf
210        */
211        virtual bool IsLeaf() const = 0;
212
213        /** Determines whether this node is a root
214        @return true if root
215        */
216        virtual bool IsRoot() const;
217
218        /** Returns parent node.
219        */
220        VspBspInterior *GetParent();
221
222        /** Sets parent node.
223        */
224        void SetParent(VspBspInterior *parent);
225
226       
227        static int sMailId;
228        int mMailbox;
229 
230        void Mail() { mMailbox = sMailId; }
231        static void NewMail() { ++ sMailId; }
232        bool Mailed() const { return mMailbox == sMailId; }
233
234protected:
235
236        /// parent of this node
237        VspBspInterior *mParent;
238};
239
240/** BSP interior node implementation
241*/
242class VspBspInterior : public VspBspNode
243{
244        friend class VspBspTree;
245public:
246        /** Standard contructor taking split plane as argument.
247        */
248        VspBspInterior(const Plane3 &plane);
249        ~VspBspInterior();
250        /** @return false since it is an interior node
251        */
252        bool IsLeaf() const;
253
254        VspBspNode *GetBack();
255        VspBspNode *GetFront();
256
257        Plane3 *GetPlane();
258
259        void ReplaceChildLink(VspBspNode *oldChild, VspBspNode *newChild);
260        void SetupChildLinks(VspBspNode *b, VspBspNode *f);
261
262        /** Splits polygons with respect to the split plane.
263                @param polys the polygons to be split. the polygons are consumed and
264                           distributed to the containers frontPolys, backPolys, coincident.
265                @param frontPolys returns the polygons in the front of the split plane
266                @param backPolys returns the polygons in the back of the split plane
267                @param coincident returns the polygons coincident to the split plane
268
269                @returns the number of splits   
270        */
271        int SplitPolygons(PolygonContainer &polys,
272                                          PolygonContainer &frontPolys,
273                                          PolygonContainer &backPolys,
274                                          PolygonContainer &coincident);
275
276        friend ostream &operator<<(ostream &s, const VspBspInterior &A)
277        {
278                return s << A.mPlane;
279        }
280
281protected:
282
283        /// Splitting plane corresponding to this node
284        Plane3 mPlane;
285        /// back node
286        VspBspNode *mBack;
287        /// front node
288        VspBspNode *mFront;
289};
290
291/** BSP leaf node implementation.
292*/
293class VspBspLeaf : public VspBspNode
294{
295        friend class VspBspTree;
296
297public:
298        VspBspLeaf();
299        VspBspLeaf(BspViewCell *viewCell);
300        VspBspLeaf(VspBspInterior *parent);
301        VspBspLeaf(VspBspInterior *parent, BspViewCell *viewCell);
302
303        /** @return true since it is an interior node
304        */
305        bool IsLeaf() const;
306       
307        /** Returns pointer of view cell.
308        */
309        BspViewCell *GetViewCell() const;
310
311        /** Sets pointer to view cell.
312        */
313        void SetViewCell(BspViewCell *viewCell);
314
315        /** Adds ray sample contributions to the PVS.
316                @param sampleContributions the number contributions of the samples
317                @param contributingSampels the number of contributing rays
318               
319        */
320        void AddToPvs(const RayInfoContainer &rays,
321                                  int &sampleContributions,
322                                  int &contributingSamples,
323                                  bool storeLeavesWithRays = false);
324
325protected:
326
327        /// if NULL this does not correspond to feasible viewcell
328        BspViewCell *mViewCell;
329};
330
331/** Implementation of the view cell BSP tree.
332*/
333class VspBspTree
334{
335public:
336       
337        /** Additional data which is passed down the BSP tree during traversal.
338        */
339        struct VspBspTraversalData
340        { 
341                /// the current node
342                VspBspNode *mNode;
343                /// polygonal data for splitting
344                PolygonContainer *mPolygons;
345                /// current depth
346                int mDepth;
347                /// the view cell associated with this subdivsion
348                ViewCell *mViewCell;
349                /// rays piercing this node
350                RayInfoContainer *mRays;
351                /// area of current node
352                float mArea;
353                /// geometry of current node induced by split planes
354                VspBspNodeGeometry *mGeometry;
355
356                /// pvs size
357                int mPvs;
358               
359                /** Returns average ray contribution.
360                */
361                float GetAvgRayContribution() const
362                {
363                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
364                }
365
366
367                VspBspTraversalData():
368                mNode(NULL),
369                mPolygons(NULL),
370                mDepth(0),
371                mViewCell(NULL),
372                mRays(NULL),
373                mPvs(0),
374                mArea(0.0),
375                mGeometry(NULL)
376                {}
377               
378                VspBspTraversalData(VspBspNode *node,
379                                                 PolygonContainer *polys,
380                                                 const int depth,
381                                                 ViewCell *viewCell,
382                                                 RayInfoContainer *rays,
383                                                 int pvs,
384                                                 float area,
385                                                 VspBspNodeGeometry *cell):
386                mNode(node),
387                mPolygons(polys),
388                mDepth(depth),
389                mViewCell(viewCell),
390                mRays(rays),
391                mPvs(pvs),
392                mArea(area),
393                mGeometry(cell)
394                {}
395    };
396       
397        typedef std::stack<VspBspTraversalData> VspBspTraversalStack;
398
399        /** Default constructor creating an empty tree.
400        */
401        VspBspTree();
402
403        ~VspBspTree();
404
405        const VspBspTreeStatistics &GetStatistics() const;
406 
407
408        /** Constructs the tree from a given set of rays.
409                @param sampleRays the set of sample rays the construction is based on
410                @param viewCells if not NULL, new view cells are
411                created in the leafs and stored in the conatainer
412        */
413        void Construct(const VssRayContainer &sampleRays);
414
415        /** Returns list of BSP leaves.
416        */
417        void CollectLeaves(vector<VspBspLeaf *> &leaves) const;
418
419        /** Returns box which bounds the whole tree.
420        */
421        AxisAlignedBox3 GetBoundingBox()const;
422
423        /** Returns root of BSP tree.
424        */
425        VspBspNode *GetRoot() const;
426
427        /** Exports VspBsp tree to file.
428        */
429        bool Export(const string filename);
430
431        /** Collects the leaf view cells of the tree
432                @param viewCells returns the view cells
433        */
434        void CollectViewCells(ViewCellContainer &viewCells) const;
435
436        /** A ray is cast possible intersecting the tree.
437                @param the ray that is cast.
438                @returns the number of intersections with objects stored in the tree.
439        */
440        int CastRay(Ray &ray);
441
442        /// bsp tree construction types
443        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
444
445        /** Returns statistics.
446        */
447        VspBspTreeStatistics &GetStat();
448
449        /** finds neighbouring leaves of this tree node.
450        */
451        int FindNeighbors(VspBspNode *n, vector<VspBspLeaf *> &neighbors,
452                                          const bool onlyUnmailed) const;
453
454        /** Constructs geometry associated with the half space intersections
455                leading to this node.
456        */
457        void ConstructGeometry(VspBspNode *n, PolygonContainer &cell) const;
458
459        /** Constructs geometry associated with the half space intersections
460                leading to this node.
461        */
462        void ConstructGeometry(BspViewCell *vc, PolygonContainer &cell) const;
463
464        /** Construct geometry and stores it in a geometry node container.
465        */
466        void ConstructGeometry(VspBspNode *n, VspBspNodeGeometry &cell) const;
467
468        /** Returns random leaf of BSP tree.
469                @param halfspace defines the halfspace from which the leaf is taken.
470        */
471        VspBspLeaf *GetRandomLeaf(const Plane3 &halfspace);
472
473        /** Returns random leaf of BSP tree.
474                @param onlyUnmailed if only unmailed leaves should be returned.
475        */
476        VspBspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
477
478        /** Returns true if merge criteria are reached.
479        */
480    bool ShouldMerge(VspBspLeaf *front, VspBspLeaf *back) const;
481
482        /** Merges view cells based on some criteria
483            E.g., empty view cells can pe purged, view cells which have
484                a very similar PVS can be merged to one larger view cell.
485
486                @returns true if merge was successful.
487        */
488        bool MergeViewCells(VspBspLeaf *front, VspBspLeaf *back) const;
489
490        /** Traverses tree and counts all view cells as well as their PVS size.
491        */
492        void EvaluateViewCellsStats(VspBspViewCellsStatistics &stat) const;
493
494
495        /** Returns view cell corresponding to unbounded space.
496        */
497        BspViewCell *GetRootCell() const;
498
499protected:
500
501        // --------------------------------------------------------------
502        // For sorting objects
503        // --------------------------------------------------------------
504        struct SortableEntry
505        {
506                enum {POLY_MIN, POLY_MAX};
507   
508                int type;
509                float value;
510                Polygon3 *poly;
511                SortableEntry() {}
512                SortableEntry(const int t, const float v, Polygon3 *poly):
513                type(t), value(v), poly(poly) {}
514               
515                bool operator<(const SortableEntry &b) const
516                {
517                        return value < b.value;
518                } 
519        };
520
521        /** Evaluates tree stats in the BSP tree leafs.
522        */
523        void EvaluateLeafStats(const VspBspTraversalData &data);
524
525        /** Subdivides node with respect to the traversal data.
526            @param tStack current traversal stack
527                @param tData traversal data also holding node to be subdivided
528                @returns new root of the subtree
529        */
530        VspBspNode *Subdivide(VspBspTraversalStack &tStack, VspBspTraversalData &tData);
531
532        /** Constructs the tree from the given list of polygons and rays.
533                @param polys stores set of polygons on which subdivision may be based
534                @param rays storesset of rays on which subdivision may be based
535        */
536        void Construct(PolygonContainer *polys, RayInfoContainer *rays);
537
538        /** Selects the best possible splitting plane.
539                @param leaf the leaf to be split
540                @param polys the polygon list on which the split decition is based
541                @param rays ray container on which selection may be based
542                @note the polygons can be reordered in the process
543                @returns the split plane
544        */
545        Plane3 SelectPlane(VspBspLeaf *leaf,
546                                           VspBspTraversalData &data);
547
548       
549        /** Strategies where the effect of the split plane is tested
550            on all input rays.
551
552                @returns the cost of the candidate split plane
553        */
554        float SplitPlaneCost(const Plane3 &candidatePlane,
555                                                 const VspBspTraversalData &data);
556
557
558
559        /** Subdivide leaf.
560                @param leaf the leaf to be subdivided
561               
562                @param polys the polygons to be split
563                @param frontPolys returns the polygons in front of the split plane
564                @param backPolys returns the polygons in the back of the split plane
565               
566                @param rays the polygons to be filtered
567                @param frontRays returns the polygons in front of the split plane
568                @param backRays returns the polygons in the back of the split plane
569
570                @returns the root of the subdivision
571        */
572
573        VspBspInterior *SubdivideNode(VspBspTraversalData &tData,
574                                                           VspBspTraversalData &frontData,
575                                                           VspBspTraversalData &backData,
576                                                           PolygonContainer &coincident);
577
578        /** Selects the split plane in order to construct a tree with
579                certain characteristics (e.g., balanced tree, least splits,
580                2.5d aligned)
581                @param polygons container of polygons
582                @param rays bundle of rays on which the split can be based
583        */
584        Plane3 SelectPlaneHeuristics(VspBspLeaf *leaf,
585                                                                 VspBspTraversalData &data);
586
587        /** Extracts the meshes of the objects and adds them to polygons.
588                Adds object aabb to the aabb of the tree.
589                @param maxPolys the maximal number of objects to be stored as polygons
590                @returns the number of polygons
591        */
592        int AddToPolygonSoup(const ObjectContainer &objects,
593                                                 PolygonContainer &polys,
594                                                 int maxObjects = 0);
595
596        /** Extracts the meshes of the view cells and and adds them to polygons.
597                Adds view cell aabb to the aabb of the tree.
598                @param maxPolys the maximal number of objects to be stored as polygons
599                @returns the number of polygons
600        */
601        int AddToPolygonSoup(const ViewCellContainer &viewCells,
602                                                 PolygonContainer &polys,
603                                                 int maxObjects = 0);
604
605        /** Extract polygons of this mesh and add to polygon container.
606                @param mesh the mesh that drives the polygon construction
607                @param parent the parent intersectable this polygon is constructed from
608                @returns number of polygons
609        */
610        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
611
612        /** returns next candidate index and reorders polygons so no candidate is chosen two times
613                @param the current candidate index
614                @param max the range of candidates
615        */
616        int GetNextCandidateIdx(int currentIdx, PolygonContainer &polys);
617       
618        /** Computes best cost ratio for the suface area heuristics for axis aligned
619                splits. This heuristics minimizes the cost for ray traversal.
620                @param polys the polygons guiding the ratio computation
621                @param box the bounding box of the leaf
622                @param axis the current split axis
623                @param position returns the split position
624                @param objectsBack the number of objects in the back of the split plane
625                @param objectsFront the number of objects in the front of the split plane
626        */
627        float BestCostRatio(const PolygonContainer &polys,
628                                                const AxisAlignedBox3 &box,
629                                                const int axis,
630                                                float &position,
631                                                int &objectsBack,
632                                                int &objectsFront) const;
633       
634        /** Sorts split candidates for surface area heuristics for axis aligned splits.
635                @param polys the input for choosing split candidates
636                @param axis the current split axis
637                @param splitCandidates returns sorted list of split candidates
638        */
639        void SortSplitCandidates(const PolygonContainer &polys,
640                                                         const int axis,
641                                                         vector<SortableEntry> &splitCandidates) const;
642
643        /** Selects an axis aligned split plane.
644                Returns true if split is valied
645        */
646        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
647
648        /** Bounds ray and returns minT and maxT.
649                @returns true if ray hits BSP tree bounding box
650        */
651        bool BoundRay(const Ray &ray, float &minT, float &maxT) const;
652
653        /** Subdivides the rays into front and back rays according to the split plane.
654               
655                @param plane the split plane
656                @param rays contains the rays to be split. The rays are
657                           distributed into front and back rays.
658                @param frontRays returns rays on the front side of the plane
659                @param backRays returns rays on the back side of the plane
660               
661                @returns the number of splits
662        */
663        int SplitRays(const Plane3 &plane,
664                                  RayInfoContainer &rays,
665                              RayInfoContainer &frontRays,
666                                  RayInfoContainer &backRays);
667
668
669        /** Extracts the split planes representing the space bounded by node n.
670        */
671        void ExtractHalfSpaces(VspBspNode *n, vector<Plane3> &halfSpaces) const;
672
673        /** Adds the object to the pvs of the front and back leaf with a given classification.
674
675                @param obj the object to be added
676                @param cf the ray classification regarding the split plane
677                @param frontPvs returns the PVS of the front partition
678                @param backPvs returns the PVS of the back partition
679       
680        */
681        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
682       
683        /** Computes PVS size induced by the rays.
684        */
685        int ComputePvsSize(const RayInfoContainer &rays) const;
686
687        /** Returns true if tree can be terminated.
688        */
689        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
690
691        /** Computes accumulated ray lenght of this rays.
692        */
693        float AccumulatedRayLength(const RayInfoContainer &rays) const;
694
695
696
697        /// Pointer to the root of the tree
698        VspBspNode *mRoot;
699               
700        VspBspTreeStatistics mStat;
701
702        /// Strategies for choosing next split plane.
703        enum {NO_STRATEGY = 0,
704                  RANDOM_POLYGON = 1,
705                  AXIS_ALIGNED = 2,
706                  LEAST_SPLITS = 4,
707                  BALANCED_POLYS = 8,
708                  BALANCED_VIEW_CELLS = 16,
709                  LARGEST_POLY_AREA = 32,
710                  VERTICAL_AXIS = 64,
711                  BLOCKED_RAYS = 128,
712                  LEAST_RAY_SPLITS = 256,
713                  BALANCED_RAYS = 512,
714                  PVS = 1024
715                };
716
717        /// box around the whole view domain
718        AxisAlignedBox3 mBox;
719
720        /// view cell corresponding to unbounded space
721        BspViewCell *mRootCell;
722
723        /// minimal number of rays before subdivision termination
724        int mTermMinRays;
725        /// maximal possible depth
726        int mTermMaxDepth;
727        /// mininum area
728        float mTermMinArea;
729        /// mininum PVS
730        int mTermMinPvs;
731
732        /// minimal number of rays for axis aligned split
733        int mTermMinRaysForAxisAligned;
734        /// minimal number of objects for axis aligned split
735        int mTermMinObjectsForAxisAligned;
736        /// maximal contribution per ray
737        float mTermMaxRayContribution;
738        /// minimal accumulated ray length
739        float mTermMinAccRayLength;
740
741
742        /// strategy to get the best split plane
743        int mSplitPlaneStrategy;
744        /// number of candidates evaluated for the next split plane
745        int mMaxPolyCandidates;
746        /// number of candidates for split planes evaluated using the rays
747        int mMaxRayCandidates;
748       
749        float mCtDivCi;
750
751        /// axis aligned split criteria
752        float mAaCtDivCi;
753        float mSplitBorder;
754        float mMaxCostRatio;
755
756        // factors guiding the split plane heuristics
757        float mBlockedRaysFactor;
758        float mLeastRaySplitsFactor;
759        float mBalancedRaysFactor;
760        float mPvsFactor;
761        float mLeastSplitsFactor;
762
763        //-- thresholds used for view cells merge
764        int mMinPvsDif;
765        int mMinPvs;
766        int mMaxPvs;
767
768        /// if area or accumulated ray lenght should be used for PVS heuristics
769        bool mPvsUseArea;
770
771private:
772       
773        static const float sLeastRaySplitsTable[5];
774        /** Evaluates split plane classification with respect to the plane's
775                contribution for balanced rays.
776        */
777        static const float sBalancedRaysTable[5];
778
779        /// Generates unique ids for PVS criterium
780        static void GenerateUniqueIdsForPvs();
781
782        //-- unique ids for PVS criterium
783        static int sFrontId;
784        static int sBackId;
785        static int sFrontAndBackId;
786};
787
788#endif
Note: See TracBrowser for help on using the repository browser.