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

Revision 705, 8.9 KB checked in by mattausch, 19 years ago (diff)

fixed bug in filtering

RevLine 
[177]1#ifndef __PVS_H
2#define __PVS_H
3
4#include <map>
[469]5#include <vector>
[177]6
7class KdNode;
[240]8class BspNode;
[191]9class Ray;
[308]10class Intersectable;
[406]11class ViewCellKdNode;
[177]12
[310]13template<typename T>
14struct LtSample {
[311]15    bool operator()(const T a, const T b) const
[310]16    {
17                return a < b;
18        }
19};
20
[469]21/** Information stored with a PVS entry. Consists of the number
22        the object was seen from the view cell.
23*/
[310]24
25template<typename T>
26struct PvsData {
[556]27  //  int mVisibleSamples;
28  // sum of probability density of visible sample rays
29  float mSumPdf;
[310]30  PvsData<T>() {}
[556]31  PvsData<T>(const float sumPdf):
32        mSumPdf(sumPdf) {}
33
34  // $$JB in order to return meaningfull values
35  // it assumes that the sum pdf has been normalized somehow!!!
36  float GetVisibility() { return mSumPdf; }
[310]37};
38
[469]39/** Template class representing the Potentially Visible Set (PVS)
40        mainly from a view cell, but also e.g., from objects.
41*/
[310]42template<typename T>
[311]43class Pvs
[310]44{
45public:
[469]46  Pvs(): /*mSamples(0), */mEntries() {}
[466]47 
[469]48  //int mSamples;
[466]49 
[469]50  /** Compresses PVS lossless or lossy.
51  */
[466]52  int Compress() {return 0;}
53  int GetSize() const {return (int)mEntries.size();}
[469]54  bool Empty() const {return mEntries.empty();}
[556]55
56  /** Normalize the visibility of entries in order to get comparable
57          results */
[469]58 
[556]59  void NormalizeMaximum();
60 
[610]61  /** Merges pvs of a into this pvs.
[466]62   */
[610]63  void Merge(const Pvs<T> &a);
[469]64 
[466]65  /** Difference of pvs to pvs b.
66          @returns number of different entries.
67  */
68  int Diff(const Pvs<T> &b);
69 
[469]70  /** Finds sample in PVS.
71          @returns sample if found, NULL otherwise.
72  */
[466]73  PvsData<T> *Find(T sample);
[492]74
[556]75  bool GetSampleContribution(T sample, const float pdf, float &contribution);
[469]76 
77  /** Adds sample to PVS.
78          @contribution contribution of sample (0 or 1)
79          @returns true if sample was not already in PVS.
80  */
[556]81  bool AddSample(T sample, const float pdf, float &contribution);
[469]82
83  /** Adds sample to PVS.
84          @returns contribution of sample (0 or 1)
85  */
[556]86  float AddSample(T sample, const float pdf);
[492]87 
[485]88  /** Adds one pvs to another one.
89          @returns new pvs size
90  */
91  int AddPvs(const Pvs<T> &pvs);
92  /** Subtracts one pvs from another one.
93          @returns new pvs size
94  */
95  int SubtractPvs(const Pvs<T> &pvs);
[469]96  /** Returns PVS data, i.e., how often it was seen from the view cell,
97          and the object itsef.
98  */
[466]99  void GetData(const int index, T &entry, PvsData<T> &data);
[469]100
101  /** Collects the PVS entries and returns them in the vector.
102  */
103  void CollectEntries(std::vector<T> &entries);
104
[485]105  /** Removes sample from PVS if reference count is zero.
106          @param visibleSampels number of references to be removed
107  */
[556]108  bool RemoveSample(T sample, const float pdf);
[485]109
[677]110  /** Compute continuous PVS difference */
[704]111  void ComputeContinuousPvsDifference(Pvs<T> &pvs,
[677]112                                                                          float &pvsReduction,
113                                                                          float &pvsEnlargement);
114 
115
[695]116  /** Compute continuous PVS difference */
[704]117  float GetPvsHomogenity(Pvs<T> &pvs) {
[695]118        float
119          pvsReduction,
120          pvsEnlargement;
121
122        ComputeContinuousPvsDifference(pvs,
123                                                                   pvsReduction,
124                                                                   pvsEnlargement);
125
126        return pvsReduction + pvsEnlargement;
127  }
128
[677]129                                         
130                                         
[469]131  /// Map of PVS entries
[466]132  std::map<T, PvsData<T>, LtSample<T> > mEntries;
[310]133};
134
[581]135
[677]136
[695]137/**
138   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
139   Provides separatelly PVS reduction from PVS enlargement.
140
141*/
[341]142template <typename T>
[677]143void
[704]144Pvs<T>::ComputeContinuousPvsDifference(Pvs<T> &b,
[677]145                                                                           float &pvsReduction,
146                                                                           float &pvsEnlargement)
147{
[705]148        pvsReduction = 0.0f;
149        pvsEnlargement = 0.0f;
[695]150  // Uses sum of log differences, which corresponds to entropy
[704]151  std::map<T, PvsData<T>, LtSample<T> >::iterator it;
[677]152 
[704]153  for (it = b.mEntries.begin();
154          it != b.mEntries.end(); ++ it) {
[695]155        float bSumPdf = (*it).second.mSumPdf;
156        float aSumPdf = 0.0f;
157        PvsData<T> *data = Find((*it).first);           
158        if (data) {
[704]159          aSumPdf = data->mSumPdf;
[695]160          // mark this entry as processed to avoid double counting
[704]161          data->mSumPdf = -aSumPdf;
[695]162        }
163        float diff = bSumPdf - aSumPdf;
164       
165        if (diff > 0.0f) {
166          pvsEnlargement += diff;
167        } else {
168          pvsReduction += -diff;
169        }
170  }
171 
172  for (it = mEntries.begin(); it != mEntries.end(); ++ it) {
173        float aSumPdf = (*it).second.mSumPdf;
174        float bSumPdf = 0.0f;
175        if (aSumPdf < 0.0f) {
176          // this entry was already accounted for!
177          // just revert it back
178          (*it).second.mSumPdf = -aSumPdf;
179        } else {
180          PvsData<T> *data = b.Find((*it).first);
181          if (data) {
[704]182                bSumPdf = data->mSumPdf;
[695]183          }
184          float diff = bSumPdf - aSumPdf;
185         
186          if (diff > 0.0f) {
187                pvsEnlargement += diff;
188          } else {
189                pvsReduction += -diff;
190          }
191        }
192  }
[677]193}
194
195template <typename T>
[362]196int Pvs<T>::Diff(const Pvs<T> &b)
197{
198        int dif = 0;
199
200        std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
201
202        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
203        {
204                PvsData<T> *data = Find((*it).first);           
205                if (!data) ++ dif;
206        }
207
208        return dif;
209}
210
211template <typename T>
[610]212void Pvs<T>::Merge(const Pvs<T> &a)
[341]213{
[362]214        std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
215
[610]216        for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
[362]217        {
218                PvsData<T> *data = Find((*it).first);
219               
220                if (data)
[556]221                        data->mSumPdf += (*it).second.mSumPdf;
[362]222                else
223                        mEntries.insert(*it);
224        }
[341]225}
226
[310]227template <typename T>
[311]228PvsData<T> *Pvs<T>::Find(T sample)
[310]229{
[311]230  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.find(sample);
[310]231  if (i != mEntries.end()) {
232    return &(*i).second;
[311]233  } else
[310]234    return NULL;
235}
236
237template <typename T>
[311]238void Pvs<T>::GetData(const int index,
[485]239                                         T &entry,
240                                         PvsData<T> &data)
[310]241{
[311]242  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.begin();
[310]243  for (int k = 0; k != index && i != mEntries.end(); i++, k++);
244
245  entry = (*i).first;
[311]246  data = (*i).second;
[310]247}
248
[311]249template <typename T>
[556]250float
251Pvs<T>::AddSample(T sample, const float pdf)
[177]252{
[492]253  PvsData<T> *data = Find(sample);
254 
255  if (data)  {
[556]256        data->mSumPdf+=pdf;
257        return data->mSumPdf;
[492]258  }
259  else {
[556]260        mEntries[sample] = PvsData<T>(pdf);
261        return pdf;
[492]262  }
[466]263}
[177]264
[466]265template <typename T>
[492]266bool
[556]267Pvs<T>::AddSample(T sample,
268                                  const float pdf,
269                                  float &contribution)
[466]270{
271  PvsData<T> *data = Find(sample);
272 
273  if (data)  {
[556]274        data->mSumPdf+=pdf;
275        contribution = pdf/data->mSumPdf;
[466]276        return false;
277  }
278  else {
[556]279        mEntries[sample] = PvsData<T>(pdf);
[466]280        contribution = 1.0f;
281        return true;
282  }
[311]283}
[308]284
[469]285template <typename T>
[492]286bool
[556]287Pvs<T>::GetSampleContribution(T sample,
288                                                          const float pdf,
289                                                          float &contribution)
[492]290{
291  PvsData<T> *data = Find(sample);
292 
293  if (data)  {
[556]294        contribution = pdf/(data->mSumPdf + pdf);
[492]295        return false;
296  }
297  else {
298        contribution = 1.0f;
299        return true;
300  }
301}
302
303template <typename T>
[556]304bool Pvs<T>::RemoveSample(T sample,
305                                                  const float pdf)
[485]306{
[556]307  std::map<T, PvsData<T>, LtSample<T> >::
308        iterator it = mEntries.find(sample);
[485]309 
[556]310  if (it == mEntries.end())
311        return false;
312 
313  PvsData<T> *data = &(*it).second;
314 
315  data->mSumPdf -= pdf;
316  if (data->mSumPdf <= 0.0f)
317        mEntries.erase(it);
318 
319  return true;
[485]320}
321
322template <typename T>
323int Pvs<T>::AddPvs(const Pvs<T> &pvs)
324{
[556]325  std::map<T, PvsData<T>, LtSample<T> >::
326        const_iterator it, it_end = pvs.mEntries.end();
327 
328  float contri;
329  // output PVS of view cell
330  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
331        AddSample((*it).first, (*it).second.mSumPdf, contri);
332 
333  return GetSize();
[485]334}
335 
336template <typename T>
337int Pvs<T>::SubtractPvs(const Pvs<T> &pvs)
338{
[556]339  std::map<T, PvsData<T>, LtSample<T> >::
340        const_iterator it, it_end = pvs.mEntries.end();
341 
342  // output PVS of view cell
343  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
344        RemoveSample((*it).first, (*it).second.mSumPdf);
345 
346  return GetSize();
[485]347}
348
349template <typename T>
[469]350void Pvs<T>::CollectEntries(std::vector<T> &entries)
351{
[485]352        std::map<T, PvsData<T>, LtSample<T> >::
353                const_iterator it, it_end = mEntries.end();
[469]354
355        // output PVS of view cell
356        for (it = mEntries.begin(); it != it_end; ++ it)
357                entries.push_back((*it)->first);
358}
359
[556]360template <typename T>
361void Pvs<T>::NormalizeMaximum()
362{
363  std::map<T, PvsData<T>, LtSample<T> >::
364        const_iterator it, it_end = mEntries.end();
365
366  float maxPdfSum = -1.0f;
367
368  // output PVS of view cell
369  for (it = mEntries.begin(); it != it_end; ++ it) {
370        float sum = (*it)->second.sumPdf;
371        if (sum > maxSum)
372          maxSum = sum;
373  }
374
375  maxSum = 1.0f/maxSum;
376
377  for (it = mEntries.begin(); it != it_end; ++ it) {
378        (*it)->second.sumPdf *= maxSum;
379  }
380 
381}
382
383
[311]384/** Class instantiating the Pvs template for kd tree nodes.
385*/
386class KdPvs: public Pvs<KdNode *>
[308]387{
[311]388        int Compress();
[308]389};
390
[311]391typedef std::map<KdNode *, PvsData<KdNode *>, LtSample<KdNode *> > KdPvsMap;
[469]392typedef std::map<Intersectable *, PvsData<Intersectable *>, LtSample<Intersectable *> > ObjectPvsMap;
393typedef PvsData<Intersectable *> ObjectPvsData;
[311]394typedef PvsData<KdNode *> KdPvsData;
[308]395
[469]396typedef Pvs<Intersectable *> ObjectPvs;
[366]397
[469]398
[177]399#endif
400
Note: See TracBrowser for help on using the repository browser.