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

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