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

Revision 1983, 26.2 KB checked in by bittner, 17 years ago (diff)

merge

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#include "Vector2.h"
9#include "RndGauss.h"
10
11namespace GtpVisibilityPreprocessor {
12
13#define MUTATION_USE_CDF 0
14
15
16//HaltonSequence SamplingStrategy::sHalton;
17
18HaltonSequence ObjectBasedDistribution::sHalton;
19HaltonSequence MixtureDistribution::sHalton;
20HaltonSequence GlobalLinesDistribution::sHalton;
21HaltonSequence SpatialBoxBasedDistribution::sHalton;
22HaltonSequence ObjectDirectionBasedDistribution::sHalton;
23HaltonSequence DirectionBasedDistribution::sHalton;
24HaltonSequence HwGlobalLinesDistribution::sHalton;
25
26
27SamplingStrategy::SamplingStrategy(Preprocessor &preprocessor):
28mPreprocessor(preprocessor),
29mRatio(1.0f), 
30mTotalRays(0),
31mTotalContribution(0.0f)
32
33}
34
35
36SamplingStrategy::~SamplingStrategy()
37{
38}
39
40int
41SamplingStrategy::GenerateSamples(const int number,
42                                                                  SimpleRayContainer &rays)
43{
44        SimpleRay ray;
45        int samples = 0;
46        int i = 0;
47        const int maxTries = 20;
48        // tmp changed matt. Q: should one rejected sample
49        // terminate the whole method?
50        if (0)
51        {
52                for (; i < number; i++) {
53                        if (!GenerateSample(ray))
54                                return i;
55                        rays.push_back(ray);
56                }
57        }
58        else
59        {
60                for (; i < number; i++)
61                {
62                        int j = 0;
63                        bool sampleGenerated = false;
64
65                        for (j = 0; !sampleGenerated && (j < maxTries); ++ j)
66                        {
67                                sampleGenerated = GenerateSample(ray);
68
69                                if (sampleGenerated)
70                                {               
71                                        ++ samples;
72                                        rays.push_back(ray);
73                                }
74                        }
75                }
76        }
77       
78        return samples;
79}
80
81
82/*********************************************************************/
83/*            Individual sampling strategies implementation          */
84/*********************************************************************/
85
86
87bool ObjectBasedDistribution::GenerateSample(SimpleRay &ray)
88{
89  Vector3 origin, direction;
90 
91  float r[5];
92  sHalton.GetNext(5, r);
93 
94  mPreprocessor.mViewCellsManager->GetViewPoint(origin,
95                                                                                                Vector3(r[2],r[3],r[4]));
96 
97
98  Vector3 point, normal;
99 
100  r[0] *= (float)mPreprocessor.mObjects.size() - 1;
101  const int i = (int)r[0];
102 
103  Intersectable *object = mPreprocessor.mObjects[i];
104 
105  // take the remainder as a parameter over objects surface
106  r[0] -= (float)i;
107 
108  object->GetRandomSurfacePoint(r[0], r[1], point, normal);
109 
110  direction = point - origin;
111 
112  const float c = Magnitude(direction);
113 
114  if (c <= Limits::Small)
115        return false;
116 
117  // $$ jb the pdf is yet not correct for all sampling methods!
118  const float pdf = 1.0f;
119 
120  direction *= 1.0f / c;
121  ray = SimpleRay(origin, direction, OBJECT_BASED_DISTRIBUTION, pdf);
122 
123  return true;
124}
125
126
127bool
128ObjectDirectionBasedDistribution::GenerateSample(SimpleRay &ray)
129{       
130  Vector3 origin, direction;
131
132
133  float r[4];
134  sHalton.GetNext(4, r);
135
136  r[0] *= (float)mPreprocessor.mObjects.size() - 1;
137  const int i = (int)r[0];
138 
139  Intersectable *object = mPreprocessor.mObjects[i];
140 
141  // take the remainder as a parameter over objects surface
142  r[0] -= (float)i;
143
144  Vector3 normal;
145
146  object->GetRandomSurfacePoint(r[0], r[1], origin, normal);
147 
148  direction = Normalize(CosineRandomVector(r[2], r[3], normal));
149 
150  origin += 1e-2f*direction;
151 
152  // $$ jb the pdf is yet not correct for all sampling methods!
153  const float pdf = 1.0f;
154 
155  ray = SimpleRay(origin, direction, OBJECT_DIRECTION_BASED_DISTRIBUTION, pdf);
156 
157  return true;
158}
159
160
161bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray)
162{       
163
164  float r[5];
165  sHalton.GetNext(5, r);
166
167  Vector3 origin, direction;
168  mPreprocessor.mViewCellsManager->GetViewPoint(origin,
169                                                                                                Vector3(r[2],r[3],r[4])
170                                                                                                );
171 
172  direction = UniformRandomVector(r[0], r[1]);
173  const float c = Magnitude(direction);
174 
175  if (c <= Limits::Small)
176        return false;
177 
178  const float pdf = 1.0f;
179 
180  direction *= 1.0f / c;
181  ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
182 
183  return true;
184}
185
186
187bool DirectionBoxBasedDistribution::GenerateSample(SimpleRay &ray)
188{
189        Vector3 origin, direction;
190        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
191
192        const float alpha = RandomValue(0.0f, 2.0f * (float)M_PI);
193        const float beta = RandomValue((float)-M_PI * 0.5f, (float)M_PI * 0.5f);
194       
195        direction = VssRay::GetDirection(alpha, beta);
196       
197        const float c = Magnitude(direction);
198
199        if (c <= Limits::Small)
200                return false;
201
202        const float pdf = 1.0f;
203
204        direction *= 1.0f / c;
205        ray = SimpleRay(origin, direction, DIRECTION_BOX_BASED_DISTRIBUTION, pdf);
206
207        return true;
208}
209
210
211bool SpatialBoxBasedDistribution::GenerateSample(SimpleRay &ray)
212{
213  Vector3 origin, direction;
214
215  float r[6];
216  sHalton.GetNext(6, r);
217  mPreprocessor.mViewCellsManager->GetViewPoint(origin, Vector3(r[0],r[1],r[2]));
218 
219  direction = mPreprocessor.mKdTree->GetBox().GetRandomPoint(Vector3(r[3],
220                                                                                                                                         r[4],
221                                                                                                                                         r[5])
222                                                                                                                                         ) - origin;
223  //cout << "z";
224  const float c = Magnitude(direction);
225 
226  if (c <= Limits::Small)
227        return false;
228 
229  const float pdf = 1.0f;
230 
231  direction *= 1.0f / c;
232  ray = SimpleRay(origin, direction, SPATIAL_BOX_BASED_DISTRIBUTION, pdf);
233 
234  return true;
235}
236
237
238bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray)
239{
240        Vector3 origin, direction;
241
242        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
243
244        Vector3 point;
245        Vector3 normal;
246        //cout << "y";
247        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
248
249        Intersectable *object = mPreprocessor.mObjects[i];
250
251        object->GetRandomSurfacePoint(point, normal);
252       
253        direction = origin - point;
254       
255        // $$ jb the pdf is yet not correct for all sampling methods!
256        const float c = Magnitude(direction);
257       
258        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
259        {
260                return false;
261        }
262
263        // $$ jb the pdf is yet not correct for all sampling methods!
264        const float pdf = 1.0f;
265        //cout << "p: " << point << " ";
266        direction *= 1.0f / c;
267        // a little offset
268        point += direction * 0.001f;
269
270        ray = SimpleRay(point, direction, REVERSE_OBJECT_BASED_DISTRIBUTION, pdf);
271       
272        return true;
273}
274
275
276bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray)
277{
278        Vector3 origin, direction;
279
280        ViewCellContainer &viewCells = mPreprocessor.mViewCellsManager->GetViewCells();
281
282        Vector3 point;
283        Vector3 normal, normal2;
284       
285        const int vcIdx = (int)RandomValue(0, (float)viewCells.size() - 0.5f);
286        const int objIdx = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
287
288        Intersectable *object = mPreprocessor.mObjects[objIdx];
289        ViewCell *viewCell = viewCells[vcIdx];
290
291        //cout << "vc: " << vcIdx << endl;
292        //cout << "obj: " << objIdx << endl;
293
294        object->GetRandomSurfacePoint(point, normal);
295        viewCell->GetRandomEdgePoint(origin, normal2);
296
297        direction = point - origin;
298
299        // $$ jb the pdf is yet not correct for all sampling methods!
300        const float c = Magnitude(direction);
301
302        if ((c <= Limits::Small) /*|| (DotProd(direction, normal) < 0)*/)
303        {
304                return false;
305        }
306
307        // $$ jb the pdf is yet not correct for all sampling methods!
308        const float pdf = 1.0f;
309        //cout << "p: " << point << " ";
310        direction *= 1.0f / c;
311        ray = SimpleRay(origin, direction, VIEWCELL_BORDER_BASED_DISTRIBUTION, pdf);
312
313        //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl;
314
315        return true;
316}
317
318
319#if 0
320bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray)
321{
322        Vector3 origin, direction;
323
324        // get random object
325        const int i = RandomValue(0, mPreprocessor.mObjects.size() - 1);
326
327        const Intersectable *obj = mPreprocessor.mObjects[i];
328
329        // note: if we load the polygons as meshes,
330        // asymtotically every second sample is lost!
331        origin = obj->GetBox().GetRandomPoint();
332
333        // uniformly distributed direction
334        direction = UniformRandomVector();
335
336        const float c = Magnitude(direction);
337
338        if (c <= Limits::Small)
339                return false;
340
341        const float pdf = 1.0f;
342
343        direction *= 1.0f / c;
344        ray = SimpleRay(origin, direction, pdf);
345
346        return true;
347}
348
349#endif
350
351
352bool ReverseViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
353{
354        Vector3 origin, direction;
355
356        origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint();
357
358        Vector3 point;
359        Vector3 normal;
360        //cout << "y";
361        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
362
363        Intersectable *object = mPreprocessor.mObjects[i];
364
365        object->GetRandomSurfacePoint(point, normal);
366       
367        direction = origin - point;
368       
369        // $$ jb the pdf is yet not correct for all sampling methods!
370        const float c = Magnitude(direction);
371       
372        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
373        {
374                return false;
375        }
376
377        // $$ jb the pdf is yet not correct for all sampling methods!
378        const float pdf = 1.0f;
379        //cout << "p: " << point << " ";
380        direction *= 1.0f / c;
381        // a little offset
382        point += direction * 0.001f;
383
384        ray = SimpleRay(point, direction, REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
385       
386        return true;
387}
388
389
390bool ViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
391{
392        Vector3 origin, direction;
393
394        origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint();
395
396        Vector3 point;
397        Vector3 normal;
398        //cout << "w";
399        const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f);
400
401        Intersectable *object = mPreprocessor.mObjects[i];
402
403        object->GetRandomSurfacePoint(point, normal);
404        direction = point - origin;
405
406        // $$ jb the pdf is yet not correct for all sampling methods!
407        const float c = Magnitude(direction);
408
409        if (c <= Limits::Small)
410                return false;
411
412        // $$ jb the pdf is yet not correct for all sampling methods!
413        const float pdf = 1.0f;
414       
415        direction *= 1.0f / c;
416
417        // a little offset
418        origin += direction * 0.001f;
419
420        ray = SimpleRay(origin, direction, VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
421
422        return true;
423}
424
425
426bool
427GlobalLinesDistribution::GenerateSample(SimpleRay &ray)
428{
429  Vector3 origin, termination, direction;
430
431  float radius = 0.5f*Magnitude(mPreprocessor.mViewCellsManager->GetViewSpaceBox().Size());
432  Vector3 center = mPreprocessor.mViewCellsManager->GetViewSpaceBox().Center();
433
434  const int tries = 1000;
435  int i;
436  for (i=0; i < tries; i++) {
437        float r[4];
438        sHalton.GetNext(4, r);
439       
440        origin = center + (radius*UniformRandomVector(r[0], r[1]));
441        termination = center + (radius*UniformRandomVector(r[2], r[3]));
442       
443        direction = termination - origin;
444       
445       
446        // $$ jb the pdf is yet not correct for all sampling methods!
447        const float c = Magnitude(direction);
448        if (c <= Limits::Small)
449          return false;
450       
451        direction *= 1.0f / c;
452
453        // check if the ray intersects the view space box
454        static Ray ray;
455        ray.Init(origin, direction, Ray::LOCAL_RAY);   
456       
457        float tmin, tmax;
458        if (mPreprocessor.mViewCellsManager->
459                GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
460          break;
461  }
462 
463  if (i!=tries) {
464        // $$ jb the pdf is yet not correct for all sampling methods!
465        const float pdf = 1.0f;
466       
467       
468        ray = SimpleRay(origin, direction, GLOBAL_LINES_DISTRIBUTION, pdf);
469        ray.mType = Ray::GLOBAL_RAY;
470        return true;
471  }
472 
473  return false;
474}
475
476
477  // has to called before first usage
478void
479MixtureDistribution::Init()
480{
481  for (int i=0; i < mDistributions.size(); i++) {
482        // small non-zero value
483        mDistributions[i]->mRays = 1;
484        mDistributions[i]->mGeneratedRays = 1;
485        // unit contribution per ray
486        if (1 || mDistributions[i]->mType != RSS_BASED_DISTRIBUTION)
487          mDistributions[i]->mContribution = 1.0f;
488        else
489          mDistributions[i]->mContribution = 0.0f;
490  }
491  UpdateRatios();
492}
493
494void
495MixtureDistribution::Reset()
496{
497  for (int i=0; i < mDistributions.size(); i++) {
498        // small non-zero value
499        mDistributions[i]->mTotalRays = 0;
500        // unit contribution per ray
501        mDistributions[i]->mTotalContribution = 0.0f;
502  }
503  UpdateRatios();
504}
505
506// Generate a new sample according to a mixture distribution
507bool
508MixtureDistribution::GenerateSample(SimpleRay &ray)
509{
510  float r;
511  sHalton.GetNext(1, &r);
512  int i;
513  // pickup a distribution
514  for (i=0; i < mDistributions.size()-1; i++)
515        if (r < mDistributions[i]->mRatio)
516          break;
517
518  bool result = mDistributions[i]->GenerateSample(ray);
519
520  if (result)
521        mDistributions[i]->mGeneratedRays++;
522 
523  return result;
524}
525
526  // add contributions of the sample to the strategies
527void
528MixtureDistribution::ComputeContributions(VssRayContainer &vssRays)
529{
530  int i;
531 
532  VssRayContainer::iterator it = vssRays.begin();
533
534  for (i=0; i < mDistributions.size(); i++) {
535        mDistributions[i]->mContribution = 0;
536        mDistributions[i]->mRays = 0;
537  }
538
539  for(; it != vssRays.end(); ++it) {
540        VssRay *ray = *it;
541        for (i=0; i < mDistributions.size()-1; i++) {
542          if (mDistributions[i]->mType == ray->mDistribution)
543                break;
544        }
545 
546        float contribution =
547          mPreprocessor.mViewCellsManager->ComputeSampleContribution(*ray,
548                                                                                                                                 true,
549                                                                                                                                 false);
550
551        mDistributions[i]->mContribution += contribution;
552        mDistributions[i]->mRays ++;
553       
554        mDistributions[i]->mTotalContribution += contribution;
555        mDistributions[i]->mTotalRays ++;
556  }
557
558 
559  UpdateRatios();
560
561}
562
563void
564MixtureDistribution::UpdateDistributions(VssRayContainer &vssRays)
565{
566  // now update the distributions with all the rays
567  for (int i=0; i < mDistributions.size(); i++) {
568        mDistributions[i]->Update(vssRays);
569  }
570}
571
572#define RAY_CAST_TIME 0.7f
573#define VIEWCELL_CAST_TIME 0.3f
574
575void
576MixtureDistribution::UpdateRatios()
577{
578  // now compute importance (ratio) of all distributions
579  float sum = 0.0f;
580  int i;
581  for (i=0; i < mDistributions.size(); i++) {
582        cout<<i<<": c="<<mDistributions[i]->mContribution<<
583          " rays="<<mDistributions[i]->mRays<<endl;
584        float importance = 0.0f;
585        if (mDistributions[i]->mRays != 0) {
586          //importance = pow(mDistributions[i]->mContribution/mDistributions[i]->mRays, 2);
587          importance = mDistributions[i]->mContribution/
588                (RAY_CAST_TIME*mDistributions[i]->mGeneratedRays +
589                 VIEWCELL_CAST_TIME*mDistributions[i]->mRays);
590        }
591        mDistributions[i]->mRatio = importance;
592        sum += importance;
593  }
594
595  if (sum == 0.0f)
596        sum = Limits::Small;
597 
598  const float minratio = 0.01f;
599 
600  for (i=0; i < mDistributions.size(); i++) {
601        mDistributions[i]->mRatio /= sum;
602        if (mDistributions[i]->mRatio < minratio)
603          mDistributions[i]->mRatio = minratio;
604  }
605
606  // recaluate the sum after clip
607  sum = 0.0f;
608  for (i=0; i < mDistributions.size(); i++)
609        sum += mDistributions[i]->mRatio;
610
611  for (i=0; i < mDistributions.size(); i++)
612        mDistributions[i]->mRatio /= sum;
613 
614  for (i=1; i < mDistributions.size(); i++) {
615        mDistributions[i]->mRatio = mDistributions[i-1]->mRatio + mDistributions[i]->mRatio;
616  }
617 
618  cout<<"ratios: ";
619  float last = 0.0f;
620  for (i=0; i < mDistributions.size(); i++) {
621        cout<<mDistributions[i]->mRatio-last<<" ";
622        last = mDistributions[i]->mRatio;
623  }
624  cout<<endl;
625}
626
627
628
629bool
630MixtureDistribution::Construct(char *str)
631{
632  char *curr = str;
633
634  while (1) {
635        char *e = strchr(curr,'+');
636        if (e!=NULL) {
637          *e=0;
638        }
639       
640        if (strcmp(curr, "rss")==0) {
641          mDistributions.push_back(new RssBasedDistribution(mPreprocessor));
642        } else
643          if (strcmp(curr, "object")==0) {
644                mDistributions.push_back(new ObjectBasedDistribution(mPreprocessor));
645          } else
646                if (strcmp(curr, "spatial")==0) {
647                  mDistributions.push_back(new SpatialBoxBasedDistribution(mPreprocessor));
648                } else
649                  if (strcmp(curr, "global")==0) {
650                        mDistributions.push_back(new GlobalLinesDistribution(mPreprocessor));
651                  } else
652                        if (strcmp(curr, "direction")==0) {
653                          mDistributions.push_back(new DirectionBasedDistribution(mPreprocessor));
654                        } else
655                          if (strcmp(curr, "object_direction")==0) {
656                                mDistributions.push_back(new ObjectDirectionBasedDistribution(mPreprocessor));
657                          } else
658                                if (strcmp(curr, "reverse_object")==0) {
659                                  mDistributions.push_back(new ReverseObjectBasedDistribution(mPreprocessor));
660                                } else
661                                  if (strcmp(curr, "reverse_viewspace_border")==0) {
662                                        mDistributions.push_back(new ReverseViewSpaceBorderBasedDistribution(mPreprocessor));
663                                  } else
664                                        if (strcmp(curr, "mutation")==0) {
665                                          mDistributions.push_back(new MutationBasedDistribution(mPreprocessor));
666                                        }
667       
668       
669        if (e==NULL)
670          break;
671        curr = e+1;
672  }
673
674  Init();
675  return true;
676}
677
678int
679MixtureDistribution::GenerateSamples(const int number,
680                                                                         SimpleRayContainer &rays)
681{
682  for (int i=0; i < mDistributions.size(); i++)
683        mDistributions[i]->mGeneratedRays = 0;
684
685  return SamplingStrategy::GenerateSamples(number, rays);
686}
687
688void
689MutationBasedDistribution::Update(VssRayContainer &vssRays)
690{
691  //  for (int i=0; i < mRays.size(); i++)
692  //    cout<<mRays[i].mSamples<<" ";
693  //  cout<<endl;
694  cerr<<"Muattion update..."<<endl;
695  cerr<<"rays = "<<mRays.size()<<endl;
696  if (mRays.size()) {
697        cerr<<"Oversampling factors = "<<
698          GetEntry(0).mSamples<<" "<<
699          GetEntry(1).mSamples<<" "<<
700          GetEntry(2).mSamples<<" "<<
701          GetEntry(3).mSamples<<" "<<
702          GetEntry(4).mSamples<<" "<<
703          GetEntry(5).mSamples<<" ... "<<
704          GetEntry(mRays.size()-6).mSamples<<" "<<
705          GetEntry(mRays.size()-5).mSamples<<" "<<
706          GetEntry(mRays.size()-4).mSamples<<" "<<
707          GetEntry(mRays.size()-3).mSamples<<" "<<
708          GetEntry(mRays.size()-2).mSamples<<" "<<
709          GetEntry(mRays.size()-1).mSamples<<endl;
710  }
711  int contributingRays = 0;
712  for (int i=0; i < vssRays.size(); i++) {
713        if (vssRays[i]->mPvsContribution) {
714          contributingRays++;
715          if (mRays.size() < mMaxRays) {
716                VssRay *newRay = new VssRay(*vssRays[i]);
717                // add this ray
718                newRay->Ref();
719                mRays.push_back(RayEntry(newRay));
720          } else {
721                // unref the old ray
722                *mRays[mBufferStart].mRay = *vssRays[i];
723                mRays[mBufferStart].mSamples = 0;
724                //              mRays[mBufferStart] = RayEntry(newRay);
725                mBufferStart++;
726                if (mBufferStart >= mMaxRays)
727                  mBufferStart = 0;
728          }
729        }
730  }
731 
732  float pContributingRays = contributingRays/(float)vssRays.size();
733  float importance = sqr(1.0f/(pContributingRays + 1e-5));
734  // set this values for last contributingRays
735  int index = mBufferStart - 1;
736 
737  for (int i=0; i < contributingRays; i++, index--) {
738        if (index < 0)
739          index = mRays.size()-1;
740        mRays[index].mImportance = importance;
741  }
742
743#if MUTATION_USE_CDF
744  // compute cdf
745  mRays[0].mCdf = mRays[0].mImportance/(mRays[0].mSamples+1);
746  for (int i=1; i < mRays.size(); i++)
747        mRays[i].mCdf = mRays[i-1].mCdf + mRays[i].mImportance/(mRays[i].mSamples+1);
748 
749  float scale = 1.0f/mRays[i-1].mCdf;
750  for (i=0; i < mRays.size(); i++) {
751        mRays[i].mCdf *= scale;
752  }
753#endif
754 
755  cout<<"Importance = "<<
756        GetEntry(0).mImportance<<" "<<
757        GetEntry(mRays.size()-1).mImportance<<endl;
758 
759  cerr<<"Mutation update done."<<endl;
760}
761
762
763Vector3
764MutationBasedDistribution::ComputeOriginMutation(const VssRay &ray,
765                                                                                                 const Vector3 &U,
766                                                                                                 const Vector3 &V,
767                                                                                                 const Vector2 vr2,
768                                                                                                 const float radius
769                                                                                                 )
770{
771#if 0
772  Vector3 v;
773  if (d.DrivingAxis() == 0)
774        v = Vector3(0, r[0]-0.5f, r[1]-0.5f);
775  else
776        if (d.DrivingAxis() == 1)
777          v = Vector3(r[0]-0.5f, 0, r[1]-0.5f);
778        else
779          v = Vector3(r[0]-0.5f, r[1]-0.5f, 0);
780  return v*(2*radius);
781#endif
782#if 0
783  return (U*(r[0] - 0.5f) + V*(r[1] - 0.5f))*(2*radius);
784#endif
785
786
787  // Output random variable
788  Vector2 gaussvec2;
789 
790  // Here we apply transform to gaussian, so 2D bivariate
791  // normal distribution
792  //  float sigma = ComputeSigmaFromRadius(radius);
793  float sigma = radius;
794  GaussianOn2D(vr2,
795                           sigma, // input
796                           gaussvec2);  // output
797
798       
799    // Here we tranform the point correctly to 3D space using base
800    // vectors of the 3D space defined by the direction
801    Vector3 shift = gaussvec2.xx * U + gaussvec2.yy * V;
802       
803        //      cout<<shift<<endl;
804        return shift;
805}
806
807Vector3
808MutationBasedDistribution::ComputeTerminationMutation(const VssRay &ray,
809                                                                                                          const Vector3 &U,
810                                                                                                          const Vector3 &V,
811                                                                                                          const Vector2 vr2,
812                                                                                                          const float radius
813                                                                                                          )
814{
815#if 0
816  Vector3 v;
817  // mutate the termination
818  if (d.DrivingAxis() == 0)
819        v = Vector3(0, r[2]-0.5f, r[3]-0.5f);
820  else
821        if (d.DrivingAxis() == 1)
822          v = Vector3(r[2]-0.5f, 0, r[3]-0.5f);
823        else
824          v = Vector3(r[2]-0.5f, r[3]-0.5f, 0);
825 
826  //   Vector3 nv;
827 
828  //   if (Magnitude(v) > Limits::Small)
829  //    nv = Normalize(v);
830  //   else
831  //    nv = v;
832 
833  //  v = nv*size + v*size;
834
835  return v*(4.0f*radius);
836#endif
837#if 0
838  return (U*(vr2.xx - 0.5f) + V*(vr2.yy - 0.5f))*(4.0f*radius);
839#endif
840  Vector2 gaussvec2;
841#if 1
842  float sigma = radius;
843  GaussianOn2D(vr2,
844                           sigma, // input
845                           gaussvec2);  // output
846  Vector3 shift = gaussvec2.xx * U + gaussvec2.yy * V;
847  //    cout<<shift<<endl;
848  return shift;
849#endif
850#if 0
851  // Here we estimate standard deviation (sigma) from radius
852  float sigma = 1.1f*ComputeSigmaFromRadius(radius);
853  Vector3 vr3(vr2.xx, vr2.yy, RandomValue(0,1));
854  PolarGaussianOnDisk(vr3,
855                                          sigma,
856                                          radius, // input
857                                          gaussvec2); // output
858 
859  // Here we tranform the point correctly to 3D space using base
860  // vectors of the 3D space defined by the direction
861  Vector3 shift = gaussvec2.xx * U + gaussvec2.yy * V;
862 
863  //    cout<<shift<<endl;
864  return shift;
865#endif
866}
867
868
869bool
870MutationBasedDistribution::GenerateSample(SimpleRay &sray)
871{
872  float rr[5];
873
874  if (mRays.size() == 0) {
875        // use direction based distribution
876        Vector3 origin, direction;
877        static HaltonSequence halton;
878       
879        halton.GetNext(5, rr);
880        mPreprocessor.mViewCellsManager->GetViewPoint(origin,
881                                                                                                  Vector3(rr[0], rr[1], rr[2]));
882       
883
884        direction = UniformRandomVector(rr[3], rr[4]);
885       
886        const float pdf = 1.0f;
887        sray = SimpleRay(origin, direction, MUTATION_BASED_DISTRIBUTION, pdf);
888
889        return true;
890  }
891
892  int index;
893
894#if !MUTATION_USE_CDF
895  // get tail of the buffer
896  index = (mLastIndex+1)%mRays.size();
897  if (mRays[index].GetSamplingFactor() >
898          mRays[mLastIndex].GetSamplingFactor()) {
899        // search back for index where this is valid
900        index = (mLastIndex - 1 + mRays.size())%mRays.size();
901        for (int i=0; i < mRays.size(); i++) {
902         
903          //      if (mRays[index].mSamples > mRays[mLastIndex].mSamples)
904          //            break;
905          if (mRays[index].GetSamplingFactor() >
906                  mRays[mLastIndex].GetSamplingFactor() )
907                break;
908          index = (index - 1 + mRays.size())%mRays.size();
909        }
910        // go one step back
911        index = (index+1)%mRays.size();
912  }
913#else
914  static HaltonSequence iHalton;
915  iHalton.GetNext(1, rr);
916  //rr[0] = RandomValue(0,1);
917  // use binary search to find index with this cdf
918  int l=0, r=mRays.size()-1;
919  while(l<r) {
920        int i = (l+r)/2;
921        if (rr[0] < mRays[i].mCdf )
922          r = i;
923        else
924          l = i+1;
925  }
926  index = l;
927  //  if (rr[0] >= mRays[r].mCdf)
928  //    index = r;
929  //  else
930  //    index = l;
931       
932       
933#endif
934  //  cout<<index<<" "<<rr[0]<<" "<<mRays[index].mCdf<<" "<<mRays[(index+1)%mRays.size()].mCdf<<endl;
935 
936  VssRay *ray = mRays[index].mRay;
937  mRays[index].mSamples++;
938  mLastIndex = index;
939
940  mRays[index].mHalton.GetNext(4, rr);
941
942  // mutate the origin
943  Vector3 d = ray->GetDir();
944
945
946  AxisAlignedBox3 box = ray->mTerminationObject->GetBox();
947  float objectRadius = 0.5f*Magnitude(box.Diagonal());
948  //  cout<<objectRadius<<endl;
949  if (objectRadius < Limits::Small)
950        return false;
951 
952  // Compute right handed coordinate system from direction
953  Vector3 U, V;
954  Vector3 nd = Normalize(d);
955  nd.RightHandedBase(U, V);
956
957  Vector3 origin = ray->mOrigin;
958  Vector3 termination = ray->mTermination; //box.Center(); //ray->mTermination; //box.Center();
959
960  float radiusExtension = 1.0f;
961  //  + mRays[index].mSamples/50.0f;
962 
963  //  origin += ComputeOriginMutation(*ray, U, V, Vector2(r[0], r[1]), 0.5f*mOriginMutationSize*radiusExtension);
964  origin += ComputeOriginMutation(*ray, U, V,
965                                                                  Vector2(rr[0], rr[1]),
966                                                                  objectRadius*radiusExtension);
967  termination += ComputeTerminationMutation(*ray, U, V,
968                                                                                        Vector2(rr[2], rr[3]),
969                                                                                        objectRadius*radiusExtension);
970 
971  Vector3 direction = termination - origin;
972 
973  if (Magnitude(direction) < Limits::Small)
974        return false;
975 
976  // shift the origin a little bit
977  origin += direction*0.5f;
978 
979  direction.Normalize();
980 
981  // $$ jb the pdf is yet not correct for all sampling methods!
982  const float pdf = 1.0f;
983 
984  sray = SimpleRay(origin, direction, MUTATION_BASED_DISTRIBUTION, pdf);
985  return true;
986}
987
988MutationBasedDistribution::MutationBasedDistribution(Preprocessor &preprocessor
989                                                                                                         ) :
990  SamplingStrategy(preprocessor)
991{
992  mType = MUTATION_BASED_DISTRIBUTION;
993  mBufferStart = 0;
994  mMaxRays = 500000;
995  mRays.reserve(mMaxRays);
996  mOriginMutationSize = 10.0f;
997  mLastIndex = 0;
998  //  mOriginMutationSize = Magnitude(preprocessor.mViewCellsManager->
999  //                                                              GetViewSpaceBox().Diagonal())*1e-3;
1000 
1001}
1002
1003
1004bool HwGlobalLinesDistribution::GenerateSample(SimpleRay &ray)
1005{
1006        Vector3 origin, termination, direction;
1007
1008        float radius = 0.5f *
1009                Magnitude(mPreprocessor.mViewCellsManager->GetViewSpaceBox().Size());
1010
1011        Vector3 center = mPreprocessor.mViewCellsManager->GetViewSpaceBox().Center();
1012
1013        const int tries = 1000;
1014        int i;
1015        for (i=0; i < tries; i++)
1016        {
1017                float r[2];
1018                sHalton.GetNext(2, r);
1019
1020                origin = center + (radius * UniformRandomVector(r[0], r[1]));
1021                termination = center;
1022               
1023                if (0)
1024                {
1025                        // add a small offset to provide some more randomness in the sampling
1026                        Vector3 offset(Random(radius * 1e-3f),
1027                                                   Random(radius * 1e-3f),
1028                                                   Random(radius * 1e-3f));
1029                        termination += offset;
1030                }
1031
1032                direction = termination - origin;
1033
1034                // $$ jb the pdf is yet not correct for all sampling methods!
1035                const float c = Magnitude(direction);
1036
1037                if (c <= Limits::Small)
1038                        return false;
1039
1040                direction *= 1.0f / c;
1041
1042                // check if the ray intersects the view space box
1043                static Ray ray;
1044                ray.Init(origin, direction, Ray::LOCAL_RAY);   
1045
1046                float tmin, tmax;
1047                if (mPreprocessor.mViewCellsManager->
1048                        GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
1049                        break;
1050        }
1051
1052        if (i != tries)
1053        {
1054                // $$ jb the pdf is yet not correct for all sampling methods!
1055                const float pdf = 1.0f;
1056
1057                ray = SimpleRay(origin, direction, HW_GLOBAL_LINES_DISTRIBUTION, pdf);
1058                ray.mType = Ray::GLOBAL_RAY;
1059                return true;
1060        }
1061
1062        return false;
1063}
1064
1065
1066}
1067
1068
Note: See TracBrowser for help on using the repository browser.