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

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