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

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