#include "SamplingStrategy.h" #include "Ray.h" #include "Intersectable.h" #include "Preprocessor.h" #include "ViewCellsManager.h" #include "AxisAlignedBox3.h" namespace GtpVisibilityPreprocessor { SamplingStrategy::SamplingStrategy(const Preprocessor &preprocessor): mPreprocessor(preprocessor), mRatio(1.0f) { } SamplingStrategy::~SamplingStrategy() { } int SamplingStrategy::GenerateSamples(const int number, SimpleRayContainer &rays) const { SimpleRay ray; int samples = 0; int i = 0; const int maxTries = 20; // tmp changed matt. Q: should one rejected sample // terminate the whole method? if (0) { for (; i < number; i++) { if (!GenerateSample(ray)) return i; rays.push_back(ray); } } else { for (; i < number; i++) { int j = 0; bool sampleGenerated = false; for (j = 0; !sampleGenerated && (j < maxTries); ++ j) { sampleGenerated = GenerateSample(ray); if (sampleGenerated) { ++ samples; rays.push_back(ray); } } } } return samples; } /*********************************************************************/ /* Individual sampling strategies implementation */ /*********************************************************************/ bool ObjectBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; mPreprocessor.mViewCellsManager->GetViewPoint(origin); Vector3 point; Vector3 normal; //cout << "y"; const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[i]; object->GetRandomSurfacePoint(point, normal); direction = point - origin; // $$ jb the pdf is yet not correct for all sampling methods! const float c = Magnitude(direction); if (c <= Limits::Small) return false; // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } bool ObjectDirectionBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; const int i = (int)RandomValue(0, (Real)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[i]; Vector3 normal; //cout << "x"; object->GetRandomSurfacePoint(origin, normal); direction = UniformRandomVector(normal); origin += 0.1f * direction; const float c = Magnitude(direction); if (c <= Limits::Small) return false; // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } bool DirectionBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; mPreprocessor.mViewCellsManager->GetViewPoint(origin); direction = UniformRandomVector(); const float c = Magnitude(direction); if (c <= Limits::Small) return false; const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } bool DirectionBoxBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; mPreprocessor.mViewCellsManager->GetViewPoint(origin); const float alpha = RandomValue(0.0f, 2.0f * (float)M_PI); const float beta = RandomValue((float)-M_PI * 0.5f, (float)M_PI * 0.5f); direction = VssRay::GetDirection(alpha, beta); const float c = Magnitude(direction); if (c <= Limits::Small) return false; const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } bool SpatialBoxBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; mPreprocessor.mViewCellsManager->GetViewPoint(origin); direction = mPreprocessor.mKdTree->GetBox().GetRandomPoint() - origin; //cout << "z"; const float c = Magnitude(direction); if (c <= Limits::Small) return false; const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } bool ReverseObjectBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; mPreprocessor.mViewCellsManager->GetViewPoint(origin); Vector3 point; Vector3 normal; //cout << "y"; const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[i]; object->GetRandomSurfacePoint(point, normal); direction = origin - point; // $$ jb the pdf is yet not correct for all sampling methods! const float c = Magnitude(direction); if ((c <= Limits::Small) || (DotProd(direction, normal) < 0)) { return false; } // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; //cout << "p: " << point << " "; direction *= 1.0f / c; // a little offset point += direction * 0.001f; ray = SimpleRay(point, direction, pdf); return true; } bool ViewCellBorderBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; ViewCellContainer &viewCells = mPreprocessor.mViewCellsManager->GetViewCells(); Vector3 point; Vector3 normal, normal2; const int vcIdx = (int)RandomValue(0, (float)viewCells.size() - 0.5f); const int objIdx = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[objIdx]; ViewCell *viewCell = viewCells[vcIdx]; //cout << "vc: " << vcIdx << endl; //cout << "obj: " << objIdx << endl; object->GetRandomSurfacePoint(point, normal); viewCell->GetRandomEdgePoint(origin, normal2); direction = point - origin; // $$ jb the pdf is yet not correct for all sampling methods! const float c = Magnitude(direction); if ((c <= Limits::Small) /*|| (DotProd(direction, normal) < 0)*/) { return false; } // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; //cout << "p: " << point << " "; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); //cout << "ray: " << ray.mOrigin << " " << ray.mDirection << endl; return true; } #if 0 bool ObjectsInteriorDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; // get random object const int i = RandomValue(0, mPreprocessor.mObjects.size() - 1); const Intersectable *obj = mPreprocessor.mObjects[i]; // note: if we load the polygons as meshes, // asymtotically every second sample is lost! origin = obj->GetBox().GetRandomPoint(); // uniformly distributed direction direction = UniformRandomVector(); const float c = Magnitude(direction); if (c <= Limits::Small) return false; const float pdf = 1.0f; direction *= 1.0f / c; ray = SimpleRay(origin, direction, pdf); return true; } #endif bool ReverseViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint(); Vector3 point; Vector3 normal; //cout << "y"; const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[i]; object->GetRandomSurfacePoint(point, normal); direction = origin - point; // $$ jb the pdf is yet not correct for all sampling methods! const float c = Magnitude(direction); if ((c <= Limits::Small) || (DotProd(direction, normal) < 0)) { return false; } // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; //cout << "p: " << point << " "; direction *= 1.0f / c; // a little offset point += direction * 0.001f; ray = SimpleRay(point, direction, pdf); return true; } bool ViewSpaceBorderBasedDistribution::GenerateSample(SimpleRay &ray) const { Vector3 origin, direction; origin = mPreprocessor.mViewCellsManager->GetViewSpaceBox().GetRandomSurfacePoint(); Vector3 point; Vector3 normal; //cout << "w"; const int i = (int)RandomValue(0, (float)mPreprocessor.mObjects.size() - 0.5f); Intersectable *object = mPreprocessor.mObjects[i]; object->GetRandomSurfacePoint(point, normal); direction = point - origin; // $$ jb the pdf is yet not correct for all sampling methods! const float c = Magnitude(direction); if (c <= Limits::Small) return false; // $$ jb the pdf is yet not correct for all sampling methods! const float pdf = 1.0f; direction *= 1.0f / c; // a little offset origin += direction * 0.001f; ray = SimpleRay(origin, direction, pdf); return true; } bool RssBasedDistribution::GenerateSample(SimpleRay &ray) const { return false; } }