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

Revision 1706, 11.2 KB checked in by mattausch, 18 years ago (diff)

worked on full evaluation framework

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
[310]17template<typename T>
[1189]18struct LtSample
19{
[311]20    bool operator()(const T a, const T b) const
[310]21    {
22                return a < b;
23        }
24};
25
[469]26/** Information stored with a PVS entry. Consists of the number
27        the object was seen from the view cell.
28*/
[1189]29class PvsData {
30public:
[1706]31        /// sum of probability density of visible sample rays
32        float mSumPdf;
[310]33
[1706]34        PvsData() {}
35        PvsData(const float sumPdf):
[1189]36        mSumPdf(sumPdf) {}
37
[1706]38        // $$JB in order to return meaningfull values
39        // it assumes that the sum pdf has been normalized somehow!!!
40        float GetVisibility()
41        {
42                return mSumPdf;
43        }
[1189]44};
45
46
47class MailablePvsData
48{
[1706]49        ////////////////////////////
50        //  Mailing stuff
[1184]51protected:
52        int mMailbox;
53
54public:
[1706]55        // last mail id -> warning not thread safe!
56        // both mailId and mailbox should be unique for each thread!!!
57        static int sMailId;
58        static int sReservedMailboxes;
59
60
[1184]61        static void NewMail(const int reserve = 1) {
62                sMailId += sReservedMailboxes;
63                sReservedMailboxes = reserve;
64        }
[1706]65
[1184]66        void Mail() { mMailbox = sMailId; }
67        bool Mailed() const { return mMailbox == sMailId; }
68
69        void Mail(const int mailbox) { mMailbox = sMailId + mailbox; }
70        bool Mailed(const int mailbox) const { return mMailbox == sMailId + mailbox; }
71
72        int IncMail() { return ++ mMailbox - sMailId; }
[1706]73        //////////////////////////////////////////
[1184]74
[1706]75        // sum of probability density of visible sample rays
76        float mSumPdf;
77        int mCounter;
[1184]78
[1706]79        MailablePvsData() {}
80        MailablePvsData(const float sumPdf):
[556]81        mSumPdf(sumPdf) {}
82
[1706]83        // $$JB in order to return meaningfull values
84        // it assumes that the sum pdf has been normalized somehow!!!
85        float GetVisibility()
86        {
87                return mSumPdf;
88        }
[310]89};
90
[1184]91
[469]92/** Template class representing the Potentially Visible Set (PVS)
93        mainly from a view cell, but also e.g., from objects.
94*/
[1189]95template<typename T, typename S>
[311]96class Pvs
[310]97{
98public:
[1706]99        Pvs(): /*mSamples(0), */mEntries() {}
[556]100
[1706]101        //virtual ~Pvs();
[492]102
[1706]103        /** Compresses PVS lossless or lossy.
104        */
105        int Compress() {return 0;}
106        int GetSize() const {return (int)mEntries.size();}
107        bool Empty() const {return mEntries.empty();}
[469]108
[1706]109        /** Normalize the visibility of entries in order to get comparable
110                results
111        */
112        void NormalizeMaximum();
[1184]113
[1706]114        /** Merges pvs of a into this pvs.
115        */
116        void Merge(const Pvs<T, S> &a);
[752]117
[1706]118        /** Difference of pvs to pvs b.
119                @returns number of different entries.
120        */
121        int Diff(const Pvs<T, S> &b);
[469]122
[1706]123        /** Finds sample in PVS.
124                @returns sample if found, NULL otherwise.
125        */
126        S *Find(T sample);
[469]127
[1706]128        bool GetSampleContribution(T sample, const float pdf, float &contribution);
[485]129
[1706]130        /** Adds sample to PVS.
131                @contribution contribution of sample (0 or 1)
132                @returns true if sample was not already in PVS.
133        */
134        bool AddSample(T sample, const float pdf, float &contribution);
[677]135
[1706]136        /** Adds sample to PVS.
137                @returns contribution of sample (0 or 1)
138        */
139        float AddSample(T sample, const float pdf);
[752]140
[1706]141        /** Adds sample to PVS.
142                @returns PvsData
143        */
144        S *AddSample2(T sample, const float pdf);
[1667]145
[1706]146        /** Adds one pvs to another one.
147                @returns new pvs size
148        */
149        int AddPvs(const Pvs<T, S> &pvs);
150
151        /** Subtracts one pvs from another one.
152                WARNING: could contains bugs
153                @returns new pvs size
154        */
155        int SubtractPvs(const Pvs<T, S> &pvs);
156        /** Returns PVS data, i.e., how often it was seen from the view cell,
157                and the object itsef.
158        */
159        void GetData(const int index, T &entry, S &data);
160
161        /** Collects the PVS entries and returns them in the vector.
162        */
163        void CollectEntries(std::vector<T> &entries);
164
165        /** Removes sample from PVS if reference count is zero.
166                @param visibleSamples number of references to be removed
167        */
168        bool RemoveSample(T sample, const float pdf);
169
170        /** Compute continuous PVS difference
171        */
172        void ComputeContinuousPvsDifference(Pvs<T, S> &pvs,
173                float &pvsReduction,
174                float &pvsEnlargement);
175
176
177        /** Clears the pvs.
178        */
179        void Clear();
180
181        static int GetEntrySizeByte();
182        static float GetEntrySize();
183
184        /** Compute continuous PVS difference */
185        float GetPvsHomogenity(Pvs<T, S> &pvs) {
186                float
187                        pvsReduction,
188                        pvsEnlargement;
189
190                ComputeContinuousPvsDifference(pvs,
191                        pvsReduction,
192                        pvsEnlargement);
193
194                return pvsReduction + pvsEnlargement;
195        }
196
197        int Size() { return mEntries.size(); }
198
199        /// Map of PVS entries
200        std::map<T, S, LtSample<T> > mEntries;
[310]201};
202
[581]203
[677]204
[695]205/**
206   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
207   Provides separatelly PVS reduction from PVS enlargement.
208
209*/
[1189]210template <typename T, typename S>
[677]211void
[1189]212Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
[677]213                                                                           float &pvsReduction,
214                                                                           float &pvsEnlargement)
215{
[705]216        pvsReduction = 0.0f;
217        pvsEnlargement = 0.0f;
[695]218  // Uses sum of log differences, which corresponds to entropy
[1189]219  std::map<T, S, LtSample<T> >::iterator it;
[677]220 
[1189]221  for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
222  {
[695]223        float bSumPdf = (*it).second.mSumPdf;
224        float aSumPdf = 0.0f;
[1189]225        S *data = Find((*it).first);           
226       
227        if (data)
228        {
229                aSumPdf = data->mSumPdf;
230                // mark this entry as processed to avoid double counting
231                data->mSumPdf = -aSumPdf;
[695]232        }
[713]233
234#if 0
[695]235        float diff = bSumPdf - aSumPdf;
236       
237        if (diff > 0.0f) {
238          pvsEnlargement += diff;
239        } else {
240          pvsReduction += -diff;
241        }
[713]242#else
243        if (!data)
244          pvsEnlargement += 1.0f;
245#endif
[695]246  }
247 
248  for (it = mEntries.begin(); it != mEntries.end(); ++ it) {
249        float aSumPdf = (*it).second.mSumPdf;
250        float bSumPdf = 0.0f;
251        if (aSumPdf < 0.0f) {
252          // this entry was already accounted for!
253          // just revert it back
254          (*it).second.mSumPdf = -aSumPdf;
255        } else {
[1189]256          S *data = b.Find((*it).first);
[695]257          if (data) {
[704]258                bSumPdf = data->mSumPdf;
[695]259          }
[713]260#if 0
[695]261          float diff = bSumPdf - aSumPdf;
262         
263          if (diff > 0.0f) {
264                pvsEnlargement += diff;
265          } else {
266                pvsReduction += -diff;
267          }
[713]268
269#else
270          if (!data)
271                pvsReduction += 1.0f;
272#endif
[695]273        }
274  }
[677]275}
276
[1189]277template <typename T, typename S>
278int Pvs<T, S>::Diff(const Pvs<T, S> &b)
[362]279{
280        int dif = 0;
281
[1189]282        std::map<T, S, LtSample<T> >::const_iterator it;
[362]283
284        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
285        {
[1189]286                S data = Find((*it).first);             
[362]287                if (!data) ++ dif;
288        }
289
290        return dif;
291}
292
[1189]293template <typename T, typename S> void Pvs<T, S>::Merge(const Pvs<T, S> &a)
[341]294{
[1189]295        std::map<T, S, LtSample<T> >::const_iterator it;
[362]296
[610]297        for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
[362]298        {
[1189]299                AddSample((*it).first, (*it).second.mSumPdf);
[362]300        }
[341]301}
302
[1189]303
304template <typename T, typename S> void Pvs<T, S>::Clear()
[752]305{
306        mEntries.clear();
307}
308
309
[1189]310template <typename T, typename S>
311S *Pvs<T, S>::Find(T sample)
[310]312{
[1189]313  std::map<T, S, LtSample<T> >::iterator i = mEntries.find(sample);
314
315  if (i != mEntries.end())
316  {
317          return &(*i).second;
318  }
319  else
320  {
321          return NULL;
322  }
[310]323}
324
[1189]325template <typename T, typename S>
326void Pvs<T, S>::GetData(const int index,
[485]327                                         T &entry,
[1189]328                                         S &data)
[310]329{
[1189]330  std::map<T, S, LtSample<T> >::iterator i = mEntries.begin();
[310]331  for (int k = 0; k != index && i != mEntries.end(); i++, k++);
332
333  entry = (*i).first;
[311]334  data = (*i).second;
[1189]335 
[310]336}
337
[1189]338template <typename T, typename S>
[556]339float
[1189]340Pvs<T, S>::AddSample(T sample, const float pdf)
[177]341{
[1189]342        S *data = Find(sample);
[492]343 
[1189]344        if (data) 
345        {
346                data->mSumPdf += pdf;
347                return data->mSumPdf;
348        }
349        else
350        {
351                mEntries[sample] = S(pdf);
352                return pdf;
353        }
[466]354}
[177]355
[1189]356
357template <typename T, typename S>
358S * Pvs<T, S>::AddSample2(T sample, const float pdf)
[1184]359{
[1189]360        S *data = Find(sample);
[1184]361 
[1189]362        if (data) 
363        {
364                data->mSumPdf += pdf;
365        }
366        else
367        {
368                mEntries[sample] = S(pdf);
369                data = Find(sample);
370        }
371
372        return data;
[1184]373}
374
[1189]375template <typename T, typename S>
376bool Pvs<T, S>::AddSample(T sample,
[556]377                                  const float pdf,
378                                  float &contribution)
[466]379{
[1189]380  S *data = Find(sample);
[466]381 
[1189]382  if (data) 
383  {
[1112]384        data->mSumPdf += pdf;
[1189]385        contribution = pdf / data->mSumPdf;
[466]386        return false;
387  }
388  else {
[1189]389        mEntries[sample] = S(pdf);
[466]390        contribution = 1.0f;
391        return true;
392  }
[311]393}
[308]394
[1189]395template <typename T, typename S>
[492]396bool
[1189]397Pvs<T, S>::GetSampleContribution(T sample,
[1528]398                                                                 const float pdf,
399                                                                 float &contribution)
[492]400{
[1189]401  S *data = Find(sample);
[492]402 
403  if (data)  {
[1189]404        contribution = pdf / (data->mSumPdf + pdf);
[492]405        return false;
406  }
407  else {
408        contribution = 1.0f;
409        return true;
410  }
411}
412
[1189]413template <typename T, typename S>
414bool Pvs<T, S>::RemoveSample(T sample,
[556]415                                                  const float pdf)
[485]416{
[1189]417  std::map<T, S, LtSample<T> >::
[556]418        iterator it = mEntries.find(sample);
[485]419 
[556]420  if (it == mEntries.end())
421        return false;
422 
[1189]423  S *data = &(*it).second;
[556]424 
425  data->mSumPdf -= pdf;
[1189]426
[556]427  if (data->mSumPdf <= 0.0f)
[1189]428  {
429          mEntries.erase(it);
430  }
431
[556]432  return true;
[485]433}
434
[1189]435template <typename T, typename S>
436int Pvs<T, S>::AddPvs(const Pvs<T, S> &pvs)
[485]437{
[1189]438  std::map<T, S, LtSample<T> >::
[556]439        const_iterator it, it_end = pvs.mEntries.end();
440 
441  float contri;
442  // output PVS of view cell
[1189]443  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
444  {     
445          AddSample((*it).first, (*it).second.mSumPdf, contri);
446  }
[556]447 
448  return GetSize();
[485]449}
450 
[1189]451template <typename T, typename S>
452int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
[485]453{
[1189]454  std::map<T, S, LtSample<T> >::
[556]455        const_iterator it, it_end = pvs.mEntries.end();
456 
457  // output PVS of view cell
458  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
459        RemoveSample((*it).first, (*it).second.mSumPdf);
460 
461  return GetSize();
[485]462}
463
[1189]464template <typename T, typename S>
465void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
[469]466{
[1189]467        std::map<T, S, LtSample<T> >::
[485]468                const_iterator it, it_end = mEntries.end();
[469]469
470        // output PVS of view cell
471        for (it = mEntries.begin(); it != it_end; ++ it)
472                entries.push_back((*it)->first);
473}
474
[1189]475template <typename T, typename S>
476void Pvs<T, S>::NormalizeMaximum()
[556]477{
[1189]478  std::map<T, S, LtSample<T> >::
[556]479        const_iterator it, it_end = mEntries.end();
480
481  float maxPdfSum = -1.0f;
482
483  // output PVS of view cell
484  for (it = mEntries.begin(); it != it_end; ++ it) {
485        float sum = (*it)->second.sumPdf;
486        if (sum > maxSum)
487          maxSum = sum;
488  }
489
[1189]490  maxSum = 1.0f / maxSum;
[556]491
492  for (it = mEntries.begin(); it != it_end; ++ it) {
493        (*it)->second.sumPdf *= maxSum;
494  }
495 
496}
497
498
[1667]499template <typename T, typename S>
500float Pvs<T, S>::GetEntrySize()
501{
[1673]502        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
[1667]503}
504
505
506template <typename T, typename S>
507int Pvs<T, S>::GetEntrySizeByte()
508{
509        return sizeof(T) + sizeof(S);
510}
511
512
513///////////////////////////////////////
514
[311]515/** Class instantiating the Pvs template for kd tree nodes.
516*/
[1189]517class KdPvs: public Pvs<KdNode *, PvsData>
[308]518{
[1141]519public:
[311]520        int Compress();
[308]521};
522
[1077]523
[1189]524class ObjectPvs: public Pvs<Intersectable *, PvsData>
[1141]525{
526public:
[1586]527        /** Counts object int the pvs. Different to method "GetSize", not
[1141]528                only the raw container size is returned,
529                but the individual contributions of the entries are summed up.
530        */
[1168]531        int CountObjectsInPvs() const;
[1141]532};
533
[1586]534
535////////////
[1077]536//-- typedefs
537
[1189]538typedef std::map<KdNode *, PvsData, LtSample<KdNode *> > KdPvsMap;
539typedef std::map<Intersectable *, PvsData, LtSample<Intersectable *> > ObjectPvsMap;
540typedef std::map<ViewCell *, MailablePvsData, LtSample<ViewCell *> > ViewCellPvsMap;
[1077]541
[308]542
[1189]543typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
[1184]544
[860]545}
[469]546
[177]547#endif
548
Note: See TracBrowser for help on using the repository browser.