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

Revision 1047, 40.5 KB checked in by mattausch, 18 years ago (diff)

fixed vsp part of vsp osp tree

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