source: GTP/trunk/Lib/Vis/Preprocessing/src/VspTree.h @ 2547

Revision 2547, 32.2 KB checked in by mattausch, 17 years ago (diff)
Line 
1#ifndef _VspTree_H__
2#define _VspTree_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 "SubdivisionCandidate.h"
13#include "HierarchyManager.h"
14#include "Timer/PerfTimer.h"
15
16
17#ifdef USE_SSE
18#include <xmmintrin.h>
19#endif
20
21
22namespace GtpVisibilityPreprocessor {
23
24class ViewCellLeaf;
25class Plane3;
26class AxisAlignedBox3;
27class Ray;
28class ViewCellsStatistics;
29class ViewCellsManager;
30class MergeCandidate;
31class Beam;
32class ViewCellsTree;
33class Environment;
34class VspInterior;
35class VspLeaf;
36class VspNode;
37class KdNode;
38class KdInterior;
39class KdLeaf;
40class HierarchyManager;
41class KdIntersectable;
42class KdTree;
43class VspTree;
44class KdTreeStatistics;
45class BoundingBoxConverter;
46
47
48/** View space partition statistics.
49*/
50class VspTreeStatistics: public StatisticsBase
51{
52public:
53        // total number of nodes
54        int nodes;
55        // number of splits
56        int splits[3];
57       
58        // totals number of rays
59        int rays;
60        // maximal reached depth
61        int maxDepth;
62        // minimal depth
63        int minDepth;
64       
65        // max depth nodes
66        int maxDepthNodes;
67        // minimum depth nodes
68        int minDepthNodes;
69        // max depth nodes
70        int minPvsNodes;
71        // nodes with minimum PVS
72        int minRaysNodes;
73        // max ray contribution nodes
74        int maxRayContribNodes;
75        // minimum area nodes
76        int minProbabilityNodes;
77        /// nodes termination because of max cost ratio;
78        int maxCostNodes;
79        // max number of rays per node
80        int maxObjectRefs;
81        /// samples contributing to pvs
82        int contributingSamples;
83        /// sample contributions to pvs
84        int sampleContributions;
85        /// largest pvs
86        int maxPvs;
87        /// number of invalid leaves
88        int invalidLeaves;
89        /// number of rays refs
90        int rayRefs;
91        /// overall pvs size
92        int pvs;
93        // accumulated depth (used to compute average)
94        int accumDepth;
95        // global cost ratio violations
96        int mGlobalCostMisses;
97
98        // Constructor
99        VspTreeStatistics()
100        {
101                Reset();
102        }
103
104        int Nodes() const {return nodes;}
105        int Interior() const { return nodes / 2; }
106        int Leaves() const { return (nodes / 2) + 1; }
107       
108        // TODO: computation wrong
109        double AvgDepth() const { return accumDepth / (double)Leaves();};
110        double AvgRays() const { return rayRefs / (double)Leaves();};
111
112        void Reset()
113        {
114                nodes = 0;
115                for (int i = 0; i < 3; ++ i)
116                        splits[i] = 0;
117               
118                maxDepth = 0;
119                minDepth = 99999;
120                accumDepth = 0;
121        pvs = 0;
122                maxDepthNodes = 0;
123                minPvsNodes = 0;
124                minRaysNodes = 0;
125                maxRayContribNodes = 0;
126                minProbabilityNodes = 0;
127                maxCostNodes = 0;
128
129                contributingSamples = 0;
130                sampleContributions = 0;
131
132                maxPvs = 0;
133                invalidLeaves = 0;
134                rayRefs = 0;
135                maxObjectRefs = 0;
136                mGlobalCostMisses = 0;
137        }
138
139        void Print(std::ostream &app) const;
140
141        friend std::ostream &operator<<(std::ostream &s, const VspTreeStatistics &stat)
142        {
143                stat.Print(s);
144                return s;
145        }
146};
147
148
149/** VspNode abstract class serving for interior and leaf node implementation
150*/
151class VspNode
152{
153        friend class VspTree;
154
155public:
156       
157        /// types of vsp nodes
158        enum {Interior, Leaf};
159
160        VspNode();
161        virtual ~VspNode(){};
162        VspNode(VspInterior *parent);
163
164        /** Determines whether this node is a leaf or not
165                @return true if leaf
166        */
167        virtual bool IsLeaf() const = 0;
168
169        virtual int Type() const = 0;
170
171        /** Determines whether this node is a root
172                @return true if root
173        */
174        virtual bool IsRoot() const;
175        /** Returns parent node.
176        */
177        VspInterior *GetParent();
178        /** Sets parent node.
179        */
180        void SetParent(VspInterior *parent);
181        /** Returns true if this node is a sibling of node n.
182        */
183        bool IsSibling(VspNode *n) const;
184        /** returns depth of the node.
185        */
186        int GetDepth() const;
187        /** Returns true if this node (which represents the whole subtree) is valid
188        */
189        bool TreeValid() const;
190        /** Sets this node to valid.
191        */
192        void SetTreeValid(const bool v);
193        /** Cost of mergin this node.
194        */
195        float GetMergeCost() {return (float)-mTimeStamp; }
196
197        /// timestamp of this node
198        int mTimeStamp;
199
200        /////////
201        //-- mailing options
202
203        void Mail() { mMailbox = sMailId; }
204        static void NewMail() { ++ sMailId; }
205        bool Mailed() const { return mMailbox == sMailId; }
206
207
208        static int sMailId;
209        int mMailbox;
210
211       
212protected:
213
214        /// if this sub tree is a completely valid view space region
215        bool mTreeValid;
216        /// parent of this node
217        VspInterior *mParent;
218};
219
220
221/** BSP interior node implementation
222*/
223class VspInterior: public VspNode
224{
225        friend class VspTree;
226
227public:
228
229        /** Standard contructor taking split plane as argument.
230        */
231        VspInterior(const AxisAlignedPlane &plane);
232
233        ~VspInterior();
234        /** @return false since it is an interior node
235        */
236        bool IsLeaf() const { return false; }
237
238        int Type() const;
239        /** Returns back child.
240        */
241        VspNode *GetBack() { return mBack; }
242        /** Returns front child.
243        */
244        VspNode *GetFront() { return mFront; }
245        /** Returns split plane.
246        */
247        AxisAlignedPlane GetPlane() const { return mPlane; }
248        /** Returns position of split plane.
249        */
250        float GetPosition() const { return mPlane.mPosition; }
251        /** Returns split axis.
252        */
253        int GetAxis() const { return mPlane.mAxis; }
254        /** Replace front or back child with new child.
255        */
256        void ReplaceChildLink(VspNode *oldChild, VspNode *newChild);
257        /** Replace front and back child.
258        */
259        void SetupChildLinks(VspNode *front, VspNode *back);
260        /** Returns bounding box of this node.
261        */
262        AxisAlignedBox3 GetBoundingBox() const;
263        /** Sets boundiong box of this node.
264        */
265        void SetBoundingBox(const AxisAlignedBox3 &box);
266        /** Computes intersection of this plane with the ray segment.
267        */
268        int ComputeRayIntersection(const RayInfo &rayData, float &t) const
269        {
270                return rayData.ComputeRayIntersection(mPlane.mAxis, mPlane.mPosition, t);
271        }
272
273        friend std::ostream &operator<<(std::ostream &s, const VspInterior &A)
274        {
275                return s << A.mPlane.mAxis << " " << A.mPlane.mPosition;
276        }
277
278
279protected:
280
281        /// bounding box for this interior node: should we really store this?
282        AxisAlignedBox3 mBoundingBox;
283        /// Splitting plane corresponding to this node
284        AxisAlignedPlane mPlane;
285        /// back node
286        VspNode *mBack;
287        /// front node
288        VspNode *mFront;
289};
290
291
292/** BSP leaf node implementation.
293*/
294class VspLeaf: public VspNode
295{
296        friend VspTree;
297
298public:
299        VspLeaf();
300        VspLeaf(ViewCellLeaf *viewCell);
301        VspLeaf(VspInterior *parent);
302        VspLeaf(VspInterior *parent, ViewCellLeaf *viewCell);
303
304        ~VspLeaf();
305
306        /** @return true since it is an interior node
307        */
308        bool IsLeaf() const { return true; }
309       
310        int Type() const;
311
312        /** Returns pointer of view cell.
313        */
314        ViewCellLeaf *GetViewCell() const { return mViewCell; }
315        /** Sets pointer to view cell.
316        */
317        void SetViewCell(ViewCellLeaf *viewCell);
318
319        SubdivisionCandidate *GetSubdivisionCandidate()
320        {
321                return mSubdivisionCandidate;
322        }
323
324        void SetSubdivisionCandidate(SubdivisionCandidate *candidate)
325        {
326                mSubdivisionCandidate = candidate;
327        }
328
329
330public:
331
332        /// Rays piercing this leaf.
333        VssRayContainer mVssRays;
334       
335        /// Probability that the view point lies in this leaf
336        float mProbability;
337
338protected:
339
340        /// pointer to a split plane candidate splitting this leaf
341        SubdivisionCandidate *mSubdivisionCandidate;
342       
343        /// if NULL this does not correspond to feasible viewcell
344        ViewCellLeaf *mViewCell;
345};
346
347
348/** View Space Partitioning tree.
349*/
350class VspTree
351{
352        friend class ViewCellsParseHandlers;
353        friend class HierarchyManager;
354
355public:
356       
357        ///////////
358        //-- Helper structs / classes
359
360        /** Additional data which is passed down the BSP tree during traversal.
361        */
362        struct VspTraversalData
363        { 
364        public:
365               
366                VspTraversalData();
367               
368                VspTraversalData(VspLeaf *node,
369                                                 const int depth,
370                                                 RayInfoContainer *rays,
371                                                 const float pvs,
372                                                 const float p,
373                                                 const AxisAlignedBox3 &box);
374
375       
376                /** Returns cost of the traversal data.
377                */
378                inline float GetCost() const;
379                /** Returns average ray contribution.
380                */
381                inline float GetAvgRayContribution() const;
382                /** Returns average rays per object.
383                */
384                inline float GetAvgRaysPerObject() const;
385                /** deletes contents and sets them to NULL.
386                */
387                void Clear();
388
389
390                //////////////////////
391
392                /// the current node
393                VspLeaf *mNode;
394                /// current depth
395                int mDepth;
396                /// rays piercing this node
397                RayInfoContainer *mRays;
398                /// the probability that this node contains view point
399                float mProbability;
400                /// the bounding box of the node
401                AxisAlignedBox3 mBoundingBox;
402                /// how often this branch has missed the max-cost ratio
403                int mMaxCostMisses;
404                // current priority
405                float mPriority;
406                /// pvs size
407                float mPvs;
408                /// the correction factor for this pvs
409                float mCorrectedPvs;
410                /// pvs size
411                float mRenderCost;
412                /// the correction factor for this pvs
413                float mCorrectedRenderCost;
414
415                friend bool operator<(const VspTraversalData &a, const VspTraversalData &b)
416                {
417                        return a.GetCost() < b.GetCost();
418                }
419    };
420
421        /** Helper struct for data that comes with a split of a node.
422        */
423        struct SplitData
424        {
425                SplitData():
426        mFrontRenderCost(0),
427                mBackRenderCost(0),
428                mTotalRenderCost(0),
429                mFrontObjects(0),
430        mBackObjects(0),
431                mTotalObjects(0),
432                mFrontTriangles(0),
433                mBackTriangles(0),
434                mTotalTriangles(0)
435                {}
436
437                //////////////
438
439                float mFrontRenderCost;
440                float mBackRenderCost;
441                float mTotalRenderCost;
442
443                int mFrontObjects;
444                int mBackObjects;
445                int mTotalObjects;
446
447                int mFrontTriangles;
448                int mBackTriangles;
449                int mTotalTriangles;
450        };
451
452
453        /** Candidate for a view space split.
454        */
455        class VspSubdivisionCandidate: public SubdivisionCandidate
456        { 
457        public:
458
459                VspSubdivisionCandidate(const VspTraversalData &tData): mParentData(tData)
460                {};
461
462                ~VspSubdivisionCandidate()
463                {
464                        mParentData.Clear();
465                }
466
467                int Type() const { return VIEW_SPACE; }
468
469                void EvalCandidate(bool computeSplitplane = true)
470                {
471                        mDirty = false;
472                        sVspTree->EvalSubdivisionCandidate(*this, computeSplitplane);
473                }
474
475                bool GlobalTerminationCriteriaMet() const
476                {
477                        return sVspTree->GlobalTerminationCriteriaMet(mParentData);
478                }
479
480                bool Apply(SplitQueue &splitQueue,
481                                   bool terminationCriteriaMet,
482                                   SubdivisionCandidateContainer &dirtyList)
483                {
484                        VspNode *n = sVspTree->Subdivide(splitQueue, this, terminationCriteriaMet);
485                       
486                        // local or global termination criteria failed
487                        const bool success = !n->IsLeaf();     
488
489                        if (success)
490                                CollectDirtyCandidates(dirtyList, true);
491
492                        return success;
493                }
494
495                void CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList,
496                                                                        const bool onlyUnmailed)
497                {
498                        sVspTree->CollectDirtyCandidates(this, dirtyList, onlyUnmailed);
499                }
500
501                VspSubdivisionCandidate(const AxisAlignedPlane &plane, const VspTraversalData &tData):
502                        mSplitPlane(plane), mParentData(tData)
503                {}
504
505                float GetPriority() const {     return mPriority; }
506
507
508                ////////////////////
509
510                static VspTree* sVspTree;
511                /// the current split plane
512                AxisAlignedPlane mSplitPlane;
513                /// parent node traversal data
514                VspTraversalData mParentData;
515       
516                float mCorrectedFrontPvs;
517                float mCorrectedBackPvs;
518
519                float mFrontPvs;
520                float mBackPvs;
521
522                float mFrontTriangles;
523                float mBackTriangles;
524               
525                float mCorrectedFrontRenderCost;
526                float mCorrectedBackRenderCost;
527               
528                float mFrontRenderCost;
529                float mBackRenderCost;
530        };
531
532        /** Struct for traversing line segment.
533        */
534        struct LineTraversalData
535        {
536                VspNode *mNode;
537                Vector3 mExitPoint;
538                float mMaxT;
539   
540                LineTraversalData () {}
541                LineTraversalData (VspNode *n, const Vector3 &p, const float maxt):
542                mNode(n), mExitPoint(p), mMaxT(maxt) {}
543        };
544
545
546        //////////////////////
547
548
549        /** Default constructor creating an empty tree.
550        */
551        VspTree();
552        /** Constructor just setting the bounds of the tree.
553        */
554        VspTree(const AxisAlignedBox3 &bbox);
555        /** Default destructor.
556        */
557        ~VspTree();
558        /** Returns BSP Tree statistics.
559        */
560        const VspTreeStatistics &GetStatistics() const;
561        /** Returns bounding box of the specified node.
562        */
563        AxisAlignedBox3 GetBoundingBox(VspNode *node) const;
564        /** Returns list of BSP leaves with pvs smaller than
565                a certain threshold.
566                @param onlyUnmailed if only the unmailed leaves should be considered
567                @param maxPvs the maximal pvs of a leaf to be added (-1 means unlimited)
568        */
569        void CollectLeaves(vector<VspLeaf *> &leaves,
570                                           const bool onlyUnmailed = false,
571                                           const int maxPvs = -1) const;
572        /** Returns box which bounds the whole tree.
573        */
574        AxisAlignedBox3 GetBoundingBox() const;
575        /** Returns root of the view space partitioning tree.
576        */
577        VspNode *GetRoot() const;
578        /** Collects the leaf view cells of the tree
579                @param viewCells returns the view cells
580        */
581        void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
582        /** A ray is cast possible intersecting the tree.
583                @param the ray that is cast.
584                @returns the number of intersections with objects stored in the tree.
585        */
586        int CastRay(Ray &ray);
587        /** finds neighbouring leaves of this tree node.
588        */
589        int FindNeighbors(VspLeaf *n,
590                                          vector<VspLeaf *> &neighbors,
591                                          const bool onlyUnmailed) const;
592        /** Returns random leaf of BSP tree.
593                @param halfspace defines the halfspace from which the leaf is taken.
594        */
595        VspLeaf *GetRandomLeaf(const Plane3 &halfspace);
596
597        /** Returns random leaf of BSP tree.
598                @param onlyUnmailed if only unmailed leaves should be returned.
599        */
600        VspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
601        /** Returns epsilon of this tree.
602        */
603        float GetEpsilon() const;
604        /** Casts line segment into the tree.
605                @param origin the origin of the line segment
606                @param termination the end point of the line segment
607                @returns view cells intersecting the line segment.
608        */
609    int CastLineSegment(const Vector3 &origin,
610                                                const Vector3 &termination,
611                                                ViewCellContainer &viewcells,
612                                                const bool useMailboxing = true);
613        /** Sets pointer to view cells manager.
614        */
615        void SetViewCellsManager(ViewCellsManager *vcm);
616        /** Returns view cell the current point is located in.
617                @param point the current view point
618                @param active if currently active view cells should be returned or
619                elementary view cell
620        */
621        ViewCell *GetViewCell(const Vector3 &point, const bool active = false);
622        /** Returns true if this view point is in a valid view space,
623                false otherwise.
624        */
625        bool ViewPointValid(const Vector3 &viewPoint) const;
626        /** Returns view cell corresponding to
627                the invalid view space.
628        */
629        VspViewCell *GetOutOfBoundsCell();
630        /** Casts beam, i.e. a 5D frustum of rays, into tree.
631                Tests conservative using the bounding box of the nodes.
632                @returns number of view cells it intersected
633        */
634        int CastBeam(Beam &beam);
635        /** Checks if tree validity-flags are right
636                with respect to view cell valitiy.
637                If not, marks subtree as invalid.
638        */
639        void ValidateTree();
640        /** Collects rays stored in the leaves.
641        */
642        void CollectRays(VssRayContainer &rays);
643        /** Intersects box with the tree and returns the number of intersected boxes.
644                @returns number of view cells found
645        */
646        int ComputeBoxIntersections(const AxisAlignedBox3 &box,
647                                                                ViewCellContainer &viewCells) const;
648        /** Returns view cells of this ray, either taking precomputed cells
649                or by recomputation.
650        */
651        void GetViewCells(const VssRay &ray, ViewCellContainer &viewCells);
652        /** Returns view cells tree.
653        */
654        ViewCellsTree *GetViewCellsTree() const { return mViewCellsTree; }
655        /** Sets the view cells tree.
656        */
657        void SetViewCellsTree(ViewCellsTree *vt) { mViewCellsTree = vt; }
658        /** Writes vsp tree to output stream
659        */
660        bool Export(OUT_STREAM &stream);
661        /** Writes vsp tree to binary output stream.
662        */
663        bool ExportBinary(OUT_STREAM &stream);
664        /** Imports tree from binary format.
665        */
666        bool ImportBinary(IN_STREAM &stream);
667
668        void TestOutput(const std::string &filename);
669
670        ////////////
671
672        PerfTimer mSortTimer;
673        PerfTimer mSplitTimer;
674        PerfTimer mNodeTimer;
675        PerfTimer mSubdivTimer;
676        PerfTimer mEvalTimer;
677        PerfTimer mPlaneTimer;
678        PerfTimer mViewCellsTimer;
679
680protected:
681
682        // --------------------------------------------------------------
683        // For sorting objects
684        // --------------------------------------------------------------
685        struct SortableEntry
686        {
687                enum EType
688                {
689                        ERayMin,
690                        ERayMax
691                };
692
693                int type;
694                float value;
695                VssRay *ray;
696 
697                SortableEntry() {}
698                SortableEntry(const int t, const float v, VssRay *r):
699                type(t), value(v), ray(r)
700                {
701                }
702               
703                friend inline bool operator<(const SortableEntry &a, const SortableEntry &b)
704                {       // prefer max event
705                        //if (EpsilonEqual(a.value, b.value, 0.0001f))
706                        //      return (a.type == ERayMax);
707
708                        return (a.value < b.value);
709                }
710        };
711        /** Parse the environment settings.
712        */
713        void ParseEnvironment();
714        /** faster evaluation of split plane cost for kd axis aligned cells.
715        */
716        float EvalLocalSplitCost(const VspTraversalData &data,
717                                                         const AxisAlignedBox3 &box,
718                                                         const int axis,
719                                                         const float &position,
720                                                         float &pFront,
721                                                         float &pBack) const;
722        /** If != NULL, sets the bounding box to the forced  bounding box.
723                Else computes the bounding box of the view space using the
724                hit points gathered from the ray-object intersections.
725        */
726        void ComputeBoundingBox(const VssRayContainer &rays,
727                                                        AxisAlignedBox3 *forcedBoundingBox);
728        /** Evaluates candidate for splitting.
729        */
730        void EvalSubdivisionCandidate(VspSubdivisionCandidate &candidate,
731                                                                  bool computeSplitPlane = true);
732        /** Evaluates render cost decrease of next split.
733        */
734        float EvalRenderCostDecrease(VspSubdivisionCandidate &candidate,
735                                                                 float &normalizedOldRenderCost,
736                                                                 const SplitData &data) const;
737        /** Collects view cells in the subtree under root.
738        */
739        void CollectViewCells(VspNode *root,
740                                                  bool onlyValid,
741                                                  ViewCellContainer &viewCells,
742                                                  bool onlyUnmailed = false) const;
743        /** Returns view cell corresponding to
744                the invalid view space. If it does not exist, it is created.
745        */
746        VspViewCell *GetOrCreateOutOfBoundsCell();
747        /** Collapses the tree with respect to the view cell partition,
748                i.e. leaves having the same view cell are collapsed.
749                @param node the root of the subtree to be collapsed
750                @param collapsed returns the number of collapsed nodes
751                @returns node of type leaf if the node could be collapsed,
752                this node otherwise
753        */
754        VspNode *CollapseTree(VspNode *node, int &collapsed);
755        /** Helper function revalidating the view cell leaf list after merge.
756        */
757        void RepairViewCellsLeafLists();
758        /** Evaluates tree stats in the BSP tree leafs.
759        */
760        void EvaluateLeafStats(const VspTraversalData &data);
761        /** Subdivides node using a best split priority queue.
762            @param tQueue the best split priority queue
763                @param splitCandidate the candidate for the next split
764                @param globalCriteriaMet if the global termination criteria were already met
765                @returns new root of the subtree
766        */
767        VspNode *Subdivide(SplitQueue &tQueue,
768                                           SubdivisionCandidate *splitCandidate,
769                                           const bool globalCriteriaMet);
770        /** Adds stats to subdivision log file.
771        */
772        void AddSubdivisionStats(const int viewCells,
773                                                         const float renderCostDecr,
774                                                         const float totalRenderCost,
775                                                         const float avgRenderCost);
776        /** Subdivides leaf.
777                @param tData data object holding, e.g., a pointer to the leaf
778                @param frontData returns the data (e.g., pointer to the leaf) in front of the split plane
779                @param backData returns the data (e.g., pointer to the leaf) in the back of the split plane
780       
781                @returns the root of the subdivision
782        */
783        VspInterior *SubdivideNode(const VspSubdivisionCandidate &sc,
784                                                           VspTraversalData &frontData,
785                               VspTraversalData &backData);
786
787        /** Selects an axis aligned for the next split.
788                @returns cost for this split
789        */
790        float SelectSplitPlane(const VspTraversalData &tData,
791                                                   AxisAlignedPlane &plane,
792                                                   float &pFront,
793                                                   float &pBack);
794        /** Sorts split candidates along the specified axis.
795                The split candidates are generated on possible visibility
796                events (i.e., where ray segments intersect the ray boundaries).
797                The sorted candidates are needed to compute the heuristics.
798
799                @param polys the input for choosing split candidates
800                @param axis the current split axis
801                @param splitCandidates returns sorted list of split candidates
802        */
803        void SortSubdivisionCandidates(const RayInfoContainer &rays,
804                                                                   const int axis,
805                                                                   float minBand,
806                                                                   float maxBand);
807        /** Evaluate render cost of this pvs.
808        */
809        float EvalPvsCost(const RayInfoContainer &rays) const;
810        /** Helper function for split cost evaluation.
811        */
812        int EvalPvsEntriesIncr(VspSubdivisionCandidate &splitCandidate,
813                                                   const SplitData &sData) const;
814        /** Returns number of effective entries in the pvs.
815        */
816        int EvalPvsEntriesSize(const RayInfoContainer &rays) const;
817
818        int EvalPvsEntriesContribution(const VssRay &ray, const bool isTermination) const;
819        /** Computes best cost for axis aligned planes.
820        */
821        float EvalLocalCostHeuristics(const VspTraversalData &tData,
822                                                                  const AxisAlignedBox3 &box,
823                                                                  const int axis,
824                                                                  float &position,
825                                                                  const RayInfoContainer &usedRays);
826
827
828        ///////////////////////
829        //-- Helper function for computing heuristics
830
831        /** Evaluates the contribution to left and right pvs at a visibility event ve.
832                @param ve the visibility event
833                @param pvsLeft updates the left pvs
834                @param rightPvs updates the right pvs
835        */
836        inline void EvalHeuristics(const SortableEntry &ve, float &pvsLeft, float &pvsRight) const;
837        /** Evaluates contribution of min event to pvs
838        */
839        inline float EvalMinEventContribution(const VssRay &ray, const bool isTermination) const;
840        /** Evaluates contribution of max event to pvs
841        */
842        inline float EvalMaxEventContribution(const VssRay &ray, const bool isTermination) const;
843        /** Evaluates contribution of kd leaf when encountering a min event
844        */
845        inline float EvalMinEventContribution(KdLeaf *leaf) const;
846        /**  Evaluates contribution of kd leaf when encountering a max event
847        */
848        inline float EvalMaxEventContribution(KdLeaf *leaf) const;
849        /** Prepares objects for the heuristics.
850                @returns pvs size as seen by the rays.
851        */
852        float PrepareHeuristics(const RayInfoContainer &rays);
853        /** Prepare a single ray for heuristics.
854        */
855        float PrepareHeuristics(const VssRay &ray, const bool isTermination);
856        /** Prepare a single kd leaf for heuristics.
857        */
858        float PrepareHeuristics(KdLeaf *leaf);
859        /** Evaluates minimal and maximal depth in the tree.
860        */
861        void EvalMinMaxDepth(int &minDepth, int &maxDepth);
862        /** Writes the node to disk
863                @note: should be implemented as visitor.
864        */
865        void ExportNode(VspNode *node, OUT_STREAM &stream);
866       
867
868        ////////////////
869
870        void ExportBinInterior(OUT_STREAM &stream, VspInterior *interior);
871        void ExportBinLeaf(OUT_STREAM &stream, VspLeaf *leaf);
872
873        VspInterior *ImportBinInterior(IN_STREAM  &stream, VspInterior *parent);
874        VspLeaf *ImportBinLeaf(IN_STREAM &stream, VspInterior *parent);
875
876        VspNode *ImportNextNode(IN_STREAM &stream,
877                                                        VspInterior *parent);
878
879
880        //////////////////////////////////////////////////
881
882        /** Subdivides the rays into front and back rays according to the split plane.
883                @param plane the split plane
884                @param rays contains the rays to be split. The rays are
885                           distributed into front and back rays.
886                @param frontRays returns rays on the front side of the plane
887                @param backRays returns rays on the back side of the plane
888               
889                @returns the number of splits
890        */
891        int SplitRays(const AxisAlignedPlane &plane,
892                                  RayInfoContainer &rays,
893                              RayInfoContainer &frontRays,
894                                  RayInfoContainer &backRays) const;
895        /** Add contributions of this ray to fron, back, and overall pvs of the parent.
896        */
897        inline void UpdatePvsEntriesContribution(const VssRay &ray,
898                                                                                         const bool isTermination,
899                                                                                         const int cf,
900                                                                                         float &frontPvs,
901                                                                                         float &backPvs,
902                                                                                         float &totalPvs) const;
903        /** Classfifies the object with respect to the
904                pvs of the front and back leaf and updates pvs size
905                accordingly.
906
907                @param obj the object to be added
908                @param cf the ray classification regarding the split plane
909                @param frontPvs returns the PVS of the front partition
910                @param backPvs returns the PVS of the back partition
911       
912        */
913        inline void UpdateContributionsToPvs(const VssRay &ray,
914                                                                                 const bool isTermination,
915                                                                                 const int cf,
916                                                                                 float &frontPvs,
917                                                                                 float &backPvs,
918                                                                                 float &totalPvs) const;
919        /** Evaluates the contribution for objects.
920        */
921        inline void UpdateContributionsToPvs(Intersectable *obj,
922                                                                                 const int cf,
923                                                                                 float &frontPvs,
924                                                                                 float &backPvs,
925                                                                                 float &totalPvs) const;
926        /** Evaluates the contribution for bounding volume leaves.
927        */
928        inline void UpdateContributionsToPvs(BvhLeaf *leaf,
929                                                                                 const int cf,
930                                                                                 float &frontPvs,
931                                                                                 float &backPvs,
932                                                                                 float &totalPvs,
933                                                                                 const bool countEntries) const;
934        /** Updates contribution to pvs caused by this bvh leaf.
935        */
936        inline void UpdateContributionsToPvs(BvhLeaf *leaf,
937                                                                                 const int cf,
938                                                                                 SplitData &sdata) const;
939        /** Evaluates the contribution for kd leaves.
940        */
941        inline void UpdateContributionsToPvs(KdLeaf *leaf,
942                                                                                 const int cf,
943                                                                                 float &frontPvs,
944                                                                                 float &backPvs,
945                                                                                 float &totalPvs) const;
946        /** Returns true if tree can be terminated.
947        */
948        inline bool LocalTerminationCriteriaMet(const VspTraversalData &data) const;
949        /** Returns true if global tree can be terminated.
950        */
951        bool GlobalTerminationCriteriaMet(const VspTraversalData &data) const;
952        /** Adds ray sample contributions to the PVS.
953                @param sampleContributions the number contributions of the samples
954                @param contributingSampels the number of contributing rays
955               
956        */
957        void AddSamplesToPvs(VspLeaf *leaf,
958                                                 const RayInfoContainer &rays,
959                                                 float &sampleContributions,
960                                                 int &contributingSamples);
961        /** Propagates valid flag up the tree.
962        */
963        void PropagateUpValidity(VspNode *node);
964        /** Returns estimated memory usage of tree.
965        */
966        float GetMemUsage() const;
967        /** Updates view cell pvs of objects.
968        */
969        void ProcessViewCellObjects(ViewCell *parent,
970                                                                ViewCell *front,
971                                                                ViewCell *back) const;
972        /** Creates a new view cell from the traversal data.
973        */
974        void CreateViewCell(VspTraversalData &tData,
975                                                const bool updatePvs,
976                                                const float renderCost,
977                                                const int pvs);
978        /** Collect split candidates which are affected by the last split
979                and must be reevaluated.
980        */
981        void CollectDirtyCandidates(VspSubdivisionCandidate *sc,
982                                                                vector<SubdivisionCandidate *> &dirtyList,
983                                                                const bool onlyUnmailed);
984        /** Adds the split candidate associated with this ray to the dirty list.
985        */
986        void AddCandidateToDirtyList(const VssRay &ray,
987                                                           const bool isTermination,
988                                                           vector<SubdivisionCandidate *> &dirtyList,
989                                                           const bool onlyUnmailed) const;
990        /** Rays will be clipped to the bounding box.
991        */
992        void PreprocessRays(const VssRayContainer &sampleRays, RayInfoContainer &rays);
993        /** Evaluate subdivision statistics.
994        */
995        void EvalSubdivisionStats(const SubdivisionCandidate &tData);
996        /** Prepares the construction of the vsp tree.
997        */
998        void PrepareConstruction(SplitQueue &tQueue,
999                                                         const VssRayContainer &sampleRays,
1000                                                         RayInfoContainer &rays);
1001        /** Evaluates pvs contribution of this ray.
1002        */
1003        float EvalContributionToPvs(const VssRay &ray, const bool isTermination) const;
1004        /** Evaluates pvs contribution of a kd node.
1005        */
1006        float EvalContributionToPvs(KdLeaf *leaf) const;
1007        /** Creates new root of hierarchy and computes bounding box.
1008                Has to be called before the preparation of the subdivision.
1009        */
1010        void Initialise(const VssRayContainer &rays,
1011                                        AxisAlignedBox3 *forcedBoundingBox,
1012                                        const ObjectContainer &objects);
1013
1014        int CompressObjects();
1015
1016        int CompressObjects(VspLeaf *leaf);
1017
1018        int TraverseRayPacket(RayPacket &rp, const bool useMailboxing);
1019
1020
1021#ifdef USE_SSE
1022        struct PacketTraversalData
1023        {
1024                PacketTraversalData () {}
1025       
1026                PacketTraversalData (VspNode *n,
1027                                         const __m128 &px, const __m128 &py, const __m128 &pz,
1028                                                         const __m128 &maxt,
1029                                                         const __m128 &mask):
1030                mNode(n),
1031                mExitPointX4(px), mExitPointY4(py), mExitPointZ4(pz),
1032                mMaxT4(maxt),
1033                mMask4(mask)
1034                {}
1035
1036                VspNode *mNode;
1037
1038                union { __m128 mExitPointX4; float mExitPointX[4]; };
1039                union { __m128 mExitPointY4; float mExitPointY[4]; };
1040                union { __m128 mExitPointZ4; float mExitPointZ[4]; };
1041
1042                union { __m128 mMaxT4; float mMaxT[4]; };
1043                union { __m128 mMask4; float mMask[4]; };
1044        };
1045
1046
1047        struct __declspec(align(16)) PacketTraversalStack
1048        {
1049                // for performance
1050                friend class VspTree;
1051
1052        public:
1053                PacketTraversalStack(const int depth):
1054                mStackPtr(0),
1055                //mDepth(depth)
1056                mDepth(1000)
1057                {
1058                        //mData = new PacketTraversalData[mDepth];
1059                }
1060
1061                ~PacketTraversalStack()
1062                {
1063                        //delete [] mData;
1064                }
1065               
1066                //PacketTraversalStack() {}
1067
1068                void Pop() {-- mStackPtr;}
1069                const PacketTraversalData &Top() const { return mData[mStackPtr - 1];}
1070               
1071                void Push(const PacketTraversalData &tData)
1072                {
1073                        // note: faster with direct assignments
1074                        mData[mStackPtr ++] = tData;
1075                        //if (mStackPtr == mDepth) std::cerr << "this can never happen!!" << std::endl;
1076                }
1077
1078                bool Empty() const {return mStackPtr <= 0;}
1079
1080        protected:
1081
1082                // static array to avoid using operator new
1083                //PacketTraversalData *mData;
1084                PacketTraversalData mData[1000];
1085
1086                int mStackPtr;
1087                int mDepth;
1088        };
1089
1090#endif
1091       
1092
1093protected:
1094
1095        /// pointer to the hierarchy of view cells
1096        ViewCellsTree *mViewCellsTree;
1097        /// Pointer to the hierarchy manager which is responsible for both
1098        /// view and object space
1099        HierarchyManager *mHierarchyManager;
1100        /// Pointer to the bv hierarchy
1101        BvHierarchy *mBvHierarchy;
1102        /// Pointer to the view cells manager
1103        ViewCellsManager *mViewCellsManager;
1104        /// Buffer for subdivision candidates used for split heuristics evaluation
1105        vector<SortableEntry> *mLocalSubdivisionCandidates;
1106        /// Pointer to the root of the tree
1107        VspNode *mRoot;
1108        /// The statistics
1109        VspTreeStatistics mVspStats;
1110        /// View cell corresponding to the space outside the valid view space
1111        VspViewCell *mOutOfBoundsCell;
1112        /// box around the whole view domain
1113        AxisAlignedBox3 mBoundingBox;
1114
1115
1116        /////////
1117        //-- local termination
1118
1119        /// minimal number of rays before subdivision termination
1120        int mTermMinRays;
1121        /// maximal possible depth
1122        int mTermMaxDepth;
1123        /// mininum probability
1124        float mTermMinProbability;
1125        /// mininum PVS
1126        int mTermMinPvs;
1127        /// maximal contribution per ray
1128        float mTermMaxRayContribution;
1129        /// maximal acceptable cost ratio
1130        float mTermMaxCostRatio;
1131        /// tolerance value indicating how often the max cost ratio can be failed
1132        int mTermMissTolerance;
1133
1134        ////////////
1135        //-- global criteria
1136
1137        float mTermMinGlobalCostRatio;
1138        int mTermGlobalCostMissTolerance;
1139       
1140
1141        /// maximal number of view cells
1142        int mMaxViewCells;
1143        /// maximal tree memory
1144        float mMaxMemory;
1145        /// the tree is out of memory
1146        bool mOutOfMemory;
1147
1148        ////////////
1149        //-- split heuristics based parameters
1150       
1151        bool mUseCostHeuristics;
1152        /// balancing factor for PVS criterium
1153        float mCtDivCi;
1154        /// if only driving axis should be used for split
1155        bool mOnlyDrivingAxis;
1156        /// if random split axis should be used
1157        bool mUseRandomAxis;
1158        /// if vsp bsp tree should simulate octree
1159        bool mCirculatingAxis;
1160        /// minimal relative position where the split axis can be placed
1161        float mMinBand;
1162        /// maximal relative position where the split axis can be placed
1163        float mMaxBand;
1164
1165
1166        /// current time stamp (used for keeping split history)
1167        int mTimeStamp;
1168        // if rays should be stored in leaves
1169        bool mStoreRays;
1170        /// epsilon for geometric comparisons
1171        float mEpsilon;
1172        /// subdivision stats output file
1173        std::ofstream mSubdivisionStats;
1174        /// keeps track of cost during subdivision
1175        float mTotalCost;
1176        /// keeps track of #pvs entries during subdivison
1177        int mPvsEntries;
1178        /// keeps track of overall pvs size during subdivision
1179        int mTotalPvsSize;
1180        /// number of currenly generated view cells
1181        int mCreatedViewCells;
1182
1183        /// weight between render cost decrease and node render cost
1184        float mRenderCostDecreaseWeight;
1185        /// maximal #of rays used for heuristics evalution
1186        int mMaxTests;
1187        /// constant value for driving the heuristics
1188        float mMemoryConst;
1189};
1190
1191
1192}
1193
1194#endif
Note: See TracBrowser for help on using the repository browser.