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

Revision 1176, 47.2 KB checked in by mattausch, 18 years ago (diff)

corrected errors in the object space partition, but still buggy!

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