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

Revision 1989, 17.8 KB checked in by bittner, 17 years ago (diff)

mutation updates

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