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

Revision 1877, 20.2 KB checked in by bittner, 18 years ago (diff)

sampling updates

RevLine 
[177]1#ifndef __PVS_H
2#define __PVS_H
3
4#include <map>
[469]5#include <vector>
[1189]6#include "common.h"
[177]7
[860]8namespace GtpVisibilityPreprocessor {
9
[177]10class KdNode;
[240]11class BspNode;
[191]12class Ray;
[308]13class Intersectable;
[1077]14class ViewCell;
[177]15
[1077]16
[1740]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
[1189]22{
[1740]23public:
24
[1741]25        PvsEntry() {}
26
[1740]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);
[1789]34        template<typename T, typename S>
35        friend int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b);
[1740]36};
37
38
39template<typename T, typename S>
40int operator< (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
41{
42        return a.mObject < b.mObject;
43}
44
[1789]45template<typename T, typename S>
46int operator== (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
47{
48        return a.mObject == b.mObject;
49}
[1740]50
[1789]51
[1740]52template<typename T, typename S>
53struct LtSample
54{
55    bool operator()(const PvsEntry<T, S> &a, const PvsEntry<T, S> &b) const
[310]56    {
[1740]57                return a.mObject < b.mObject;
[310]58        }
59};
60
[1789]61template<typename T, typename S>
62int equalSample (const PvsEntry<T, S> &a, const PvsEntry<T, S> &b)
63{
64        return a.mObject == b.mObject;
65}
[1740]66
[469]67/** Information stored with a PVS entry. Consists of the number
68        the object was seen from the view cell.
69*/
[1189]70class PvsData {
71public:
[1706]72        PvsData() {}
73        PvsData(const float sumPdf):
[1189]74        mSumPdf(sumPdf) {}
[1740]75       
[1706]76        // $$JB in order to return meaningfull values
77        // it assumes that the sum pdf has been normalized somehow!!!
[1740]78        inline float GetVisibility()
[1706]79        {
80                return mSumPdf;
81        }
[1740]82
83        /// sum of probability density of visible sample rays
84        float mSumPdf;
[1189]85};
86
87
88class MailablePvsData
89{
[1740]90public:
91        // sum of probability density of visible sample rays
92        float mSumPdf;
93        int mCounter;
94
95        MailablePvsData() {}
96        MailablePvsData(const float sumPdf):
97        mSumPdf(sumPdf) {}
98
99        // $$JB in order to return meaningfull values
100        // it assumes that the sum pdf has been normalized somehow!!!
101        float GetVisibility()
102        {
103                return mSumPdf;
104        }
105
[1706]106        ////////////////////////////
107        //  Mailing stuff
[1184]108
[1706]109        // last mail id -> warning not thread safe!
110        // both mailId and mailbox should be unique for each thread!!!
111        static int sMailId;
112        static int sReservedMailboxes;
113
[1184]114        static void NewMail(const int reserve = 1) {
115                sMailId += sReservedMailboxes;
116                sReservedMailboxes = reserve;
117        }
[1706]118
[1184]119        void Mail() { mMailbox = sMailId; }
120        bool Mailed() const { return mMailbox == sMailId; }
121
122        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
123        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
124
125        int IncMail() { return ++ mMailbox - sMailId; }
[1740]126       
[1706]127        //////////////////////////////////////////
[1184]128
[1740]129protected:
[1184]130
[1740]131        int mMailbox;
[556]132
[310]133};
[1740]134
135
[1742]136template<typename T, typename S>
137class PvsIterator
138{
139public:
140PvsIterator<T, S>(){}
141        PvsIterator<T, S>(const typename vector<PvsEntry<T, S> >::const_iterator &itCurrent,
142                                          const typename vector<PvsEntry<T, S> >::const_iterator &itEnd):
143        mItCurrent(itCurrent), mItEnd(itEnd)
144        {
145        }
146
147        bool HasMoreEntries() const
148        {
149                return (mItCurrent != mItEnd);
150        }
151
[1744]152        const PvsEntry<T, S> &Next()
[1742]153        {
154                return *(mItCurrent ++);
155        }
156       
157private:
158        typename vector<PvsEntry<T, S> >::const_iterator mItCurrent;
159        typename vector<PvsEntry<T, S> >::const_iterator mItEnd;
[1740]160};
161
162
[469]163/** Template class representing the Potentially Visible Set (PVS)
164        mainly from a view cell, but also e.g., from objects.
165*/
[1189]166template<typename T, typename S>
[311]167class Pvs
[310]168{
[1740]169        template<typename T, typename S>
170        friend class PvsIterator;
171
[310]172public:
[1738]173
[1757]174        Pvs(): mSamples(0), mEntries(), mLastSorted(0) {}
[1738]175
[1742]176        /** creates pvs and initializes it with the given entries.
177                Assumes that entries are sorted-
178        */
[1740]179        Pvs(const vector<PvsEntry<T, S> > &samples);
[1742]180        virtual ~Pvs() {};
[492]181
[1706]182        /** Compresses PVS lossless or lossy.
183        */
184        int Compress() {return 0;}
185        int GetSize() const {return (int)mEntries.size();}
[1877]186  bool Empty() const {return mEntries.empty();}
[469]187
[1877]188  void Reserve(const int n) { mEntries.reserve(n); }
[1740]189        /** Normalize the visibility of entries in order to get
190                comparable results.
[1706]191        */
192        void NormalizeMaximum();
[1184]193
[1706]194        /** Merges pvs of a into this pvs.
[1740]195                Warning: very slow!
[1706]196        */
[1740]197        void MergeInPlace(const Pvs<T, S> &a);
[752]198
[1706]199        /** Difference of pvs to pvs b.
200                @returns number of different entries.
201        */
202        int Diff(const Pvs<T, S> &b);
[469]203
[1706]204        /** Finds sample in PVS.
[1789]205                @param checkDirty if dirty part of the pvs should be checked for entry
206                        (warning: linear runtime in dirty part)
[1740]207                @returns iterator on the sample.
[1706]208        */
[1790]209        bool Find(T sample,
210                          typename vector<PvsEntry<T, S> >::iterator &it,
211                          const bool checkDirty = true);
[469]212
[1706]213        bool GetSampleContribution(T sample, const float pdf, float &contribution);
[485]214
[1706]215        /** Adds sample to PVS.
216                @returns contribution of sample (0 or 1)
217        */
218        float AddSample(T sample, const float pdf);
[1757]219
[1789]220        /** Adds sample to PVS without checking for presence of the sample
221                pvs remains unsorted!
222        */
223        void AddSampleDirty(T sample, const float pdf);
[1757]224
[1789]225        /** Adds sample dirty (on the end of the vector) but
226                first checks if sample is already in clean part of the pvs.
227        */
228        bool AddSampleDirtyCheck(T sample, const float pdf);//, float &contribution);
229
230        /** Sort pvs entries - this should always be called after a
231                sequence of AddSampleDirty calls
232        */
233        void Sort();
234
[1877]235  /** Sort pvs entries assume that the pvs contains unique entries
236   */
237  void SimpleSort();
238
[1742]239        /** Adds sample to PVS. Assumes that the pvs is sorted
[1740]240                @returns contribution of sample (0 or 1)
241        */
[1844]242        //float AddSamples(const vector<PvsEntry<T, S> > &samples);
[752]243
[1706]244        /** Adds sample to PVS.
245                @returns PvsData
246        */
[1740]247        typename std::vector<PvsEntry<T, S> >::iterator AddSample2(T sample, const float pdf);
[1667]248
[1706]249        /** Subtracts one pvs from another one.
250                WARNING: could contains bugs
251                @returns new pvs size
252        */
253        int SubtractPvs(const Pvs<T, S> &pvs);
[1740]254
[1706]255        /** Returns PVS data, i.e., how often it was seen from the view cell,
256                and the object itsef.
257        */
258        void GetData(const int index, T &entry, S &data);
259
260        /** Collects the PVS entries and returns them in the vector.
261        */
262        void CollectEntries(std::vector<T> &entries);
263
264        /** Removes sample from PVS if reference count is zero.
265                @param visibleSamples number of references to be removed
266        */
267        bool RemoveSample(T sample, const float pdf);
268
269        /** Compute continuous PVS difference
270        */
[1740]271        void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
272                                                                                float &pvsReduction,
273                                                                                float &pvsEnlargement);
[1706]274
275        /** Clears the pvs.
276        */
[1750]277        void Clear(const bool trim = true);
[1706]278
[1750]279        void Trim();
280
[1706]281        static int GetEntrySizeByte();
282        static float GetEntrySize();
283
[1740]284        /** Compute continuous PVS difference
285        */
286        float GetPvsHomogenity(Pvs<T, S> &pvs);
[1706]287
[1740]288        static void Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b);
[1706]289
[1789]290        static void Merge(Pvs<T, S> &mergedPvs,
291                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
292                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
293                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
294                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
295                                          const int aSamples,
296                                          const int bSamples);
297
[1742]298        int GetSamples() const
299        {
300                return mSamples;
301        }
[1738]302
[1789]303
304        bool IsDirty() const
305        {
306                return mLastSorted < mEntries.size();
307        }
308
309        bool RequiresResort() const
310        {
311                // the last part should not be more than log of the sorted part. this
312                // way we can achieve logarithmic behaviour for insertion and find
313                const int dirtySize = (int)mEntries.size() - mLastSorted;
[1877]314                return dirtySize > 4*(int)(log((double)mEntries.size()) / log(2.0));
[1789]315        }
316
317
318        int GetLastSorted() const
319        {
320                return mLastSorted;
321        }
322
[1742]323        typename PvsIterator<T, S> GetIterator() const;
324
325protected:
326
[1738]327        /// vector of PVS entries
[1740]328        vector<PvsEntry<T, S> > mEntries;
[1736]329       
330        /// Number of samples used to create the PVS
331        int mSamples;
[1757]332 
[1789]333        /// Last sorted entry in the pvs (important for find and merge)
334        int mLastSorted; 
[310]335};
336
[581]337
[1740]338template <typename T, typename S>
339Pvs<T, S>::Pvs(const vector<PvsEntry<T, S> > &samples)
340{
341        mEntries.reserve(samples.size());
342        mEntries = samples;
[1757]343        mLastSorted = 0;
[1789]344        mSamples = samples.size();
[1740]345}
[677]346
[1789]347
[1757]348template <typename T, typename S>
349void Pvs<T, S>::Sort()
350{
[1789]351        std::vector<PvsEntry<T, S> >::iterator it = mEntries.begin() + mLastSorted;
352        //std::vector<PvsEntry<T, S> >::const_iterator it = mEntries.begin() + mLastSorted;
353        std::vector<PvsEntry<T, S> >::iterator it_end = mEntries.end();
354
355        // throw out double entries
356        std::vector<PvsEntry<T, S> >::iterator newEnd = unique(it, it_end);
357        sort(it, newEnd);
358        //sort(mEntries.begin(), mEntries.end());
359
360        // now merge sorted ranges
361        ObjectPvs newPvs;
362        Merge(newPvs,
363                  mEntries.begin(), it,
364                  it, newEnd,
365                  mSamples, 0);
366       
367        mEntries = newPvs.mEntries;
368        mLastSorted = (int)mEntries.size();
[1757]369}
[1740]370
[1877]371template <typename T, typename S>
372void Pvs<T, S>::SimpleSort()
373{
374  sort(mEntries.begin(), mEntries.end());
375  mLastSorted = (int)mEntries.size();
376}
[1789]377
[1877]378
[695]379/**
380   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
381   Provides separatelly PVS reduction from PVS enlargement.
382
383*/
[1189]384template <typename T, typename S>
[677]385void
[1189]386Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
[1740]387                                                                                  float &pvsReduction,
388                                                                                  float &pvsEnlargement)
[677]389{
[705]390        pvsReduction = 0.0f;
391        pvsEnlargement = 0.0f;
[1740]392
[1738]393        // Uses sum of log differences, which corresponds to entropy
[1740]394        std::vector<PvsEntry<T, S> >::iterator it;
[1738]395
396        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
[1189]397        {
[1740]398                float bSumPdf = (*it).mData.mSumPdf;
[1738]399                float aSumPdf = 0.0f;
[713]400
[1790]401                vector<PvsEntry<T, S> >::iterator oit;
402                const bool entryFound = Find((*it).mObject, oit);               
[1740]403
404                if (entryFound)
[1738]405                {
[1740]406                        aSumPdf = (*it).mData.mSumPdf;
407
[1738]408                        // mark this entry as processed to avoid double counting
[1740]409                        (*it).mData.mSumPdf = -aSumPdf;
[1738]410                }
411
[713]412#if 0
[1740]413                const float diff = bSumPdf - aSumPdf;
[1738]414
415                if (diff > 0.0f) {
416                        pvsEnlargement += diff;
417                } else {
418                        pvsReduction += -diff;
419                }
[713]420#else
[1740]421                if (!entryFound)
[1738]422                        pvsEnlargement += 1.0f;
[713]423#endif
[1738]424        }
425
[1740]426        for (it = mEntries.begin(); it != mEntries.end(); ++ it)
427        {
428                float aSumPdf = (*it).mData.mSumPdf;
[1738]429                float bSumPdf = 0.0f;
430                if (aSumPdf < 0.0f) {
[1740]431               
[1738]432                        // this entry was already accounted for!
433                        // just revert it back
[1740]434                        (*it).mData.mSumPdf = -aSumPdf;
[1738]435                } else {
[1790]436                        vector<PvsEntry<T, S> >::iterator oit;
437               
438                        const bool entryFound = b.Find((*it).mObject, oit);
439                                               
[1740]440                        if (entryFound) {
441                                bSumPdf = (*oit).mData.mSumPdf;
[1738]442                        }
[713]443#if 0
[1740]444                        const float diff = bSumPdf - aSumPdf;
[713]445
[1738]446                        if (diff > 0.0f) {
447                                pvsEnlargement += diff;
448                        } else {
449                                pvsReduction += -diff;
450                        }
451
[713]452#else
[1740]453                        if (!entryFound)
[1738]454                                pvsReduction += 1.0f;
[713]455#endif
[1738]456                }
[695]457        }
[677]458}
459
[1738]460
[1189]461template <typename T, typename S>
462int Pvs<T, S>::Diff(const Pvs<T, S> &b)
[362]463{
464        int dif = 0;
465
[1740]466        std::vector<PvsEntry<T, S> >::const_iterator it;
[362]467
468        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
469        {
[1790]470                vector<PvsEntry<T, S> >::iterator bit;
471                const bool entryFound = Find((*it).first, bit);
472
473                if (!entryFound) ++ dif;
[362]474        }
475
476        return dif;
477}
478
[1740]479
480template <typename T, typename S>
481void Pvs<T, S>::MergeInPlace(const Pvs<T, S> &a)
[341]482{
[1786]483        // early exit
484        if (a.Empty())
485        {
486                return;
487        }
488        else if (Empty())
489        {
490                mEntries.reserve(a.GetSize());
491                mEntries = a.mEntries;
492                mSamples = a.mSamples;
493                return;
494        }
495
[1740]496        ObjectPvs interPvs;
497       
498        Merge(interPvs, *this, a);
499       
500        mEntries.reserve(interPvs.GetSize());
501        mEntries = interPvs.mEntries;
[1751]502        mSamples = interPvs.mSamples;
[1740]503}
504
505
506template <typename T, typename S>
507void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs, const Pvs<T, S> &a, const Pvs<T, S> &b)
508{
509        std::vector<PvsEntry<T, S> >::const_iterator ait = a.mEntries.begin(), ait_end = a.mEntries.end();
510        std::vector<PvsEntry<T, S> >::const_iterator bit = b.mEntries.begin(), bit_end = b.mEntries.end();
[1741]511       
[1789]512        Merge(mergedPvs,
513                  ait, ait_end,
514                  bit, bit_end,
515                  a.mSamples,
516                  b.mSamples);
517}
518
519
520template <typename T, typename S>
521void Pvs<T, S>::Merge(Pvs<T, S> &mergedPvs,
522                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aBegin,
523                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &aEnd,
524                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bBegin,
525                                          const typename std::vector<PvsEntry<T, S> >::const_iterator &bEnd,
526                                          const int aSamples,
527                                          const int bSamples)
528{
529        std::vector<PvsEntry<T, S> >::const_iterator ait = aBegin;
530        std::vector<PvsEntry<T, S> >::const_iterator bit = bBegin;
531       
532        for (; (ait != aEnd); ++ ait)
[1741]533        {
534                Intersectable *aObj = (*ait).mObject;
535                Intersectable *bObj = NULL;
[1789]536                //Intersectable *bObjOld = NULL;
537       
538                const PvsEntry<T, S> &aEntry = (*ait);
[1740]539
[1789]540                for (; (bit != bEnd) && ((*bit).mObject <= (*ait).mObject); ++ bit)
[1741]541                {
542                        bObj = (*bit).mObject;
543
544                        // object found => add up probabilities
[1742]545                        if (bObj == aEntry.mObject)
[1741]546                        {
547                                PvsData newData(aEntry.mData.mSumPdf + (*bit).mData.mSumPdf);
548                                PvsEntry<T, S> entry(bObj, newData);
549                                mergedPvs.mEntries.push_back(entry);
550                        }
551                        else
552                        {
553                                mergedPvs.mEntries.push_back(*bit);
554                        }
[1789]555                       
556                        //bObjOld = bObj;
[1741]557                }
558
559                // only push back if objects different
560                // (equal case is handled by second loop)
561                if (aObj != bObj)
562                {
563                        mergedPvs.mEntries.push_back(*ait);
564                }
565        }
566
567        // add the rest
[1789]568        for (; (bit != bEnd); ++ bit)
[1740]569        {
[1741]570                mergedPvs.mEntries.push_back(*bit);
571        }
[1789]572
573        mergedPvs.mSamples = aSamples + bSamples;
[1740]574}
575
576
[1750]577template <typename T, typename S> void Pvs<T, S>::Clear(const bool trim = true)
[752]578{
579        mEntries.clear();
[1750]580        mSamples = 0;
[1789]581        mLastSorted = 0;
[1786]582
583        if (trim)
584        {
585                vector<PvsEntry<T,S> >().swap(mEntries);
586        }
[752]587}
588
589
[1750]590template <typename T, typename S> void Pvs<T, S>::Trim()
591{
[1786]592        vector<PvsEntry<T,S> >(mEntries).swap(mEntries);
[1750]593}
594
595
[1189]596template <typename T, typename S>
[1790]597bool Pvs<T, S>::Find(T sample,
598                                         typename vector<PvsEntry<T, S> >::iterator &it,
599                                         const bool checkDirty)
[310]600{
[1877]601  bool found = false;
602 
603  PvsEntry<T, S> dummy(sample, PvsData());
604 
605  // only check clean part
606  vector<PvsEntry<T, S> >::iterator sorted_end = mEntries.begin() + mLastSorted;
607 
608  // binary search
609  it = lower_bound(mEntries.begin(), sorted_end, dummy);
610 
611  if ((it != mEntries.end()) && ((*it).mObject == sample))
612        found = true;
613 
614  // sample not found yet => search further in the unsorted part
615  if (!found && checkDirty) {
616        vector<PvsEntry<T, S> >::const_iterator dit, dit_end = mEntries.end();
[1790]617       
[1877]618        for (dit = sorted_end; (dit != dit_end) && ((*dit).mObject != sample); ++ dit) ;
619       
620        if (dit != dit_end)
621          found = true;
622  }
623 
624  return found;
[310]625}
626
[1740]627
[1189]628template <typename T, typename S>
[1740]629void Pvs<T, S>::GetData(const int index, T &entry, S &data)
[310]630{
[1740]631        std::vector<PvsEntry<T, S> >::iterator i = mEntries.begin();
[1738]632        for (int k = 0; k != index && i != mEntries.end(); ++ i, ++ k);
[310]633
[1738]634        entry = (*i).first;
635        data = (*i).second;
[310]636}
637
[1738]638
[1189]639template <typename T, typename S>
[1740]640float Pvs<T, S>::AddSample(T sample, const float pdf)
[177]641{
[1738]642        ++ mSamples;
[1790]643       
644        vector<PvsEntry<T, S> >::iterator it;
645        const bool entryFound = Find(sample, it);               
[1738]646
[1790]647        if (entryFound)
648        {       
[1740]649                S &data = (*it).mData;
650                data.mSumPdf += pdf;
651                return data.mSumPdf;
[1189]652        }
[1738]653        else
[1790]654        {
[1740]655                PvsEntry<T, S> entry(sample, pdf);
656                mEntries.insert(it, entry);
[1789]657                ++ mLastSorted;
[1738]658                return pdf;
[1189]659        }
[466]660}
[177]661
[1189]662
663template <typename T, typename S>
[1757]664void Pvs<T, S>::AddSampleDirty(T sample, const float pdf)
665{
[1789]666        ++ mSamples;
667        mEntries.push_back(PvsEntry<T, S>(sample, pdf));
[1757]668}
669                                         
670
671template <typename T, typename S>
[1790]672typename vector< PvsEntry<T, S> >::iterator Pvs<T, S>::AddSample2(T sample,
673                                                                                                                                  const float pdf)
[1184]674{
[1740]675        ++ mSamples;
[1789]676       
[1790]677        vector<PvsEntry<T, S> >::iterator it;
678        const bool entryFound == Find(sample, it);
[1740]679
[1790]680        if (entryFound)
[1189]681        {
[1740]682                S &data = (*it).second;
683                data->mSumPdf += pdf;
[1189]684        }
[1740]685        else
[1189]686        {
[1740]687                PvsEntry<T, S> entry(sample, pdf);
688                mEntries.insert(it, entry);
[1789]689                ++ mLastSorted;
[1189]690        }
[1740]691
692        return it;
[1184]693}
694
[1740]695
[1789]696/** Adds sample dirty (on the end of the vector) but
697        first checks if sample is already in clean part of the pvs.
698*/
699template <typename T, typename S>
700bool Pvs<T, S>::AddSampleDirtyCheck(T sample,
701                                                                        const float pdf)
702                                                                        //,float &contribution)
703{
704        ++ mSamples;
705
[1790]706        vector<PvsEntry<T, S> >::iterator it;
707        const bool entryFound = Find(sample, it);
[1789]708
[1877]709        if (entryFound) {
710          S &data = (*it).mData;
711         
712          data.mSumPdf += pdf;
713          //contribution = pdf / data.mSumPdf;
714         
715          return false;
[1789]716        }
[1877]717        else {
718          AddSampleDirty(sample, pdf);
719          //contribution = 1.0f;
720          return true;
[1789]721        }
[311]722}
[308]723
[492]724
[1189]725template <typename T, typename S>
[1740]726bool Pvs<T, S>::GetSampleContribution(T sample,
727                                                                          const float pdf,
728                                                                          float &contribution)
[485]729{
[1790]730        vector<PvsEntry<T, S> >::iterator it;
731        const bool entryFound = Find(sample, it);
[1189]732
[1790]733        if (entryFound) 
[1740]734        {
735                S &data = (*it).mData;
736                contribution = pdf / (data.mSumPdf + pdf);
737                return false;
738        }
739        else
740        {
741                contribution = 1.0f;
742                return true;
743        }
[485]744}
745
[1740]746
[1189]747template <typename T, typename S>
[1740]748bool Pvs<T, S>::RemoveSample(T sample, const float pdf)
[485]749{
[1740]750        -- mSamples;
[1789]751       
[1790]752        vector<PvsEntry<T, S> >::iterator it;
753        const bool entryFound = Find(sample, it);
[1737]754
[1790]755        if (!entryFound)
[1740]756                return false;
757
758        S &data = (*it).mData;
759
760        data.mSumPdf -= pdf;
761
762        if (data.mSumPdf <= 0.0f)
763        {
764                mEntries.erase(it);
[1789]765                -- mLastSorted; // wrong if sample was in tail!!
[1740]766        }
767
768        return true;
[485]769}
[1740]770
771
[1189]772template <typename T, typename S>
773int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
[485]774{
[1738]775        const int samples = mSamples - pvs.mSamples;
[1740]776
777        std::vector<PvsEntry<T, S> >::
[1738]778                const_iterator it, it_end = pvs.mEntries.end();
[1737]779
[1738]780        // output PVS of view cell
781        for (it = pvs.mEntries.begin(); it != it_end; ++ it)
[1740]782                RemoveSample((*it).mObject, (*it).mData.mSumPdf);
[1738]783
784        mSamples = samples;
[1740]785
[1738]786        return GetSize();
[485]787}
788
[1740]789
[1189]790template <typename T, typename S>
791void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
[469]792{
[1740]793        std::vector<PvsEntry<T, S> >::
[485]794                const_iterator it, it_end = mEntries.end();
[469]795
796        // output PVS of view cell
797        for (it = mEntries.begin(); it != it_end; ++ it)
798                entries.push_back((*it)->first);
799}
800
[1740]801
[1189]802template <typename T, typename S>
803void Pvs<T, S>::NormalizeMaximum()
[556]804{
[1740]805        std::vector<PvsEntry<T, S> >::
806                const_iterator it, it_end = mEntries.end();
[556]807
[1740]808        float maxPdfSum = -1.0f;
[556]809
[1740]810        // output PVS of view cell
811        for (it = mEntries.begin(); it != it_end; ++ it) {
812                float sum = (*it)->second.sumPdf;
813                if (sum > maxSum)
814                        maxSum = sum;
815        }
[556]816
[1740]817        maxSum = 1.0f / maxSum;
[556]818
[1740]819        for (it = mEntries.begin(); it != it_end; ++ it) {
820                (*it)->second.sumPdf *= maxSum;
821        }
822
[556]823}
824
825
[1667]826template <typename T, typename S>
827float Pvs<T, S>::GetEntrySize()
828{
[1673]829        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
[1667]830}
831
832
833template <typename T, typename S>
834int Pvs<T, S>::GetEntrySizeByte()
835{
836        return sizeof(T) + sizeof(S);
837}
838
839
[1740]840template <typename T, typename S>
841float Pvs<T, S>::GetPvsHomogenity(Pvs<T, S> &pvs)
842{
843        float pvsReduction, pvsEnlargement;
844
845        ComputeContinuousPvsDifference(pvs,     pvsReduction, pvsEnlargement);
846
847        return pvsReduction + pvsEnlargement;
848}
849
850
[1742]851template <typename T, typename S>
852typename PvsIterator<T, S> Pvs<T, S>::GetIterator() const
853{
854        PvsIterator<T, S> pit(mEntries.begin(), mEntries.end());
855
856        return pit;
857}
858
859
[1667]860///////////////////////////////////////
861
[311]862/** Class instantiating the Pvs template for kd tree nodes.
863*/
[1189]864class KdPvs: public Pvs<KdNode *, PvsData>
[308]865{
[1141]866public:
[311]867        int Compress();
[308]868};
869
[1077]870
[1842]871////////////
872//-- typedefs
873
874typedef PvsEntry<Intersectable *, PvsData> ObjectPvsEntry;
875typedef std::vector<ObjectPvsEntry> ObjectPvsEntries;
876typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
877typedef PvsIterator<Intersectable *, PvsData> ObjectPvsIterator;
878
879
[1189]880class ObjectPvs: public Pvs<Intersectable *, PvsData>
[1141]881{
882public:
[1586]883        /** Counts object int the pvs. Different to method "GetSize", not
[1141]884                only the raw container size is returned,
885                but the individual contributions of the entries are summed up.
886        */
[1707]887        float EvalPvsCost() const;
[1842]888
889        friend ostream &operator<<(ostream &s, const ObjectPvs &p)
890        {
891                ObjectPvsIterator pit = p.GetIterator();
892
893                while (pit.HasMoreEntries())
894                {               
895                        const ObjectPvsEntry &entry = pit.Next();
896                        Intersectable *obj = entry.mObject;
897
[1845]898                        cout << obj << " ";
[1842]899                }
900               
901                return s;
902        }
903
[1141]904};
905
[1586]906
[1077]907
[860]908}
[469]909
[177]910#endif
911
Note: See TracBrowser for help on using the repository browser.