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

Revision 1751, 15.5 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(const bool trim = true);
247
248        void Trim();
249
250        static int GetEntrySizeByte();
251        static float GetEntrySize();
252
253        /** Compute continuous PVS difference
254        */
255        float GetPvsHomogenity(Pvs<T, S> &pvs);
256
257        static void Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b);
258
259        int GetSamples() const
260        {
261                return mSamples;
262        }
263
264        typename PvsIterator<T, S> GetIterator() const;
265
266protected:
267
268        /// vector of PVS entries
269        vector<PvsEntry<T, S> > mEntries;
270       
271        /// Number of samples used to create the PVS
272        int mSamples;
273};
274
275
276template <typename T, typename S>
277Pvs<T, S>::Pvs(const vector<PvsEntry<T, S> > &samples)
278{
279        mEntries.reserve(samples.size());
280        mEntries = samples;
281}
282
283
284/**
285   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
286   Provides separatelly PVS reduction from PVS enlargement.
287
288*/
289template <typename T, typename S>
290void
291Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
292                                                                                  float &pvsReduction,
293                                                                                  float &pvsEnlargement)
294{
295        pvsReduction = 0.0f;
296        pvsEnlargement = 0.0f;
297
298        // Uses sum of log differences, which corresponds to entropy
299        std::vector<PvsEntry<T, S> >::iterator it;
300
301        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
302        {
303                float bSumPdf = (*it).mData.mSumPdf;
304                float aSumPdf = 0.0f;
305
306                vector<PvsEntry<T, S> >::iterator oit = Find((*it).mObject);           
307
308                const bool entryFound = (it != mEntries.end()) && ((*it).mObject == (*oit).mObject);
309
310                if (entryFound)
311                {
312                        aSumPdf = (*it).mData.mSumPdf;
313
314                        // mark this entry as processed to avoid double counting
315                        (*it).mData.mSumPdf = -aSumPdf;
316                }
317
318#if 0
319                const float diff = bSumPdf - aSumPdf;
320
321                if (diff > 0.0f) {
322                        pvsEnlargement += diff;
323                } else {
324                        pvsReduction += -diff;
325                }
326#else
327                if (!entryFound)
328                        pvsEnlargement += 1.0f;
329#endif
330        }
331
332        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
333        {
334                float aSumPdf = (*it).mData.mSumPdf;
335                float bSumPdf = 0.0f;
336                if (aSumPdf < 0.0f) {
337               
338                        // this entry was already accounted for!
339                        // just revert it back
340                        (*it).mData.mSumPdf = -aSumPdf;
341                } else {
342                        vector<PvsEntry<T, S> >::iterator oit = b.Find((*it).mObject);
343
344                        const bool entryFound = (it != mEntries.end()) && ((*it).mObject == (*oit).mObject);
345                       
346                        if (entryFound) {
347                                bSumPdf = (*oit).mData.mSumPdf;
348                        }
349#if 0
350                        const float diff = bSumPdf - aSumPdf;
351
352                        if (diff > 0.0f) {
353                                pvsEnlargement += diff;
354                        } else {
355                                pvsReduction += -diff;
356                        }
357
358#else
359                        if (!entryFound)
360                                pvsReduction += 1.0f;
361#endif
362                }
363        }
364}
365
366
367template <typename T, typename S>
368int Pvs<T, S>::Diff(const Pvs<T, S> &b)
369{
370        int dif = 0;
371
372        std::vector<PvsEntry<T, S> >::const_iterator it;
373
374        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
375        {
376                std::vector<PvsEntry<T, S> >::const_iterator bit = Find((*it).first);           
377                if (bit == mEntries.end()) ++ dif;
378        }
379
380        return dif;
381}
382
383
384template <typename T, typename S>
385void Pvs<T, S>::MergeInPlace(const Pvs<T, S> &a)
386{
387    //const int samples = mSamples + a.mSamples;
388        ObjectPvs interPvs;
389       
390        Merge(interPvs, *this, a);
391       
392        mEntries.reserve(interPvs.GetSize());
393        mEntries = interPvs.mEntries;
394        mSamples = interPvs.mSamples;
395        //mSamples = samples;
396}
397
398
399template <typename T, typename S>
400void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b)
401{
402        std::vector<PvsEntry<T, S> >::const_iterator ait = a.mEntries.begin(), ait_end = a.mEntries.end();
403        std::vector<PvsEntry<T, S> >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end();
404       
405        for (; (ait != ait_end); ++ ait)
406        {
407                Intersectable *aObj = (*ait).mObject;
408                Intersectable *bObj = NULL;
409                PvsEntry<T, S> aEntry = (*ait);
410
411                for (; (bit != bit_end) && ((*bit).mObject <= (*ait).mObject); ++ bit)
412                {
413                        bObj = (*bit).mObject;
414
415                        // object found => add up probabilities
416                        if (bObj == aEntry.mObject)
417                        {
418                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
419                                PvsEntry<T, S> entry(bObj, newData);
420                                mergedPvs.mEntries.push_back(entry);
421                        }
422                        else
423                        {
424                                mergedPvs.mEntries.push_back(*bit);
425                        }
426                }
427
428                // only push back if objects different
429                // (equal case is handled by second loop)
430                if (aObj != bObj)
431                {
432                        mergedPvs.mEntries.push_back(*ait);
433                }
434        }
435
436        // add the rest
437        for (; (bit != bit_end); ++ bit)
438        {
439                mergedPvs.mEntries.push_back(*bit);
440        }
441        mergedPvs.mSamples = a.mSamples + b.mSamples;
442}
443
444
445template <typename T, typename S> void Pvs<T, S>::Clear(const bool trim = true)
446{
447        mEntries.clear();
448        mSamples = 0;
449        vector<PvsEntry<T,S> >().swap(mEntries);
450}
451
452
453template <typename T, typename S> void Pvs<T, S>::Trim()
454{
455        vector<PvsEntry<T,S> >(mEntries).swap(mEntries);//trim vi
456}
457
458
459template <typename T, typename S>
460typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample)
461{
462        PvsEntry<T, S> dummy(sample, PvsData());
463        vector<PvsEntry<T, S> >::iterator it = lower_bound(mEntries.begin(), mEntries.end(), dummy);
464                               
465        return it;
466}
467
468
469template <typename T, typename S>
470void Pvs<T, S>::GetData(const int index, T &entry, S &data)
471{
472        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
473        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
474
475        entry = (*i).first;
476        data = (*i).second;
477}
478
479
480template <typename T, typename S>
481float Pvs<T, S>::AddSample(T sample, const float pdf)
482{
483        ++ mSamples;
484        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
485
486        if ((it != mEntries.end()) && ((*it).mObject == sample))
487        {
488                S &data = (*it).mData;
489                data.mSumPdf += pdf;
490                return data.mSumPdf;
491        }
492        else
493        {
494                PvsEntry<T, S> entry(sample, pdf);
495                mEntries.insert(it, entry);
496                return pdf;
497        }
498}
499
500
501template <typename T, typename S>
502typename vector< PvsEntry<T, S> >::iterator Pvs<T, S>::AddSample2(T sample, const float pdf)
503{
504        ++ mSamples;
505        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
506
507        if ((it != mEntries.end()) && ((*it).mObject == sample))
508        {
509                S &data = (*it).second;
510                data->mSumPdf += pdf;
511        }
512        else
513        {
514                PvsEntry<T, S> entry(sample, pdf);
515                mEntries.insert(it, entry);
516        }
517
518        return it;
519}
520
521
522template <typename T, typename S>
523bool Pvs<T, S>::AddSample(T sample,
524                                                  const float pdf,
525                                                  float &contribution)
526{
527        ++ mSamples;
528
529        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
530
531        if ((it != mEntries.end()) && ((*it).mObject == sample))
532        {
533                S &data = (*it).mData;
534
535                data.mSumPdf += pdf;
536                contribution = pdf / data.mSumPdf;
537
538                return false;
539        }
540        else
541        {
542                PvsEntry<T, S> entry(sample, pdf);
543
544                mEntries.insert(it, entry);
545                contribution = 1.0f;
546
547                return true;
548        }
549}
550
551
552template <typename T, typename S>
553bool Pvs<T, S>::GetSampleContribution(T sample,
554                                                                          const float pdf,
555                                                                          float &contribution)
556{
557        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
558
559        if (it != mEntries.end() && ((*it).mObject == sample)) 
560        {
561                S &data = (*it).mData;
562                contribution = pdf / (data.mSumPdf + pdf);
563                return false;
564        }
565        else
566        {
567                contribution = 1.0f;
568                return true;
569        }
570}
571
572
573template <typename T, typename S>
574bool Pvs<T, S>::RemoveSample(T sample, const float pdf)
575{
576        -- mSamples;
577
578        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
579
580        if (it == mEntries.end())
581                return false;
582
583        S &data = (*it).mData;
584
585        data.mSumPdf -= pdf;
586
587        if (data.mSumPdf <= 0.0f)
588        {
589                mEntries.erase(it);
590        }
591
592        return true;
593}
594
595
596template <typename T, typename S>
597int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
598{
599        const int samples = mSamples - pvs.mSamples;
600
601        std::vector<PvsEntry<T, S> >::
602                const_iterator it, it_end = pvs.mEntries.end();
603
604        // output PVS of view cell
605        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
606                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
607
608        mSamples = samples;
609
610        return GetSize();
611}
612
613
614template <typename T, typename S>
615void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
616{
617        std::vector<PvsEntry<T, S> >::
618                const_iterator it, it_end = mEntries.end();
619
620        // output PVS of view cell
621        for (it = mEntries.begin(); it != it_end; ++ it)
622                entries.push_back((*it)->first);
623}
624
625
626template <typename T, typename S>
627void Pvs<T, S>::NormalizeMaximum()
628{
629        std::vector<PvsEntry<T, S> >::
630                const_iterator it, it_end = mEntries.end();
631
632        float maxPdfSum = -1.0f;
633
634        // output PVS of view cell
635        for (it = mEntries.begin(); it != it_end; ++ it) {
636                float sum = (*it)->second.sumPdf;
637                if (sum > maxSum)
638                        maxSum = sum;
639        }
640
641        maxSum = 1.0f / maxSum;
642
643        for (it = mEntries.begin(); it != it_end; ++ it) {
644                (*it)->second.sumPdf *= maxSum;
645        }
646
647}
648
649
650template <typename T, typename S>
651float Pvs<T, S>::GetEntrySize()
652{
653        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
654}
655
656
657template <typename T, typename S>
658int Pvs<T, S>::GetEntrySizeByte()
659{
660        return sizeof(T) + sizeof(S);
661}
662
663
664template <typename T, typename S>
665float Pvs<T, S>::GetPvsHomogenity(Pvs<T, S> &pvs)
666{
667        float pvsReduction, pvsEnlargement;
668
669        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
670
671        return pvsReduction + pvsEnlargement;
672}
673
674
675template <typename T, typename S>
676typename PvsIterator<T, S> Pvs<T, S>::GetIterator() const
677{
678        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
679
680        return pit;
681}
682
683
684///////////////////////////////////////
685
686/** Class instantiating the Pvs template for kd tree nodes.
687*/
688class KdPvs: public Pvs<KdNode *, PvsData>
689{
690public:
691        int Compress();
692};
693
694
695class ObjectPvs: public Pvs<Intersectable *, PvsData>
696{
697public:
698        /** Counts object int the pvs. Different to method "GetSize", not
699                only the raw container size is returned,
700                but the individual contributions of the entries are summed up.
701        */
702        float EvalPvsCost() const;
703};
704
705
706////////////
707//-- typedefs
708
709typedef PvsEntry<Intersectable *, PvsData> ObjectPvsEntry;
710typedef std::vector<ObjectPvsEntry> ObjectPvsEntries;
711typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
712typedef PvsIterator<Intersectable *, PvsData> ObjectPvsIterator;
713}
714
715#endif
716
Note: See TracBrowser for help on using the repository browser.