source: GTP/trunk/Lib/Vis/Preprocessing/src/Pvs.h @ 1745

Revision 1745, 15.2 KB checked in by mattausch, 18 years ago (diff)
RevLine 
[177]1#ifndef __PVS_H
2#define __PVS_H
3
4#include <map>
[469]5#include <vector>
[1189]6#include "common.h"
[177]7
[860]8namespace GtpVisibilityPreprocessor {
9
[177]10class KdNode;
[240]11class BspNode;
[191]12class Ray;
[308]13class Intersectable;
[1077]14class ViewCell;
[177]15
[1077]16
[1740]17/** Information stored with a PVS entry. Consists of the number
18        the object was seen from the view cell.
19*/
20template<typename T, typename S>
21class PvsEntry
[1189]22{
[1740]23public:
24
[1741]25        PvsEntry() {}
26
[1740]27        PvsEntry(T sample, const S &data): mObject(sample), mData(data) {}
28
29        T mObject;
30        S mData;
31
32        template<typename T, typename S>
33        friend int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
34};
35
36
37template<typename T, typename S>
38int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
39{
40        return a.mObject < b.mObject;
41}
42
43
44template<typename T, typename S>
45struct LtSample
46{
47    bool operator()(const PvsEntry<T, S> &a, const PvsEntry<T, S> &b) const
[310]48    {
[1740]49                return a.mObject < b.mObject;
[310]50        }
51};
52
[1740]53
[469]54/** Information stored with a PVS entry. Consists of the number
55        the object was seen from the view cell.
56*/
[1189]57class PvsData {
58public:
[1706]59        PvsData() {}
60        PvsData(const float sumPdf):
[1189]61        mSumPdf(sumPdf) {}
[1740]62       
[1706]63        // $$JB in order to return meaningfull values
64        // it assumes that the sum pdf has been normalized somehow!!!
[1740]65        inline float GetVisibility()
[1706]66        {
67                return mSumPdf;
68        }
[1740]69
70        /// sum of probability density of visible sample rays
71        float mSumPdf;
[1189]72};
73
74
75class MailablePvsData
76{
[1740]77public:
78        // sum of probability density of visible sample rays
79        float mSumPdf;
80        int mCounter;
81
82        MailablePvsData() {}
83        MailablePvsData(const float sumPdf):
84        mSumPdf(sumPdf) {}
85
86        // $$JB in order to return meaningfull values
87        // it assumes that the sum pdf has been normalized somehow!!!
88        float GetVisibility()
89        {
90                return mSumPdf;
91        }
92
[1706]93        ////////////////////////////
94        //  Mailing stuff
[1184]95
[1706]96        // last mail id -> warning not thread safe!
97        // both mailId and mailbox should be unique for each thread!!!
98        static int sMailId;
99        static int sReservedMailboxes;
100
[1184]101        static void NewMail(const int reserve = 1) {
102                sMailId += sReservedMailboxes;
103                sReservedMailboxes = reserve;
104        }
[1706]105
[1184]106        void Mail() { mMailbox = sMailId; }
107        bool Mailed() const { return mMailbox == sMailId; }
108
109        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
110        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
111
112        int IncMail() { return ++ mMailbox - sMailId; }
[1740]113       
[1706]114        //////////////////////////////////////////
[1184]115
[1740]116protected:
[1184]117
[1740]118        int mMailbox;
[556]119
[310]120};
[1740]121
122
[1742]123template<typename T, typename S>
124class PvsIterator
125{
126public:
127PvsIterator<T, S>(){}
128        PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
129                                          const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
130        mItCurrent(itCurrent), mItEnd(itEnd)
131        {
132        }
133
134        bool HasMoreEntries() const
135        {
136                return (mItCurrent != mItEnd);
137        }
138
[1744]139        const PvsEntry<T, S> &Next()
[1742]140        {
141                return *(mItCurrent ++);
142        }
143       
144private:
145        typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
146        typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
[1740]147};
148
149
[469]150/** Template class representing the Potentially Visible Set (PVS)
151        mainly from a view cell, but also e.g., from objects.
152*/
[1189]153template<typename T, typename S>
[311]154class Pvs
[310]155{
[1740]156        template<typename T, typename S>
157        friend class PvsIterator;
158
[310]159public:
[1738]160
[1740]161        Pvs(): mSamples(0), mEntries() {}
[1738]162
[1742]163        /** creates pvs and initializes it with the given entries.
164                Assumes that entries are sorted-
165        */
[1740]166        Pvs(const vector<PvsEntry<T, S> > &samples);
[1742]167        virtual ~Pvs() {};
[492]168
[1706]169        /** Compresses PVS lossless or lossy.
170        */
171        int Compress() {return 0;}
172        int GetSize() const {return (int)mEntries.size();}
173        bool Empty() const {return mEntries.empty();}
[469]174
[1740]175        /** Normalize the visibility of entries in order to get
176                comparable results.
[1706]177        */
178        void NormalizeMaximum();
[1184]179
[1706]180        /** Merges pvs of a into this pvs.
[1740]181                Warning: very slow!
[1706]182        */
[1740]183        void MergeInPlace(const Pvs<T, S> &a);
[752]184
[1706]185        /** Difference of pvs to pvs b.
186                @returns number of different entries.
187        */
188        int Diff(const Pvs<T, S> &b);
[469]189
[1706]190        /** Finds sample in PVS.
[1740]191                @returns iterator on the sample.
[1706]192        */
[1740]193        typename vector<PvsEntry<T, S> >::iterator Find(T sample);
[469]194
[1706]195        bool GetSampleContribution(T sample, const float pdf, float &contribution);
[485]196
[1706]197        /** Adds sample to PVS.
198                @contribution contribution of sample (0 or 1)
199                @returns true if sample was not already in PVS.
200        */
201        bool AddSample(T sample, const float pdf, float &contribution);
[677]202
[1706]203        /** Adds sample to PVS.
204                @returns contribution of sample (0 or 1)
205        */
206        float AddSample(T sample, const float pdf);
[1740]207       
[1742]208        /** Adds sample to PVS. Assumes that the pvs is sorted
[1740]209                @returns contribution of sample (0 or 1)
210        */
211        float AddSamples(const vector<PvsEntry<T, S> > &samples);
[752]212
[1706]213        /** Adds sample to PVS.
214                @returns PvsData
215        */
[1740]216        typename std::vector<PvsEntry<T, S> >::iterator AddSample2(T sample, const float pdf);
[1667]217
[1706]218        /** Subtracts one pvs from another one.
219                WARNING: could contains bugs
220                @returns new pvs size
221        */
222        int SubtractPvs(const Pvs<T, S> &pvs);
[1740]223
[1706]224        /** Returns PVS data, i.e., how often it was seen from the view cell,
225                and the object itsef.
226        */
227        void GetData(const int index, T &entry, S &data);
228
229        /** Collects the PVS entries and returns them in the vector.
230        */
231        void CollectEntries(std::vector<T> &entries);
232
233        /** Removes sample from PVS if reference count is zero.
234                @param visibleSamples number of references to be removed
235        */
236        bool RemoveSample(T sample, const float pdf);
237
238        /** Compute continuous PVS difference
239        */
[1740]240        void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
241                                                                                float &pvsReduction,
242                                                                                float &pvsEnlargement);
[1706]243
244        /** Clears the pvs.
245        */
246        void Clear();
247
248        static int GetEntrySizeByte();
249        static float GetEntrySize();
250
[1740]251        /** Compute continuous PVS difference
252        */
253        float GetPvsHomogenity(Pvs<T, S> &pvs);
[1706]254
[1740]255        static void Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b);
[1706]256
[1742]257        int GetSamples() const
258        {
259                return mSamples;
260        }
[1738]261
[1742]262        typename PvsIterator<T, S> GetIterator() const;
263
264protected:
265
[1738]266        /// vector of PVS entries
[1740]267        vector<PvsEntry<T, S> > mEntries;
[1736]268       
269        /// Number of samples used to create the PVS
270        int mSamples;
[310]271};
272
[581]273
[1740]274template <typename T, typename S>
275Pvs<T, S>::Pvs(const vector<PvsEntry<T, S> > &samples)
276{
277        mEntries.reserve(samples.size());
278        mEntries = samples;
279}
[677]280
[1740]281
[695]282/**
283   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
284   Provides separatelly PVS reduction from PVS enlargement.
285
286*/
[1189]287template <typename T, typename S>
[677]288void
[1189]289Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
[1740]290                                                                                  float &pvsReduction,
291                                                                                  float &pvsEnlargement)
[677]292{
[705]293        pvsReduction = 0.0f;
294        pvsEnlargement = 0.0f;
[1740]295
[1738]296        // Uses sum of log differences, which corresponds to entropy
[1740]297        std::vector<PvsEntry<T, S> >::iterator it;
[1738]298
299        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
[1189]300        {
[1740]301                float bSumPdf = (*it).mData.mSumPdf;
[1738]302                float aSumPdf = 0.0f;
[713]303
[1740]304                vector<PvsEntry<T, S> >::iterator oit = Find((*it).mObject);           
305
306                const bool entryFound = (it != mEntries.end()) && ((*it).mObject == (*oit).mObject);
307
308                if (entryFound)
[1738]309                {
[1740]310                        aSumPdf = (*it).mData.mSumPdf;
311
[1738]312                        // mark this entry as processed to avoid double counting
[1740]313                        (*it).mData.mSumPdf = -aSumPdf;
[1738]314                }
315
[713]316#if 0
[1740]317                const float diff = bSumPdf - aSumPdf;
[1738]318
319                if (diff > 0.0f) {
320                        pvsEnlargement += diff;
321                } else {
322                        pvsReduction += -diff;
323                }
[713]324#else
[1740]325                if (!entryFound)
[1738]326                        pvsEnlargement += 1.0f;
[713]327#endif
[1738]328        }
329
[1740]330        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
331        {
332                float aSumPdf = (*it).mData.mSumPdf;
[1738]333                float bSumPdf = 0.0f;
334                if (aSumPdf < 0.0f) {
[1740]335               
[1738]336                        // this entry was already accounted for!
337                        // just revert it back
[1740]338                        (*it).mData.mSumPdf = -aSumPdf;
[1738]339                } else {
[1740]340                        vector<PvsEntry<T, S> >::iterator oit = b.Find((*it).mObject);
341
342                        const bool entryFound = (it != mEntries.end()) && ((*it).mObject == (*oit).mObject);
343                       
344                        if (entryFound) {
345                                bSumPdf = (*oit).mData.mSumPdf;
[1738]346                        }
[713]347#if 0
[1740]348                        const float diff = bSumPdf - aSumPdf;
[713]349
[1738]350                        if (diff > 0.0f) {
351                                pvsEnlargement += diff;
352                        } else {
353                                pvsReduction += -diff;
354                        }
355
[713]356#else
[1740]357                        if (!entryFound)
[1738]358                                pvsReduction += 1.0f;
[713]359#endif
[1738]360                }
[695]361        }
[677]362}
363
[1738]364
[1189]365template <typename T, typename S>
366int Pvs<T, S>::Diff(const Pvs<T, S> &b)
[362]367{
368        int dif = 0;
369
[1740]370        std::vector<PvsEntry<T, S> >::const_iterator it;
[362]371
372        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
373        {
[1740]374                std::vector<PvsEntry<T, S> >::const_iterator bit = Find((*it).first);           
375                if (bit == mEntries.end()) ++ dif;
[362]376        }
377
378        return dif;
379}
380
[1740]381
382template <typename T, typename S>
383void Pvs<T, S>::MergeInPlace(const Pvs<T, S> &a)
[341]384{
[1740]385    const int samples = mSamples + a.mSamples;
386
387        ObjectPvs interPvs;
388       
389        Merge(interPvs, *this, a);
390       
391        mEntries.reserve(interPvs.GetSize());
392        mEntries = interPvs.mEntries;
393
394        mSamples = samples;
395}
396
397
398template <typename T, typename S>
399void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b)
400{
401        std::vector<PvsEntry<T, S> >::const_iterator ait = a.mEntries.begin(), ait_end = a.mEntries.end();
402        std::vector<PvsEntry<T, S> >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end();
[1741]403       
404        for (; (ait != ait_end); ++ ait)
405        {
406                Intersectable *aObj = (*ait).mObject;
407                Intersectable *bObj = NULL;
408                PvsEntry<T, S> aEntry = (*ait);
[1740]409
[1741]410                for (; (bit != bit_end) && ((*bit).mObject <= (*ait).mObject); ++ bit)
411                {
412                        bObj = (*bit).mObject;
413
414                        // object found => add up probabilities
[1742]415                        if (bObj == aEntry.mObject)
[1741]416                        {
417                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
418                                PvsEntry<T, S> entry(bObj, newData);
419                                mergedPvs.mEntries.push_back(entry);
420                        }
421                        else
422                        {
423                                mergedPvs.mEntries.push_back(*bit);
424                        }
425                }
426
427                // only push back if objects different
428                // (equal case is handled by second loop)
429                if (aObj != bObj)
430                {
431                        mergedPvs.mEntries.push_back(*ait);
432                }
433        }
434
435        // add the rest
436        for (; (bit != bit_end); ++ bit)
[1740]437        {
[1741]438                mergedPvs.mEntries.push_back(*bit);
439        }
[1740]440}
441
442
[1189]443template <typename T, typename S> void Pvs<T, S>::Clear()
[752]444{
445        mEntries.clear();
446}
447
448
[1189]449template <typename T, typename S>
[1740]450typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample)
[310]451{
[1740]452        PvsEntry<T, S> dummy(sample, PvsData());
453        vector<PvsEntry<T, S> >::iterator it = lower_bound(mEntries.begin(), mEntries.end(), dummy);
454                               
455        return it;
[310]456}
457
[1740]458
[1189]459template <typename T, typename S>
[1740]460void Pvs<T, S>::GetData(const int index, T &entry, S &data)
[310]461{
[1740]462        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
[1738]463        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
[310]464
[1738]465        entry = (*i).first;
466        data = (*i).second;
[310]467}
468
[1738]469
[1189]470template <typename T, typename S>
[1740]471float Pvs<T, S>::AddSample(T sample, const float pdf)
[177]472{
[1738]473        ++ mSamples;
[1740]474        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
[1738]475
[1740]476        if ((it != mEntries.end()) && ((*it).mObject == sample))
[1189]477        {
[1740]478                S &data = (*it).mData;
479                data.mSumPdf += pdf;
480                return data.mSumPdf;
[1189]481        }
[1738]482        else
[1189]483        {
[1740]484                PvsEntry<T, S> entry(sample, pdf);
485                mEntries.insert(it, entry);
[1738]486                return pdf;
[1189]487        }
[466]488}
[177]489
[1189]490
491template <typename T, typename S>
[1740]492typename vector< PvsEntry<T, S> >::iterator Pvs<T, S>::AddSample2(T sample, const float pdf)
[1184]493{
[1740]494        ++ mSamples;
495        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
496
[1742]497        if ((it != mEntries.end()) && ((*it).mObject == sample))
[1189]498        {
[1740]499                S &data = (*it).second;
500                data->mSumPdf += pdf;
[1189]501        }
[1740]502        else
[1189]503        {
[1740]504                PvsEntry<T, S> entry(sample, pdf);
505                mEntries.insert(it, entry);
[1189]506        }
[1740]507
508        return it;
[1184]509}
510
[1740]511
[1189]512template <typename T, typename S>
513bool Pvs<T, S>::AddSample(T sample,
[1740]514                                                  const float pdf,
515                                                  float &contribution)
[466]516{
[1738]517        ++ mSamples;
[1740]518
519        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
520
521        if ((it != mEntries.end()) && ((*it).mObject == sample))
[1738]522        {
[1740]523                S &data = (*it).mData;
524
525                data.mSumPdf += pdf;
526                contribution = pdf / data.mSumPdf;
527
[1738]528                return false;
529        }
[1740]530        else
531        {
532                PvsEntry<T, S> entry(sample, pdf);
533
534                mEntries.insert(it, entry);
[1738]535                contribution = 1.0f;
[1740]536
[1738]537                return true;
538        }
[311]539}
[308]540
[492]541
[1189]542template <typename T, typename S>
[1740]543bool Pvs<T, S>::GetSampleContribution(T sample,
544                                                                          const float pdf,
545                                                                          float &contribution)
[485]546{
[1740]547        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
[1189]548
[1740]549        if (it != mEntries.end() && ((*it).mObject == sample)) 
550        {
551                S &data = (*it).mData;
552                contribution = pdf / (data.mSumPdf + pdf);
553                return false;
554        }
555        else
556        {
557                contribution = 1.0f;
558                return true;
559        }
[485]560}
561
[1740]562
[1189]563template <typename T, typename S>
[1740]564bool Pvs<T, S>::RemoveSample(T sample, const float pdf)
[485]565{
[1740]566        -- mSamples;
[1737]567
[1740]568        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
[1737]569
[1740]570        if (it == mEntries.end())
571                return false;
572
573        S &data = (*it).mData;
574
575        data.mSumPdf -= pdf;
576
577        if (data.mSumPdf <= 0.0f)
578        {
579                mEntries.erase(it);
580        }
581
582        return true;
[485]583}
[1740]584
585
[1189]586template <typename T, typename S>
587int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
[485]588{
[1738]589        const int samples = mSamples - pvs.mSamples;
[1740]590
591        std::vector<PvsEntry<T, S> >::
[1738]592                const_iterator it, it_end = pvs.mEntries.end();
[1737]593
[1738]594        // output PVS of view cell
595        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
[1740]596                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
[1738]597
598        mSamples = samples;
[1740]599
[1738]600        return GetSize();
[485]601}
602
[1740]603
[1189]604template <typename T, typename S>
605void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
[469]606{
[1740]607        std::vector<PvsEntry<T, S> >::
[485]608                const_iterator it, it_end = mEntries.end();
[469]609
610        // output PVS of view cell
611        for (it = mEntries.begin(); it != it_end; ++ it)
612                entries.push_back((*it)->first);
613}
614
[1740]615
[1189]616template <typename T, typename S>
617void Pvs<T, S>::NormalizeMaximum()
[556]618{
[1740]619        std::vector<PvsEntry<T, S> >::
620                const_iterator it, it_end = mEntries.end();
[556]621
[1740]622        float maxPdfSum = -1.0f;
[556]623
[1740]624        // output PVS of view cell
625        for (it = mEntries.begin(); it != it_end; ++ it) {
626                float sum = (*it)->second.sumPdf;
627                if (sum > maxSum)
628                        maxSum = sum;
629        }
[556]630
[1740]631        maxSum = 1.0f / maxSum;
[556]632
[1740]633        for (it = mEntries.begin(); it != it_end; ++ it) {
634                (*it)->second.sumPdf *= maxSum;
635        }
636
[556]637}
638
639
[1667]640template <typename T, typename S>
641float Pvs<T, S>::GetEntrySize()
642{
[1673]643        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
[1667]644}
645
646
647template <typename T, typename S>
648int Pvs<T, S>::GetEntrySizeByte()
649{
650        return sizeof(T) + sizeof(S);
651}
652
653
[1740]654template <typename T, typename S>
655float Pvs<T, S>::GetPvsHomogenity(Pvs<T, S> &pvs)
656{
657        float pvsReduction, pvsEnlargement;
658
659        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
660
661        return pvsReduction + pvsEnlargement;
662}
663
664
[1742]665template <typename T, typename S>
666typename PvsIterator<T, S> Pvs<T, S>::GetIterator() const
667{
668        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
669
670        return pit;
671}
672
673
[1667]674///////////////////////////////////////
675
[311]676/** Class instantiating the Pvs template for kd tree nodes.
677*/
[1189]678class KdPvs: public Pvs<KdNode *, PvsData>
[308]679{
[1141]680public:
[311]681        int Compress();
[308]682};
683
[1077]684
[1189]685class ObjectPvs: public Pvs<Intersectable *, PvsData>
[1141]686{
687public:
[1586]688        /** Counts object int the pvs. Different to method "GetSize", not
[1141]689                only the raw container size is returned,
690                but the individual contributions of the entries are summed up.
691        */
[1707]692        float EvalPvsCost() const;
[1141]693};
694
[1586]695
696////////////
[1077]697//-- typedefs
698
[1742]699typedef PvsEntry<Intersectable *, PvsData> ObjectPvsEntry;
700typedef std::vector<ObjectPvsEntry> ObjectPvsEntries;
[1189]701typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
[1742]702typedef PvsIterator<Intersectable *, PvsData> ObjectPvsIterator;
[860]703}
[469]704
[177]705#endif
706
Note: See TracBrowser for help on using the repository browser.