source: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingStrategy.cpp @ 1888

Revision 1888, 12.9 KB checked in by mattausch, 18 years ago (diff)

removed possible bug in mixtedstrategy

RevLine 
[1020]1#include "SamplingStrategy.h"
2#include "Ray.h"
3#include "Intersectable.h"
4#include "Preprocessor.h"
5#include "ViewCellsManager.h"
6#include "AxisAlignedBox3.h"
7
8
9namespace GtpVisibilityPreprocessor {
10
11
[1884]12SamplingStrategy::SamplingStrategy(Preprocessor &preprocessor):
[1877]13  mPreprocessor(preprocessor), mRatio(1.0f),  mTotalRays(0), mTotalContribution(0.0f)
[1520]14{
[1877]15 
[1520]16}
17
18
19SamplingStrategy::~SamplingStrategy()
20{
21}
22
[1771]23int
24SamplingStrategy::GenerateSamples(const int number,
[1867]25                                                                  SimpleRayContainer &rays)
[1771]26{
[1772]27        SimpleRay ray;
28        int samples = 0;
29        int i = 0;
30        const int maxTries = 20;
31        // tmp changed matt. Q: should one rejected sample
32        // terminate the whole method?
33        if (0)
34        {
35                for (; i < number; i++) {
36                        if (!GenerateSample(ray))
37                                return i;
38                        rays.push_back(ray);
39                }
40        }
41        else
42        {
43                for (; i < number; i++)
44                {
45                        int j = 0;
46                        bool sampleGenerated = false;
[1520]47
[1772]48                        for (j = 0; !sampleGenerated && (j < maxTries); ++ j)
49                        {
50                                sampleGenerated = GenerateSample(ray);
51
52                                if (sampleGenerated)
53                                {               
54                                        ++ samples;
55                                        rays.push_back(ray);
56                                }
57                        }
58                }
59        }
60       
61        return samples;
[1771]62}
[1520]63
[1771]64
[1020]65/*********************************************************************/
66/*            Individual sampling strategies implementation          */
67/*********************************************************************/
68
69
[1867]70bool ObjectBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]71{
[1883]72  Vector3 origin, direction;
73 
74  float r[5];
75  mHalton.GetNext(5, r);
76 
77  mPreprocessor.mViewCellsManager->GetViewPoint(origin,
78                                                                                                Vector3(r[2],r[3],r[4]));
79 
[1020]80
[1883]81  Vector3 point, normal;
82 
83  r[0] *= mPreprocessor.mObjects.size()-1;
84  const int i = (int)r[0];
85 
86  Intersectable *object = mPreprocessor.mObjects[i];
87 
88  // take the remainder as a parameter over objects surface
89  r[0] -= (float)i;
90 
91  object->GetRandomSurfacePoint(r[0], r[1], point, normal);
92 
93  direction = point - origin;
94 
95  const float c = Magnitude(direction);
96 
97  if (c <= Limits::Small)
98        return false;
99 
100  // $$ jb the pdf is yet not correct for all sampling methods!
101  const float pdf = 1.0f;
102 
103  direction *= 1.0f / c;
104  ray = SimpleRay(origin, direction, OBJECT_BASED_DISTRIBUTION, pdf);
105 
106  return true;
107}
[1020]108
109
[1883]110bool
111ObjectDirectionBasedDistribution::GenerateSample(SimpleRay &ray)
112{       
113  Vector3 origin, direction;
[1877]114
[1020]115
[1883]116  float r[4];
117  mHalton.GetNext(4, r);
[1877]118
[1883]119  r[0] *= mPreprocessor.mObjects.size()-1;
120  const int i = (int)r[0];
121 
122  Intersectable *object = mPreprocessor.mObjects[i];
123 
124  // take the remainder as a parameter over objects surface
125  r[0] -= (float)i;
[1020]126
[1883]127  Vector3 normal;
[1020]128
[1883]129  object->GetRandomSurfacePoint(r[0], r[1], origin, normal);
130 
131  direction = Normalize(CosineRandomVector(r[2], r[3], normal));
132 
133  origin += 1e-2*direction;
134 
135  // $$ jb the pdf is yet not correct for all sampling methods!
136  const float pdf = 1.0f;
137 
138  ray = SimpleRay(origin, direction, OBJECT_DIRECTION_BASED_DISTRIBUTION, pdf);
139 
140  return true;
[1020]141}
142
143
[1867]144bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray)
[1278]145{       
[1020]146        Vector3 origin, direction;
147        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
148         
149        direction = UniformRandomVector();
150        const float c = Magnitude(direction);
151
152        if (c <= Limits::Small)
153                return false;
154
155        const float pdf = 1.0f;
156
157        direction *= 1.0f / c;
[1883]158        ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
[1020]159
160        return true;
161}
162
163
[1867]164bool DirectionBoxBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]165{
166        Vector3 origin, direction;
167        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
168
[1297]169        const float alpha = RandomValue(0.0f, 2.0f * (float)M_PI);
170        const float beta = RandomValue((float)-M_PI * 0.5f, (float)M_PI * 0.5f);
[1020]171       
172        direction = VssRay::GetDirection(alpha, beta);
173       
174        const float c = Magnitude(direction);
175
176        if (c <= Limits::Small)
177                return false;
178
179        const float pdf = 1.0f;
180
181        direction *= 1.0f / c;
[1883]182        ray = SimpleRay(origin, direction, DIRECTION_BOX_BASED_DISTRIBUTION, pdf);
[1020]183
184        return true;
185}
186
187
[1867]188bool SpatialBoxBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]189{
[1867]190  Vector3 origin, direction;
[1278]191
[1867]192  float r[6];
[1877]193  mHalton.GetNext(6, r);
[1867]194  mPreprocessor.mViewCellsManager->GetViewPoint(origin, Vector3(r[0],r[1],r[2]));
195 
196  direction = mPreprocessor.mKdTree->GetBox().GetRandomPoint(Vector3(r[3],
197                                                                                                                                         r[4],
198                                                                                                                                         r[5])
199                                                                                                                                         ) - origin;
200  //cout << "z";
201  const float c = Magnitude(direction);
202 
203  if (c <= Limits::Small)
204        return false;
205 
206  const float pdf = 1.0f;
207 
208  direction *= 1.0f / c;
[1883]209  ray = SimpleRay(origin, direction, SPATIAL_BOX_BASED_DISTRIBUTION, pdf);
[1867]210 
211  return true;
[1020]212}
213
[1695]214
[1867]215bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray)
[1695]216{
217        Vector3 origin, direction;
218
219        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
220
221        Vector3 point;
222        Vector3 normal;
223        //cout << "y";
224        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
225
226        Intersectable *object = mPreprocessor.mObjects[i];
227
228        object->GetRandomSurfacePoint(point, normal);
[1765]229       
[1695]230        direction = origin - point;
[1765]231       
[1695]232        // $$ jb the pdf is yet not correct for all sampling methods!
233        const float c = Magnitude(direction);
[1765]234       
235        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
236        {
[1695]237                return false;
[1765]238        }
[1695]239
240        // $$ jb the pdf is yet not correct for all sampling methods!
241        const float pdf = 1.0f;
242        //cout << "p: " << point << " ";
243        direction *= 1.0f / c;
[1765]244        // a little offset
[1772]245        point += direction * 0.001f;
[1765]246
[1883]247        ray = SimpleRay(point, direction, REVERSE_OBJECT_BASED_DISTRIBUTION, pdf);
[1695]248       
249        return true;
250}
251
[1763]252
[1867]253bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1763]254{
255        Vector3 origin, direction;
256
257        ViewCellContainer &viewCells = mPreprocessor.mViewCellsManager->GetViewCells();
258
259        Vector3 point;
260        Vector3 normal, normal2;
261       
262        const int vcIdx = (int)RandomValue(0, (float)viewCells.size() - 0.5f);
263        const int objIdx = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
264
265        Intersectable *object = mPreprocessor.mObjects[objIdx];
266        ViewCell *viewCell = viewCells[vcIdx];
267
[1769]268        //cout << "vc: " << vcIdx << endl;
269        //cout << "obj: " << objIdx << endl;
270
[1763]271        object->GetRandomSurfacePoint(point, normal);
272        viewCell->GetRandomEdgePoint(origin, normal2);
273
274        direction = point - origin;
275
276        // $$ jb the pdf is yet not correct for all sampling methods!
277        const float c = Magnitude(direction);
278
[1769]279        if ((c <= Limits::Small) /*|| (DotProd(direction, normal) < 0)*/)
[1768]280        {
[1763]281                return false;
[1768]282        }
[1763]283
284        // $$ jb the pdf is yet not correct for all sampling methods!
285        const float pdf = 1.0f;
286        //cout << "p: " << point << " ";
287        direction *= 1.0f / c;
[1883]288        ray = SimpleRay(origin, direction, VIEWCELL_BORDER_BASED_DISTRIBUTION, pdf);
[1769]289
290        //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl;
291
[1763]292        return true;
293}
294
[1765]295
[1520]296#if 0
[1867]297bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray)
[1020]298{
299        Vector3 origin, direction;
300
301        // get random object
302        const int i = RandomValue(0, mPreprocessor.mObjects.size() - 1);
303
304        const Intersectable *obj = mPreprocessor.mObjects[i];
305
306        // note: if we load the polygons as meshes,
307        // asymtotically every second sample is lost!
308        origin = obj->GetBox().GetRandomPoint();
309
310        // uniformly distributed direction
311        direction = UniformRandomVector();
312
313        const float c = Magnitude(direction);
314
315        if (c <= Limits::Small)
316                return false;
317
318        const float pdf = 1.0f;
319
320        direction *= 1.0f / c;
321        ray = SimpleRay(origin, direction, pdf);
322
323        return true;
[1520]324}
[1769]325
[1520]326#endif
[1771]327
[1772]328
[1867]329bool ReverseViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1772]330{
331        Vector3 origin, direction;
332
333        origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint();
334
335        Vector3 point;
336        Vector3 normal;
337        //cout << "y";
338        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
339
340        Intersectable *object = mPreprocessor.mObjects[i];
341
342        object->GetRandomSurfacePoint(point, normal);
343       
344        direction = origin - point;
345       
346        // $$ jb the pdf is yet not correct for all sampling methods!
347        const float c = Magnitude(direction);
348       
349        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
350        {
351                return false;
352        }
353
354        // $$ jb the pdf is yet not correct for all sampling methods!
355        const float pdf = 1.0f;
356        //cout << "p: " << point << " ";
357        direction *= 1.0f / c;
358        // a little offset
359        point += direction * 0.001f;
360
[1883]361        ray = SimpleRay(point, direction, REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
[1772]362       
363        return true;
364}
365
366
[1867]367bool ViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1772]368{
369        Vector3 origin, direction;
370
371        origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint();
372
373        Vector3 point;
374        Vector3 normal;
375        //cout << "w";
376        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
377
378        Intersectable *object = mPreprocessor.mObjects[i];
379
380        object->GetRandomSurfacePoint(point, normal);
381        direction = point - origin;
382
383        // $$ jb the pdf is yet not correct for all sampling methods!
384        const float c = Magnitude(direction);
385
386        if (c <= Limits::Small)
387                return false;
388
389        // $$ jb the pdf is yet not correct for all sampling methods!
390        const float pdf = 1.0f;
391       
392        direction *= 1.0f / c;
393
394        // a little offset
395        origin += direction * 0.001f;
396
[1883]397        ray = SimpleRay(origin, direction, VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
[1772]398
399        return true;
400}
401
402
[1771]403
[1824]404
405bool
[1867]406GlobalLinesDistribution::GenerateSample(SimpleRay &ray)
[1824]407{
[1867]408  Vector3 origin, termination, direction;
[1824]409
[1867]410  float radius = 0.5f*Magnitude(mPreprocessor.mViewCellsManager->GetViewSpaceBox().Size());
411  Vector3 center = mPreprocessor.mViewCellsManager->GetViewSpaceBox().Center();
412
413  const int tries = 1000;
414  int i;
415  for (i=0; i < tries; i++) {
416        float r[4];
[1877]417        mHalton.GetNext(4, r);
[1824]418       
[1867]419        origin = center + (radius*UniformRandomVector(r[0], r[1]));
420        termination = center + (radius*UniformRandomVector(r[2], r[3]));
421       
[1824]422        direction = termination - origin;
[1867]423       
424       
[1824]425        // $$ jb the pdf is yet not correct for all sampling methods!
426        const float c = Magnitude(direction);
427        if (c <= Limits::Small)
[1867]428          return false;
[1824]429       
430        direction *= 1.0f / c;
[1867]431
432        // check if the ray intersects the view space box
433        static Ray ray;
434        ray.Init(origin, direction, Ray::LOCAL_RAY);   
[1824]435       
[1867]436        float tmin, tmax;
437        if (mPreprocessor.mViewCellsManager->
438                GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
439          break;
440  }
441 
442  if (i!=tries) {
[1824]443        // $$ jb the pdf is yet not correct for all sampling methods!
444        const float pdf = 1.0f;
[1867]445       
446       
[1883]447        ray = SimpleRay(origin, direction, GLOBAL_LINES_DISTRIBUTION, pdf);
[1824]448        ray.mType = Ray::GLOBAL_RAY;
449        return true;
[1867]450  }
451 
452  return false;
[1771]453}
454
[1883]455
456  // has to called before first usage
457void
458MixtureDistribution::Init()
459{
[1884]460  for (int i=0; i < mDistributions.size(); i++) {
461        // small non-zero value
462        mDistributions[i]->mRays = 1;
463        // unit contribution per ray
464        if (1 || mDistributions[i]->mType != RSS_BASED_DISTRIBUTION)
465          mDistributions[i]->mContribution = 1.0f;
466        else
467          mDistributions[i]->mContribution = 0.0f;
468  }
469  UpdateRatios();
[1824]470}
[1884]471
472void
473MixtureDistribution::Reset()
474{
475  for (int i=0; i < mDistributions.size(); i++) {
476        // small non-zero value
477        mDistributions[i]->mRays = 1;
478        // unit contribution per ray
479        mDistributions[i]->mContribution = 1.0f;
480  }
481  UpdateRatios();
482}
483
484// Generate a new sample according to a mixture distribution
[1883]485bool
486MixtureDistribution::GenerateSample(SimpleRay &ray)
487{
[1884]488  float r;
489  mHalton.GetNext(1, &r);
[1771]490
[1884]491  // pickup a distribution
492  for (int i=0; i < mDistributions.size(); i++)
493        if (r < mDistributions[i]->mRatio)
494          break;
495 
496  return mDistributions[i]->GenerateSample(ray);
[1883]497}
[1824]498
[1883]499  // add contributions of the sample to the strategies
500void
[1884]501MixtureDistribution::ComputeContributions(VssRayContainer &vssRays)
[1883]502{
[1884]503  int i;
504 
505  VssRayContainer::iterator it = vssRays.begin();
[1883]506
[1884]507  for(; it != vssRays.end(); ++it) {
508        VssRay *ray = *it;
509        for (i=0; i < mDistributions.size()-1; i++)
510          if (mDistributions[i]->mType == ray->mDistribution)
511                break;
512        float contribution =
513          mPreprocessor.mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
[1888]514        mDistributions[i]->mContribution += contribution;
[1884]515        mDistributions[i]->mRays ++;
516  }
517
518  // now update the distributions with all the rays
519  for (i=0; i < mDistributions.size(); i++)
520        mDistributions[i]->Update(vssRays);
521 
522 
523  UpdateRatios();
[1883]524}
525
[1884]526void
527MixtureDistribution::UpdateRatios()
528{
529  // now compute importance (ratio) of all distributions
530  float sum = 0.0f;
531  int i;
532  for (i=0; i < mDistributions.size(); i++) {
533        float importance = mDistributions[i]->mContribution/mDistributions[i]->mRays;
534        mDistributions[i]->mRatio = importance;
535        sum += importance;
536  }
537 
538 
539  mDistributions[0]->mRatio /= sum;
540  for (i=1; i < mDistributions.size(); i++) {
541        float r = mDistributions[i]->mRatio / sum;
542        mDistributions[i]->mRatio = mDistributions[i-1]->mRatio + r;
543  }
544 
545  cout<<"ratios: ";
546  for (i=0; i < mDistributions.size(); i++)
547        cout<<mDistributions[i]->mRatio<<" ";
548  cout<<endl;
[1883]549}
[1884]550}
[1883]551
552
Note: See TracBrowser for help on using the repository browser.