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

Revision 1974, 26.1 KB checked in by bittner, 17 years ago (diff)

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