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

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