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

Revision 1891, 14.9 KB checked in by bittner, 18 years ago (diff)

combined preprocessor

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
12SamplingStrategy::SamplingStrategy(Preprocessor &preprocessor):
13  mPreprocessor(preprocessor), mRatio(1.0f),  mTotalRays(0), mTotalContribution(0.0f)
14{
15 
16}
17
18
19SamplingStrategy::~SamplingStrategy()
20{
21}
22
23int
24SamplingStrategy::GenerateSamples(const int number,
25                                                                  SimpleRayContainer &rays)
26{
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;
47
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;
62}
63
64
65/*********************************************************************/
66/*            Individual sampling strategies implementation          */
67/*********************************************************************/
68
69
70bool ObjectBasedDistribution::GenerateSample(SimpleRay &ray)
71{
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 
80
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}
108
109
110bool
111ObjectDirectionBasedDistribution::GenerateSample(SimpleRay &ray)
112{       
113  Vector3 origin, direction;
114
115
116  float r[4];
117  mHalton.GetNext(4, r);
118
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;
126
127  Vector3 normal;
128
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;
141}
142
143
144bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray)
145{       
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;
158        ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
159
160        return true;
161}
162
163
164bool DirectionBoxBasedDistribution::GenerateSample(SimpleRay &ray)
165{
166        Vector3 origin, direction;
167        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
168
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);
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;
182        ray = SimpleRay(origin, direction, DIRECTION_BOX_BASED_DISTRIBUTION, pdf);
183
184        return true;
185}
186
187
188bool SpatialBoxBasedDistribution::GenerateSample(SimpleRay &ray)
189{
190  Vector3 origin, direction;
191
192  float r[6];
193  mHalton.GetNext(6, r);
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;
209  ray = SimpleRay(origin, direction, SPATIAL_BOX_BASED_DISTRIBUTION, pdf);
210 
211  return true;
212}
213
214
215bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray)
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);
229       
230        direction = origin - point;
231       
232        // $$ jb the pdf is yet not correct for all sampling methods!
233        const float c = Magnitude(direction);
234       
235        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
236        {
237                return false;
238        }
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;
244        // a little offset
245        point += direction * 0.001f;
246
247        ray = SimpleRay(point, direction, REVERSE_OBJECT_BASED_DISTRIBUTION, pdf);
248       
249        return true;
250}
251
252
253bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray)
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
268        //cout << "vc: " << vcIdx << endl;
269        //cout << "obj: " << objIdx << endl;
270
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
279        if ((c <= Limits::Small) /*|| (DotProd(direction, normal) < 0)*/)
280        {
281                return false;
282        }
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;
288        ray = SimpleRay(origin, direction, VIEWCELL_BORDER_BASED_DISTRIBUTION, pdf);
289
290        //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl;
291
292        return true;
293}
294
295
296#if 0
297bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray)
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;
324}
325
326#endif
327
328
329bool ReverseViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
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
361        ray = SimpleRay(point, direction, REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
362       
363        return true;
364}
365
366
367bool ViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
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
397        ray = SimpleRay(origin, direction, VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
398
399        return true;
400}
401
402
403
404
405bool
406GlobalLinesDistribution::GenerateSample(SimpleRay &ray)
407{
408  Vector3 origin, termination, direction;
409
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];
417        mHalton.GetNext(4, r);
418       
419        origin = center + (radius*UniformRandomVector(r[0], r[1]));
420        termination = center + (radius*UniformRandomVector(r[2], r[3]));
421       
422        direction = termination - origin;
423       
424       
425        // $$ jb the pdf is yet not correct for all sampling methods!
426        const float c = Magnitude(direction);
427        if (c <= Limits::Small)
428          return false;
429       
430        direction *= 1.0f / c;
431
432        // check if the ray intersects the view space box
433        static Ray ray;
434        ray.Init(origin, direction, Ray::LOCAL_RAY);   
435       
436        float tmin, tmax;
437        if (mPreprocessor.mViewCellsManager->
438                GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
439          break;
440  }
441 
442  if (i!=tries) {
443        // $$ jb the pdf is yet not correct for all sampling methods!
444        const float pdf = 1.0f;
445       
446       
447        ray = SimpleRay(origin, direction, GLOBAL_LINES_DISTRIBUTION, pdf);
448        ray.mType = Ray::GLOBAL_RAY;
449        return true;
450  }
451 
452  return false;
453}
454
455
456  // has to called before first usage
457void
458MixtureDistribution::Init()
459{
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();
470}
471
472void
473MixtureDistribution::Reset()
474{
475  for (int i=0; i < mDistributions.size(); i++) {
476        // small non-zero value
477        mDistributions[i]->mTotalRays = 0;
478        // unit contribution per ray
479        mDistributions[i]->mTotalContribution = 0.0f;
480  }
481  UpdateRatios();
482}
483
484// Generate a new sample according to a mixture distribution
485bool
486MixtureDistribution::GenerateSample(SimpleRay &ray)
487{
488  float r;
489  mHalton.GetNext(1, &r);
490
491  // pickup a distribution
492  for (int i=0; i < mDistributions.size()-1; i++)
493        if (r < mDistributions[i]->mRatio)
494          break;
495
496  return mDistributions[i]->GenerateSample(ray);
497}
498
499  // add contributions of the sample to the strategies
500void
501MixtureDistribution::ComputeContributions(VssRayContainer &vssRays)
502{
503  int i;
504 
505  VssRayContainer::iterator it = vssRays.begin();
506
507  for (i=0; i < mDistributions.size(); i++) {
508        mDistributions[i]->mContribution = 0;
509        mDistributions[i]->mRays = 0;
510  }
511
512  for(; it != vssRays.end(); ++it) {
513        VssRay *ray = *it;
514        for (i=0; i < mDistributions.size()-1; i++) {
515          if (mDistributions[i]->mType == ray->mDistribution)
516                break;
517        }
518 
519        float contribution =
520          mPreprocessor.mViewCellsManager->ComputeSampleContribution(*ray, true, false);
521        mDistributions[i]->mContribution += contribution;
522        mDistributions[i]->mRays ++;
523
524        mDistributions[i]->mTotalContribution += contribution;
525        mDistributions[i]->mTotalRays ++;
526  }
527
528  // now update the distributions with all the rays
529  for (i=0; i < mDistributions.size(); i++) {
530        mDistributions[i]->Update(vssRays);
531  }
532 
533 
534  UpdateRatios();
535}
536
537void
538MixtureDistribution::UpdateRatios()
539{
540  // now compute importance (ratio) of all distributions
541  float sum = 0.0f;
542  int i;
543  for (i=0; i < mDistributions.size(); i++) {
544        cout<<i<<": c="<<mDistributions[i]->mContribution<<
545          " rays="<<mDistributions[i]->mRays<<endl;
546        float importance = 0.0f;
547        if (mDistributions[i]->mRays != 0) {
548          importance = pow(mDistributions[i]->mContribution/mDistributions[i]->mRays, 3);
549        }
550        if (importance < Limits::Small)
551          importance = Limits::Small;
552        mDistributions[i]->mRatio = importance;
553        sum += importance;
554  }
555
556  const float minratio = 0.05f;
557  float threshold = minratio*sum;
558  for (i=0; i < mDistributions.size(); i++) {
559        if (mDistributions[i]->mRatio < threshold) {
560          sum += threshold - mDistributions[i]->mRatio;
561          mDistributions[i]->mRatio = threshold;
562        }
563  }
564 
565  mDistributions[0]->mRatio /= sum;
566       
567  for (i=1; i < mDistributions.size(); i++) {
568        float r = mDistributions[i]->mRatio / sum;
569        mDistributions[i]->mRatio = mDistributions[i-1]->mRatio + r;
570  }
571 
572  cout<<"ratios: ";
573  for (i=0; i < mDistributions.size(); i++)
574        cout<<mDistributions[i]->mRatio<<" ";
575  cout<<endl;
576}
577
578
579
580bool
581MixtureDistribution::Construct(char *str)
582{
583  char *curr = str;
584
585  while (1) {
586        char *e = strchr(curr,'+');
587        if (e!=NULL) {
588          *e=0;
589        }
590       
591        if (strcmp(curr, "rss")==0) {
592          mDistributions.push_back(new RssBasedDistribution(mPreprocessor));
593        } else
594          if (strcmp(curr, "object")==0) {
595                mDistributions.push_back(new ObjectBasedDistribution(mPreprocessor));
596          } else
597                if (strcmp(curr, "spatial")==0) {
598                  mDistributions.push_back(new SpatialBoxBasedDistribution(mPreprocessor));
599                } else
600                  if (strcmp(curr, "global")==0) {
601                        mDistributions.push_back(new GlobalLinesDistribution(mPreprocessor));
602                  } else
603                        if (strcmp(curr, "direction")==0) {
604                          mDistributions.push_back(new DirectionBasedDistribution(mPreprocessor));
605                        } else
606                          if (strcmp(curr, "object_direction")==0) {
607                                mDistributions.push_back(new ObjectDirectionBasedDistribution(mPreprocessor));
608                          } else
609                                if (strcmp(curr, "reverse_object")==0) {
610                                  mDistributions.push_back(new ReverseObjectBasedDistribution(mPreprocessor));
611                                } else
612                                  if (strcmp(curr, "reverse_viewspace_border")==0) {
613                                        mDistributions.push_back(new ReverseViewSpaceBorderBasedDistribution(mPreprocessor));
614                                  }
615       
616        if (e==NULL)
617          break;
618        curr = e+1;
619  }
620
621  Init();
622  return true;
623}
624
625}
626
627
Note: See TracBrowser for help on using the repository browser.