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

Revision 1764, 16.2 KB checked in by mattausch, 18 years ago (diff)

removed error in sample registration

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