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

Revision 1189, 11.0 KB checked in by mattausch, 18 years ago (diff)

changed osp partition to something taking mult references into account

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