#include "Environment.h" #include "GvsPreprocessor.h" #include "GlRenderer.h" #include "VssRay.h" #include "ViewCellsManager.h" #include "Triangle3.h" #include "IntersectableWrapper.h" namespace GtpVisibilityPreprocessor { GvsPreprocessor::GvsPreprocessor(): Preprocessor(), mSamplingType(0) { Environment::GetSingleton()->GetIntValue("GvsPreprocessor.totalSamples", mTotalSamples); Environment::GetSingleton()->GetIntValue("GvsPreprocessor.initialSamples", mInitialSamples); Environment::GetSingleton()->GetIntValue("GvsPreprocessor.samplesPerPass", mSamplesPerPass); Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.epsilon", mEps); Debug << "Gvs preprocessor options" << endl; Debug << "number of total samples: " << mTotalSamples << endl; Debug << "number of initial samples: " << mInitialSamples << endl; Debug << "number of samples per pass: " << mSamplesPerPass << endl; mStats.open("gvspreprocessor.log"); } const bool GvsPreprocessor::DiscontinuityFound(const VssRay &ray, const VssRay &oldRay) const { //const Plane3 plane = tri->GetPlane(); return false; } int GvsPreprocessor::HandleRay(const GvsRayInfo &gvsRay) { VssRay *ray = gvsRay.mRay; if (!mViewCellsManager->ComputeSampleContribution(*ray, true, false)) return 1; if (gvsRay.mFoundDiscontinuity) { return ReverseSampling(*ray); } else { return AdaptiveBorderSampling(*ray); } } /** Hepler function for adaptive border sampling. It finds new sample points around a triangle in a eps environment */ static void CreateNewSamples(VertexContainer &samples, const Triangle3 &hitTriangle, const VssRay &ray, const int index, const float eps) { const int indexU = (index + 1) % 3; const int indexL = (index == 0) ? 2 : index - 1; const Vector3 a = hitTriangle.mVertices[index] - ray.GetDir(); const Vector3 b = hitTriangle.mVertices[indexU] - hitTriangle.mVertices[index]; const Vector3 c = hitTriangle.mVertices[index] - hitTriangle.mVertices[indexL]; const float len = Magnitude(a); // compute the new three hit points // pi, i + 1 const Vector3 dir1 = CrossProd(a, b); //N((pi-xp)×(pi+1- pi)); const Vector3 pt1 = hitTriangle.mVertices[index] + eps * len * dir1; //pi+ e·|pi-xp|·di, j samples.push_back(pt1); // pi, i - 1 const Vector3 dir2 = CrossProd(a, c); // N((pi-xp)×(pi- pi-1)) const Vector3 pt2 = hitTriangle.mVertices[index] + eps * len * dir2; //pi+ e·|pi-xp|·di, j samples.push_back(pt2); // pi, i const Vector3 dir3 = DotProd(dir1, dir2) > 0 ? Normalize(dir2 + dir1) : Normalize(CrossProd(a, dir2) + CrossProd(dir1, a)); // N((pi-xp)×di,i-1+di,i+1×(pi-xp)) const Vector3 pt3 = hitTriangle.mVertices[index] + eps * len * dir3; //pi+ e·|pi-xp|·di, j samples.push_back(pt3); } /** Generate rays from sample points. */ static void CreateRays(VssRayContainer &rays, const VertexContainer &samples) { VertexContainer::const_iterator vit, vit_end = samples.end(); for (vit = samples.begin(); vit != vit_end; ++ vit) { const Vector3 currentSample = *vit; VssRay *ray;// = new VssRay(ray->mOrigin, currentSample); } } int GvsPreprocessor::AdaptiveBorderSampling(const VssRay &prevRay) { cout << "a"; Intersectable *tObj = prevRay.mTerminationObject; Triangle3 hitTriangle; // other types not implemented yet if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE) { hitTriangle = dynamic_cast(tObj)->GetItem(); } VertexContainer samples; samples.reserve(9); CreateNewSamples(samples, hitTriangle, prevRay, 0, mEps); CreateNewSamples(samples, hitTriangle, prevRay, 1, mEps); CreateNewSamples(samples, hitTriangle, prevRay, 2, mEps); VssRayContainer vssRays; CreateRays(vssRays, samples); VssRayContainer::const_iterator rit, rit_end = vssRays.end(); for (rit = vssRays.begin(); rit != rit_end; ++ rit) { VssRay *ray = *rit; // discontinuity found? // schedule for reverse sampling or adaptive border sampling const bool gap = DiscontinuityFound(*ray, prevRay); mRayQueue.push(GvsRayInfo(ray, gap)); } return 9; } int GvsPreprocessor::ReverseSampling(const VssRay &ray) { cout << "r" << endl; // TODO return 1; } int GvsPreprocessor::CastInitialSamples(const int numSamples, const int sampleType) { const long startTime = GetTime(); // generate simple rays SimpleRayContainer simpleRays; GenerateRays(numSamples, sampleType, simpleRays); // generate vss rays VssRayContainer samples; CastRays(simpleRays, samples); // add to ray queue EnqueueSamples(samples); Debug << "generated " << numSamples << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl; return (int)samples.size(); } void GvsPreprocessor::EnqueueSamples(VssRayContainer &samples, VssRay *oldRay) { // add samples to ray queue VssRayContainer::const_iterator vit, vit_end = samples.end(); for (vit = samples.begin(); vit != vit_end; ++ vit) { /// if there is no old ray, no discontinuity const bool gap = oldRay ? DiscontinuityFound(*(*vit), *oldRay) : false; mRayQueue.push(GvsRayInfo(*vit, gap)); } } int GvsPreprocessor::Pass() { int castSamples = 0; const int mSampleType = 0; while (castSamples < mSamplesPerPass) { // Ray queue empty => // cast a number of uniform samples to fill ray Queue CastInitialSamples(mInitialSamples, mSampleType); const int gvsSamples = ProcessQueue(); castSamples += gvsSamples; //cout << "\ncast " << castSamples << " of " << mSamplesPerPass << endl; } return castSamples; } int GvsPreprocessor::ProcessQueue() { int castSamples = 0; while (!mRayQueue.empty()) { // handle next ray GvsRayInfo rayInfo = mRayQueue.top(); mRayQueue.pop(); castSamples += HandleRay(rayInfo); } return castSamples; } bool GvsPreprocessor::ComputeVisibility() { Randomize(0); const long startTime = GetTime(); mViewSpaceBox = mKdTree->GetBox(); cout << "Gvs Preprocessor started\n" << flush; if (!mLoadViewCells) { /// construct the view cells from the scratch ConstructViewCells(mViewSpaceBox); cout << "view cells loaded" << endl; } int castSamples = 0; while (castSamples < mTotalSamples) { const int passSamples = Pass(); castSamples += passSamples; ///////////// // -- stats cout << "+"; cout << "\nsamples cast " << passSamples << " (=" << castSamples << " of " << mTotalSamples << ")" << endl; //mVssRays.PrintStatistics(mStats); mStats << "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl << "#TotalSamples\n" << castSamples << endl; mViewCellsManager->PrintPvsStatistics(mStats); // ComputeRenderError(); } return true; } }