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

Revision 1141, 44.5 KB checked in by mattausch, 18 years ago (diff)

added kd pvs support, changed way of counting pvs

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