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

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