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

Revision 1694, 11.4 KB checked in by bittner, 18 years ago (diff)

obj exporter, vienna.obj + kdf added

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  static int GetEntrySizeByte();
181  static float GetEntrySize();
182
183  /** Compute continuous PVS difference */
184  float GetPvsHomogenity(Pvs<T, S> &pvs) {
185        float
186          pvsReduction,
187          pvsEnlargement;
188       
189        ComputeContinuousPvsDifference(pvs,
190                                                                   pvsReduction,
191                                                                   pvsEnlargement);
192       
193        return pvsReduction + pvsEnlargement;
194  }
195 
196  int Size() { return mEntries.size(); }
197                                         
198  /// Map of PVS entries
199  std::map<T, S, LtSample<T> > mEntries;
200};
201
202
203
204/**
205   Compute continuous PVS difference of 'b' with respect to the base PVS (*this).
206   Provides separatelly PVS reduction from PVS enlargement.
207
208*/
209template <typename T, typename S>
210void
211Pvs<T, S>::ComputeContinuousPvsDifference(Pvs<T, S> &b,
212                                                                           float &pvsReduction,
213                                                                           float &pvsEnlargement)
214{
215        pvsReduction = 0.0f;
216        pvsEnlargement = 0.0f;
217  // Uses sum of log differences, which corresponds to entropy
218  std::map<T, S, LtSample<T> >::iterator it;
219 
220  for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
221  {
222        float bSumPdf = (*it).second.mSumPdf;
223        float aSumPdf = 0.0f;
224        S *data = Find((*it).first);           
225       
226        if (data)
227        {
228                aSumPdf = data->mSumPdf;
229                // mark this entry as processed to avoid double counting
230                data->mSumPdf = -aSumPdf;
231        }
232
233#if 0
234        float diff = bSumPdf - aSumPdf;
235       
236        if (diff > 0.0f) {
237          pvsEnlargement += diff;
238        } else {
239          pvsReduction += -diff;
240        }
241#else
242        if (!data)
243          pvsEnlargement += 1.0f;
244#endif
245  }
246 
247  for (it = mEntries.begin(); it != mEntries.end(); ++ it) {
248        float aSumPdf = (*it).second.mSumPdf;
249        float bSumPdf = 0.0f;
250        if (aSumPdf < 0.0f) {
251          // this entry was already accounted for!
252          // just revert it back
253          (*it).second.mSumPdf = -aSumPdf;
254        } else {
255          S *data = b.Find((*it).first);
256          if (data) {
257                bSumPdf = data->mSumPdf;
258          }
259#if 0
260          float diff = bSumPdf - aSumPdf;
261         
262          if (diff > 0.0f) {
263                pvsEnlargement += diff;
264          } else {
265                pvsReduction += -diff;
266          }
267
268#else
269          if (!data)
270                pvsReduction += 1.0f;
271#endif
272        }
273  }
274}
275
276template <typename T, typename S>
277int Pvs<T, S>::Diff(const Pvs<T, S> &b)
278{
279        int dif = 0;
280
281        std::map<T, S, LtSample<T> >::const_iterator it;
282
283        for (it = b.mEntries.begin(); it != b.mEntries.end(); ++ it)
284        {
285                S data = Find((*it).first);             
286                if (!data) ++ dif;
287        }
288
289        return dif;
290}
291
292template <typename T, typename S> void Pvs<T, S>::Merge(const Pvs<T, S> &a)
293{
294        std::map<T, S, LtSample<T> >::const_iterator it;
295
296        for (it = a.mEntries.begin(); it != a.mEntries.end(); ++ it)
297        {
298                AddSample((*it).first, (*it).second.mSumPdf);
299        }
300}
301
302
303template <typename T, typename S> void Pvs<T, S>::Clear()
304{
305        mEntries.clear();
306}
307
308
309template <typename T, typename S>
310S *Pvs<T, S>::Find(T sample)
311{
312  std::map<T, S, LtSample<T> >::iterator i = mEntries.find(sample);
313
314  if (i != mEntries.end())
315  {
316          return &(*i).second;
317  }
318  else
319  {
320          return NULL;
321  }
322}
323
324template <typename T, typename S>
325void Pvs<T, S>::GetData(const int index,
326                                         T &entry,
327                                         S &data)
328{
329  std::map<T, S, LtSample<T> >::iterator i = mEntries.begin();
330  for (int k = 0; k != index && i != mEntries.end(); i++, k++);
331
332  entry = (*i).first;
333  data = (*i).second;
334 
335}
336
337template <typename T, typename S>
338float
339Pvs<T, S>::AddSample(T sample, const float pdf)
340{
341        S *data = Find(sample);
342 
343        if (data) 
344        {
345                data->mSumPdf += pdf;
346                return data->mSumPdf;
347        }
348        else
349        {
350                mEntries[sample] = S(pdf);
351                return pdf;
352        }
353}
354
355
356template <typename T, typename S>
357S * Pvs<T, S>::AddSample2(T sample, const float pdf)
358{
359        S *data = Find(sample);
360 
361        if (data) 
362        {
363                data->mSumPdf += pdf;
364        }
365        else
366        {
367                mEntries[sample] = S(pdf);
368                data = Find(sample);
369        }
370
371        return data;
372}
373
374template <typename T, typename S>
375bool Pvs<T, S>::AddSample(T sample,
376                                  const float pdf,
377                                  float &contribution)
378{
379  S *data = Find(sample);
380 
381  if (data) 
382  {
383        data->mSumPdf += pdf;
384        contribution = pdf / data->mSumPdf;
385        return false;
386  }
387  else {
388        mEntries[sample] = S(pdf);
389        contribution = 1.0f;
390        return true;
391  }
392}
393
394template <typename T, typename S>
395bool
396Pvs<T, S>::GetSampleContribution(T sample,
397                                                                 const float pdf,
398                                                                 float &contribution)
399{
400  S *data = Find(sample);
401 
402  if (data)  {
403        contribution = pdf / (data->mSumPdf + pdf);
404        return false;
405  }
406  else {
407        contribution = 1.0f;
408        return true;
409  }
410}
411
412template <typename T, typename S>
413bool Pvs<T, S>::RemoveSample(T sample,
414                                                  const float pdf)
415{
416  std::map<T, S, LtSample<T> >::
417        iterator it = mEntries.find(sample);
418 
419  if (it == mEntries.end())
420        return false;
421 
422  S *data = &(*it).second;
423 
424  data->mSumPdf -= pdf;
425
426  if (data->mSumPdf <= 0.0f)
427  {
428          mEntries.erase(it);
429  }
430
431  return true;
432}
433
434template <typename T, typename S>
435int Pvs<T, S>::AddPvs(const Pvs<T, S> &pvs)
436{
437  std::map<T, S, LtSample<T> >::
438        const_iterator it, it_end = pvs.mEntries.end();
439 
440  float contri;
441  // output PVS of view cell
442  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
443  {     
444          AddSample((*it).first, (*it).second.mSumPdf, contri);
445  }
446 
447  return GetSize();
448}
449 
450template <typename T, typename S>
451int Pvs<T, S>::SubtractPvs(const Pvs<T, S> &pvs)
452{
453  std::map<T, S, LtSample<T> >::
454        const_iterator it, it_end = pvs.mEntries.end();
455 
456  // output PVS of view cell
457  for (it = pvs.mEntries.begin(); it != it_end; ++ it)
458        RemoveSample((*it).first, (*it).second.mSumPdf);
459 
460  return GetSize();
461}
462
463template <typename T, typename S>
464void Pvs<T, S>::CollectEntries(std::vector<T> &entries)
465{
466        std::map<T, S, LtSample<T> >::
467                const_iterator it, it_end = mEntries.end();
468
469        // output PVS of view cell
470        for (it = mEntries.begin(); it != it_end; ++ it)
471                entries.push_back((*it)->first);
472}
473
474template <typename T, typename S>
475void Pvs<T, S>::NormalizeMaximum()
476{
477  std::map<T, S, LtSample<T> >::
478        const_iterator it, it_end = mEntries.end();
479
480  float maxPdfSum = -1.0f;
481
482  // output PVS of view cell
483  for (it = mEntries.begin(); it != it_end; ++ it) {
484        float sum = (*it)->second.sumPdf;
485        if (sum > maxSum)
486          maxSum = sum;
487  }
488
489  maxSum = 1.0f / maxSum;
490
491  for (it = mEntries.begin(); it != it_end; ++ it) {
492        (*it)->second.sumPdf *= maxSum;
493  }
494 
495}
496
497
498template <typename T, typename S>
499float Pvs<T, S>::GetEntrySize()
500{
501        return (float)(sizeof(T) + sizeof(S)) / float(1024 * 1024);
502}
503
504
505template <typename T, typename S>
506int Pvs<T, S>::GetEntrySizeByte()
507{
508        return sizeof(T) + sizeof(S);
509}
510
511
512///////////////////////////////////////
513
514/** Class instantiating the Pvs template for kd tree nodes.
515*/
516class KdPvs: public Pvs<KdNode *, PvsData>
517{
518public:
519        int Compress();
520};
521
522
523class ObjectPvs: public Pvs<Intersectable *, PvsData>
524{
525public:
526        /** Counts object int the pvs. Different to method "GetSize", not
527                only the raw container size is returned,
528                but the individual contributions of the entries are summed up.
529        */
530        int CountObjectsInPvs() const;
531};
532
533
534////////////
535//-- typedefs
536
537typedef std::map<KdNode *, PvsData, LtSample<KdNode *> > KdPvsMap;
538typedef std::map<Intersectable *, PvsData, LtSample<Intersectable *> > ObjectPvsMap;
539typedef std::map<ViewCell *, MailablePvsData, LtSample<ViewCell *> > ViewCellPvsMap;
540
541
542typedef Pvs<ViewCell *, MailablePvsData> ViewCellPvs;
543
544}
545
546#endif
547
Note: See TracBrowser for help on using the repository browser.