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

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