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

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