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

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