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

Revision 752, 9.2 KB checked in by mattausch, 18 years ago (diff)

after rendering workshop submissioin
x3dparser can use def - use constructs
implemented improved evaluation (samples are only stored in leaves, only propagate pvs size)

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
93  /** Subtracts one pvs from another one.
94  WARNING: could contains bugs
95          @returns new pvs size
96  */
97  int SubtractPvs(const Pvs<T> &pvs);
98  /** Returns PVS data, i.e., how often it was seen from the view cell,
99          and the object itsef.
100  */
101  void GetData(const int index, T &entry, PvsData<T> &data);
102
103  /** Collects the PVS entries and returns them in the vector.
104  */
105  void CollectEntries(std::vector<T> &entries);
106
107  /** Removes sample from PVS if reference count is zero.
108          @param visibleSampels number of references to be removed
109  */
110  bool RemoveSample(T sample, const float pdf);
111
112  /** Compute continuous PVS difference */
113  void ComputeContinuousPvsDifference(Pvs<T> &pvs,
114                                                                          float &pvsReduction,
115                                                                          float &pvsEnlargement);
116 
117
118  /** Clears the pvs.
119  */
120  void Clear();
121
122  /** Compute continuous PVS difference */
123  float GetPvsHomogenity(Pvs<T> &pvs) {
124        float
125          pvsReduction,
126          pvsEnlargement;
127       
128        ComputeContinuousPvsDifference(pvs,
129                                                                   pvsReduction,
130                                                                   pvsEnlargement);
131       
132        return pvsReduction + pvsEnlargement;
133  }
134
135                                         
136                                         
137  /// Map of PVS entries
138  std::map<T, PvsData<T>, LtSample<T> > mEntries;
139};
140
141
142
143/**
144   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
145   Provides separatelly PVS reduction from PVS enlargement.
146
147*/
148template <typename T>
149void
150Pvs<T>::ComputeContinuousPvsDifference(Pvs<T> &b,
151                                                                           float &pvsReduction,
152                                                                           float &pvsEnlargement)
153{
154        pvsReduction = 0.0f;
155        pvsEnlargement = 0.0f;
156  // Uses sum of log differences, which corresponds to entropy
157  std::map<T, PvsData<T>, LtSample<T> >::iterator it;
158 
159  for (it = b.mEntries.begin();
160          it != b.mEntries.end(); ++ it) {
161        float bSumPdf = (*it).second.mSumPdf;
162        float aSumPdf = 0.0f;
163        PvsData<T> *data = Find((*it).first);           
164        if (data) {
165          aSumPdf = data->mSumPdf;
166          // mark this entry as processed to avoid double counting
167          data->mSumPdf = -aSumPdf;
168        }
169
170#if 0
171        float diff = bSumPdf - aSumPdf;
172       
173        if (diff > 0.0f) {
174          pvsEnlargement += diff;
175        } else {
176          pvsReduction += -diff;
177        }
178#else
179        if (!data)
180          pvsEnlargement += 1.0f;
181#endif
182  }
183 
184  for (it = mEntries.begin(); it != mEntries.end(); ++ it) {
185        float aSumPdf = (*it).second.mSumPdf;
186        float bSumPdf = 0.0f;
187        if (aSumPdf < 0.0f) {
188          // this entry was already accounted for!
189          // just revert it back
190          (*it).second.mSumPdf = -aSumPdf;
191        } else {
192          PvsData<T> *data = b.Find((*it).first);
193          if (data) {
194                bSumPdf = data->mSumPdf;
195          }
196#if 0
197          float diff = bSumPdf - aSumPdf;
198         
199          if (diff > 0.0f) {
200                pvsEnlargement += diff;
201          } else {
202                pvsReduction += -diff;
203          }
204
205#else
206          if (!data)
207                pvsReduction += 1.0f;
208#endif
209        }
210  }
211}
212
213template <typename T>
214int Pvs<T>::Diff(const Pvs<T> &b)
215{
216        int dif = 0;
217
218        std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
219
220        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
221        {
222                PvsData<T> *data = Find((*it).first);           
223                if (!data) ++ dif;
224        }
225
226        return dif;
227}
228
229template <typename T>
230void Pvs<T>::Merge(const Pvs<T> &a)
231{
232        std::map<T, PvsData<T>, LtSample<T> >::const_iterator it;
233
234        for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
235        {
236                PvsData<T> *data = Find((*it).first);
237               
238                if (data)
239                        data->mSumPdf += (*it).second.mSumPdf;
240                else
241                        mEntries.insert(*it);
242        }
243}
244
245template <typename T> void Pvs<T>::Clear()
246{
247        mEntries.clear();
248       
249
250}
251
252
253template <typename T>
254PvsData<T> *Pvs<T>::Find(T sample)
255{
256  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.find(sample);
257  if (i != mEntries.end()) {
258    return &(*i).second;
259  } else
260    return NULL;
261}
262
263template <typename T>
264void Pvs<T>::GetData(const int index,
265                                         T &entry,
266                                         PvsData<T> &data)
267{
268  std::map<T, PvsData<T>, LtSample<T> >::iterator i = mEntries.begin();
269  for (int k = 0; k != index && i != mEntries.end(); i++, k++);
270
271  entry = (*i).first;
272  data = (*i).second;
273}
274
275template <typename T>
276float
277Pvs<T>::AddSample(T sample, const float pdf)
278{
279  PvsData<T> *data = Find(sample);
280 
281  if (data)  {
282        data->mSumPdf+=pdf;
283        return data->mSumPdf;
284  }
285  else {
286        mEntries[sample] = PvsData<T>(pdf);
287        return pdf;
288  }
289}
290
291template <typename T>
292bool
293Pvs<T>::AddSample(T sample,
294                                  const float pdf,
295                                  float &contribution)
296{
297  PvsData<T> *data = Find(sample);
298 
299  if (data)  {
300        data->mSumPdf+=pdf;
301        contribution = pdf/data->mSumPdf;
302        return false;
303  }
304  else {
305        mEntries[sample] = PvsData<T>(pdf);
306        contribution = 1.0f;
307        return true;
308  }
309}
310
311template <typename T>
312bool
313Pvs<T>::GetSampleContribution(T sample,
314                                                          const float pdf,
315                                                          float &contribution)
316{
317  PvsData<T> *data = Find(sample);
318 
319  if (data)  {
320        contribution = pdf/(data->mSumPdf + pdf);
321        return false;
322  }
323  else {
324        contribution = 1.0f;
325        return true;
326  }
327}
328
329template <typename T>
330bool Pvs<T>::RemoveSample(T sample,
331                                                  const float pdf)
332{
333  std::map<T, PvsData<T>, LtSample<T> >::
334        iterator it = mEntries.find(sample);
335 
336  if (it == mEntries.end())
337        return false;
338 
339  PvsData<T> *data = &(*it).second;
340 
341  data->mSumPdf -= pdf;
342  if (data->mSumPdf <= 0.0f)
343        mEntries.erase(it);
344 
345  return true;
346}
347
348template <typename T>
349int Pvs<T>::AddPvs(const Pvs<T> &pvs)
350{
351  std::map<T, PvsData<T>, LtSample<T> >::
352        const_iterator it, it_end = pvs.mEntries.end();
353 
354  float contri;
355  // output PVS of view cell
356  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
357        AddSample((*it).first, (*it).second.mSumPdf, contri);
358 
359  return GetSize();
360}
361 
362template <typename T>
363int Pvs<T>::SubtractPvs(const Pvs<T> &pvs)
364{
365  std::map<T, PvsData<T>, LtSample<T> >::
366        const_iterator it, it_end = pvs.mEntries.end();
367 
368  // output PVS of view cell
369  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
370        RemoveSample((*it).first, (*it).second.mSumPdf);
371 
372  return GetSize();
373}
374
375template <typename T>
376void Pvs<T>::CollectEntries(std::vector<T> &entries)
377{
378        std::map<T, PvsData<T>, LtSample<T> >::
379                const_iterator it, it_end = mEntries.end();
380
381        // output PVS of view cell
382        for (it = mEntries.begin(); it != it_end; ++ it)
383                entries.push_back((*it)->first);
384}
385
386template <typename T>
387void Pvs<T>::NormalizeMaximum()
388{
389  std::map<T, PvsData<T>, LtSample<T> >::
390        const_iterator it, it_end = mEntries.end();
391
392  float maxPdfSum = -1.0f;
393
394  // output PVS of view cell
395  for (it = mEntries.begin(); it != it_end; ++ it) {
396        float sum = (*it)->second.sumPdf;
397        if (sum > maxSum)
398          maxSum = sum;
399  }
400
401  maxSum = 1.0f/maxSum;
402
403  for (it = mEntries.begin(); it != it_end; ++ it) {
404        (*it)->second.sumPdf *= maxSum;
405  }
406 
407}
408
409
410/** Class instantiating the Pvs template for kd tree nodes.
411*/
412class KdPvs: public Pvs<KdNode *>
413{
414        int Compress();
415};
416
417typedef std::map<KdNode *, PvsData<KdNode *>, LtSample<KdNode *> > KdPvsMap;
418typedef std::map<Intersectable *, PvsData<Intersectable *>, LtSample<Intersectable *> > ObjectPvsMap;
419typedef PvsData<Intersectable *> ObjectPvsData;
420typedef PvsData<KdNode *> KdPvsData;
421
422typedef Pvs<Intersectable *> ObjectPvs;
423
424
425#endif
426
Note: See TracBrowser for help on using the repository browser.