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

Revision 1745, 15.2 KB checked in by mattausch, 18 years ago (diff)
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
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
139        const PvsEntry<T, S> &Next()
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;
147};
148
149
150/** Template class representing the Potentially Visible Set (PVS)
151        mainly from a view cell, but also e.g., from objects.
152*/
153template<typename T, typename S>
154class Pvs
155{
156        template<typename T, typename S>
157        friend class PvsIterator;
158
159public:
160
161        Pvs(): mSamples(0), mEntries() {}
162
163        /** creates pvs and initializes it with the given entries.
164                Assumes that entries are sorted-
165        */
166        Pvs(const vector<PvsEntry<T, S> > &samples);
167        virtual ~Pvs() {};
168
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();}
174
175        /** Normalize the visibility of entries in order to get
176                comparable results.
177        */
178        void NormalizeMaximum();
179
180        /** Merges pvs of a into this pvs.
181                Warning: very slow!
182        */
183        void MergeInPlace(const Pvs<T, S> &a);
184
185        /** Difference of pvs to pvs b.
186                @returns number of different entries.
187        */
188        int Diff(const Pvs<T, S> &b);
189
190        /** Finds sample in PVS.
191                @returns iterator on the sample.
192        */
193        typename vector<PvsEntry<T, S> >::iterator Find(T sample);
194
195        bool GetSampleContribution(T sample, const float pdf, float &contribution);
196
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);
202
203        /** Adds sample to PVS.
204                @returns contribution of sample (0 or 1)
205        */
206        float AddSample(T sample, const float pdf);
207       
208        /** Adds sample to PVS. Assumes that the pvs is sorted
209                @returns contribution of sample (0 or 1)
210        */
211        float AddSamples(const vector<PvsEntry<T, S> > &samples);
212
213        /** Adds sample to PVS.
214                @returns PvsData
215        */
216        typename std::vector<PvsEntry<T, S> >::iterator AddSample2(T sample, const float pdf);
217
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);
223
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        */
240        void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
241                                                                                float &pvsReduction,
242                                                                                float &pvsEnlargement);
243
244        /** Clears the pvs.
245        */
246        void Clear();
247
248        static int GetEntrySizeByte();
249        static float GetEntrySize();
250
251        /** Compute continuous PVS difference
252        */
253        float GetPvsHomogenity(Pvs<T, S> &pvs);
254
255        static void Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b);
256
257        int GetSamples() const
258        {
259                return mSamples;
260        }
261
262        typename PvsIterator<T, S> GetIterator() const;
263
264protected:
265
266        /// vector of PVS entries
267        vector<PvsEntry<T, S> > mEntries;
268       
269        /// Number of samples used to create the PVS
270        int mSamples;
271};
272
273
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}
280
281
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*/
287template <typename T, typename S>
288void
289Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
290                                                                                  float &pvsReduction,
291                                                                                  float &pvsEnlargement)
292{
293        pvsReduction = 0.0f;
294        pvsEnlargement = 0.0f;
295
296        // Uses sum of log differences, which corresponds to entropy
297        std::vector<PvsEntry<T, S> >::iterator it;
298
299        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
300        {
301                float bSumPdf = (*it).mData.mSumPdf;
302                float aSumPdf = 0.0f;
303
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)
309                {
310                        aSumPdf = (*it).mData.mSumPdf;
311
312                        // mark this entry as processed to avoid double counting
313                        (*it).mData.mSumPdf = -aSumPdf;
314                }
315
316#if 0
317                const float diff = bSumPdf - aSumPdf;
318
319                if (diff > 0.0f) {
320                        pvsEnlargement += diff;
321                } else {
322                        pvsReduction += -diff;
323                }
324#else
325                if (!entryFound)
326                        pvsEnlargement += 1.0f;
327#endif
328        }
329
330        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
331        {
332                float aSumPdf = (*it).mData.mSumPdf;
333                float bSumPdf = 0.0f;
334                if (aSumPdf < 0.0f) {
335               
336                        // this entry was already accounted for!
337                        // just revert it back
338                        (*it).mData.mSumPdf = -aSumPdf;
339                } else {
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;
346                        }
347#if 0
348                        const float diff = bSumPdf - aSumPdf;
349
350                        if (diff > 0.0f) {
351                                pvsEnlargement += diff;
352                        } else {
353                                pvsReduction += -diff;
354                        }
355
356#else
357                        if (!entryFound)
358                                pvsReduction += 1.0f;
359#endif
360                }
361        }
362}
363
364
365template <typename T, typename S>
366int Pvs<T, S>::Diff(const Pvs<T, S> &b)
367{
368        int dif = 0;
369
370        std::vector<PvsEntry<T, S> >::const_iterator it;
371
372        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
373        {
374                std::vector<PvsEntry<T, S> >::const_iterator bit = Find((*it).first);           
375                if (bit == mEntries.end()) ++ dif;
376        }
377
378        return dif;
379}
380
381
382template <typename T, typename S>
383void Pvs<T, S>::MergeInPlace(const Pvs<T, S> &a)
384{
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();
403       
404        for (; (ait != ait_end); ++ ait)
405        {
406                Intersectable *aObj = (*ait).mObject;
407                Intersectable *bObj = NULL;
408                PvsEntry<T, S> aEntry = (*ait);
409
410                for (; (bit != bit_end) && ((*bit).mObject <= (*ait).mObject); ++ bit)
411                {
412                        bObj = (*bit).mObject;
413
414                        // object found => add up probabilities
415                        if (bObj == aEntry.mObject)
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)
437        {
438                mergedPvs.mEntries.push_back(*bit);
439        }
440}
441
442
443template <typename T, typename S> void Pvs<T, S>::Clear()
444{
445        mEntries.clear();
446}
447
448
449template <typename T, typename S>
450typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample)
451{
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;
456}
457
458
459template <typename T, typename S>
460void Pvs<T, S>::GetData(const int index, T &entry, S &data)
461{
462        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
463        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
464
465        entry = (*i).first;
466        data = (*i).second;
467}
468
469
470template <typename T, typename S>
471float Pvs<T, S>::AddSample(T sample, const float pdf)
472{
473        ++ mSamples;
474        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
475
476        if ((it != mEntries.end()) && ((*it).mObject == sample))
477        {
478                S &data = (*it).mData;
479                data.mSumPdf += pdf;
480                return data.mSumPdf;
481        }
482        else
483        {
484                PvsEntry<T, S> entry(sample, pdf);
485                mEntries.insert(it, entry);
486                return pdf;
487        }
488}
489
490
491template <typename T, typename S>
492typename vector< PvsEntry<T, S> >::iterator Pvs<T, S>::AddSample2(T sample, const float pdf)
493{
494        ++ mSamples;
495        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
496
497        if ((it != mEntries.end()) && ((*it).mObject == sample))
498        {
499                S &data = (*it).second;
500                data->mSumPdf += pdf;
501        }
502        else
503        {
504                PvsEntry<T, S> entry(sample, pdf);
505                mEntries.insert(it, entry);
506        }
507
508        return it;
509}
510
511
512template <typename T, typename S>
513bool Pvs<T, S>::AddSample(T sample,
514                                                  const float pdf,
515                                                  float &contribution)
516{
517        ++ mSamples;
518
519        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
520
521        if ((it != mEntries.end()) && ((*it).mObject == sample))
522        {
523                S &data = (*it).mData;
524
525                data.mSumPdf += pdf;
526                contribution = pdf / data.mSumPdf;
527
528                return false;
529        }
530        else
531        {
532                PvsEntry<T, S> entry(sample, pdf);
533
534                mEntries.insert(it, entry);
535                contribution = 1.0f;
536
537                return true;
538        }
539}
540
541
542template <typename T, typename S>
543bool Pvs<T, S>::GetSampleContribution(T sample,
544                                                                          const float pdf,
545                                                                          float &contribution)
546{
547        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
548
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        }
560}
561
562
563template <typename T, typename S>
564bool Pvs<T, S>::RemoveSample(T sample, const float pdf)
565{
566        -- mSamples;
567
568        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
569
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;
583}
584
585
586template <typename T, typename S>
587int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
588{
589        const int samples = mSamples - pvs.mSamples;
590
591        std::vector<PvsEntry<T, S> >::
592                const_iterator it, it_end = pvs.mEntries.end();
593
594        // output PVS of view cell
595        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
596                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
597
598        mSamples = samples;
599
600        return GetSize();
601}
602
603
604template <typename T, typename S>
605void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
606{
607        std::vector<PvsEntry<T, S> >::
608                const_iterator it, it_end = mEntries.end();
609
610        // output PVS of view cell
611        for (it = mEntries.begin(); it != it_end; ++ it)
612                entries.push_back((*it)->first);
613}
614
615
616template <typename T, typename S>
617void Pvs<T, S>::NormalizeMaximum()
618{
619        std::vector<PvsEntry<T, S> >::
620                const_iterator it, it_end = mEntries.end();
621
622        float maxPdfSum = -1.0f;
623
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        }
630
631        maxSum = 1.0f / maxSum;
632
633        for (it = mEntries.begin(); it != it_end; ++ it) {
634                (*it)->second.sumPdf *= maxSum;
635        }
636
637}
638
639
640template <typename T, typename S>
641float Pvs<T, S>::GetEntrySize()
642{
643        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
644}
645
646
647template <typename T, typename S>
648int Pvs<T, S>::GetEntrySizeByte()
649{
650        return sizeof(T) + sizeof(S);
651}
652
653
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
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
674///////////////////////////////////////
675
676/** Class instantiating the Pvs template for kd tree nodes.
677*/
678class KdPvs: public Pvs<KdNode *, PvsData>
679{
680public:
681        int Compress();
682};
683
684
685class ObjectPvs: public Pvs<Intersectable *, PvsData>
686{
687public:
688        /** Counts object int the pvs. Different to method "GetSize", not
689                only the raw container size is returned,
690                but the individual contributions of the entries are summed up.
691        */
692        float EvalPvsCost() const;
693};
694
695
696////////////
697//-- typedefs
698
699typedef PvsEntry<Intersectable *, PvsData> ObjectPvsEntry;
700typedef std::vector<ObjectPvsEntry> ObjectPvsEntries;
701typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
702typedef PvsIterator<Intersectable *, PvsData> ObjectPvsIterator;
703}
704
705#endif
706
Note: See TracBrowser for help on using the repository browser.