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

Revision 713, 9.0 KB checked in by bittner, 18 years ago (diff)

visibility filter used in glrenderer

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