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

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