source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellBsp.h @ 748

Revision 748, 28.6 KB checked in by mattausch, 18 years ago (diff)
Line 
1#ifndef _ViewCellBsp_H__
2#define _ViewCellBsp_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 "ViewCell.h"
11
12
13
14class ViewCell;
15//class BspViewCell;
16class Plane3;
17class BspTree; 
18class BspInterior;
19//class Polygon3;
20class AxisAlignedBox3;
21class Ray;
22class ViewCellsStatistics;
23class ViewCellsManager;
24class ViewCellsTree;
25
26class BspNodeGeometry
27{
28public:
29        BspNodeGeometry()
30        {}; 
31
32        /** copy constructor copying the polygon array.
33                The polygons are deeply copied.
34        */
35        BspNodeGeometry(const BspNodeGeometry &rhs);
36        /** This operator uses a deep copy to copy the polygons.
37        */
38        BspNodeGeometry& operator=(const BspNodeGeometry& p);
39
40        /** Builds node geometry using this polygons.
41                @NOTE The polygons are NOT duplicated, only
42                a shallow copy is used.
43        */     
44    BspNodeGeometry(const PolygonContainer &polys);
45
46        ~BspNodeGeometry();
47
48        /** Returns accumulated area of all polygons.
49        */
50        float GetArea() const;
51        /** Returns volume of this node geometry.
52        */
53        float GetVolume() const;
54
55        /** Computes new front and back geometry based on the old cell
56                geometry and a new split plane
57                @returns true if the geometry is actually split by this plane
58        */
59        bool SplitGeometry(BspNodeGeometry &front,
60                                           BspNodeGeometry &back,
61                                           const Plane3 &splitPlane,
62                       const AxisAlignedBox3 &box,
63                                           const float epsilon) const;
64
65        /** Computes the intersection of the box with the node geometry.
66        */
67        int ComputeIntersection(const AxisAlignedBox3 &box) const;
68
69        /** Computes bounding box of the geometry.
70        */
71        void GetBoundingBox(AxisAlignedBox3 &box) const;
72
73        /** Returns
74                1 of geometry in front of plane
75                0 if plane intersects geometry,
76                -1 if geometry in back of plane
77        */
78        int Side(const Plane3 &plane, const float eps = 0.0f) const;
79
80        /** Splits the polygon and returns the part of the polygon inside of the node geometry.
81        */
82        Polygon3 *SplitPolygon(Polygon3 *poly, const float epsilon) const;
83
84        /** Adds node geometry to mesh.
85                @note the mesh vertices will not be connected
86        */
87        void AddToMesh(Mesh &mesh);
88
89        /** Computes mass center of bsp node geometry.
90        */
91        Vector3 CenterOfMass() const;
92
93        bool Valid() const;
94
95       
96        friend ostream &operator<<(ostream &s, const BspNodeGeometry &a)
97        {
98                PolygonContainer::const_iterator it, it_end = a.mPolys.end();
99
100                for (it = a.mPolys.begin(); it != it_end; ++ it)
101                        s << *(*it) << endl;
102                return s << endl;
103        }
104
105        int Size() const;
106        const PolygonContainer &GetPolys();
107
108    /** Adds polygon and plane equation to this geometry.
109        */
110        void Add(Polygon3 *p, const Plane3 &plane);
111
112protected:
113        /** The polygons the geometry consists of.
114        */
115        PolygonContainer mPolys;
116
117        /** The corresponding set of planes for the polygons.
118                Need this because of precision issues.
119        */
120        vector<Plane3> mPlanes;
121};
122
123
124/** Data structure used for optimized ray casting.
125*/
126struct BspRayTraversalData
127{
128    BspNode *mNode;
129    Vector3 mExitPoint;
130    float mMaxT;
131   
132    BspRayTraversalData() {}
133
134    BspRayTraversalData(BspNode *n, const Vector3 &extp, const float maxt):
135    mNode(n), mExitPoint(extp), mMaxT(maxt)
136        {}
137
138        BspRayTraversalData(BspNode *n, const Vector3 &extp):
139        mNode(n), mExitPoint(extp)
140        {}
141};
142
143/** Data used for passing ray data down the tree.
144*/
145struct BoundedRay
146{
147        Ray *mRay;
148        float mMinT;
149        float mMaxT;
150               
151        BoundedRay(): mMinT(0), mMaxT(1e6), mRay(NULL)
152        {}
153        BoundedRay(Ray *r, float minT, float maxT):
154        mRay(r), mMinT(minT), mMaxT(maxT)
155        {}
156};
157
158typedef vector<BoundedRay *> BoundedRayContainer;
159
160class BspTreeStatistics: public StatisticsBase
161{
162public:
163        // total number of nodes
164        int nodes;
165        // number of splits
166        int splits[3];
167       
168        // totals number of rays
169        int rays;
170        // maximal reached depth
171        int maxDepth;
172        // minimal depth
173        int minDepth;
174       
175        // max depth nodes
176        int maxDepthNodes;
177        // minimum depth nodes
178        int minDepthNodes;
179        // max depth nodes
180        int minPvsNodes;
181        // nodes with minimum PVS
182        int minRaysNodes;
183        // max ray contribution nodes
184        int maxRayContribNodes;
185        // minimum area nodes
186        int minProbabilityNodes;
187        /// nodes termination because of max cost ratio;
188        int maxCostNodes;
189        // max number of rays per node
190        int maxObjectRefs;
191        // accumulated depth (used to compute average)
192        int accumDepth;
193        // number of initial polygons
194        int polys;
195        /// samples contributing to pvs
196        int contributingSamples;
197        /// sample contributions to pvs
198        int sampleContributions;
199        /// largest pvs
200        int maxPvs;
201        /// number of invalid leaves
202        int invalidLeaves;
203        /// polygon splits
204        int polySplits;
205        /// accumulated number of rays refs
206        int accumRays;
207        int pvs;
208
209        // Constructor
210        BspTreeStatistics()
211        {
212                Reset();
213        }
214
215        int Nodes() const {return nodes;}
216        int Interior() const { return nodes / 2; }
217        int Leaves() const { return (nodes / 2) + 1; }
218       
219        // TODO: computation wrong
220        double AvgDepth() const { return accumDepth / (double)Leaves();};
221        double AvgRays() const { return accumRays / (double)Leaves();};
222
223        void Reset()
224        {
225                nodes = 0;
226                for (int i = 0; i < 3; ++ i)
227                        splits[i] = 0;
228               
229                maxDepth = 0;
230                minDepth = 99999;
231                polys = 0;
232                accumDepth = 0;
233        pvs = 0;
234                maxDepthNodes = 0;
235                minPvsNodes = 0;
236                minRaysNodes = 0;
237                maxRayContribNodes = 0;
238                minProbabilityNodes = 0;
239                maxCostNodes = 0;
240
241                contributingSamples = 0;
242                sampleContributions = 0;
243
244                maxPvs = 0;
245                invalidLeaves = 0;
246                polySplits = 0;
247                accumRays = 0;
248        }
249
250        void Print(ostream &app) const;
251
252        friend ostream &operator<<(ostream &s, const BspTreeStatistics &stat)
253        {
254                stat.Print(s);
255                return s;
256        }
257};
258
259
260/**
261    BspNode abstract class serving for interior and leaf node implementation
262*/
263class BspNode
264{
265        friend class BspTree;
266
267public:
268        BspNode();
269        virtual ~BspNode(){};
270        BspNode(BspInterior *parent);
271
272        /** Determines whether this node is a leaf or not
273        @return true if leaf
274        */
275        virtual bool IsLeaf() const = 0;
276
277        /** Determines whether this node is a root
278        @return true if root
279        */
280        virtual bool IsRoot() const;
281
282        /** Returns parent node.
283        */
284        BspInterior *GetParent();
285
286        /** Sets parent node.
287        */
288        void SetParent(BspInterior *parent);
289
290        /** Returns true if this node is a sibling of node n.
291        */
292        bool IsSibling(BspNode *n) const;
293
294        /** returns depth of the node.
295        */
296        int GetDepth() const;
297
298        /** returns true if the whole subtree is valid
299        */
300        bool TreeValid() const;
301
302        void SetTreeValid(const bool v);
303
304        //-- mailing options
305
306        void Mail() { mMailbox = sMailId; }
307        static void NewMail() { ++ sMailId; }
308        bool Mailed() const { return mMailbox == sMailId; }
309
310        static int sMailId;
311        int mMailbox;
312
313        int mTimeStamp;
314
315protected:
316
317        /// if this sub tree is a completely valid view space region
318        bool mTreeValid;
319        /// parent of this node
320        BspInterior *mParent;
321};
322
323/** BSP interior node implementation
324*/
325class BspInterior: public BspNode
326{
327        friend class BspTree;
328public:
329        /** Standard contructor taking split plane as argument.
330        */
331        BspInterior(const Plane3 &plane);
332        ~BspInterior();
333        /** @return false since it is an interior node
334        */
335        bool IsLeaf() const;
336
337        BspNode *GetBack();
338        BspNode *GetFront();
339
340        /** Returns split plane.
341        */
342        Plane3 GetPlane() const;
343
344        /** Replace front or back child with new child.
345        */
346        void ReplaceChildLink(BspNode *oldChild, BspNode *newChild);
347        /** Replace front and back child.
348        */
349        void SetupChildLinks(BspNode *b, BspNode *f);
350
351        friend ostream &operator<<(ostream &s, const BspInterior &A)
352        {
353                return s << A.mPlane;
354        }
355
356protected:
357
358        /// Splitting plane corresponding to this node
359        Plane3 mPlane;
360
361        /// back node
362        BspNode *mBack;
363        /// front node
364        BspNode *mFront;
365};
366
367/** BSP leaf node implementation.
368*/
369class BspLeaf: public BspNode
370{
371        friend class BspTree;
372
373public:
374        BspLeaf();
375        BspLeaf(ViewCell *viewCell);
376        BspLeaf(BspInterior *parent);
377        BspLeaf(BspInterior *parent, ViewCell *viewCell);
378
379        ~BspLeaf();
380
381        /** @return true since it is an interior node
382        */
383        bool IsLeaf() const;
384       
385        /** Returns pointer of view cell.
386        */
387        ViewCell *GetViewCell() const;
388
389        /** Sets pointer to view cell.
390        */
391        void SetViewCell(ViewCell *viewCell);
392
393        /// Rays piercing this leaf.
394        VssRayContainer mVssRays;
395       
396        /// leaf pvs
397        ObjectPvs *mPvs;
398
399        /// Probability that the view point lies in this leaf
400        float mProbability;
401
402protected:
403       
404        /// if NULL this does not correspond to feasible viewcell
405        ViewCell *mViewCell;
406};
407
408/** Implementation of the view cell BSP tree.
409*/
410class BspTree
411{
412        friend class ViewCellsParseHandlers;
413
414public:
415       
416        /** Additional data which is passed down the BSP tree during traversal.
417        */
418        struct BspTraversalData
419        { 
420                /// the current node
421                BspNode *mNode;
422                /// polygonal data for splitting
423                PolygonContainer *mPolygons;
424                /// current depth
425                int mDepth;
426                /// the view cell associated with this subdivsion
427                ViewCell *mViewCell;
428                /// rays piercing this node
429                BoundedRayContainer *mRays;
430                /// probability of current node
431                float mProbability;
432                /// geometry of node as induced by planes
433                BspNodeGeometry *mGeometry;
434               
435                /// pvs size
436                int mPvs;
437               
438                /** Returns average ray contribution.
439                */
440                float GetAvgRayContribution() const
441                {
442                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
443                }
444
445
446                BspTraversalData():
447                mNode(NULL),
448                mPolygons(NULL),
449                mDepth(0),
450                mViewCell(NULL),
451                mRays(NULL),
452                mPvs(0),
453                mProbability(0.0),
454                mGeometry(NULL)
455                {}
456               
457                BspTraversalData(BspNode *node,
458                                                 PolygonContainer *polys,
459                                                 const int depth,
460                                                 ViewCell *viewCell,
461                                                 BoundedRayContainer *rays,
462                                                 int pvs,
463                                                 float p,
464                                                 BspNodeGeometry *cell):
465                mNode(node),
466                mPolygons(polys),
467                mDepth(depth),
468                mViewCell(viewCell),
469                mRays(rays),
470                mPvs(pvs),
471                mProbability(p),
472                mGeometry(cell)
473                {}
474
475
476                float GetCost() const
477                {
478#if 0
479                        return mPvs * mProbability;
480#endif
481#if 0
482                        return (float) (-mDepth); // for regular grid
483#endif
484#if 1
485                        return (float) mDepth; // depth first
486#endif
487#if 0
488                        return mProbability;
489#endif
490#if 0
491                        return (float)mPvs;
492#endif
493#if 0
494                        return (float)mRays->size();
495#endif
496                }
497               
498                friend bool operator<(const BspTraversalData &a, const BspTraversalData &b)
499                {
500                        return a.GetCost() < b.GetCost();
501                }
502    };
503       
504        //typedef std::stack<BspTraversalData> BspTraversalStack;
505        typedef std::priority_queue<BspTraversalData> BspTraversalStack;
506
507        /** Default constructor reading the environment file and
508                creating an empty tree.
509        */
510        BspTree();
511        /** Destroys tree and nodes.
512        */
513        ~BspTree();
514
515        /** Returns detailed statistics of the BSP tree.
516        */
517        const BspTreeStatistics &GetStatistics() const;
518 
519        /** Constructs tree using the given list of view cells.
520            For this type of construction we filter all view cells down the
521                tree. If there is no polygon left, the last split plane
522            decides inside or outside of the viewcell. A pointer to the
523                appropriate view cell is stored within each leaf.
524                Many leafs can point to the same viewcell.
525        */
526        void Construct(const ViewCellContainer &viewCells);
527
528        /** Constructs tree using the given list of objects.
529            @note the objects are not taken as view cells, but the view cells are
530                constructed from the subdivision: Each leaf is taken as one viewcell.
531                @param objects list of objects
532        */
533        void Construct(const ObjectContainer &objects);
534
535        void Construct(const ObjectContainer &objects,
536                                   const RayContainer &sampleRays,
537                                   AxisAlignedBox3 *forcedBoundingBox);
538
539        /** Constructs the tree from a given set of rays.
540                @param sampleRays the set of sample rays the construction is based on
541                @param viewCells if not NULL, new view cells are
542                created in the leafs and stored in the conatainer
543        */
544        void Construct(const RayContainer &sampleRays,
545                                   AxisAlignedBox3 *forcedBoundingBox);
546
547        /** Returns list of BSP leaves.
548        */
549        void CollectLeaves(vector<BspLeaf *> &leaves) const;
550
551        /** Returns box which bounds the whole tree.
552        */
553        AxisAlignedBox3 GetBoundingBox()const;
554
555        /** Returns root of BSP tree.
556        */
557        BspNode *GetRoot() const;
558
559       
560        //bool Export(const string filename);
561
562        /** Collects the leaf view cells of the tree
563                @param viewCells returns the view cells
564        */
565        void CollectViewCells(ViewCellContainer &viewCells) const;
566
567        /** A ray is cast possible intersecting the tree.
568                @param the ray that is cast.
569                @returns the number of intersections with objects stored in the tree.
570        */
571        int     _CastRay(Ray &ray);
572
573
574        int     CastLineSegment(const Vector3 &origin,
575                                                const Vector3 &termination,
576                                                ViewCellContainer &viewcells
577                                                );
578
579        ViewCell *GetViewCell(const Vector3 &point);
580 
581        /// bsp tree construction types
582        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
583
584        /** Returns statistics.
585        */
586        BspTreeStatistics &GetStat();
587
588        /** finds neighbouring leaves of this tree node.
589        */
590        int FindNeighbors(BspNode *n, vector<BspLeaf *> &neighbors,
591                                          const bool onlyUnmailed) const;
592
593        /** Constructs geometry of view cell returning a BSP node geometry type.
594        */
595        void ConstructGeometry(BspNode *n, BspNodeGeometry &cell) const;
596       
597        /** Construct geometry of view cell.
598        */
599        void ConstructGeometry(ViewCell *vc, BspNodeGeometry &geom) const;
600
601                       
602        /** Sets pointer to view cells manager.
603        */
604        void SetViewCellsManager(ViewCellsManager *vcm);
605
606        /** Returns random leaf of BSP tree.
607                @param halfspace defines the halfspace from which the leaf is taken.
608        */
609        BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
610
611        /** Returns random leaf of BSP tree.
612                @param onlyUnmailed if only unmailed leaves should be returned.
613        */
614        BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
615
616
617        /** Returns epsilon of this tree.
618        */
619        float GetEpsilon() const;
620
621        int CollectMergeCandidates(const vector<BspLeaf *> leaves,
622                                                           vector<MergeCandidate> &candidates);
623
624        int CollectMergeCandidates(const VssRayContainer &rays,
625                                                   vector<MergeCandidate> &candidates);
626
627        /** Exports Bsp tree to file.
628        */
629        bool Export(ofstream &stream);
630
631
632        /** Returns view cell corresponding to
633                the invalid view space. If it does not exist, it is created.
634        */
635        BspViewCell *GetOutOfBoundsCell();
636
637        ViewCellsTree *mViewCellsTree;
638       
639protected:
640
641        // --------------------------------------------------------------
642        // For sorting objects
643        // --------------------------------------------------------------
644        struct SortableEntry
645        {
646                enum {POLY_MIN, POLY_MAX};
647   
648                int type;
649                float value;
650                Polygon3 *poly;
651                SortableEntry() {}
652                SortableEntry(const int t, const float v, Polygon3 *poly):
653                type(t), value(v), poly(poly) {}
654               
655                bool operator<(const SortableEntry &b) const
656                {
657                        return value < b.value;
658                } 
659        };
660
661        void ExportNode(BspNode *node, ofstream &stream);
662
663        /** Evaluates tree stats in the BSP tree leafs.
664        */
665        void EvaluateLeafStats(const BspTraversalData &data);
666
667        /** Subdivides node with respect to the traversal data.
668            @param tStack current traversal stack
669                @param tData traversal data also holding node to be subdivided
670                @returns new root of the subtree
671        */
672        BspNode *Subdivide(BspTraversalStack &tStack, BspTraversalData &tData);
673
674        /** Constructs the tree from the given list of polygons and rays.
675                @param polys stores set of polygons on which subdivision may be based
676                @param rays storesset of rays on which subdivision may be based
677        */
678        void Construct(PolygonContainer *polys, BoundedRayContainer *rays);
679
680        /** Selects the best possible splitting plane.
681                @param leaf the leaf to be split
682                @param polys the polygon list on which the split decition is based
683                @param rays ray container on which selection may be based
684                @note the polygons can be reordered in the process
685                @returns the split plane
686        */
687        Plane3 SelectPlane(BspLeaf *leaf,
688                                           BspTraversalData &data);
689
690        /** Evaluates the contribution of the candidate split plane.
691               
692                @param candidatePlane the candidate split plane
693                @param polys the polygons the split can be based on
694                @param rays the rays the split can be based on
695
696                @returns the cost of the candidate split plane
697        */
698        float SplitPlaneCost(const Plane3 &candidatePlane,
699                                                 BspTraversalData &data) const;
700
701        /** Strategies where the effect of the split plane is tested
702            on all input rays.
703                @returns the cost of the candidate split plane
704        */
705        float SplitPlaneCost(const Plane3 &candidatePlane,
706                                                 const PolygonContainer &polys) const;
707
708        /** Strategies where the effect of the split plane is tested
709            on all input rays.
710
711                @returns the cost of the candidate split plane
712        */
713        float SplitPlaneCost(const Plane3 &candidatePlane,
714                                                 const BoundedRayContainer &rays,
715                                                 const int pvs,
716                                                 const float probability,
717                                                 const BspNodeGeometry &cell) const;
718
719        /** Filters next view cell down the tree and inserts it into the appropriate leaves
720                (i.e., possibly more than one leaf).
721        */
722        void InsertViewCell(ViewCell *viewCell);
723        /** Inserts polygons down the tree. The polygons are filtered until a leaf is reached,
724                then further subdivided.
725        */
726        void InsertPolygons(PolygonContainer *polys);
727
728        /** Subdivide leaf.
729                @param leaf the leaf to be subdivided
730               
731                @param polys the polygons to be split
732                @param frontPolys returns the polygons in front of the split plane
733                @param backPolys returns the polygons in the back of the split plane
734               
735                @param rays the polygons to be filtered
736                @param frontRays returns the polygons in front of the split plane
737                @param backRays returns the polygons in the back of the split plane
738
739                @returns the root of the subdivision
740        */
741
742        BspInterior *SubdivideNode(BspTraversalData &tData,
743                                                           BspTraversalData &frontData,
744                                                           BspTraversalData &backData,
745                                                           PolygonContainer &coincident);
746
747        /** Filters polygons down the tree.
748                @param node the current BSP node
749                @param polys the polygons to be filtered
750                @param frontPolys returns the polygons in front of the split plane
751                @param backPolys returns the polygons in the back of the split plane
752        */
753        void FilterPolygons(BspInterior *node,
754                                                PolygonContainer *polys,
755                                                PolygonContainer *frontPolys,
756                                                PolygonContainer *backPolys);
757
758        /** Take 3 ray endpoints, where two are minimum and one a maximum
759                point or the other way round.
760        */
761        Plane3 ChooseCandidatePlane(const BoundedRayContainer &rays) const;
762
763        /** Take plane normal as plane normal and the midpoint of the ray.
764                PROBLEM: does not resemble any point where visibility is likely to change
765        */
766        Plane3 ChooseCandidatePlane2(const BoundedRayContainer &rays) const;
767
768        /** Fit the plane between the two lines so that the plane has equal shortest
769                distance to both lines.
770        */
771        Plane3 ChooseCandidatePlane3(const BoundedRayContainer &rays) const;
772
773        /** Selects the split plane in order to construct a tree with
774                certain characteristics (e.g., balanced tree, least splits,
775                2.5d aligned)
776                @param polygons container of polygons
777                @param rays bundle of rays on which the split can be based
778        */
779        Plane3 SelectPlaneHeuristics(BspLeaf *leaf,
780                                                                 BspTraversalData &data);
781
782        /** Extracts the meshes of the objects and adds them to polygons.
783                Adds object aabb to the aabb of the tree.
784                @param maxPolys the maximal number of objects to be stored as polygons
785                @returns the number of polygons
786        */
787        int AddToPolygonSoup(const ObjectContainer &objects,
788                                                 PolygonContainer &polys,
789                                                 int maxObjects = 0,
790                                                 bool addToBbox = true);
791
792        /** Extracts the meshes of the view cells and and adds them to polygons.
793                Adds view cell aabb to the aabb of the tree.
794                @param maxPolys the maximal number of objects to be stored as polygons
795                @returns the number of polygons
796        */
797        int AddToPolygonSoup(const ViewCellContainer &viewCells,
798                                                 PolygonContainer &polys,
799                                                 int maxObjects = 0);
800
801        /** Extract polygons of this mesh and add to polygon container.
802                @param mesh the mesh that drives the polygon construction
803                @param parent the parent intersectable this polygon is constructed from
804                @returns number of polygons
805        */
806        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
807
808        /** Helper function which extracts a view cell on the front and the back
809                of the split plane.
810                @param backViewCell returns view cell on the back of the split plane
811                @param frontViewCell returns a view cell on the front of the split plane
812                @param coincident container of polygons coincident to the split plane
813                @param splitPlane the split plane which decides about back and front
814                @param extractBack if a back view cell is extracted
815                @param extractFront if a front view cell is extracted
816        */
817        void ExtractViewCells(BspTraversalData &frontData,
818                                                  BspTraversalData &backData,
819                                                  const PolygonContainer &coincident,
820                                                  const Plane3 &splitPlane) const;
821       
822        /** Computes best cost ratio for the suface area heuristics for axis aligned
823                splits. This heuristics minimizes the cost for ray traversal.
824                @param polys the polygons guiding the ratio computation
825                @param box the bounding box of the leaf
826                @param axis the current split axis
827                @param position returns the split position
828                @param objectsBack the number of objects in the back of the split plane
829                @param objectsFront the number of objects in the front of the split plane
830        */
831        float BestCostRatio(const PolygonContainer &polys,
832                                                const AxisAlignedBox3 &box,
833                                                const int axis,
834                                                float &position,
835                                                int &objectsBack,
836                                                int &objectsFront) const;
837       
838        /** Sorts split candidates for surface area heuristics for axis aligned splits.
839                @param polys the input for choosing split candidates
840                @param axis the current split axis
841                @param splitCandidates returns sorted list of split candidates
842        */
843        void SortSplitCandidates(const PolygonContainer &polys,
844                                                         const int axis,
845                                                         vector<SortableEntry> &splitCandidates) const;
846
847        /** Selects an axis aligned split plane.
848                Returns true if split is valied
849        */
850        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
851
852        /** Subdivides the rays into front and back rays according to the split plane.
853               
854                @param plane the split plane
855                @param rays contains the rays to be split. The rays are
856                           distributed into front and back rays.
857                @param frontRays returns rays on the front side of the plane
858                @param backRays returns rays on the back side of the plane
859               
860                @returns the number of splits
861        */
862        int SplitRays(const Plane3 &plane,
863                                  BoundedRayContainer &rays,
864                              BoundedRayContainer &frontRays,
865                                  BoundedRayContainer &backRays);
866
867
868        /** Extracts the split planes representing the space bounded by node n.
869        */
870        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
871
872        /** Adds the object to the pvs of the front and back leaf with a given classification.
873
874                @param obj the object to be added
875                @param cf the ray classification regarding the split plane
876                @param frontPvs returns the PVS of the front partition
877                @param backPvs returns the PVS of the back partition
878       
879        */
880        void AddObjToPvs(Intersectable *obj, const int cf, int &frontPvs, int &backPvs) const;
881
882        /** Computes PVS size induced by the rays.
883        */
884        int ComputePvsSize(const BoundedRayContainer &rays) const;
885
886        /** Returns true if tree can be terminated.
887        */
888        inline bool TerminationCriteriaMet(const BspTraversalData &data) const;
889
890        /** Computes accumulated ray lenght of this rays.
891        */
892        float AccumulatedRayLength(BoundedRayContainer &rays) const;
893
894        /** Splits polygons with respect to the split plane.
895                @param polys the polygons to be split. the polygons are consumed and
896                           distributed to the containers frontPolys, backPolys, coincident.
897                @param frontPolys returns the polygons in the front of the split plane
898                @param backPolys returns the polygons in the back of the split plane
899                @param coincident returns the polygons coincident to the split plane
900
901                @returns the number of splits   
902        */
903        int SplitPolygons(const Plane3 &plane,
904                                          PolygonContainer &polys,
905                                          PolygonContainer &frontPolys,
906                                          PolygonContainer &backPolys,
907                                          PolygonContainer &coincident) const;
908
909        /** Adds ray sample contributions to the PVS.
910                @param sampleContributions the number contributions of the samples
911                @param contributingSampels the number of contributing rays
912               
913        */
914        void AddToPvs(BspLeaf *leaf,
915                                  const BoundedRayContainer &rays,
916                                  int &sampleContributions,     
917                                  int &contributingSamples);
918
919        /** Preprocesses polygons and throws out all polygons which
920                are coincident to the view space box faces:
921                These polygons can can be problematic for bsp because they create
922                bad view cells.
923        */
924        void PreprocessPolygons(PolygonContainer &polys);
925
926        /** Returns view cell corresponding to the invalid view space.
927                If it does not exist, it is created.
928        */
929        BspViewCell *GetOrCreateOutOfBoundsCell();
930
931        /// Pointer to the root of the tree.
932        BspNode *mRoot;
933
934        /// Stores statistics during traversal.
935        BspTreeStatistics mStat;
936
937        /// Strategies for choosing next split plane.
938        enum {NO_STRATEGY = 0,
939                  RANDOM_POLYGON = 1,
940                  AXIS_ALIGNED = 2,
941                  LEAST_SPLITS = 4,
942                  BALANCED_POLYS = 8,
943                  BALANCED_VIEW_CELLS = 16,
944                  LARGEST_POLY_AREA = 32,
945                  VERTICAL_AXIS = 64,
946                  BLOCKED_RAYS = 128,
947                  LEAST_RAY_SPLITS = 256,
948                  BALANCED_RAYS = 512,
949                  PVS = 1024
950                };
951
952        /// box around the whole view domain
953        AxisAlignedBox3 mBox;
954
955        /// view cell corresponding to unbounded space
956        BspViewCell *mOutOfBoundsCell;
957
958        /// if view cells should be generated or the given view cells should be used.
959        bool mGenerateViewCells;
960
961        /// maximal number of polygons before subdivision termination
962        int mTermMinPolys;
963        /// maximal number of rays before subdivision termination
964        int mTermMinRays;
965        /// maximal possible depth
966        int mTermMaxDepth;
967        /// mininum area
968        float mTermMinProbability;
969        /// mininum PVS
970        int mTermMinPvs;
971
972        /// minimal number of polygons for axis aligned split
973        int mTermMinPolysForAxisAligned;
974        /// minimal number of rays for axis aligned split
975        int mTermMinRaysForAxisAligned;
976        /// minimal number of objects for axis aligned split
977        int mTermMinObjectsForAxisAligned;
978        /// maximal contribution per ray
979        float mTermMaxRayContribution;
980        /// minimal accumulated ray length
981        float mTermMinAccRayLength;
982
983
984        /// strategy to get the best split plane
985        int mSplitPlaneStrategy;
986        /// number of candidates evaluated for the next split plane
987        int mMaxPolyCandidates;
988        /// number of candidates for split planes evaluated using the rays
989        int mMaxRayCandidates;
990        /// maximum tests for split plane evaluation with a single candidate
991        int mMaxTests;
992
993        float mCtDivCi;
994
995        /// axis aligned split criteria
996        float mAxisAlignedCtDivCi;
997        float mSplitBorder;
998        float mMaxCostRatio;
999
1000        // factors guiding the split plane heuristics
1001        float mVerticalSplitsFactor;
1002        float mLargestPolyAreaFactor;
1003        float mBlockedRaysFactor;
1004        float mLeastRaySplitsFactor;
1005        float mBalancedRaysFactor;
1006        float mPvsFactor;
1007        float mLeastSplitsFactor;
1008        float mBalancedPolysFactor;
1009        float mBalancedViewCellsFactor;
1010
1011        /// if area or accumulated ray lenght should be used for PVS heuristics
1012        bool mUseAreaForPvs;
1013
1014        int mMaxViewCells;
1015
1016        /// epsilon where two points are still considered equal
1017        float mEpsilon;
1018
1019        ViewCellsManager *mViewCellsManager;
1020
1021        int mTimeStamp;
1022
1023        float mTotalCost;
1024        int mTotalPvsSize;
1025
1026        //int mSplits;
1027        ofstream  mSubdivisionStats;
1028
1029private:
1030       
1031        /** Evaluates split plane classification with respect to the plane's
1032                contribution for a balanced tree.
1033        */
1034        static const float sLeastPolySplitsTable[4];
1035        /** Evaluates split plane classification with respect to the plane's
1036                contribution for a minimum number splits in the tree.
1037        */
1038        static const float sBalancedPolysTable[4];
1039        /** Evaluates split plane classification with respect to the plane's
1040                contribution for a minimum number of ray splits.
1041        */
1042        static const float sLeastRaySplitsTable[5];
1043        /** Evaluates split plane classification with respect to the plane's
1044                contribution for balanced rays.
1045        */
1046        static const float sBalancedRaysTable[5];
1047
1048        /// Generates unique ids for PVS criterium
1049        static void GenerateUniqueIdsForPvs();
1050
1051        //-- unique ids for PVS criterium
1052        static int sFrontId;
1053        static int sBackId;
1054        static int sFrontAndBackId;
1055};
1056
1057
1058struct BspIntersection
1059{
1060        // the point of intersection
1061        float mT;
1062 
1063        BspLeaf *mLeaf;
1064 
1065        BspIntersection(const float t, BspLeaf *l):
1066        mT(t), mLeaf(l) {}
1067 
1068        BspIntersection() {}
1069 
1070        bool operator<(const BspIntersection &b) const
1071        {
1072                return mT < b.mT;
1073        }
1074};
1075
1076struct BspRay
1077{
1078        VssRay *vssRay;
1079
1080        std::vector<BspIntersection> intersections;
1081
1082        BspRay(VssRay *ray): vssRay(ray) {}
1083};
1084
1085#endif
Note: See TracBrowser for help on using the repository browser.