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

Revision 1742, 15.8 KB checked in by mattausch, 18 years ago (diff)

pvs can be accessed through iterator

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