source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.h @ 1297

Revision 1297, 18.1 KB checked in by mattausch, 18 years ago (diff)
RevLine 
[372]1#ifndef _ViewCell_H__
2#define _ViewCell_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include "Ray.h"
[462]7#include "Statistics.h"
[608]8#include "Material.h"
[955]9#include "gzstream.h"
[469]10
[1010]11
[860]12namespace GtpVisibilityPreprocessor {
13
[469]14struct Triangle3;
15
[372]16class BspInterior;
17class BspPvs;
18class BspLeaf;
[1008]19class VspLeaf;
[469]20class KdLeaf;
[580]21class ViewCellInterior;
22class MergeCandidate;
23class ViewCellsManager;
[881]24class ViewCellLeaf;
[372]25
[955]26
[1264]27
[479]28/** Statistics for a view cell partition.
29*/
30
31class ViewCellsStatistics: public StatisticsBase
32{
33public:
34
35        /// number of view cells
36        int viewCells;
37
38        /// size of the PVS
[613]39        int pvsSize;
[479]40
41        /// largest PVS of all view cells
42        int maxPvs;
43
44        /// smallest PVS of all view cells
45        int minPvs;
46
47        /// view cells with empty PVS
48        int emptyPvs;
49
50        /// number of leaves covering the view space
51        int leaves;
52
53        /// largest number of leaves covered by one view cell
54        int maxLeaves;
55
[564]56        int invalid;
57
[479]58    // Constructor
59        ViewCellsStatistics()
60        {
61                Reset();
62        }
63
64        double AvgLeaves() const {return (double)leaves / (double)viewCells;};
[613]65        double AvgPvs() const {return (double)pvsSize / (double)viewCells;};
[479]66
67        void Reset()
68        {
69                viewCells = 0;
[613]70                pvsSize = 0;
[479]71                maxPvs = 0;
72
73                minPvs = 999999;
74                emptyPvs = 0;
75                leaves = 0;
76                maxLeaves = 0;
[564]77                invalid = 0;
[479]78        }
79
80        void Print(ostream &app) const;
81
82        friend ostream &operator<<(ostream &s, const ViewCellsStatistics &stat)
83        {
84                stat.Print(s);
85                return s;
86        }
87};
88
[580]89
[372]90/**
91        View cell with an optional mesh representation
92*/
[580]93
94
[372]95class ViewCell: public MeshInstance
96{
[752]97        friend class ViewCellsTree;
98        friend class ViewCellsManager;
99
[372]100public:
101        ViewCell();
[471]102
[372]103        /** Constructor taking a mesh representing the shape of the viewcell.
104        */
105        ViewCell(Mesh *mesh);
[462]106
[469]107        /** Default destructor.
108        */
[462]109        virtual ~ViewCell() {}
[580]110
[471]111        /** Returns Pvs.
[372]112        */
[469]113        const ObjectPvs &GetPvs() const;
[752]114
[1002]115        /** Returns pvs.
116        */
[469]117        ObjectPvs &GetPvs();
[372]118
[1002]119        /** Completely substitutes the pvs.
120        */
[880]121        void SetPvs(const ObjectPvs &pvs);
122
[752]123        /** Type of view cells.
124        */
[372]125        int Type() const;
[471]126
[1002]127       
[372]128        /** Adds a passing ray to the passing ray container.
129        */
[471]130        void AddPassingRay(const Ray &ray, const int contributions);
[372]131
[469]132        /** Returns volume of the view cell.
133        */
[478]134        float GetVolume() const;
[372]135
[478]136        /** Returns area of the view cell.
[469]137        */
[478]138        float GetArea() const;
[469]139
[478]140        /** Sets the volume of the view cell.
141        */
142        void SetVolume(float volume);
143       
144        /** Sets the area of the view cell.
145        */
146        void SetArea(float area);
[503]147
[478]148
[580]149        /** if this view cell is the root of a view cell hierarchy
150        */
151        bool IsRoot() const;
[372]152
[580]153        /** Returns parent view cell.
154        */
155        ViewCellInterior *GetParent() const;
[372]156
[1002]157        /** Sets parent of this view cell.
158        */
159        void SetParent(ViewCellInterior *parent);
160
161
[503]162        /** Sets the mesh for this view cell.
163        */
164        void SetMesh(Mesh *mesh);
165
[1002]166        /** Sets this view cell to be a valid view cell according to some criteria.
167        */
[547]168        void SetValid(const bool valid);
[1002]169        /** Returns true if this view cell is considered to be valid according to
170                some criteria.
171        */
[547]172        bool GetValid() const;
173
[728]174        /** Returns estimated render cost of this view cell.
175        */
176        float GetRenderCost() const;
[580]177
[752]178        /** set color for visiualizations.
179        */
180        void SetColor(const RgbColor &color);
[580]181
[752]182        /** get color for visualuzations.
183        */
184    RgbColor GetColor() const;
[580]185
[1002]186        /** Adds a sample to the pvs.
187                @param sample the sample to be added
188                @param pdf a continuos measure of visibility
189                @param contribution returns the contribution of this sample to the pvs
190        */
191        bool AddPvsSample(Intersectable *sample, const float pdf, float &contribution);
[608]192 
[580]193        /// Rays piercing this view cell.
[1284]194        //RayContainer mPiercingRays;
[580]195
196        /** if this is a view cell correspending to a leaf in a hierarchy.
197        */
198        virtual bool IsLeaf() const = 0;
199
[752]200        static bool SmallerPvs(const ViewCell *a, const ViewCell *b)
201        {
[997]202                // HACK: take scalar value because pvs may not have been stored properly
203#if 1
204                return a->mPvsSize < b->mPvsSize;
205#else
[1168]206                return a->GetPvs().CountObjectsInPvs() < b->GetPvs().CountObjectsInPvs();
[997]207#endif
208        }
[569]209
[997]210        static bool SmallerRenderCost(const ViewCell *a, const ViewCell *b)
211        {
212                return a->GetRenderCost() < b->GetRenderCost();
213        }
[580]214
[997]215        static bool LargerRenderCost(const ViewCell *a, const ViewCell *b)
216        {
217                return a->GetRenderCost() > b->GetRenderCost();
218        }
[801]219
[1002]220        /** Sets merge cost used for merging this view cell from other cells.
221                @hack The function is available for leaves also to have a common interface,
222                but it should be less than zero for leaves.
223                */
[600]224        void SetMergeCost(const float mergeCost);
[997]225
[1002]226        /** Returns merge cost needed to merge this leaf from other cells.
227                @hack The function is available for leaves also to have a common interface,
228                but it should be less than zero for leaves.
229        */
[600]230        float GetMergeCost() const;
[997]231
[1002]232
233
234        ////////////////////////////////////////////
[1297]235        //-- mailing stuff
[1002]236
237
[997]238        static void NewMail(const int reserve = 1)
239        {
[580]240                sMailId += sReservedMailboxes;
241                sReservedMailboxes = reserve;
242        }
[997]243
[580]244        void Mail() { mMailbox = sMailId; }
245        bool Mailed() const { return mMailbox == sMailId; }
246
247        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
248        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
249
[1145]250        int IncMail() { return ++ mMailbox - sMailId; }
[580]251
252
253        // last mail id -> warning not thread safe!
254        // both mailId and mailbox should be unique for each thread!!!
255        static int sMailId;
256        static int sReservedMailboxes;
[1297]257        //int mMailbox;
[609]258       
[372]259protected:
260
[1002]261        /// parent view cell in the view cell hierarchy
262        ViewCellInterior *mParent;
[372]263        /// the potentially visible objects
[469]264        ObjectPvs mPvs;
[1160]265        /// the volume of this view cell
[469]266        float mVolume;
[1297]267       
[478]268        float mArea;
[1160]269        /// the cost that were paid for merging this view cells from two others.
[600]270        float mMergeCost;
[1160]271        /// if the view cell is valid view space
[547]272        bool mValid;
[881]273        /// color used for consistent visualization
[660]274        RgbColor mColor;
[1002]275        /// store pvs size, used for evaluation purpose when pvss are stored only in the leaves
[752]276        int mPvsSize;
[1297]277
[1161]278        /** stores number of entries in pvs
279            this variable has the same value as mPvsSize for object pvs,
280                but usually not for kd cell based pvs
281        */
[1160]282        int mEntriesInPvs;
283
[1297]284        /** if the pvs size scalar (+ entries into pvs)
285                is up to date and corresponding to the real pvs size
286        */
[752]287        bool mPvsSizeValid;
[1297]288
[372]289};
290
[580]291
292class ViewCellInterior: public ViewCell
293{
[752]294        friend class ViewCellsManager;
[1284]295
[580]296public:
297        ViewCellInterior();
298        ~ViewCellInterior();
299
300        ViewCellInterior(Mesh *mesh);
301       
302        /** Sets pointer from parent to child and vice versa.
303        */
304        void SetupChildLink(ViewCell *l);
[1286]305        void ReplaceChildLink(ViewCell *prev, ViewCell *cur);
306
[586]307        void RemoveChildLink(ViewCell *l);
[580]308        bool IsLeaf() const;
309
[1284]310        void SetCost(const float c) {
311                mCost = c;
312        }
313       
314        float GetCost() const {
315                return mCost;
316        }
[608]317 
[1284]318  ViewCellContainer mChildren;
319
[608]320protected:
321  /** overall cost resulting from the merge */
322  float mCost;
[580]323};
324
[881]325
[469]326/**
[881]327        Leaf of the view cell.
[469]328*/
[580]329class ViewCellLeaf: public ViewCell
[366]330{
331public:
[881]332        ViewCellLeaf()  {  mActiveViewCell = this; }
333        ViewCellLeaf(Mesh *mesh):
334        ViewCell(mesh) { mActiveViewCell = this; }
[469]335
[881]336        bool IsLeaf() const
337        {
338                return true;
339        }
340
341        /** Returns if this view cell is active.
342        */
343        ViewCell *GetActiveViewCell() const
344        { return mActiveViewCell; }
345
346        /** Sets this view cell to be an active view cell.
347        */
348        void SetActiveViewCell(ViewCell *vc)
349        { mActiveViewCell = vc;}
350
[605]351       
[997]352        /** points to the currently active view cell. This is the
353                view cell representing the current brach.
354        */
[881]355        ViewCell *mActiveViewCell;
356};
[479]357
[1121]358/** Leaf of the view cell hierarchy corresponding
359        to a leaf in a spatial hierarchy.
[881]360*/
361template<typename T>
362class HierarchyLeafViewCell: public ViewCellLeaf
363{
364public:
365
366        HierarchyLeafViewCell<T>(): ViewCellLeaf() {  }
367        HierarchyLeafViewCell<T>(Mesh *mesh):
368        ViewCellLeaf(mesh) {  }
369               
370
[580]371        bool IsLeaf() const
372        {
373                return true;
374        }
375
[881]376
[580]377        /// Leaf of some hierarchy which is part of this view cell.
378        T mLeaf;
[469]379};
380
[479]381
[1010]382typedef HierarchyLeafViewCell<VspLeaf *> VspViewCell;
[881]383typedef HierarchyLeafViewCell<BspLeaf *> BspViewCell;
384typedef HierarchyLeafViewCell<KdLeaf *> KdViewCell;
[469]385
[366]386
[580]387
[1008]388
[580]389class ViewCellsTree
390{
[600]391        friend class ViewCellsManager;
[1263]392        friend class ViewCellsParseHandlers;
[752]393
[580]394public:
[1264]395        ViewCellsTree();
[1004]396        /** View cells tree constructor taking a view cell mnanager as parameter
[997]397        */
[1004]398        ViewCellsTree(ViewCellsManager *vcm);
[580]399        ~ViewCellsTree();
400
401        /** Returns number of leaves this view cell consists of.
402        */
[736]403        int GetNumInitialViewCells(ViewCell *vc) const;
[580]404
405        /** Collects leaves corresponding to a view cell.
406        */
407        void CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const;
408
409        /** Merges view cells according to some cost heuristics.
410        */
411        int ConstructMergeTree(const VssRayContainer &rays, const ObjectContainer &objects);
412       
413        /** Refines view cells using shuffling, i.e., border leaves
414                of two view cells are exchanged if the resulting view cells
415                are tested to be "better" than the old ones.
416                @returns number of refined view cells
417        */
418        int RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects);
[651]419       
420        /** Assign colors to the viewcells so that they can be renderered interactively without
[997]421            color flickering. 
422        */
[651]423        void AssignRandomColors();
[580]424
[997]425        /** Updates view cell stats for this particular view cell.
[605]426        */
427        void UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat);
[580]428
[997]429        /** Get costs resulting from each merge step.
430        */
[651]431        void GetCostFunction(vector<float> &costFunction);
[608]432 
[580]433        /** Returns optimal set of view cells for a given number of view cells.
434        */
435        void CollectBestViewCellSet(ViewCellContainer &viewCells, const int numViewCells);
436
[581]437        /** Root of view cells tree.
438        */
[584]439        ViewCell *GetRoot() const;
[581]440
[584]441        /** Returns pvs of view cell.
442                @note pvs is returned per reference if tree is not compressed,
443                per copy else.
444        */
445        void GetPvs(ViewCell *vc, ObjectPvs &pvs) const;
446
[1161]447        /** Returns pvs size (i.e. the number of stored objects
[584]448        */
[1142]449        int GetPvsSize(ViewCell *vc) const;
[584]450
[1161]451        /** Returns number of entries associated with this view cell.
452                This returns the same value as the GetPvsSize function for object pvs,
453                but most likely different values for kd node based pvs.
[584]454        */
[1161]455        int GetPvsEntries(ViewCell *vc) const;
[584]456
[1161]457        /** Returns the actual number of stored entries in the view cells sub tree.
458        */
459        int GetStoredPvsEntriesNum(ViewCell *root) const;
460
[584]461        /** Returns memory cost of this view cell.
462        */
463        float GetMemoryCost(ViewCell *vc) const;
464
[752]465        /** Sets method of storage for view cells.
[584]466        */
[752]467        void SetViewCellsStorage(int type);
[584]468
[837]469        /** pvs storage methods
470        */
[752]471        enum {PVS_IN_INTERIORS, COMPRESSED, PVS_IN_LEAVES};
472
[840]473       
[584]474        /** If view cells in this tree have compressed pvs.
475        */
[752]476        int ViewCellsStorage() const;
[584]477
[660]478        /** Returns active view cell that is in the path of this view cell.
479        */
[881]480        ViewCell *GetActiveViewCell(ViewCellLeaf *vc) const;
[590]481
[660]482        /** Sets the leaves to be the currently active view cells.
483        */
484    void SetActiveSetToLeaves();
485
[651]486        /** Propagates pvs up the tree to the root and downwards the tree.
[610]487        */
[651]488        void PropagatePvs(ViewCell *vc);
[610]489
[837]490        /** Exports view cells to file.
491        */
[1201]492        bool Export(OUT_STREAM &stream, const bool exportPvs = false);
[610]493
[649]494        /** Export statistics of this view cell tree.
495        */
[660]496        void ExportStats(const string &mergeStats);
[610]497
[650]498        /** Sets root of hierarchy.
499        */
500        void SetRoot(ViewCell *root);
501
502        //float ComputeVolume(ViewCell *vc);
503
[651]504        /** Assignes unique ids to view cells.
505        */
506        void CreateUniqueViewCellsIds();
507
[660]508        /** Resets pvs of whole tree.
509        */
510        void ResetPvs();
[651]511
[1121]512        /** Counts pvs of the view cell taking the kd cells into account.
513        */
514        int CountKdPvs(const ViewCellLeaf *vc) const;
515
[1264]516        void SetViewCellsManager(ViewCellsManager *vcm)
517        {
518                mViewCellsManager = vcm;
519        }
520
[580]521protected:
522
[1264]523        void ReadEnvironment();
[580]524
[997]525        /////////////////////////////////////////////////////////////////
526        //                    merge related stuff                      //
527        /////////////////////////////////////////////////////////////////
[580]528
[729]529        /** Computes render cost of the merged pvs.
530        */
531        float ComputeMergedPvsCost(const ObjectPvs &pvs1, const ObjectPvs &pvs2) const;
532
[580]533        /** Returns cost of this leaf according to current heuristics.
534        */
535        float GetCostHeuristics(ViewCell *vc) const;
536
537        /** Returns cost of leaf.
538        */
539        float GetRenderCost(ViewCell *vc) const;
540
541        /** Evaluates the merge cost of this merge candidate pair.
542        */
543        void EvalMergeCost(MergeCandidate &mc) const;
544
545        /** Variance of leaf.
546        */
547        float GetVariance(ViewCell *vc) const;
548
549        /** Standard deviation of leaf.
550        */
551        float GetDeviation(ViewCell *vc) const;
552
[582]553        /** Tries to set this merge candidate to valid.
554                @returns false if both view cells are the same
[580]555        */
[582]556        bool ValidateMergeCandidate(MergeCandidate &mc) const;
[580]557
558        /** Merge view cells of leaves l1 and l2.
559                @returns difference in pvs size
560        */
561        ViewCellInterior *MergeViewCells(ViewCell *l, ViewCell *r, int &pvsDiff); //const;
562
563        /** Shuffles, i.e. takes border leaf from view cell 1 and adds it
564                to view cell 2.
565        */
[586]566        void ShuffleLeaf(ViewCell *leaf, ViewCellInterior *vc1, ViewCellInterior *vc2) const;   
[580]567               
568        /** Shuffles the leaves, i.e., tests if exchanging
569                the leaves helps in improving the view cells.
570        */
[586]571        bool ShuffleLeaves(MergeCandidate &mc) const;
[580]572
573        /** Calculates cost for merge of view cell 1 and 2.
574        */
[586]575        float EvalShuffleCost(ViewCell *leaf,
576                                                  ViewCellInterior *vc1,
577                                                  ViewCellInterior *vc2) const;
[580]578
579        /** Exports a snapshot of the merged view cells to disc.
580        */
581        void ExportMergedViewCells(ViewCellContainer &viewCells,
582                                                           const ObjectContainer &objects,
583                                                           const int numNewViewCells);
584
[997]585        /** Merge queue must be reset after some time because expected value
[580]586                may not be valid.
587        */
588        void ResetMergeQueue();
589
590        /** Updates the current top level of view cells.
[582]591                @returns number of newly merged view cells
[580]592        */
[582]593        int UpdateActiveViewCells(ViewCellContainer &viewCells);
[580]594
[997]595        /** Helper function pullling pvs as high up in the tree as possible.
596        */
[610]597        void PullUpVisibility(ViewCellInterior *interior);
[580]598
[997]599        /** Compress pvs of view cell and children.
600        */
[584]601        void CompressViewCellsPvs(ViewCell *root);
[580]602
[582]603        /** Returns memory usage of view cells.
604        */
605        float GetMemUsage() const;
[837]606
607        /**     Exports single view cell.
[610]608                NOTE: should be in exporter!!
609        */
[1201]610        void ExportViewCell(ViewCell *viewCell, OUT_STREAM &stream, const bool exportPvs);     
[581]611
[837]612        /** Exports pvs of a view cell.
613        */
[1201]614        void ExportPvs(ViewCell *viewCell, OUT_STREAM &stream);
[582]615
[1166]616        int GetEntriesInPvsForCompressedStorage(ViewCell *vc) const;
617        int GetPvsSizeForCompressedStorage(ViewCell *vc) const;
618        int GetPvsSizeForLeafStorage(ViewCell *vc) const;
619        int GetEntriesInPvsForLeafStorage(ViewCell *vc) const;
[610]620
[1166]621        void UpdateStats(
622                ofstream &stats,
623                const int pass,
624                const int viewCells,
625                const float renderCostDecrease,
626                const float totalRenderCost,
627                const int currentPvs,
628                const float expectedCost,
629                const float avgRenderCost,
630                const float deviation,
631                const int totalPvs,
632                const int entriesInPvs,
633                const int pvsSizeDecr,
634                const float volume);
635
[584]636        /// if the view cell tree hold compressed pvs
[752]637        int mViewCellsStorage;
[582]638
[580]639        ViewCellsManager *mViewCellsManager;
640        ViewCell *mRoot;
641
642        /// if merge visualization should be shown
643        bool mExportMergedViewCells;
644
645       
[837]646        /// intermediate container of merged view cells.
[582]647        ViewCellContainer mMergedViewCells;
648       
[580]649
[837]650        /// if merged view cells are refined.
[586]651        bool mRefineViewCells;
652
[580]653        /// weights between variance and render cost increase (must be between zero and one)
654        float mRenderCostWeight;
655
656        /// overall cost used to normalize cost ratio
657        float mOverallCost;
658        float mExpectedCost;
659    float mDeviation;
660        float mAvgRenderCost;
[837]661        /// the area is used for pvs heuristics
[580]662        int mUseAreaForPvs;
663
[582]664        int mNumActiveViewCells;
[580]665
666        /// minimal number of view cells
667        int mMergeMinViewCells;
668        /// maximal cost ratio for the merge
669        float mMergeMaxCostRatio;
670
671        typedef priority_queue<MergeCandidate> MergeQueue;
672
673        MergeQueue mMergeQueue;
674
[582]675        float mMaxMemory;
[580]676
[938]677        int mMaxMergesPerPass;
678        float mAvgCostMaxDeviation;
[580]679};
680
681
682/**
683        Candidate for leaf merging based on priority.
684*/
685class MergeCandidate
686
687        friend class ViewCellsTree;
688
689public:
690
691        MergeCandidate(ViewCell *l, ViewCell *r);
692
693        /** If this merge pair is still valid.
694        */
695        bool IsValid() const;
696
697       
698        friend bool operator<(const MergeCandidate &leafa, const MergeCandidate &leafb)
699        {
700                return leafb.GetMergeCost() < leafa.GetMergeCost();
701        }
702
703        void SetLeftViewCell(ViewCell *l);
704        void SetRightViewCell(ViewCell *l);
705
706        ViewCell *GetLeftViewCell() const;
707        ViewCell *GetRightViewCell() const;
708
[703]709        /** Returns leaf view cell initially associated with this merge candidate.
710        */
[580]711        ViewCell *GetInitialLeftViewCell() const;
[1133]712        /** Returns leaf view cell initially associated with this merge candidate.
713        */
[580]714        ViewCell *GetInitialRightViewCell() const;
715
716        /** Returns the increase of the standard deviation of this merge candidate.
717        */
718        float GetDeviationIncr() const;
719
720        /** Merge cost of this candidate pair.
721        */
722        float GetMergeCost() const;
723
724        /** Render cost of this candidate.
725        */
726        float GetRenderCost() const;
727       
728        static float sRenderCostWeight;
729
730protected:
731
732        /// render cost increase by this merge
733        float mRenderCost;
734        /// increase / decrease of standard deviation
735        float mDeviationIncr;
736
737        ViewCell *mLeftViewCell;
738        ViewCell *mRightViewCell;
739
740        ViewCell *mInitialLeftViewCell;
741        ViewCell *mInitialRightViewCell;
742};
743
744
745class MergeStatistics: public StatisticsBase
746{
747public:
748       
749        int merged;
750        int siblings;
751        int candidates;
752        int nodes;
753
754        int accTreeDist;
755        int maxTreeDist;
756       
757        Real collectTime;
758        Real mergeTime;
759
760        Real overallCost;
761
762        Real expectedRenderCost;
763        Real deviation;
764        Real heuristics;
765
766        // Constructor
767        MergeStatistics()
768        {
769                Reset();
770        }
771       
772        double AvgTreeDist() const {return (double)accTreeDist / (double)merged;};
773
774        void Reset()
775        {
776                nodes = 0;
777                merged = 0;
778                siblings = 0;
779                candidates = 0;
780       
781                accTreeDist = 0;
782                maxTreeDist = 0;
783
784                collectTime = 0;
785                mergeTime = 0;
786                overallCost = 0;
787
788                expectedRenderCost = 0;
789                deviation = 0;
790                heuristics = 0;
791
792        }
793
794        void Print(ostream &app) const;
795
796        friend ostream &operator<<(ostream &s, const MergeStatistics &stat)
797        {
798                stat.Print(s);
799                return s;
800        }
801};
802
[860]803}
804
[372]805#endif
Note: See TracBrowser for help on using the repository browser.