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

Revision 2353, 31.5 KB checked in by mattausch, 18 years ago (diff)

cleaned up project files

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