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

Revision 1757, 16.3 KB checked in by bittner, 18 years ago (diff)

pvs updates

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    //const int samples = mSamples + a.mSamples;
410        ObjectPvs interPvs;
411       
412        Merge(interPvs, *this, a);
413       
414        mEntries.reserve(interPvs.GetSize());
415        mEntries = interPvs.mEntries;
416        mSamples = interPvs.mSamples;
417        //mSamples = samples;
418}
419
420
421template <typename T, typename S>
422void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b)
423{
424        std::vector<PvsEntry<T, S> >::const_iterator ait = a.mEntries.begin(), ait_end = a.mEntries.end();
425        std::vector<PvsEntry<T, S> >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end();
426       
427        for (; (ait != ait_end); ++ ait)
428        {
429                Intersectable *aObj = (*ait).mObject;
430                Intersectable *bObj = NULL;
431                PvsEntry<T, S> aEntry = (*ait);
432
433                for (; (bit != bit_end) && ((*bit).mObject <= (*ait).mObject); ++ bit)
434                {
435                        bObj = (*bit).mObject;
436
437                        // object found => add up probabilities
438                        if (bObj == aEntry.mObject)
439                        {
440                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
441                                PvsEntry<T, S> entry(bObj, newData);
442                                mergedPvs.mEntries.push_back(entry);
443                        }
444                        else
445                        {
446                                mergedPvs.mEntries.push_back(*bit);
447                        }
448                }
449
450                // only push back if objects different
451                // (equal case is handled by second loop)
452                if (aObj != bObj)
453                {
454                        mergedPvs.mEntries.push_back(*ait);
455                }
456        }
457
458        // add the rest
459        for (; (bit != bit_end); ++ bit)
460        {
461                mergedPvs.mEntries.push_back(*bit);
462        }
463        mergedPvs.mSamples = a.mSamples + b.mSamples;
464}
465
466
467template <typename T, typename S> void Pvs<T, S>::Clear(const bool trim = true)
468{
469        mEntries.clear();
470        mSamples = 0;
471        vector<PvsEntry<T,S> >().swap(mEntries);
472}
473
474
475template <typename T, typename S> void Pvs<T, S>::Trim()
476{
477        vector<PvsEntry<T,S> >(mEntries).swap(mEntries);//trim vi
478}
479
480
481template <typename T, typename S>
482typename std::vector<PvsEntry<T, S> >::iterator Pvs<T, S>::Find(T sample)
483{
484        PvsEntry<T, S> dummy(sample, PvsData());
485        vector<PvsEntry<T, S> >::iterator it = lower_bound(mEntries.begin(), mEntries.end(), dummy);
486                               
487        return it;
488}
489
490
491template <typename T, typename S>
492void Pvs<T, S>::GetData(const int index, T &entry, S &data)
493{
494        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
495        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
496
497        entry = (*i).first;
498        data = (*i).second;
499}
500
501
502template <typename T, typename S>
503float Pvs<T, S>::AddSample(T sample, const float pdf)
504{
505        ++ mSamples;
506        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
507
508        if ((it != mEntries.end()) && ((*it).mObject == sample))
509        {
510                S &data = (*it).mData;
511                data.mSumPdf += pdf;
512                return data.mSumPdf;
513        }
514        else
515        {
516                PvsEntry<T, S> entry(sample, pdf);
517                mEntries.insert(it, entry);
518                return pdf;
519        }
520}
521
522
523template <typename T, typename S>
524void Pvs<T, S>::AddSampleDirty(T sample, const float pdf)
525{
526  ++ mSamples;
527  mEntries.push_back(PvsEntry<T, S>(sample, pdf));
528}
529                                         
530
531template <typename T, typename S>
532typename vector< PvsEntry<T, S> >::iterator Pvs<T, S>::AddSample2(T sample, const float pdf)
533{
534        ++ mSamples;
535        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
536
537        if ((it != mEntries.end()) && ((*it).mObject == sample))
538        {
539                S &data = (*it).second;
540                data->mSumPdf += pdf;
541        }
542        else
543        {
544                PvsEntry<T, S> entry(sample, pdf);
545                mEntries.insert(it, entry);
546        }
547
548        return it;
549}
550
551
552template <typename T, typename S>
553bool Pvs<T, S>::AddSample(T sample,
554                                                  const float pdf,
555                                                  float &contribution)
556{
557        ++ mSamples;
558
559        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
560
561        if ((it != mEntries.end()) && ((*it).mObject == sample))
562        {
563                S &data = (*it).mData;
564
565                data.mSumPdf += pdf;
566                contribution = pdf / data.mSumPdf;
567
568                return false;
569        }
570        else
571        {
572                PvsEntry<T, S> entry(sample, pdf);
573
574                mEntries.insert(it, entry);
575                contribution = 1.0f;
576
577                return true;
578        }
579}
580
581
582template <typename T, typename S>
583bool Pvs<T, S>::GetSampleContribution(T sample,
584                                                                          const float pdf,
585                                                                          float &contribution)
586{
587        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
588
589        if (it != mEntries.end() && ((*it).mObject == sample)) 
590        {
591                S &data = (*it).mData;
592                contribution = pdf / (data.mSumPdf + pdf);
593                return false;
594        }
595        else
596        {
597                contribution = 1.0f;
598                return true;
599        }
600}
601
602
603template <typename T, typename S>
604bool Pvs<T, S>::RemoveSample(T sample, const float pdf)
605{
606        -- mSamples;
607
608        std::vector<PvsEntry<T, S> >::iterator it = Find(sample);
609
610        if (it == mEntries.end())
611                return false;
612
613        S &data = (*it).mData;
614
615        data.mSumPdf -= pdf;
616
617        if (data.mSumPdf <= 0.0f)
618        {
619                mEntries.erase(it);
620        }
621
622        return true;
623}
624
625
626template <typename T, typename S>
627int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
628{
629        const int samples = mSamples - pvs.mSamples;
630
631        std::vector<PvsEntry<T, S> >::
632                const_iterator it, it_end = pvs.mEntries.end();
633
634        // output PVS of view cell
635        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
636                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
637
638        mSamples = samples;
639
640        return GetSize();
641}
642
643
644template <typename T, typename S>
645void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
646{
647        std::vector<PvsEntry<T, S> >::
648                const_iterator it, it_end = mEntries.end();
649
650        // output PVS of view cell
651        for (it = mEntries.begin(); it != it_end; ++ it)
652                entries.push_back((*it)->first);
653}
654
655
656template <typename T, typename S>
657void Pvs<T, S>::NormalizeMaximum()
658{
659        std::vector<PvsEntry<T, S> >::
660                const_iterator it, it_end = mEntries.end();
661
662        float maxPdfSum = -1.0f;
663
664        // output PVS of view cell
665        for (it = mEntries.begin(); it != it_end; ++ it) {
666                float sum = (*it)->second.sumPdf;
667                if (sum > maxSum)
668                        maxSum = sum;
669        }
670
671        maxSum = 1.0f / maxSum;
672
673        for (it = mEntries.begin(); it != it_end; ++ it) {
674                (*it)->second.sumPdf *= maxSum;
675        }
676
677}
678
679
680template <typename T, typename S>
681float Pvs<T, S>::GetEntrySize()
682{
683        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
684}
685
686
687template <typename T, typename S>
688int Pvs<T, S>::GetEntrySizeByte()
689{
690        return sizeof(T) + sizeof(S);
691}
692
693
694template <typename T, typename S>
695float Pvs<T, S>::GetPvsHomogenity(Pvs<T, S> &pvs)
696{
697        float pvsReduction, pvsEnlargement;
698
699        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
700
701        return pvsReduction + pvsEnlargement;
702}
703
704
705template <typename T, typename S>
706typename PvsIterator<T, S> Pvs<T, S>::GetIterator() const
707{
708        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
709
710        return pit;
711}
712
713
714///////////////////////////////////////
715
716/** Class instantiating the Pvs template for kd tree nodes.
717*/
718class KdPvs: public Pvs<KdNode *, PvsData>
719{
720public:
721        int Compress();
722};
723
724
725class ObjectPvs: public Pvs<Intersectable *, PvsData>
726{
727public:
728        /** Counts object int the pvs. Different to method "GetSize", not
729                only the raw container size is returned,
730                but the individual contributions of the entries are summed up.
731        */
732        float EvalPvsCost() const;
733};
734
735
736////////////
737//-- typedefs
738
739typedef PvsEntry<Intersectable *, PvsData> ObjectPvsEntry;
740typedef std::vector<ObjectPvsEntry> ObjectPvsEntries;
741typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
742typedef PvsIterator<Intersectable *, PvsData> ObjectPvsIterator;
743}
744
745#endif
746
Note: See TracBrowser for help on using the repository browser.