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

Revision 2570, 18.1 KB checked in by mattausch, 17 years ago (diff)
Line 
1#ifndef __VERBOSEPVS_H
2#define __VERBOSEPVS_H
3
4#include <vector>
5#include "common.h"
6#include <math.h>
7#include "PvsBase.h"
8
9
10
11namespace GtpVisibilityPreprocessor {
12
13
14/** Iterator over the pvs.
15*/
16template<typename T, typename S>
17class PvsIterator
18{
19public:
20        PvsIterator<T, S>(){}
21        PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
22                                          const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
23        mItCurrent(itCurrent), mItEnd(itEnd)
24        {
25        }
26
27        inline bool HasMoreEntries() const { return (mItCurrent != mItEnd);     }
28
29        inline T Next(S &pdf) {
30                pdf = (*mItCurrent).mData;
31                return (*(mItCurrent ++)).mObject;
32        }
33
34        inline T Next() { return (*(mItCurrent ++)).mObject; }
35
36
37private:
38       
39        typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
40        typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
41};
42
43
44struct VerbosePvsStats
45{
46        VerbosePvsStats(): mDistanceWeightedTriangles(0), mDistanceWeightedPvs(0), mWeightedTriangles(0)
47        {}
48
49        float mDistanceWeightedTriangles;
50        float mDistanceWeightedPvs;
51        float mWeightedTriangles;
52};
53
54
55/** Template class representing the Potentially Visible Set (PVS)
56        mainly from a view cell, but also e.g., from objects.
57*/
58template<typename T, typename S>
59class VerbosePvs
60{
61        template<typename T, typename S> friend class PvsIterator;
62
63public:
64
65        VerbosePvs(): mSamples(0), mEntries(), mLastSorted(0), mQueriesSinceSort(0)
66        {}
67
68        /** creates pvs and initializes it with the given entries.
69                Assumes that entries are sorted.
70        */
71        VerbosePvs(const vector<PvsEntry<T, S> > &samples);
72        virtual ~VerbosePvs() {};
73
74        /** Compresses PVS lossless or lossy.
75        */
76        int Compress() { return 0; }
77       
78        inline int GetSize() const { return (int)mEntries.size(); }
79       
80        inline bool Empty() const { return mEntries.empty(); }
81
82        inline void Reserve(const int n) { mEntries.reserve(n); }
83        /** Normalize the visibility of entries in order to get
84                comparable results.
85        */
86        void NormalizeMaximum();
87        /** Merges pvs of a into this pvs.
88                Warning: very slow!
89        */
90        void MergeInPlace(const VerbosePvs<T, S> &a);
91        /** Difference of pvs to pvs b.
92        @returns number of different entries.
93        */
94        int Diff(const VerbosePvs<T, S> &b);
95        /** Finds sample in PVS.
96                @param checkDirty if dirty part of the pvs should be checked for entry
97                (warning: linear runtime in dirty part)
98                @returns iterator on the sample if found, else the place where
99                it would be added in the sorted vector.
100        */
101        bool Find(T sample,
102                          typename vector<PvsEntry<T, S> >::iterator &it,
103                          const bool checkDirty = true);
104
105        bool GetSampleContribution(T sample, const float pdf, float &contribution);
106        /** Adds sample to PVS.
107                @returns contribution of sample (0 or 1)
108        */
109        float AddSample(T sample, const float pdf);
110        /** Adds sample to PVS without checking for presence of the sample
111                warning: pvs remains unsorted!
112        */
113        void AddSampleDirty(T sample, const float pdf);
114        /** Adds sample dirty (on the end of the vector) but
115                first checks if sample is already in clean part of the pvs.
116        */
117        bool AddSampleDirtyCheck(T sample, const float pdf);
118        /** Sort pvs entries. This should always be called after a
119                sequence of AddSampleDirty calls
120        */
121        void Sort();
122        /** Sort pvs entries assume that the pvs contains unique entries
123        */
124        void SimpleSort();
125        /** Adds sample to PVS.
126                @returns PvsData
127        */
128        typename std::vector<PvsEntry<T, S> >::iterator
129                AddSample2(T sample, const float pdf);
130        /** Subtracts one pvs from another one.
131                WARNING: could contains bugs
132                @returns new pvs size
133        */
134        int SubtractPvs(const VerbosePvs<T, S> &pvs);
135
136        /** Returns PVS data, i.e., how often it was seen from the view cell,
137                and the object itsef.
138        */
139        void GetData(const int index, T &entry, S &data);
140
141        /** Collects the PVS entries and returns them in the vector.
142        */
143        void CollectEntries(std::vector<T> &entries);
144
145        /** Removes sample from PVS if reference count is zero.
146        @param visibleSamples number of references to be removed
147        */
148        bool RemoveSample(T sample, const float pdf);
149
150        /** Compute continuous PVS difference
151        */
152        void ComputeContinuousPvsDifference(VerbosePvs<T, S> &pvs,
153                                                                                float &pvsReduction,
154                                                                                float &pvsEnlargement);
155
156        /** Clears the pvs.
157        */
158        void Clear(const bool trim = true);
159        /** Trim the vector containing the pvs.
160        */
161        void Trim();
162
163        static int GetEntrySizeByte();
164        static float GetEntrySize();
165
166        /** Compute continuous PVS difference
167        */
168        float GetPvsHomogenity(VerbosePvs<T, S> &pvs);
169
170        static void Merge(VerbosePvs<T, S> &mergedPvs,
171                                          const VerbosePvs<T, S> &a,
172                                          const VerbosePvs<T, S> &b);
173
174        inline int GetSamples() const { return mSamples; }
175
176        /** If there is an unsorted part in the pvs.
177        */
178        bool IsDirty() const { return mLastSorted < mEntries.size(); }
179
180        /** If this pvs requires a resort to stay efficient.
181        */
182        bool RequiresResort() const
183        {
184                // the last part should not be more than log of the sorted part. this
185                // way we can achieve logarithmic behaviour for insertion and find
186                const int n = mEntries.size();
187                const int dirtySize = n - mLastSorted;
188
189                const double LOG2E = 1.442695040f;
190
191                const float logN = log((float)max(1, n))/LOG2E;
192                const float logS = log((float)max(1, mLastSorted))/LOG2E;
193                const float logD = log((float)max(1, dirtySize))/LOG2E;
194
195                if (8*(n + 2*dirtySize*logD) <
196                        mQueriesSinceSort*((mLastSorted*logS + dirtySize*dirtySize/2)/n - logN))
197                {
198                        // cout<<"Q="<<mQueriesSinceSort<<" N="<<n<<" D="<<dirtySize<<endl;
199                        return true;
200                }
201               
202                return false;
203        }
204
205        /** If this pvs requires a resort to stay efficient.
206        */
207        bool RequiresResortLog() const
208        {
209                // the last part should not be more than log of the sorted part. this
210                // way we can achieve logarithmic behaviour for insertion and find
211                const int dirtySize = (int)mEntries.size() - mLastSorted;
212                return dirtySize > 4 * (int)(log((double)mEntries.size()) / log(2.0));
213        }
214
215        inline int GetLastSorted() const { return mLastSorted; }
216
217        typename PvsIterator<T, S> GetIterator() const;
218
219        VerbosePvsStats mStats;
220
221protected:
222
223        /** Merge pvs 1 from begin iterator to end iterator with
224                pvs 2 from begin iterator to end iterator.
225        */
226        static void Merge(VerbosePvs<T, S> &mergedPvs,
227                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
228                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
229                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
230                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
231                                          const int aSamples,
232                                          const int bSamples);
233
234
235        //////////////////////////////
236
237        /// vector of PVS entries
238        vector<PvsEntry<T, S> > mEntries;
239
240        /// Number of samples used to create the PVS
241        int mSamples;
242
243        /// Last sorted entry in the pvs (important for find and merge)
244        int mLastSorted;
245
246        int mQueriesSinceSort;
247};
248
249
250template <typename T, typename S>
251VerbosePvs<T, S>::VerbosePvs(const vector<PvsEntry<T, S> > &samples):
252mLastSorted(0)
253{
254        mEntries.reserve(samples.size());
255        mEntries = samples;
256        mSamples = samples.size();
257}
258
259
260template <typename T, typename S>
261void VerbosePvs<T, S>::Sort()
262{
263        vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
264        vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
265
266        // throw out double entries
267        std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
268        sort(it, newEnd);
269       
270        // now merge sorted ranges
271        ObjectPvs newPvs;
272        Merge(newPvs,
273                  mEntries.begin(),
274                  it,
275                  it,
276                  newEnd,
277                  mSamples,
278                  0);
279       
280        mEntries = newPvs.mEntries;
281        mLastSorted = (int)mEntries.size();
282        mQueriesSinceSort = 0;
283}
284
285template <typename T, typename S>
286void VerbosePvs<T, S>::SimpleSort()
287{
288        //  sort(mEntries.begin(), mEntries.end());
289        vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
290
291        sort(it, mEntries.end());
292        inplace_merge(mEntries.begin(), it, mEntries.end());
293 
294        mLastSorted = (int)mEntries.size();
295        mQueriesSinceSort = 0;
296}
297
298
299/**
300   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
301   Provides separatelly PVS reduction from PVS enlargement.
302
303*/
304template <typename T, typename S>
305void
306VerbosePvs<T, S>::ComputeContinuousPvsDifference(VerbosePvs<T, S> &b,
307                                                                                  float &pvsReduction,
308                                                                                  float &pvsEnlargement)
309{
310        pvsReduction = 0.0f;
311        pvsEnlargement = 0.0f;
312
313        // Uses sum of log differences, which corresponds to entropy
314        vector<PvsEntry<T, S> >::iterator it;
315
316        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
317        {
318                float bSumPdf = (*it).mData.mSumPdf;
319                float aSumPdf = 0.0f;
320
321                vector<PvsEntry<T, S> >::iterator oit;
322                const bool entryFound = Find((*it).mObject, oit);               
323
324                if (entryFound)
325                {
326                        aSumPdf = (*it).mData.mSumPdf;
327
328                        // mark this entry as processed to avoid double counting
329                        (*it).mData.mSumPdf = -aSumPdf;
330                }
331
332#if 0
333                const float diff = bSumPdf - aSumPdf;
334
335                if (diff > 0.0f)
336                {
337                        pvsEnlargement += diff;
338                }
339                else
340                {
341                        pvsReduction += -diff;
342                }
343#else
344                if (!entryFound)
345                {
346                        pvsEnlargement += 1.0f;
347                }
348#endif
349        }
350
351        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
352        {
353                float aSumPdf = (*it).mData.mSumPdf;
354                float bSumPdf = 0.0f;
355                if (aSumPdf < 0.0f)
356                {
357                        // this entry was already accounted for!
358                        // just revert it back
359                        (*it).mData.mSumPdf = -aSumPdf;
360                }
361                else
362                {
363                        vector<PvsEntry<T, S> >::iterator oit;
364               
365                        const bool entryFound = b.Find((*it).mObject, oit);
366                                               
367                        if (entryFound) {
368                                bSumPdf = (*oit).mData.mSumPdf;
369                        }
370#if 0
371                        const float diff = bSumPdf - aSumPdf;
372
373                        if (diff > 0.0f) {
374                                pvsEnlargement += diff;
375                        } else {
376                                pvsReduction += -diff;
377                        }
378
379#else
380                        if (!entryFound)
381                                pvsReduction += 1.0f;
382#endif
383                }
384        }
385}
386
387
388template <typename T, typename S>
389int VerbosePvs<T, S>::Diff(const VerbosePvs<T, S> &b)
390{
391        int dif = 0;
392
393        std::vector<PvsEntry<T, S> >::const_iterator it;
394
395        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
396        {
397                vector<PvsEntry<T, S> >::iterator bit;
398                const bool entryFound = Find((*it).first, bit);
399
400                if (!entryFound) ++ dif;
401        }
402
403        return dif;
404}
405
406
407template <typename T, typename S>
408void VerbosePvs<T, S>::MergeInPlace(const VerbosePvs<T, S> &a)
409{
410        // early exit
411        if (a.Empty())
412        {
413                return;
414        }
415        else if (Empty())
416        {
417                mEntries.reserve(a.GetSize());
418                mEntries = a.mEntries;
419                mSamples = a.mSamples;
420                return;
421        }
422
423        ObjectPvs interPvs;
424       
425        Merge(interPvs, *this, a);
426       
427        mEntries.reserve(interPvs.GetSize());
428        mEntries = interPvs.mEntries;
429        mSamples = interPvs.mSamples;
430}
431
432
433template <typename T, typename S>
434void VerbosePvs<T, S>::Merge(VerbosePvs<T, S> &mergedPvs,
435                                                         const VerbosePvs<T, S> &a,
436                                                         const VerbosePvs<T, S> &b)
437{
438        std::vector<PvsEntry<T, S> >::const_iterator ait =
439                a.mEntries.begin(), ait_end = a.mEntries.end();
440        std::vector<PvsEntry<T, S> >::const_iterator bit =
441                b.mEntries.begin(), bit_end = b.mEntries.end();
442       
443        Merge(mergedPvs,
444                  ait, ait_end,
445                  bit, bit_end,
446                  a.mSamples,
447                  b.mSamples);
448}
449
450
451template <typename T, typename S>
452void VerbosePvs<T, S>::Merge(VerbosePvs<T, S> &mergedPvs,
453                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
454                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
455                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
456                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
457                                          const int aSamples,
458                                          const int bSamples)
459{
460        std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
461        std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
462       
463        for (; (ait != aEnd); ++ ait)
464        {
465                Intersectable *aObj = (*ait).mObject;
466                Intersectable *bObj = NULL;
467                //Intersectable *bObjOld = NULL;
468       
469                const PvsEntry<T, S> &aEntry = (*ait);
470
471                for (; (bit != bEnd) && ((*bit).mObject <= (*ait).mObject); ++ bit)
472                {
473                        bObj = (*bit).mObject;
474
475                        // object found => add up probabilities
476                        if (bObj == aEntry.mObject)
477                        {
478                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
479                                PvsEntry<T, S> entry(bObj, newData);
480                                mergedPvs.mEntries.push_back(entry);
481                        }
482                        else
483                        {
484                                mergedPvs.mEntries.push_back(*bit);
485                        }
486                }
487
488                // only push back if objects different
489                // (equal case is handled by second loop)
490                if (aObj != bObj)
491                {
492                        mergedPvs.mEntries.push_back(*ait);
493                }
494        }
495
496        // add the rest
497        for (; (bit != bEnd); ++ bit)
498        {
499                mergedPvs.mEntries.push_back(*bit);
500        }
501
502        mergedPvs.mSamples = aSamples + bSamples;
503}
504
505
506template <typename T, typename S> void VerbosePvs<T, S>::Clear(const bool trim)
507{
508        mEntries.clear();
509        mSamples = 0;
510        mLastSorted = 0;
511
512        if (trim)
513        {
514                vector<PvsEntry<T,S> >().swap(mEntries);
515        }
516}
517
518
519template <typename T, typename S> void VerbosePvs<T, S>::Trim()
520{
521        vector<PvsEntry<T,S> >(mEntries).swap(mEntries);
522}
523
524
525template <typename T, typename S>
526bool VerbosePvs<T, S>::Find(T sample,
527                                         typename vector<PvsEntry<T, S> >::iterator &it,
528                                         const bool checkDirty)
529{
530        bool found = false;
531       
532        PvsEntry<T, S> dummy(sample, PvsData());
533
534        // only check clean part
535        vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
536        mQueriesSinceSort++;
537
538        // binary search
539        it = lower_bound(mEntries.begin(), sorted_end, dummy);
540
541        if ((it != mEntries.end()) && ((*it).mObject == sample))
542                found = true;
543
544        // sample not found yet => search further in the unsorted part
545        if (!found && checkDirty)
546        {
547                vector<PvsEntry<T, S> >::iterator dit, dit_end = mEntries.end();
548
549        for (dit = sorted_end; (dit != dit_end) && ((*dit).mObject != sample); ++ dit);
550       
551                if (dit != dit_end)
552                {
553                        found = true;
554                        it = dit;
555                }
556        }
557
558        return found;
559}
560
561
562template <typename T, typename S>
563void VerbosePvs<T, S>::GetData(const int index, T &entry, S &data)
564{
565        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
566        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
567
568        entry = (*i).first;
569        data = (*i).second;
570}
571
572
573template <typename T, typename S>
574float VerbosePvs<T, S>::AddSample(T sample, const float pdf)
575{
576        ++ mSamples;
577       
578        vector<PvsEntry<T, S> >::iterator it;
579        const bool entryFound = Find(sample, it);               
580
581        if (entryFound)
582        {       
583                S &data = (*it).mData;
584                data.mSumPdf += pdf;
585                return data.mSumPdf;
586        }
587        else
588        {
589                PvsEntry<T, S> entry(sample, pdf);
590                mEntries.insert(it, entry);
591                ++ mLastSorted;
592                return pdf;
593        }
594}
595
596
597template <typename T, typename S>
598void VerbosePvs<T, S>::AddSampleDirty(T sample, const float pdf)
599{
600        ++ mSamples;
601        mEntries.push_back(PvsEntry<T, S>(sample, pdf));
602}
603                                         
604
605template <typename T, typename S>
606typename vector< PvsEntry<T, S> >::iterator
607VerbosePvs<T, S>::AddSample2(T sample, const float pdf)
608{
609        ++ mSamples;
610       
611        vector<PvsEntry<T, S> >::iterator it;
612        const bool entryFound = Find(sample, it);
613
614        if (entryFound)
615        {
616                S &data = (*it).second;
617                data->mSumPdf += pdf;
618        }
619        else
620        {
621                PvsEntry<T, S> entry(sample, pdf);
622                mEntries.insert(it, entry);
623                ++ mLastSorted;
624        }
625
626        return it;
627}
628
629
630template <typename T, typename S>
631bool VerbosePvs<T, S>::AddSampleDirtyCheck(T sample, const float pdf)
632{
633        ++ mSamples;
634
635        vector<PvsEntry<T, S> >::iterator it;
636        const bool entryFound = Find(sample, it);
637
638        if (entryFound)
639        {
640                S &data = (*it).mData;
641         
642                data.mSumPdf += pdf;
643        return false;
644        }
645        else
646        {
647                AddSampleDirty(sample, pdf);
648                return true;
649        }
650}
651
652
653template <typename T, typename S>
654bool VerbosePvs<T, S>::GetSampleContribution(T sample,
655                                                                          const float pdf,
656                                                                          float &contribution)
657{
658        vector<PvsEntry<T, S> >::iterator it;
659        const bool entryFound = Find(sample, it);
660
661        if (entryFound) 
662        {
663                S &data = (*it).mData;
664                contribution = pdf / (data.mSumPdf + pdf);
665                return false;
666        }
667        else
668        {
669                contribution = 1.0f;
670                return true;
671        }
672}
673
674
675template <typename T, typename S>
676bool VerbosePvs<T, S>::RemoveSample(T sample, const float pdf)
677{
678        -- mSamples;
679       
680        vector<PvsEntry<T, S> >::iterator it;
681        const bool entryFound = Find(sample, it);
682
683        if (!entryFound)
684                return false;
685
686        S &data = (*it).mData;
687
688        data.mSumPdf -= pdf;
689
690        if (data.mSumPdf <= 0.0f)
691        {
692                mEntries.erase(it);
693                -- mLastSorted; // wrong if sample was in tail!!
694        }
695
696        return true;
697}
698
699
700template <typename T, typename S>
701int VerbosePvs<T, S>::SubtractPvs(const VerbosePvs<T, S> &pvs)
702{
703        const int samples = mSamples - pvs.mSamples;
704
705        std::vector<PvsEntry<T, S> >::
706                const_iterator it, it_end = pvs.mEntries.end();
707
708        // output PVS of view cell
709        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
710                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
711
712        mSamples = samples;
713
714        return GetSize();
715}
716
717
718template <typename T, typename S>
719void VerbosePvs<T, S>::CollectEntries(std::vector<T> &entries)
720{
721        std::vector<PvsEntry<T, S> >::
722                const_iterator it, it_end = mEntries.end();
723
724        // output PVS of view cell
725        for (it = mEntries.begin(); it != it_end; ++ it)
726                entries.push_back((*it)->first);
727}
728
729
730template <typename T, typename S>
731void VerbosePvs<T, S>::NormalizeMaximum()
732{
733        std::vector<PvsEntry<T, S> >::
734                const_iterator it, it_end = mEntries.end();
735
736        float maxPdfSum = -1.0f;
737
738        // output PVS of view cell
739        for (it = mEntries.begin(); it != it_end; ++ it) {
740                float sum = (*it)->second.sumPdf;
741                if (sum > maxSum)
742                        maxSum = sum;
743        }
744
745        maxSum = 1.0f / maxSum;
746
747        for (it = mEntries.begin(); it != it_end; ++ it) {
748                (*it)->second.sumPdf *= maxSum;
749        }
750}
751
752
753template <typename T, typename S>
754float VerbosePvs<T, S>::GetEntrySize()
755{
756        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
757}
758
759
760template <typename T, typename S>
761int VerbosePvs<T, S>::GetEntrySizeByte()
762{
763        return sizeof(T) + sizeof(S);
764}
765
766
767template <typename T, typename S>
768float VerbosePvs<T, S>::GetPvsHomogenity(VerbosePvs<T, S> &pvs)
769{
770        float pvsReduction, pvsEnlargement;
771
772        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
773        return pvsReduction + pvsEnlargement;
774}
775
776
777template <typename T, typename S>
778typename PvsIterator<T, S> VerbosePvs<T, S>::GetIterator() const
779{
780        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
781        return pit;
782}
783
784}
785
786#endif
787
Note: See TracBrowser for help on using the repository browser.