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

Revision 1942, 15.4 KB checked in by bittner, 17 years ago (diff)

tmp commit

RevLine 
[1020]1#include "SamplingStrategy.h"
2#include "Ray.h"
3#include "Intersectable.h"
4#include "Preprocessor.h"
5#include "ViewCellsManager.h"
6#include "AxisAlignedBox3.h"
[1891]7#include "RssTree.h"
[1020]8
9namespace GtpVisibilityPreprocessor {
10
11
[1901]12//HaltonSequence SamplingStrategy::sHalton;
13
[1899]14HaltonSequence ObjectBasedDistribution::sHalton;
15HaltonSequence MixtureDistribution::sHalton;
16HaltonSequence GlobalLinesDistribution::sHalton;
17HaltonSequence SpatialBoxBasedDistribution::sHalton;
18HaltonSequence ObjectDirectionBasedDistribution::sHalton;
19
20
[1884]21SamplingStrategy::SamplingStrategy(Preprocessor &preprocessor):
[1877]22  mPreprocessor(preprocessor), mRatio(1.0f),  mTotalRays(0), mTotalContribution(0.0f)
[1520]23{
[1877]24 
[1520]25}
26
27
28SamplingStrategy::~SamplingStrategy()
29{
30}
31
[1771]32int
33SamplingStrategy::GenerateSamples(const int number,
[1867]34                                                                  SimpleRayContainer &rays)
[1771]35{
[1772]36        SimpleRay ray;
37        int samples = 0;
38        int i = 0;
39        const int maxTries = 20;
40        // tmp changed matt. Q: should one rejected sample
41        // terminate the whole method?
42        if (0)
43        {
44                for (; i < number; i++) {
45                        if (!GenerateSample(ray))
46                                return i;
47                        rays.push_back(ray);
48                }
49        }
50        else
51        {
52                for (; i < number; i++)
53                {
54                        int j = 0;
55                        bool sampleGenerated = false;
[1520]56
[1772]57                        for (j = 0; !sampleGenerated && (j < maxTries); ++ j)
58                        {
59                                sampleGenerated = GenerateSample(ray);
60
61                                if (sampleGenerated)
62                                {               
63                                        ++ samples;
64                                        rays.push_back(ray);
65                                }
66                        }
67                }
68        }
69       
70        return samples;
[1771]71}
[1520]72
[1771]73
[1020]74/*********************************************************************/
75/*            Individual sampling strategies implementation          */
76/*********************************************************************/
77
78
[1867]79bool ObjectBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]80{
[1883]81  Vector3 origin, direction;
82 
83  float r[5];
[1898]84  sHalton.GetNext(5, r);
[1883]85 
86  mPreprocessor.mViewCellsManager->GetViewPoint(origin,
87                                                                                                Vector3(r[2],r[3],r[4]));
88 
[1020]89
[1883]90  Vector3 point, normal;
91 
[1898]92  r[0] *= (float)mPreprocessor.mObjects.size() - 1;
[1883]93  const int i = (int)r[0];
94 
95  Intersectable *object = mPreprocessor.mObjects[i];
96 
97  // take the remainder as a parameter over objects surface
98  r[0] -= (float)i;
99 
100  object->GetRandomSurfacePoint(r[0], r[1], point, normal);
101 
102  direction = point - origin;
103 
104  const float c = Magnitude(direction);
105 
106  if (c <= Limits::Small)
107        return false;
108 
109  // $$ jb the pdf is yet not correct for all sampling methods!
110  const float pdf = 1.0f;
111 
112  direction *= 1.0f / c;
113  ray = SimpleRay(origin, direction, OBJECT_BASED_DISTRIBUTION, pdf);
114 
115  return true;
116}
[1020]117
118
[1883]119bool
120ObjectDirectionBasedDistribution::GenerateSample(SimpleRay &ray)
121{       
122  Vector3 origin, direction;
[1877]123
[1020]124
[1883]125  float r[4];
[1898]126  sHalton.GetNext(4, r);
[1877]127
[1901]128  r[0] *= (float)mPreprocessor.mObjects.size() - 1;
[1883]129  const int i = (int)r[0];
130 
131  Intersectable *object = mPreprocessor.mObjects[i];
132 
133  // take the remainder as a parameter over objects surface
134  r[0] -= (float)i;
[1020]135
[1883]136  Vector3 normal;
[1020]137
[1883]138  object->GetRandomSurfacePoint(r[0], r[1], origin, normal);
139 
140  direction = Normalize(CosineRandomVector(r[2], r[3], normal));
141 
[1899]142  origin += 1e-2f*direction;
[1883]143 
144  // $$ jb the pdf is yet not correct for all sampling methods!
145  const float pdf = 1.0f;
146 
147  ray = SimpleRay(origin, direction, OBJECT_DIRECTION_BASED_DISTRIBUTION, pdf);
148 
149  return true;
[1020]150}
151
152
[1867]153bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray)
[1278]154{       
[1020]155        Vector3 origin, direction;
156        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
157         
158        direction = UniformRandomVector();
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;
[1883]167        ray = SimpleRay(origin, direction, DIRECTION_BASED_DISTRIBUTION, pdf);
[1020]168
169        return true;
170}
171
172
[1867]173bool DirectionBoxBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]174{
175        Vector3 origin, direction;
176        mPreprocessor.mViewCellsManager->GetViewPoint(origin);
177
[1297]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);
[1020]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;
[1883]191        ray = SimpleRay(origin, direction, DIRECTION_BOX_BASED_DISTRIBUTION, pdf);
[1020]192
193        return true;
194}
195
196
[1867]197bool SpatialBoxBasedDistribution::GenerateSample(SimpleRay &ray)
[1020]198{
[1867]199  Vector3 origin, direction;
[1278]200
[1867]201  float r[6];
[1898]202  sHalton.GetNext(6, r);
[1867]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;
[1883]218  ray = SimpleRay(origin, direction, SPATIAL_BOX_BASED_DISTRIBUTION, pdf);
[1867]219 
220  return true;
[1020]221}
222
[1695]223
[1867]224bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray)
[1695]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);
[1765]238       
[1695]239        direction = origin - point;
[1765]240       
[1695]241        // $$ jb the pdf is yet not correct for all sampling methods!
242        const float c = Magnitude(direction);
[1765]243       
244        if ((c <= Limits::Small) || (DotProd(direction, normal) < 0))
245        {
[1695]246                return false;
[1765]247        }
[1695]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;
[1765]253        // a little offset
[1772]254        point += direction * 0.001f;
[1765]255
[1883]256        ray = SimpleRay(point, direction, REVERSE_OBJECT_BASED_DISTRIBUTION, pdf);
[1695]257       
258        return true;
259}
260
[1763]261
[1867]262bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1763]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
[1769]277        //cout << "vc: " << vcIdx << endl;
278        //cout << "obj: " << objIdx << endl;
279
[1763]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
[1769]288        if ((c <= Limits::Small) /*|| (DotProd(direction, normal) < 0)*/)
[1768]289        {
[1763]290                return false;
[1768]291        }
[1763]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;
[1883]297        ray = SimpleRay(origin, direction, VIEWCELL_BORDER_BASED_DISTRIBUTION, pdf);
[1769]298
299        //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl;
300
[1763]301        return true;
302}
303
[1765]304
[1520]305#if 0
[1867]306bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray)
[1020]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;
[1520]333}
[1769]334
[1520]335#endif
[1771]336
[1772]337
[1867]338bool ReverseViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1772]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
[1883]370        ray = SimpleRay(point, direction, REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
[1772]371       
372        return true;
373}
374
375
[1867]376bool ViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray)
[1772]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
[1883]406        ray = SimpleRay(origin, direction, VIEWSPACE_BORDER_BASED_DISTRIBUTION, pdf);
[1772]407
408        return true;
409}
410
411
[1771]412
[1824]413
414bool
[1867]415GlobalLinesDistribution::GenerateSample(SimpleRay &ray)
[1824]416{
[1867]417  Vector3 origin, termination, direction;
[1824]418
[1867]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];
[1898]426        sHalton.GetNext(4, r);
[1824]427       
[1867]428        origin = center + (radius*UniformRandomVector(r[0], r[1]));
429        termination = center + (radius*UniformRandomVector(r[2], r[3]));
430       
[1824]431        direction = termination - origin;
[1867]432       
433       
[1824]434        // $$ jb the pdf is yet not correct for all sampling methods!
435        const float c = Magnitude(direction);
436        if (c <= Limits::Small)
[1867]437          return false;
[1824]438       
439        direction *= 1.0f / c;
[1867]440
441        // check if the ray intersects the view space box
442        static Ray ray;
443        ray.Init(origin, direction, Ray::LOCAL_RAY);   
[1824]444       
[1867]445        float tmin, tmax;
446        if (mPreprocessor.mViewCellsManager->
447                GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
448          break;
449  }
450 
451  if (i!=tries) {
[1824]452        // $$ jb the pdf is yet not correct for all sampling methods!
453        const float pdf = 1.0f;
[1867]454       
455       
[1883]456        ray = SimpleRay(origin, direction, GLOBAL_LINES_DISTRIBUTION, pdf);
[1824]457        ray.mType = Ray::GLOBAL_RAY;
458        return true;
[1867]459  }
460 
461  return false;
[1771]462}
463
[1883]464
465  // has to called before first usage
466void
467MixtureDistribution::Init()
468{
[1884]469  for (int i=0; i < mDistributions.size(); i++) {
470        // small non-zero value
471        mDistributions[i]->mRays = 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();
[1824]479}
[1884]480
481void
482MixtureDistribution::Reset()
483{
484  for (int i=0; i < mDistributions.size(); i++) {
485        // small non-zero value
[1891]486        mDistributions[i]->mTotalRays = 0;
[1884]487        // unit contribution per ray
[1891]488        mDistributions[i]->mTotalContribution = 0.0f;
[1884]489  }
490  UpdateRatios();
491}
492
493// Generate a new sample according to a mixture distribution
[1883]494bool
495MixtureDistribution::GenerateSample(SimpleRay &ray)
496{
[1884]497  float r;
[1898]498  sHalton.GetNext(1, &r);
[1900]499  int i;
[1884]500  // pickup a distribution
[1900]501  for (i=0; i < mDistributions.size()-1; i++)
[1884]502        if (r < mDistributions[i]->mRatio)
503          break;
[1891]504
[1884]505  return mDistributions[i]->GenerateSample(ray);
[1883]506}
[1824]507
[1883]508  // add contributions of the sample to the strategies
509void
[1884]510MixtureDistribution::ComputeContributions(VssRayContainer &vssRays)
[1883]511{
[1884]512  int i;
513 
514  VssRayContainer::iterator it = vssRays.begin();
[1883]515
[1891]516  for (i=0; i < mDistributions.size(); i++) {
517        mDistributions[i]->mContribution = 0;
518        mDistributions[i]->mRays = 0;
519  }
520
[1884]521  for(; it != vssRays.end(); ++it) {
522        VssRay *ray = *it;
[1891]523        for (i=0; i < mDistributions.size()-1; i++) {
[1884]524          if (mDistributions[i]->mType == ray->mDistribution)
525                break;
[1891]526        }
527 
[1884]528        float contribution =
[1942]529          mPreprocessor.mViewCellsManager->ComputeSampleContribution(*ray,
530                                                                                                                                 true,
531                                                                                                                                 false);
[1931]532
[1888]533        mDistributions[i]->mContribution += contribution;
[1884]534        mDistributions[i]->mRays ++;
[1900]535       
[1891]536        mDistributions[i]->mTotalContribution += contribution;
537        mDistributions[i]->mTotalRays ++;
[1884]538  }
539
540 
541  UpdateRatios();
[1883]542}
543
[1884]544void
[1942]545MixtureDistribution::UpdateDistributions(VssRayContainer &vssRays)
546{
547  // now update the distributions with all the rays
548  for (int i=0; i < mDistributions.size(); i++) {
549        mDistributions[i]->Update(vssRays);
550  }
551}
552 
553void
[1884]554MixtureDistribution::UpdateRatios()
555{
556  // now compute importance (ratio) of all distributions
557  float sum = 0.0f;
558  int i;
559  for (i=0; i < mDistributions.size(); i++) {
[1891]560        cout<<i<<": c="<<mDistributions[i]->mContribution<<
561          " rays="<<mDistributions[i]->mRays<<endl;
562        float importance = 0.0f;
563        if (mDistributions[i]->mRays != 0) {
[1900]564          //      importance = pow(mDistributions[i]->mContribution/mDistributions[i]->mRays, 3);
565          importance = mDistributions[i]->mContribution/mDistributions[i]->mRays;
[1891]566        }
[1884]567        mDistributions[i]->mRatio = importance;
568        sum += importance;
569  }
[1891]570
[1900]571  const float minratio = 0.02f;
[1891]572  float threshold = minratio*sum;
573  for (i=0; i < mDistributions.size(); i++) {
574        if (mDistributions[i]->mRatio < threshold) {
575          sum += threshold - mDistributions[i]->mRatio;
576          mDistributions[i]->mRatio = threshold;
577        }
578  }
[1884]579 
580  mDistributions[0]->mRatio /= sum;
[1891]581       
[1884]582  for (i=1; i < mDistributions.size(); i++) {
583        float r = mDistributions[i]->mRatio / sum;
584        mDistributions[i]->mRatio = mDistributions[i-1]->mRatio + r;
585  }
586 
587  cout<<"ratios: ";
[1931]588  float last = 0.0f;
589  for (i=0; i < mDistributions.size(); i++) {
590        cout<<mDistributions[i]->mRatio-last<<" ";
591        last = mDistributions[i]->mRatio;
592  }
[1884]593  cout<<endl;
[1883]594}
[1891]595
596
597
598bool
599MixtureDistribution::Construct(char *str)
600{
601  char *curr = str;
602
603  while (1) {
604        char *e = strchr(curr,'+');
605        if (e!=NULL) {
606          *e=0;
607        }
608       
609        if (strcmp(curr, "rss")==0) {
610          mDistributions.push_back(new RssBasedDistribution(mPreprocessor));
611        } else
612          if (strcmp(curr, "object")==0) {
613                mDistributions.push_back(new ObjectBasedDistribution(mPreprocessor));
614          } else
615                if (strcmp(curr, "spatial")==0) {
616                  mDistributions.push_back(new SpatialBoxBasedDistribution(mPreprocessor));
617                } else
618                  if (strcmp(curr, "global")==0) {
619                        mDistributions.push_back(new GlobalLinesDistribution(mPreprocessor));
620                  } else
621                        if (strcmp(curr, "direction")==0) {
622                          mDistributions.push_back(new DirectionBasedDistribution(mPreprocessor));
623                        } else
624                          if (strcmp(curr, "object_direction")==0) {
625                                mDistributions.push_back(new ObjectDirectionBasedDistribution(mPreprocessor));
626                          } else
627                                if (strcmp(curr, "reverse_object")==0) {
628                                  mDistributions.push_back(new ReverseObjectBasedDistribution(mPreprocessor));
629                                } else
630                                  if (strcmp(curr, "reverse_viewspace_border")==0) {
631                                        mDistributions.push_back(new ReverseViewSpaceBorderBasedDistribution(mPreprocessor));
632                                  }
633       
634        if (e==NULL)
635          break;
636        curr = e+1;
637  }
638
639  Init();
640  return true;
[1884]641}
[1883]642
[1891]643}
[1883]644
[1891]645
Note: See TracBrowser for help on using the repository browser.