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

Revision 1189, 48.7 KB checked in by mattausch, 18 years ago (diff)

changed osp partition to something taking mult references into account

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