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

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

added mesh instance support
improved support for occlusion queries + other extensions

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