source: GTP/trunk/Lib/Vis/Preprocessing/src/VspOspTree.h @ 1159

Revision 1159, 46.2 KB checked in by mattausch, 18 years ago (diff)
Line 
1#ifndef _VspOspTree_H__
2#define _VspOspTree_H__
3
4#include <stack>
5
6#include "Mesh.h"
7#include "Containers.h"
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "gzstream.h"
12#include "FlexibleHeap.h"
13
14
15namespace GtpVisibilityPreprocessor {
16
17class ViewCellLeaf;
18//class VspViewCell;
19class Plane3;
20class AxisAlignedBox3;
21class Ray;
22class ViewCellsStatistics;
23class ViewCellsManager;
24class MergeCandidate;
25class Beam;
26class ViewCellsTree;
27class Environment;
28class VspInterior;
29class VspLeaf;
30class VspNode;
31class KdNode;
32class KdInterior;
33class KdLeaf;
34class OspTree;
35class KdIntersectable;
36class KdTree;
37class VspTree;
38class KdTreeStatistics;
39
40
41
42template <typename T> class GtPriority
43{
44public:
45        bool operator() (const T c1, const T c2) const
46        {
47                //return false;
48                return c1->GetPriority() < c2->GetPriority();
49        }
50};
51
52
53/** Candidate for a view space / object space split.
54*/
55class SplitCandidate: public Heapable
56
57public:
58
59        enum {OBJECT_SPACE, VIEW_SPACE};
60
61        /// the current split plane
62        AxisAlignedPlane mSplitPlane;
63        /// split axis of this plane (0, 1, 2, or 3 if non-axis-aligned)
64        int mSplitAxis;
65        /// the number of misses of max cost ratio until this split
66        int mMaxCostMisses;
67
68        SplitCandidate()
69        {};
70
71        SplitCandidate(const AxisAlignedPlane &plane): mSplitPlane(plane)
72        {}
73
74        virtual void EvalPriority() = 0;
75        virtual int Type() const = 0;
76        virtual bool GlobalTerminationCriteriaMet() const = 0;
77
78        /** Set render cost decrease achieved through this split.
79        */
80        void SetRenderCostDecrease(const float renderCostDecr)
81        {
82                mRenderCostDecrease = renderCostDecr;
83        }
84       
85        float GetRenderCostDecrease() const
86        {
87                return mRenderCostDecrease;
88        }
89
90protected:
91
92        /// render cost decrease achieved through this split
93        float mRenderCostDecrease;
94       
95};
96
97
98/** View space partition statistics.
99*/
100class VspTreeStatistics: public StatisticsBase
101{
102public:
103        // total number of nodes
104        int nodes;
105        // number of splits
106        int splits[3];
107       
108        // totals number of rays
109        int rays;
110        // maximal reached depth
111        int maxDepth;
112        // minimal depth
113        int minDepth;
114       
115        // max depth nodes
116        int maxDepthNodes;
117        // minimum depth nodes
118        int minDepthNodes;
119        // max depth nodes
120        int minPvsNodes;
121        // nodes with minimum PVS
122        int minRaysNodes;
123        // max ray contribution nodes
124        int maxRayContribNodes;
125        // minimum area nodes
126        int minProbabilityNodes;
127        /// nodes termination because of max cost ratio;
128        int maxCostNodes;
129        // max number of rays per node
130        int maxObjectRefs;
131        /// samples contributing to pvs
132        int contributingSamples;
133        /// sample contributions to pvs
134        int sampleContributions;
135        /// largest pvs
136        int maxPvs;
137        /// number of invalid leaves
138        int invalidLeaves;
139        /// accumulated number of rays refs
140        int accumRays;
141        int pvs;
142        // accumulated depth (used to compute average)
143        int accumDepth;
144
145        // Constructor
146        VspTreeStatistics()
147        {
148                Reset();
149        }
150
151        int Nodes() const {return nodes;}
152        int Interior() const { return nodes / 2; }
153        int Leaves() const { return (nodes / 2) + 1; }
154       
155        // TODO: computation wrong
156        double AvgDepth() const { return accumDepth / (double)Leaves();};
157        double AvgRays() const { return accumRays / (double)Leaves();};
158
159        void Reset()
160        {
161                nodes = 0;
162                for (int i = 0; i < 3; ++ i)
163                        splits[i] = 0;
164               
165                maxDepth = 0;
166                minDepth = 99999;
167                accumDepth = 0;
168        pvs = 0;
169                maxDepthNodes = 0;
170                minPvsNodes = 0;
171                minRaysNodes = 0;
172                maxRayContribNodes = 0;
173                minProbabilityNodes = 0;
174                maxCostNodes = 0;
175
176                contributingSamples = 0;
177                sampleContributions = 0;
178
179                maxPvs = 0;
180                invalidLeaves = 0;
181                accumRays = 0;
182        }
183
184        void Print(ostream &app) const;
185
186        friend ostream &operator<<(ostream &s, const VspTreeStatistics &stat)
187        {
188                stat.Print(s);
189                return s;
190        }
191};
192
193
194/** View space partition statistics.
195*/
196class OspTreeStatistics: public StatisticsBase
197{
198public:
199        // total number of nodes
200        int nodes;
201        // number of splits
202        int splits[3];
203       
204        // maximal reached depth
205        int maxDepth;
206        // minimal depth
207        int minDepth;
208       
209        // max depth nodes
210        int maxDepthNodes;
211        // minimum depth nodes
212        int minDepthNodes;
213        // max depth nodes
214        int minPvsNodes;
215        // minimum area nodes
216        int minProbabilityNodes;
217        /// nodes termination because of max cost ratio;
218        int maxCostNodes;
219        // max number of objects per node
220        int maxObjectRefs;
221        int objectRefs;
222        /// samples contributing to pvs
223        int contributingSamples;
224        /// sample contributions to pvs
225        int sampleContributions;
226        /// largest pvs
227        int maxPvs;
228        /// number of invalid leaves
229        int invalidLeaves;
230        /// accumulated number of rays refs
231        int accumRays;
232        /// potentially visible objects from this leaf
233        int pvs;
234
235        // accumulated depth (used to compute average)
236        int accumDepth;
237
238        // Constructor
239        OspTreeStatistics()
240        {
241                Reset();
242        }
243
244        int Nodes() const {return nodes;}
245        int Interior() const { return nodes / 2; }
246        int Leaves() const { return (nodes / 2) + 1; }
247       
248        // TODO: computation wrong
249        double AvgDepth() const { return accumDepth / (double)Leaves();};
250       
251
252        void Reset()
253        {
254                nodes = 0;
255                for (int i = 0; i < 3; ++ i)
256                        splits[i] = 0;
257               
258                maxDepth = 0;
259                minDepth = 99999;
260                accumDepth = 0;
261        pvs = 0;
262                maxDepthNodes = 0;
263                minPvsNodes = 0;
264       
265                minProbabilityNodes = 0;
266                maxCostNodes = 0;
267
268                contributingSamples = 0;
269                sampleContributions = 0;
270
271                maxPvs = 0;
272                invalidLeaves = 0;
273                objectRefs = 0;
274        }
275
276
277        void Print(ostream &app) const;
278
279        friend ostream &operator<<(ostream &s, const OspTreeStatistics &stat)
280        {
281                stat.Print(s);
282                return s;
283        }
284};
285
286
287/**
288    VspNode abstract class serving for interior and leaf node implementation
289*/
290class VspNode
291{
292public:
293       
294        // types of vsp nodes
295        enum {Interior, Leaf};
296
297        VspNode();
298        virtual ~VspNode(){};
299        VspNode(VspInterior *parent);
300
301        /** Determines whether this node is a leaf or not
302                @return true if leaf
303        */
304        virtual bool IsLeaf() const = 0;
305
306        virtual int Type() const = 0;
307
308        /** Determines whether this node is a root
309                @return true if root
310        */
311        virtual bool IsRoot() const;
312
313        /** Returns parent node.
314        */
315        VspInterior *GetParent();
316
317        /** Sets parent node.
318        */
319        void SetParent(VspInterior *parent);
320
321        /** Returns true if this node is a sibling of node n.
322        */
323        bool IsSibling(VspNode *n) const;
324
325        /** returns depth of the node.
326        */
327        int GetDepth() const;
328
329        /** returns true if the whole subtree is valid
330        */
331        bool TreeValid() const;
332
333        void SetTreeValid(const bool v);
334
335        //-- mailing options
336
337        void Mail() { mMailbox = sMailId; }
338        static void NewMail() { ++ sMailId; }
339        bool Mailed() const { return mMailbox == sMailId; }
340
341        static int sMailId;
342        int mMailbox;
343
344        int mTimeStamp;
345
346protected:
347
348        /// if this sub tree is a completely valid view space region
349        bool mTreeValid;
350        /// parent of this node
351        VspInterior *mParent;
352};
353
354
355/** BSP interior node implementation
356*/
357class VspInterior: public VspNode
358{
359public:
360        /** Standard contructor taking split plane as argument.
361        */
362        VspInterior(const AxisAlignedPlane &plane);
363
364        ~VspInterior();
365        /** @return false since it is an interior node
366        */
367        bool IsLeaf() const;
368
369        int Type() const;
370
371        VspNode *GetBack();
372        VspNode *GetFront();
373
374        /** Returns split plane.
375        */
376        AxisAlignedPlane GetPlane() const;
377
378        /** Returns position of split plane.
379        */
380        float GetPosition() const;
381
382        /** Returns split axis.
383        */
384        int GetAxis() const;
385
386        /** Replace front or back child with new child.
387        */
388        void ReplaceChildLink(VspNode *oldChild, VspNode *newChild);
389
390        /** Replace front and back child.
391        */
392        void SetupChildLinks(VspNode *front, VspNode *back);
393
394        friend ostream &operator<<(ostream &s, const VspInterior &A)
395        {
396                return s << A.mPlane.mAxis << " " << A.mPlane.mPosition;
397        }
398
399        AxisAlignedBox3 GetBoundingBox() const;
400        void SetBoundingBox(const AxisAlignedBox3 &box);
401
402        /** Computes intersection of this plane with the ray segment.
403        */
404        int ComputeRayIntersection(const RayInfo &rayData, float &t) const
405        {
406                return rayData.ComputeRayIntersection(mPlane.mAxis, mPlane.mPosition, t);
407        }
408
409
410protected:
411
412        AxisAlignedBox3 mBoundingBox;
413
414        /// Splitting plane corresponding to this node
415        AxisAlignedPlane mPlane;
416
417        /// back node
418        VspNode *mBack;
419        /// front node
420        VspNode *mFront;
421};
422
423
424/** BSP leaf node implementation.
425*/
426class VspLeaf: public VspNode
427{
428        friend VspTree;
429
430public:
431        VspLeaf();
432        VspLeaf(ViewCellLeaf *viewCell);
433        VspLeaf(VspInterior *parent);
434        VspLeaf(VspInterior *parent, ViewCellLeaf *viewCell);
435
436        ~VspLeaf();
437
438        /** @return true since it is an interior node
439        */
440        bool IsLeaf() const;
441       
442        int Type() const;
443
444        /** Returns pointer of view cell.
445        */
446        ViewCellLeaf *GetViewCell() const;
447
448        /** Sets pointer to view cell.
449        */
450        void SetViewCell(ViewCellLeaf *viewCell);
451
452        SplitCandidate *GetSplitCandidate() const
453        { return mSplitCandidate; }
454
455public:
456
457        /// Rays piercing this leaf.
458        VssRayContainer mVssRays;
459       
460        /// leaf pvs
461        ObjectPvs *mPvs;
462
463        /// Probability that the view point lies in this leaf
464        float mProbability;
465
466protected:
467
468        /// pointer to a split plane candidate splitting this leaf
469        SplitCandidate *mSplitCandidate;
470
471        /// if NULL this does not correspond to feasible viewcell
472        ViewCellLeaf *mViewCell;
473};
474
475
476#if 0
477typedef std::priority_queue<SplitCandidate *,
478                                                        std::vector<SplitCandidate *>,
479                                                        GtPriority<std::vector<SplitCandidate *>::value_type> > SplitQueue;
480#endif
481
482typedef map<KdNode *, KdIntersectable *> KdIntersectableMap;
483
484typedef FlexibleHeap<SplitCandidate *> SplitQueue;
485
486/** View Space Partitioning tree.
487*/
488class VspTree
489{
490        friend class ViewCellsParseHandlers;
491        friend class HierarchyManager;
492
493public:
494       
495        /** Additional data which is passed down the BSP tree during traversal.
496        */
497        class VspTraversalData
498        { 
499        public:
500                /// the current node
501                VspLeaf *mNode;
502                /// current depth
503                int mDepth;
504                /// rays piercing this node
505                RayInfoContainer *mRays;
506                /// the probability that this node contains view point
507                float mProbability;
508                /// the bounding box of the node
509                AxisAlignedBox3 mBoundingBox;
510                /// pvs size
511                int mPvs;
512                /// how often this branch has missed the max-cost ratio
513                int mMaxCostMisses;
514                // current priority
515                float mPriority;
516
517               
518                /** Returns average ray contribution.
519                */
520                float GetAvgRayContribution() const
521                {
522                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
523                }
524
525
526                VspTraversalData():
527                mNode(NULL),
528                mDepth(0),
529                mRays(NULL),
530                mPvs(0),
531                mProbability(0.0),
532                mMaxCostMisses(0),
533                mPriority(0)
534                {}
535               
536                VspTraversalData(VspLeaf *node,
537                                                 const int depth,
538                                                 RayInfoContainer *rays,
539                                                 const int pvs,
540                                                 const float p,
541                                                 const AxisAlignedBox3 &box):
542                mNode(node),
543                mDepth(depth),
544                mRays(rays),
545                mPvs(pvs),
546                mProbability(p),
547                mBoundingBox(box),
548                mMaxCostMisses(0),
549                mPriority(0)
550                {}
551
552                VspTraversalData(const int depth,
553                                                 RayInfoContainer *rays,
554                                                 const AxisAlignedBox3 &box):
555                mNode(NULL),
556                mDepth(depth),
557                mRays(rays),
558                mPvs(0),
559                mProbability(0),
560                mMaxCostMisses(0),
561                mBoundingBox(box)
562                {}
563
564                /** Returns cost of the traversal data.
565                */
566                float GetCost() const
567                {
568                        //cout << mPriority << endl;
569                        return mPriority;
570                }
571
572                /// deletes contents and sets them to NULL
573                void Clear()
574                {
575                        DEL_PTR(mRays);
576                }
577
578                friend bool operator<(const VspTraversalData &a, const VspTraversalData &b)
579                {
580                        return a.GetCost() < b.GetCost();
581                }
582    };
583
584        /** Candidate for a view space split.
585        */
586        class VspSplitCandidate: public SplitCandidate
587        { 
588        public:
589
590                static VspTree* sVspTree;
591
592                /// parent node traversal data
593                VspTraversalData mParentData;
594               
595                VspSplitCandidate(const VspTraversalData &tData): mParentData(tData)
596                {};
597
598                int Type() const { return VIEW_SPACE; }
599
600                void EvalPriority()
601                {
602                        sVspTree->EvalSplitCandidate(*this);   
603                }
604
605                bool GlobalTerminationCriteriaMet() const
606                {
607                        return sVspTree->GlobalTerminationCriteriaMet(mParentData);
608                }
609
610                VspSplitCandidate(const AxisAlignedPlane &plane, const VspTraversalData &tData):
611                SplitCandidate(plane), mParentData(tData)
612                {}
613        };
614
615        /** Struct for traversing line segment.
616        */
617        struct LineTraversalData
618        {
619                VspNode *mNode;
620                Vector3 mExitPoint;
621               
622                float mMaxT;
623   
624                LineTraversalData () {}
625                LineTraversalData (VspNode *n, const Vector3 &p, const float maxt):
626                mNode(n), mExitPoint(p), mMaxT(maxt) {}
627        };
628
629        //typedef std::priority_queue<VspTraversalData> VspOspTraversalQueue;
630
631        /** Default constructor creating an empty tree.
632        */
633        VspTree();
634
635        /** Default destructor.
636        */
637        ~VspTree();
638
639        /** Returns BSP Tree statistics.
640        */
641        const VspTreeStatistics &GetStatistics() const;
642 
643        /** Returns bounding box of the specified node.
644        */
645        AxisAlignedBox3 GetBoundingBox(VspNode *node) const;
646
647        /** Returns list of BSP leaves with pvs smaller than
648                a certain threshold.
649                @param onlyUnmailed if only the unmailed leaves should be considered
650                @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited)
651        */
652        void CollectLeaves(vector<VspLeaf *> &leaves,
653                                           const bool onlyUnmailed = false,
654                                           const int maxPvs = -1) const;
655
656        /** Returns box which bounds the whole tree.
657        */
658        AxisAlignedBox3 GetBoundingBox() const;
659
660        /** Returns root of the view space partitioning tree.
661        */
662        VspNode *GetRoot() const;
663
664        /** Collects the leaf view cells of the tree
665                @param viewCells returns the view cells
666        */
667        void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
668
669        /** A ray is cast possible intersecting the tree.
670                @param the ray that is cast.
671                @returns the number of intersections with objects stored in the tree.
672        */
673        int CastRay(Ray &ray);
674
675
676        /** finds neighbouring leaves of this tree node.
677        */
678        int FindNeighbors(VspLeaf *n,
679                                          vector<VspLeaf *> &neighbors,
680                                          const bool onlyUnmailed) const;
681
682        /** Returns random leaf of BSP tree.
683                @param halfspace defines the halfspace from which the leaf is taken.
684        */
685        VspLeaf *GetRandomLeaf(const Plane3 &halfspace);
686
687        /** Returns random leaf of BSP tree.
688                @param onlyUnmailed if only unmailed leaves should be returned.
689        */
690        VspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
691
692        /** Returns epsilon of this tree.
693        */
694        float GetEpsilon() const;
695
696        /** Casts line segment into the tree.
697                @param origin the origin of the line segment
698                @param termination the end point of the line segment
699                @returns view cells intersecting the line segment.
700        */
701    int CastLineSegment(const Vector3 &origin,
702                                                const Vector3 &termination,
703                                                ViewCellContainer &viewcells);
704
705               
706        /** Sets pointer to view cells manager.
707        */
708        void SetViewCellsManager(ViewCellsManager *vcm);
709
710        /** Returns view cell the current point is located in.
711                @param point the current view point
712                @param active if currently active view cells should be returned or
713                elementary view cell
714        */
715        ViewCell *GetViewCell(const Vector3 &point, const bool active = false);
716
717
718        /** Returns true if this view point is in a valid view space,
719                false otherwise.
720        */
721        bool ViewPointValid(const Vector3 &viewPoint) const;
722
723        /** Returns view cell corresponding to
724                the invalid view space.
725        */
726        VspViewCell *GetOutOfBoundsCell();
727
728        /** Writes tree to output stream
729        */
730#if ZIPPED_VIEWCELLS
731        bool Export(ogzstream &stream);
732#else
733        bool Export(ofstream &stream);
734#endif
735
736        /** Casts beam, i.e. a 5D frustum of rays, into tree.
737                Tests conservative using the bounding box of the nodes.
738                @returns number of view cells it intersected
739        */
740        int CastBeam(Beam &beam);
741
742
743        /** Checks if tree validity-flags are right
744                with respect to view cell valitiy.
745                If not, marks subtree as invalid.
746        */
747        void ValidateTree();
748
749        /** Invalid view cells are added to the unbounded space
750        */
751        void CollapseViewCells();
752
753        /** Collects rays stored in the leaves.
754        */
755        void CollectRays(VssRayContainer &rays);
756
757        /** Intersects box with the tree and returns the number of intersected boxes.
758                @returns number of view cells found
759        */
760        int ComputeBoxIntersections(const AxisAlignedBox3 &box,
761                                                                ViewCellContainer &viewCells) const;
762
763        /** Remove the references of the parent view cell from the kd nodes associated with
764                the objects.
765        */
766        void RemoveParentViewCellReferences(ViewCell *parent) const;
767
768        /** Adds references to the view cell to the kd nodes associated with the objects.
769        */
770        void AddViewCellReferences(ViewCell *vc) const;
771
772        /** Returns view cells of this ray, either taking precomputed cells
773                or by recomputation.
774        */
775        void GetViewCells(const VssRay &ray, ViewCellContainer &viewCells);
776
777
778        /// pointer to the hierarchy of view cells
779        ViewCellsTree *mViewCellsTree;
780
781        OspTree *mOspTree;
782
783protected:
784
785        // --------------------------------------------------------------
786        // For sorting objects
787        // --------------------------------------------------------------
788        struct SortableEntry
789        {
790                enum EType
791                {
792                        ERayMin,
793                        ERayMax
794                };
795
796                int type;
797                float value;
798                VssRay *ray;
799 
800                SortableEntry() {}
801                SortableEntry(const int t, const float v, VssRay *r):
802                type(t), value(v), ray(r)
803                {
804                }
805               
806                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
807                {
808                        return a.value < b.value;
809                }
810        };
811
812        /** faster evaluation of split plane cost for kd axis aligned cells.
813        */
814        float EvalLocalSplitCost(const VspTraversalData &data,
815                                                         const AxisAlignedBox3 &box,
816                                                         const int axis,
817                                                         const float &position,
818                                                         float &pFront,
819                                                         float &pBack) const;
820
821        void ComputeBoundingBox(const VssRayContainer &rays,
822                                                        AxisAlignedBox3 *forcedBoundingBox);
823
824        /** Evaluates candidate for splitting.
825        */
826        void EvalSplitCandidate(VspSplitCandidate &splitData);
827
828        /** Evaluates render cost decrease of next split.
829        */
830        float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
831                                                                 const VspTraversalData &data,
832                                                                 float &normalizedOldRenderCost) const;
833
834        /** Collects view cells in the subtree under root.
835        */
836        void CollectViewCells(VspNode *root,
837                                                  bool onlyValid,
838                                                  ViewCellContainer &viewCells,
839                                                  bool onlyUnmailed = false) const;
840
841        /** Returns view cell corresponding to
842                the invalid view space. If it does not exist, it is created.
843        */
844        VspViewCell *GetOrCreateOutOfBoundsCell();
845
846        /** Collapses the tree with respect to the view cell partition,
847                i.e. leaves having the same view cell are collapsed.
848                @param node the root of the subtree to be collapsed
849                @param collapsed returns the number of collapsed nodes
850                @returns node of type leaf if the node could be collapsed,
851                this node otherwise
852        */
853        VspNode *CollapseTree(VspNode *node, int &collapsed);
854
855        /** Helper function revalidating the view cell leaf list after merge.
856        */
857        void RepairViewCellsLeafLists();
858
859        /** Evaluates tree stats in the BSP tree leafs.
860        */
861        void EvaluateLeafStats(const VspTraversalData &data);
862
863        /** Subdivides node using a best split priority queue.
864            @param tQueue the best split priority queue
865                @param splitCandidate the candidate for the next split
866                @param globalCriteriaMet if the global termination criteria were already met
867                @returns new root of the subtree
868        */
869        VspNode *Subdivide(SplitQueue &tQueue,
870                                           SplitCandidate *splitCandidate,
871                                           const bool globalCriteriaMet);
872
873        /** Adds stats to subdivision log file.
874        */
875        void AddSubdivisionStats(const int viewCells,
876                                                         const float renderCostDecr,
877                                                         const float totalRenderCost,
878                                                         const float avgRenderCost);
879       
880        /** Subdivides leaf.
881                       
882                @param tData data object holding, e.g., a pointer to the leaf
883                @param frontData returns the data (e.g.,  pointer to the leaf) in front of the split plane
884                @param backData returns the data (e.g.,  pointer to the leaf) in the back of the split plane
885               
886                @param rays the polygons to be filtered
887                @param frontRays returns the polygons in front of the split plane
888       
889                @returns the root of the subdivision
890        */
891        VspInterior *SubdivideNode(const AxisAlignedPlane &splitPlane,
892                                                           VspTraversalData &tData,
893                                                           VspTraversalData &frontData,
894                               VspTraversalData &backData);
895
896        /** Selects an axis aligned for the next split.
897                @returns cost for this split
898        */
899        float SelectSplitPlane(const VspTraversalData &tData,
900                                                   AxisAlignedPlane &plane,
901                                                   float &pFront,
902                                                   float &pBack);
903
904        /** Sorts split candidates along the specified axis.
905                The split candidates are generated on possible visibility
906                events (i.e., where ray segments intersect the ray boundaries).
907                The sorted candidates are needed to compute the heuristics.
908
909                @param polys the input for choosing split candidates
910                @param axis the current split axis
911                @param splitCandidates returns sorted list of split candidates
912        */
913        void SortSplitCandidates(const RayInfoContainer &rays,
914                                                         const int axis,
915                                                         float minBand,
916                                                         float maxBand);
917
918        /** Computes pvs increase with respect to the previous pvs for heuristics.
919        */
920        int GetPvsIncr(Intersectable *object, const KdPvsMap &activeNodes);
921
922        /** Returns absolute pvs contribution of this object.
923        */
924        int GetPvsContribution(Intersectable *object) const;
925
926        /** Computes best cost for axis aligned planes.
927        */
928        float EvalLocalCostHeuristics(const VspTraversalData &tData,
929                                                                  const AxisAlignedBox3 &box,
930                                                                  const int axis,
931                                                                  float &position);
932
933        /** Evaluates the influence on the pvs of the visibility event ve.
934                @param ve the visibility event
935                @param pvsLeft updates the left pvs
936                @param rightPvs updates the right pvs
937        */
938        void EvalPvsIncr(const SortableEntry &ve,
939                                          int &pvsLeft,
940                                          int &pvsRight) const;
941
942        void RemoveContriFromPvs(KdLeaf *leaf, int &pvs) const;
943        void AddContriToPvs(KdLeaf *leaf, int &pvs) const;
944
945        /** Prepares objects for the heuristics.
946                @returns pvs size of the ray container
947        */
948        int PrepareHeuristics(const RayInfoContainer &rays);
949
950        int PrepareHeuristics(KdLeaf *leaf);
951
952        /** Subdivides the rays into front and back rays according to the split plane.
953               
954                @param plane the split plane
955                @param rays contains the rays to be split. The rays are
956                           distributed into front and back rays.
957                @param frontRays returns rays on the front side of the plane
958                @param backRays returns rays on the back side of the plane
959               
960                @returns the number of splits
961        */
962        int SplitRays(const AxisAlignedPlane &plane,
963                                  RayInfoContainer &rays,
964                              RayInfoContainer &frontRays,
965                                  RayInfoContainer &backRays) const;
966
967        /** Adds the object to the pvs of the front and back leaf with a given classification.
968
969                @param obj the object to be added
970                @param cf the ray classification regarding the split plane
971                @param frontPvs returns the PVS of the front partition
972                @param backPvs returns the PVS of the back partition
973       
974        */
975        void AddObjToPvs(Intersectable *obj,
976                                         const int cf,
977                                         float &frontPvs,
978                                         float &backPvs,
979                                         float &totalPvs) const;
980       
981        /** Computes PVS size induced by the rays.
982        */
983        int ComputePvsSize(const RayInfoContainer &rays) const;
984       
985        /** Collects pvs from rays.
986        */
987        void CollectPvs(const RayInfoContainer &rays,
988                                        ObjectContainer &objects) const;
989
990        /** Returns true if tree can be terminated.
991        */
992        inline bool LocalTerminationCriteriaMet(const VspTraversalData &data) const;
993
994        /** Returns true if global tree can be terminated.
995        */
996        inline bool GlobalTerminationCriteriaMet(const VspTraversalData &data) const;
997
998        /** Adds ray sample contributions to the PVS.
999                @param sampleContributions the number contributions of the samples
1000                @param contributingSampels the number of contributing rays
1001               
1002        */
1003        void AddSamplesToPvs(VspLeaf *leaf,
1004                                  const RayInfoContainer &rays,
1005                                  float &sampleContributions,
1006                                  int &contributingSamples);
1007
1008        bool AddKdLeafToPvs(KdLeaf *leaf, ViewCell *vc, float &pvs, float &contribution);
1009
1010        /** Propagates valid flag up the tree.
1011        */
1012        void PropagateUpValidity(VspNode *node);
1013
1014        /** Writes the node to disk
1015                @note: should be implemented as visitor.
1016        */
1017#if ZIPPED_VIEWCELLS
1018        void ExportNode(VspNode *node, ogzstream &stream);
1019#else
1020        void ExportNode(VspNode *node, ofstream &stream);
1021#endif
1022
1023        /** Returns estimated memory usage of tree.
1024        */
1025        float GetMemUsage() const;
1026
1027        void ProcessViewCellObjects(ViewCell *parent,
1028                ViewCell *front,
1029                ViewCell *back) const;
1030
1031        void CreateViewCell(VspTraversalData &tData, const bool updatePvs);
1032
1033        void CollectDirtyCandidates(VspSplitCandidate *sc,
1034                vector<SplitCandidate *> &dirtyList);
1035
1036        KdNode *GetKdNode(VssRay &ray, const bool termination) const;
1037
1038        void ProcessRays(const VssRayContainer &sampleRays,
1039                RayInfoContainer &rays);
1040
1041        void EvalSubdivisionStats(const VspTraversalData &tData,
1042                                                          const VspTraversalData &tFrontData,
1043                                                          const VspTraversalData &tBackData);
1044protected:
1045
1046
1047        bool mUseKdPvsForHeuristics;
1048        bool mStoreKdPvs;
1049
1050        ViewCellsManager *mViewCellsManager;
1051       
1052        vector<SortableEntry> *mSplitCandidates;
1053
1054        /// Pointer to the root of the tree
1055        VspNode *mRoot;
1056               
1057        VspTreeStatistics mVspStats;
1058       
1059        /// View cell corresponding to the space outside the valid view space
1060        VspViewCell *mOutOfBoundsCell;
1061
1062        /// box around the whole view domain
1063        AxisAlignedBox3 mBoundingBox;
1064
1065
1066        //-- local termination
1067
1068        /// minimal number of rays before subdivision termination
1069        int mTermMinRays;
1070        /// maximal possible depth
1071        int mTermMaxDepth;
1072        /// mininum probability
1073        float mTermMinProbability;
1074        /// mininum PVS
1075        int mTermMinPvs;
1076        /// maximal contribution per ray
1077        float mTermMaxRayContribution;
1078        /// maximal acceptable cost ratio
1079        float mTermMaxCostRatio;
1080        /// tolerance value indicating how often the max cost ratio can be failed
1081        int mTermMissTolerance;
1082
1083
1084        //-- global criteria
1085        float mTermMinGlobalCostRatio;
1086        int mTermGlobalCostMissTolerance;
1087        int mGlobalCostMisses;
1088
1089        /// maximal number of view cells
1090        int mMaxViewCells;
1091        /// maximal tree memory
1092        float mMaxMemory;
1093        /// the tree is out of memory
1094        bool mOutOfMemory;
1095
1096
1097
1098        //-- split heuristics based parameters
1099       
1100        bool mUseCostHeuristics;
1101        /// balancing factor for PVS criterium
1102        float mCtDivCi;
1103        /// if only driving axis should be used for split
1104        bool mOnlyDrivingAxis;
1105        /// if random split axis should be used
1106        bool mUseRandomAxis;
1107        /// if vsp bsp tree should simulate octree
1108        bool mCirculatingAxis;
1109        /// minimal relative position where the split axis can be placed
1110        float mMinBand;
1111        /// maximal relative position where the split axis can be placed
1112        float mMaxBand;
1113
1114
1115        /// current time stamp (used for keeping split history)
1116        int mTimeStamp;
1117        // if rays should be stored in leaves
1118        bool mStoreRays;
1119
1120        /// epsilon for geometric comparisons
1121        float mEpsilon;
1122
1123
1124        /// subdivision stats output file
1125        ofstream  mSubdivisionStats;
1126        /// keeps track of cost during subdivision
1127        float mTotalCost;
1128        /// keeps track of overall pvs size during subdivision
1129        int mTotalPvsSize;
1130        /// number of currenly generated view cells
1131        int mCreatedViewCells;
1132
1133        /// weight between render cost decrease and node render cost
1134        float mRenderCostDecreaseWeight;
1135
1136        int mMaxTests;
1137};
1138
1139
1140/** View Space Partitioning tree.
1141*/
1142class OspTree
1143{
1144        friend class ViewCellsParseHandlers;
1145        friend class HierarchyManager;
1146
1147public:
1148       
1149        /** Additional data which is passed down the BSP tree during traversal.
1150        */
1151        class OspTraversalData
1152        { 
1153        public:
1154                /// the current node
1155                KdLeaf *mNode;
1156                /// current depth
1157                int mDepth;
1158                /// rays piercing this node
1159                RayInfoContainer *mRays;
1160                /// the probability that this node contains view point
1161                float mProbability;
1162                /// the bounding box of the node
1163                AxisAlignedBox3 mBoundingBox;
1164                /// pvs size
1165                int mPvs;
1166                /// how often this branch has missed the max-cost ratio
1167                int mMaxCostMisses;
1168                // current axis
1169                int mAxis;
1170                // current priority
1171                float mPriority;
1172
1173
1174                OspTraversalData():
1175                mNode(NULL),
1176                mRays(NULL),
1177                mDepth(0),
1178                mPvs(0),
1179                mProbability(0.0),
1180                mMaxCostMisses(0),
1181                mPriority(0),
1182                mAxis(0)
1183                {}
1184               
1185                OspTraversalData(KdLeaf *node,
1186                                                 const int depth,
1187                         RayInfoContainer *rays,
1188                                                 const int pvs,
1189                                                 const float p,
1190                                                 const AxisAlignedBox3 &box):
1191                mNode(node),
1192                mDepth(depth),
1193                mRays(rays),
1194                mPvs(pvs),
1195                mProbability(p),
1196                mBoundingBox(box),
1197                mMaxCostMisses(0),
1198                mPriority(0),
1199                mAxis(0)
1200                {}
1201
1202                OspTraversalData(const int depth,
1203                        RayInfoContainer *rays,
1204                        const AxisAlignedBox3 &box):
1205                mNode(NULL),
1206                mDepth(depth),
1207                mRays(rays),
1208                mPvs(0),
1209                mProbability(0),
1210                mMaxCostMisses(0),
1211                mAxis(0),
1212                mBoundingBox(box)
1213                {}
1214
1215                /** Returns cost of the traversal data.
1216                */
1217                float GetCost() const
1218                {
1219                        //cout << mPriority << endl;
1220                        return mPriority;
1221                }
1222
1223                /// deletes contents and sets them to NULL
1224                void Clear()
1225                {
1226                        DEL_PTR(mRays);
1227                }
1228
1229
1230                friend bool operator<(const OspTraversalData &a, const OspTraversalData &b)
1231                {
1232                        return a.GetCost() < b.GetCost();
1233                }
1234    };
1235
1236        /** Candidate for a view space split.
1237        */
1238        class OspSplitCandidate: public SplitCandidate
1239        { 
1240        public:
1241                static OspTree* sOspTree;
1242
1243                /// parent data
1244                OspTraversalData mParentData;
1245               
1246                OspSplitCandidate(const OspTraversalData &tData): mParentData(tData)
1247                {};
1248
1249                int Type() const { return OBJECT_SPACE; }
1250       
1251                void EvalPriority()
1252                {
1253                        sOspTree->EvalSplitCandidate(*this);   
1254                }
1255
1256                bool GlobalTerminationCriteriaMet() const
1257                {
1258                        return sOspTree->GlobalTerminationCriteriaMet(mParentData);
1259                }
1260
1261
1262                OspSplitCandidate(const AxisAlignedPlane &plane, const OspTraversalData &tData):
1263                SplitCandidate(plane), mParentData(tData)
1264                {}
1265        };
1266
1267        /** Struct for traversing line segment.
1268        */
1269        struct LineTraversalData
1270        {
1271                KdNode *mNode;
1272                Vector3 mExitPoint;
1273               
1274                float mMaxT;
1275   
1276                LineTraversalData () {}
1277                LineTraversalData (KdNode *n, const Vector3 &p, const float maxt):
1278                mNode(n), mExitPoint(p), mMaxT(maxt) {}
1279        };
1280
1281        //typedef std::priority_queue<VspTraversalData> VspOspTraversalQueue;
1282
1283        /** Default constructor creating an empty tree.
1284        */
1285        OspTree();
1286
1287        OspTree(const KdTree &kdTree);
1288
1289        /** Default destructor.
1290        */
1291        ~OspTree();
1292
1293        /** Returns tree statistics.
1294        */
1295        const OspTreeStatistics &GetStatistics() const;
1296 
1297        /** Returns bounding box of the specified node.
1298        */
1299        AxisAlignedBox3 GetBoundingBox(KdNode *node) const;
1300
1301        /** Returns list of leaves with pvs smaller than
1302                a certain threshold.
1303                @param onlyUnmailed if only the unmailed leaves should be considered
1304                @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited)
1305        */
1306       
1307        void CollectLeaves(vector<KdLeaf *> &leaves) const;
1308
1309
1310        /** Returns bounding box of the whole tree (= bbox of root node)
1311        */
1312        AxisAlignedBox3 GetBoundingBox()const;
1313
1314        /** Returns root of the view space partitioning tree.
1315        */
1316        KdNode *GetRoot() const;
1317
1318        /** Collects the leaf view cells of the tree
1319                @param viewCells returns the view cells
1320        */
1321        void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
1322
1323        /** A ray is cast possible intersecting the tree.
1324                @param the ray that is cast.
1325                @returns the number of intersections with objects stored in the tree.
1326        */
1327        int CastRay(Ray &ray);
1328
1329        /** finds neighbouring leaves of this tree node.
1330        */
1331        int FindNeighbors(KdLeaf *n,
1332                                          vector<VspLeaf *> &neighbors,
1333                                          const bool onlyUnmailed) const;
1334
1335        /** Returns random leaf of BSP tree.
1336                @param halfspace defines the halfspace from which the leaf is taken.
1337        */
1338        KdLeaf *GetRandomLeaf(const Plane3 &halfspace);
1339
1340        /** Returns random leaf of BSP tree.
1341                @param onlyUnmailed if only unmailed leaves should be returned.
1342        */
1343        KdLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
1344
1345        /** Returns epsilon of this tree.
1346        */
1347        float GetEpsilon() const;
1348
1349        /** Casts line segment into the tree.
1350                @param origin the origin of the line segment
1351                @param termination the end point of the line segment
1352                @returns view cells intersecting the line segment.
1353        */
1354    int CastLineSegment(const Vector3 &origin,
1355                                                const Vector3 &termination,
1356                                                ViewCellContainer &viewcells);
1357               
1358        /** Sets pointer to view cells manager.
1359        */
1360        void SetViewCellsManager(ViewCellsManager *vcm);
1361
1362        /** Writes tree to output stream
1363        */
1364#if ZIPPED_VIEWCELLS
1365        bool Export(ogzstream &stream);
1366#else
1367        bool Export(ofstream &stream);
1368#endif
1369
1370        /** Returns or creates a new intersectable for use in a kd based pvs.
1371                The OspTree is responsible for destruction of the intersectable.
1372        */
1373        KdIntersectable *GetOrCreateKdIntersectable(KdNode *node);
1374
1375        /** Collects rays stored in the leaves.
1376        */
1377        void CollectRays(VssRayContainer &rays);
1378
1379        /** Intersects box with the tree and returns the number of intersected boxes.
1380                @returns number of view cells found
1381        */
1382        int ComputeBoxIntersections(const AxisAlignedBox3 &box,
1383                                                                ViewCellContainer &viewCells) const;
1384
1385
1386        /** Compute "pvs size of this object container
1387                @ note bot relly pvs size just weighted sum of object taking their
1388                appearances in pvss into account
1389        */
1390        int ComputePvsSize(const ObjectContainer &objects) const;
1391
1392        /** Returns kd leaf the point pt lies in, starting from root.
1393        */
1394        KdLeaf *GetLeaf(const Vector3 &pt, KdNode *root = NULL) const;
1395
1396
1397        /// pointer to the hierarchy of view cells
1398        ViewCellsTree *mViewCellsTree;
1399
1400
1401protected:
1402
1403        // --------------------------------------------------------------
1404        // For sorting objects
1405        // --------------------------------------------------------------
1406        struct SortableEntry
1407        {
1408                /** There is a 3th "event" for rays which intersect a
1409                        box in the middle. These "events" don't induce a change in
1410                        pvs size, but may induce a change in view cell volume.
1411                */
1412                enum EType
1413                {
1414                        BOX_MIN,
1415                        BOX_MAX,
1416                        BOX_INTERSECT
1417                };
1418
1419                int mType;
1420                //int mPvs;
1421                float mPos;
1422                VssRay *mRay;
1423               
1424                Intersectable *mObject;
1425
1426                SortableEntry() {}
1427
1428                SortableEntry(const int type,
1429                        //const float pvs,
1430                        const float pos,
1431                        Intersectable *obj,
1432                        VssRay *ray):
1433                mType(type),
1434                //mPvs(pvs),
1435                mPos(pos),
1436                mObject(obj),
1437                mRay(ray)
1438                {}
1439
1440                bool operator<(const SortableEntry &b) const
1441                {
1442                        return mPos < b.mPos;
1443                }
1444        };
1445
1446 
1447        /** faster evaluation of split plane cost for kd axis aligned cells.
1448        */
1449        float EvalLocalSplitCost(const OspTraversalData &data,
1450                                                         const AxisAlignedBox3 &box,
1451                                                         const int axis,
1452                                                         const float &position,
1453                                                         float &pFront,
1454                                                         float &pBack) const;
1455
1456        /** Evaluates candidate for splitting.
1457        */
1458        void EvalSplitCandidate(OspSplitCandidate &splitData);
1459
1460        /** Computes priority of the traversal data and stores it in tData.
1461        */
1462        void EvalPriority(OspTraversalData &tData) const;
1463
1464        /** Evaluates render cost decrease of next split.
1465        */
1466        float EvalRenderCostDecrease(const AxisAlignedPlane &candidatePlane,
1467                                                                 const OspTraversalData &data,
1468                                                                 float &normalizedOldRenderCost) const;
1469
1470
1471        /** Collects view cells in the subtree under root.
1472        */
1473        void CollectViewCells(KdNode *root,
1474                                                  bool onlyValid,
1475                                                  ViewCellContainer &viewCells,
1476                                                  bool onlyUnmailed = false) const;
1477
1478        /** Evaluates tree stats in the BSP tree leafs.
1479        */
1480        void EvaluateLeafStats(const OspTraversalData &data);
1481
1482        /** Subdivides node using a best split priority queue.
1483            @param tQueue the best split priority queue
1484                @param splitCandidate the candidate for the next split
1485                @param globalCriteriaMet if the global termination criteria were already met
1486                @returns new root of the subtree
1487        */
1488        KdNode *Subdivide(SplitQueue &tQueue,
1489                                          SplitCandidate *splitCandidate,
1490                                          const bool globalCriteriaMet);
1491       
1492        /** Subdivides leaf.
1493                @param leaf the leaf to be subdivided
1494               
1495                @param polys the polygons to be split
1496                @param frontPolys returns the polygons in front of the split plane
1497                @param backPolys returns the polygons in the back of the split plane
1498               
1499                @param rays the polygons to be filtered
1500                @param frontRays returns the polygons in front of the split plane
1501                @param backRays returns the polygons in the back of the split plane
1502
1503                @returns the root of the subdivision
1504        */
1505        KdInterior *SubdivideNode(
1506                const AxisAlignedPlane &splitPlane,
1507                const OspTraversalData &tData,
1508                OspTraversalData &frontData,
1509                OspTraversalData &backData);
1510
1511        void SplitObjects(KdLeaf *leaf,
1512                                          const AxisAlignedPlane & splitPlane,
1513                                          const ObjectContainer &objects,
1514                                          ObjectContainer &front,
1515                                          ObjectContainer &back);
1516
1517        /** does some post processing on the objects in the new child leaves.
1518        */
1519        void ProcessMultipleRefs(KdLeaf *leaf) const;
1520
1521        /** Selects an axis aligned for the next split.
1522                @returns cost for this split
1523        */
1524        float SelectPlane(const OspTraversalData &tData,
1525                                          AxisAlignedPlane &plane,
1526                                          float &pFront,
1527                                          float &pBack);
1528
1529        /** Sorts split candidates for cost heuristics using axis aligned splits.
1530                @param node the current node
1531                @param axis the current split axis
1532        */
1533        void SortSplitCandidates(const OspTraversalData &data,
1534                                                         const int axis,
1535                                                         float minBand,
1536                                                         float maxBand);
1537
1538        /** Computes best cost for axis aligned planes.
1539        */
1540        float EvalLocalCostHeuristics(const OspTraversalData &tData,
1541                const AxisAlignedBox3 &box,
1542                const int axis,
1543                float &position,
1544                int &objectsFront,
1545                int &objectsBack);
1546
1547        /** Subdivides the rays into front and back rays according to the split plane.
1548               
1549                @param plane the split plane
1550                @param rays contains the rays to be split. The rays are
1551                           distributed into front and back rays.
1552                @param frontRays returns rays on the front side of the plane
1553                @param backRays returns rays on the back side of the plane
1554               
1555                @returns the number of splits
1556        */
1557        int SplitRays(const AxisAlignedPlane &plane,
1558                                  RayInfoContainer &rays,
1559                              RayInfoContainer &frontRays,
1560                                  RayInfoContainer &backRays) const;
1561
1562        /** Adds the object to the pvs of the front and back leaf with a given classification.
1563
1564                @param obj the object to be added
1565                @param cf the ray classification regarding the split plane
1566                @param frontPvs returns the PVS of the front partition
1567                @param backPvs returns the PVS of the back partition
1568       
1569        */
1570        void AddObjToPvs(Intersectable *obj,
1571                                         const int cf,
1572                                         float &frontPvs,
1573                                         float &backPvs,
1574                                         float &totalPvs) const;
1575       
1576        /** Returns true if tree can be terminated.
1577        */
1578        inline bool LocalTerminationCriteriaMet(const OspTraversalData &data) const;
1579
1580        /** Returns true if global tree can be terminated.
1581        */
1582        inline bool GlobalTerminationCriteriaMet(const OspTraversalData &data) const;
1583
1584        float SelectSplitPlane(const OspTraversalData &tData,
1585                AxisAlignedPlane &plane,
1586                float &pFront,
1587                float &pBack);
1588       
1589        /** Propagates valid flag up the tree.
1590        */
1591        void PropagateUpValidity(KdNode *node);
1592
1593        /** Writes the node to disk
1594                @note: should be implemented as visitor.
1595        */
1596#if ZIPPED_VIEWCELLS
1597        void ExportNode(KdNode *node, ogzstream &stream);
1598#else
1599        void ExportNode(KdNode *node, ofstream &stream);
1600#endif
1601
1602        /** Returns estimated memory usage of tree.
1603        */
1604        float GetMemUsage() const;
1605
1606        /** Evaluates the influence on the pvs of the event.
1607                @param ve the visibility event
1608                @param pvsLeft updates the left pvs
1609                @param rightPvs updates the right pvs
1610        */
1611        void EvalHeuristicsContribution(KdLeaf *leaf,
1612                const SortableEntry &ci,
1613                float &volLeft,
1614                float &volRight,
1615                int &pvsLeft,
1616                int &pvsRight,
1617                int &viewCellsLeft,
1618                int &viewCellsRight);
1619
1620        /** Evaluate the contributions of view cell volume of the left and the right view cell.
1621        */
1622        void EvalVolumeContribution(const VssRay &ray,
1623                                                                float &volLeft,
1624                                                                float &volRight,
1625                                                                int &viewCellsLeft,
1626                                                                int &viewCellsRight);
1627
1628        /** Prepares objects for the cost heuristics.
1629                @returns pvs size of the node
1630        */
1631        float PrepareHeuristics(const OspTraversalData &tData, int &numViewCells);
1632
1633        /** Prepares heuristics for a particular ray.
1634        */
1635        float PrepareHeuristics(const VssRay &ray, int &numViewCells);
1636
1637        /** Prepares construction for vsp and osp trees.
1638        */
1639        void ComputeBoundingBox(const ObjectContainer &objects,
1640                                                        AxisAlignedBox3 *forcedBoundingBox);
1641
1642        void CollectDirtyCandidates(OspSplitCandidate *sc,
1643                vector<SplitCandidate *> &dirtyList);
1644
1645        /** Collect view cells which see this kd leaf.
1646        */
1647        void CollectViewCells(KdLeaf *leaf,
1648                ViewCellContainer &viewCells);
1649
1650        void ProcessRays(const VssRayContainer &sampleRays,
1651                RayInfoContainer &rays);
1652
1653        /** Reads parameters from environment singleton.
1654        */
1655        void ReadEnvironment();
1656
1657        /** Returns true if the specified ray end points is inside the kd leaf.
1658                @param isTermination if origin or termination point should be checked
1659        */
1660        bool EndPointInsideNode(KdLeaf *leaf, VssRay &ray, bool isTermination) const;
1661
1662        void AddViewCellVolume(ViewCell *vc,
1663                                                   const int cf,
1664                                                   float &frontPvs,
1665                                                   float &backPvs,
1666                                                   float &totalPvs) const;
1667
1668        int ClassifyRay(VssRay *ray, KdLeaf *leaf, const AxisAlignedPlane &plane) const;
1669
1670protected:
1671
1672        VspTree *mVspTree;
1673
1674        /// The view cells manager
1675        ViewCellsManager *mViewCellsManager;
1676
1677        /// candidates for placing split planes during cost heuristics
1678        vector<SortableEntry> *mSplitCandidates;
1679
1680        /// Pointer to the root of the tree
1681        KdNode *mRoot;
1682               
1683        /// Statistics for the object space partition
1684        OspTreeStatistics mOspStats;
1685       
1686        /// box around the whole view domain
1687        AxisAlignedBox3 mBoundingBox;
1688
1689
1690        //-- local termination
1691
1692        /// maximal possible depth
1693        int mTermMaxDepth;
1694        /// mininum probability
1695        float mTermMinProbability;
1696        /// minimal number of objects
1697        int mTermMinObjects;
1698        /// maximal contribution per ray
1699        float mTermMaxRayContribution;
1700        /// maximal acceptable cost ratio
1701        float mTermMaxCostRatio;
1702        /// tolerance value indicating how often the max cost ratio can be failed
1703        int mTermMissTolerance;
1704
1705
1706        //-- global criteria
1707
1708        float mTermMinGlobalCostRatio;
1709        int mTermGlobalCostMissTolerance;
1710        int mGlobalCostMisses;
1711
1712        /// maximal number of view cells
1713        int mTermMaxLeaves;
1714        /// maximal tree memory
1715        float mMaxMemory;
1716        /// the tree is out of memory
1717        bool mOutOfMemory;
1718
1719
1720        //-- split heuristics based parameters
1721       
1722        bool mUseCostHeuristics;
1723        /// balancing factor for PVS criterium
1724        float mCtDivCi;
1725        /// if only driving axis should be used for split
1726        bool mOnlyDrivingAxis;
1727       
1728        /// current time stamp (used for keeping split history)
1729        int mTimeStamp;
1730        // if rays should be stored in leaves
1731        bool mStoreRays;
1732
1733        /// epsilon for geometric comparisons
1734        float mEpsilon;
1735
1736        /// subdivision stats output file
1737        ofstream  mSubdivisionStats;
1738        /// keeps track of cost during subdivision
1739        float mTotalCost;
1740        /// keeps track of overall pvs size during subdivision
1741        int mTotalPvsSize;
1742        /// number of currenly generated view cells
1743        int mCreatedLeaves;
1744
1745        /// represents min and max band for sweep
1746        float mSplitBorder;
1747
1748        /// weight between  render cost decrease and node render cost
1749        float mRenderCostDecreaseWeight;
1750
1751        /// stores the kd node intersectables used for pvs
1752        KdIntersectableMap mKdIntersectables;
1753
1754
1755private:
1756
1757        bool mCopyFromKdTree;
1758};
1759
1760
1761/** This class implements a structure holding two different hierarchies,
1762        one for object space partitioning and one for view space partitioning.
1763
1764        The object space and the view space are subdivided using a cost heuristics.
1765        If an object space split or a view space split is chosen is also evaluated
1766        based on the heuristics.
1767       
1768        The view space heuristics is evaluated by weighting and adding the pvss of the back and
1769        front node of each specific split. unlike for the standalone method vspbsp tree,
1770        the pvs of an object would not be the pvs of single object but that of all objects
1771        which are contained in the same leaf of the object subdivision. This could be done
1772        by storing the pointer to the object space partition parent, which would allow access to all children.
1773        Another possibility is to include traced kd-cells in the ray casing process.
1774
1775        Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object.
1776        the contribution to an object to the pvs is the number of view cells it can be seen from.
1777
1778        @note
1779        There is a potential efficiency problem involved in a sense that once a certain type
1780        of split is chosen for view space / object space, the candidates for the next split of
1781        object space / view space must be reevaluated.
1782       
1783*/
1784class HierarchyManager
1785{
1786public:
1787        /** Constructor taking an object space partition and a view space partition tree.
1788        */
1789        HierarchyManager(VspTree &vspTree, OspTree &ospTree);
1790
1791        /** Constructs the view space and object space subdivision from a given set of rays
1792                and a set of objects.
1793                @param sampleRays the set of sample rays the construction is based on
1794                @param objects the set of objects
1795        */
1796        void Construct(const VssRayContainer &sampleRays,
1797                                   const ObjectContainer &objects,
1798                                   AxisAlignedBox3 *forcedViewSpace);
1799
1800        /** Constructs first view cells, then object space partition.
1801        */
1802        void Construct2(const VssRayContainer &sampleRays,
1803                                        const ObjectContainer &objects,
1804                                        AxisAlignedBox3 *forcedViewSpace);
1805
1806        /** Constructs only vsp tree.
1807        */
1808        void Construct3(const VssRayContainer &sampleRays,
1809                                        const ObjectContainer &objects,
1810                                        AxisAlignedBox3 *forcedViewSpace);
1811
1812public:
1813        VspTree &mVspTree;
1814        OspTree &mOspTree;
1815
1816protected:
1817
1818        bool GlobalTerminationCriteriaMet(SplitCandidate *candidate) const;
1819
1820        void PrepareConstruction(const VssRayContainer &sampleRays,
1821                const ObjectContainer &objects,
1822                AxisAlignedBox3 *forcedViewSpace,
1823                RayInfoContainer &viewSpaceRays,
1824                RayInfoContainer &objectSpaceRays);
1825
1826        void RunConstruction(const bool repair);
1827        bool SubdivideSplitCandidate(SplitCandidate *sc);
1828
1829        bool FinishedConstruction() const;
1830
1831        SplitCandidate *NextSplitCandidate();
1832
1833        void RepairQueue();
1834
1835        void CollectDirtyCandidates(vector<SplitCandidate *> &dirtyList);
1836
1837        VspTree::VspSplitCandidate *PrepareVsp(const VssRayContainer &sampleRays,
1838                                                           AxisAlignedBox3 *forcedViewSpace,
1839                                                           RayInfoContainer &rays);
1840
1841        OspTree::OspSplitCandidate *PrepareOsp(const VssRayContainer &sampleRays,
1842                const ObjectContainer &objects,
1843                AxisAlignedBox3 *forcedObjectSpace,
1844                RayInfoContainer &rays);
1845
1846
1847protected:
1848
1849        AxisAlignedBox3 mBoundingBox;
1850
1851        SplitQueue mTQueue;
1852
1853        SplitCandidate *mCurrentCandidate;
1854
1855        //-- global criteria
1856        float mTermMinGlobalCostRatio;
1857        int mTermGlobalCostMissTolerance;
1858        int mGlobalCostMisses;
1859
1860        /// keeps track of cost during subdivision
1861        float mTotalCost;
1862};
1863
1864}
1865
1866#endif
Note: See TracBrowser for help on using the repository browser.