#include "SceneGraph.h" #include "KdTree.h" #include "RssPreprocessor.h" #include "X3dExporter.h" #include "Environment.h" #include "MutualVisibility.h" #include "Polygon3.h" #include "ViewCell.h" #include "VssRay.h" #include "RssTree.h" #include "ViewCellsManager.h" #include "RenderSimulator.h" #include "GlRenderer.h" #include "SamplingStrategy.h" #include "PreprocessorThread.h" namespace GtpVisibilityPreprocessor { const bool pruneInvalidRays = false; #define ADD_RAYS_IN_PLACE 1 RssPreprocessor::RssPreprocessor(): mVssRays() { // this should increase coherence of the samples // Environment::GetSingleton()->GetIntValue("RssPreprocessor.samplesPerPass", mSamplesPerPass); //Environment::GetSingleton()->GetIntValue("RssPreprocessor.initialSamples", mInitialSamples); //Environment::GetSingleton()->GetIntValue("RssPreprocessor.vssSamples", mRssSamples); //Environment::GetSingleton()->GetIntValue("RssPreprocessor.vssSamplesPerPass", mRssSamplesPerPass); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.useImportanceSampling", mUseImportanceSampling); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.useRssTree", mUseRssTree); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.Export.pvs", mExportPvs); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.Export.rssTree", mExportRssTree); //Environment::GetSingleton()->GetBoolValue("RssPreprocessor.Export.rays", mExportRays); //Environment::GetSingleton()->GetIntValue("RssPreprocessor.Export.numRays", mExportNumRays); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.useViewcells", mUseViewcells); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.objectBasedSampling", mObjectBasedSampling); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.directionalSampling", mDirectionalSampling); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.loadInitialSamples", mLoadInitialSamples); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.storeInitialSamples", mStoreInitialSamples); Environment::GetSingleton()->GetBoolValue("RssPreprocessor.updateSubdivision", mUpdateSubdivision); mRssTree = NULL; } int RssPreprocessor::GenerateRays( const int number, SamplingStrategy &strategy, SimpleRayContainer &rays) { int result = 0; Debug<<"Generate rays...\n"<GetId()) { object = *oi; break; } if (object == NULL) return; VssRayContainer selectedRays; VssRayContainer::const_iterator it= rays.begin(), it_end = rays.end(); for (; it != it_end; ++it) { if ((*it)->mTerminationObject == object) selectedRays.push_back(*it); } Exporter *exporter = Exporter::GetExporter("object-rays.x3d"); // exporter->SetWireframe(); // exporter->ExportKdTree(*mKdTree); exporter->SetFilled(); exporter->ExportIntersectable(object); exporter->ExportRays(selectedRays, RgbColor(1, 0, 0)); delete exporter; } int RssPreprocessor::GenerateImportanceRays(RssTree *rssTree, const int desiredSamples, SimpleRayContainer &rays ) { int num; rssTree->UpdateTreeStatistics(); cout<< "#RSS_AVG_PVS_SIZE\n"<stat.avgPvsSize<stat.avgRays<stat.avgRayContribution<stat.avgPvsEntropy<stat.avgRayLengthEntropy<stat.avgImportance<stat.avgRayContribution*rssTree->stat.Leaves()); num = rssTree->GenerateRays(p, rays); } else { int leaves = rssTree->stat.Leaves()/1; num = rssTree->GenerateRays(desiredSamples, leaves, rays); } return num; } bool RssPreprocessor::ExportRssTree(char *filename, RssTree *tree, const Vector3 &dir ) { Exporter *exporter = Exporter::GetExporter(filename); exporter->SetFilled(); exporter->ExportScene(mSceneGraph->GetRoot()); // exporter->SetWireframe(); bool result = exporter->ExportRssTree2( *tree, dir ); delete exporter; return result; } bool RssPreprocessor::ExportRssTreeLeaf(char *filename, RssTree *tree, RssTreeLeaf *leaf) { Exporter *exporter = NULL; exporter = Exporter::GetExporter(filename); exporter->SetWireframe(); exporter->ExportKdTree(*mKdTree); exporter->SetForcedMaterial(RgbColor(0,0,1)); exporter->ExportBox(tree->GetBBox(leaf)); exporter->ResetForcedMaterial(); VssRayContainer rays[4]; for (int i=0; i < leaf->rays.size(); i++) { int k = leaf->rays[i].GetRayClass(); rays[k].push_back(leaf->rays[i].mRay); } // SOURCE RAY exporter->ExportRays(rays[0], RgbColor(1, 0, 0)); // TERMINATION RAY exporter->ExportRays(rays[1], RgbColor(1, 1, 1)); // PASSING_RAY exporter->ExportRays(rays[2], RgbColor(1, 1, 0)); // CONTAINED_RAY exporter->ExportRays(rays[3], RgbColor(0, 0, 1)); delete exporter; return true; } void RssPreprocessor::ExportRssTreeLeaves(RssTree *tree, const int number) { vector leaves; tree->CollectLeaves(leaves); int num = 0; int i; float p = number / (float)leaves.size(); for (i=0; i < leaves.size(); i++) { if (RandomValue(0,1) < p) { char filename[64]; sprintf(filename, "rss-leaf-%04d.x3d", num); ExportRssTreeLeaf(filename, tree, leaves[i]); num++; } if (num >= number) break; } } float RssPreprocessor::GetAvgPvsSize(RssTree *tree, const vector &viewcells ) { vector::const_iterator it, it_end = viewcells.end(); int sum = 0; for (it = viewcells.begin(); it != it_end; ++ it) sum += tree->GetPvsSize(*it); return sum/(float)viewcells.size(); } void RssPreprocessor::ExportPvs(char *filename, RssTree *rssTree ) { ObjectContainer pvs; if (rssTree->CollectRootPvs(pvs)) { Exporter *exporter = Exporter::GetExporter(filename); exporter->SetFilled(); exporter->ExportGeometry(pvs); exporter->SetWireframe(); exporter->ExportBox(rssTree->bbox); exporter->ExportViewpoint(rssTree->bbox.Center(), Vector3(1,0,0)); delete exporter; } } void NormalizeRatios(vector &distributions) { int i; float sumRatios = 0.0f; for (i=0; i < distributions.size(); i++) sumRatios += distributions[i]->mRatio; if (sumRatios == 0.0f) { for (i=0; i < distributions.size(); i++) { distributions[i]->mRatio = 1.0f; sumRatios += 1.0f; } } for (i=0 ; i < distributions.size(); i++) distributions[i]->mRatio/=sumRatios; #define MIN_RATIO 0.1f for (i = 0; i < distributions.size(); i++) if (distributions[i]->mRatio < MIN_RATIO) distributions[i]->mRatio = MIN_RATIO; sumRatios = 0.0f; for (i=0; i < distributions.size(); i++) sumRatios += distributions[i]->mRatio; for (i=0 ; i < distributions.size(); i++) distributions[i]->mRatio/=sumRatios; cout<<"New ratios: "; for (i=0 ; i < distributions.size(); i++) cout<mRatio<<" "; cout< &distributions) { // now evaluate the ratios for the next pass #define TIME_WEIGHT 0.0f for (int i=0; i < distributions.size(); i++) { distributions[i]->mRatio = distributions[i]->mContribution/ (Limits::Small + (TIME_WEIGHT*distributions[i]->mTime + (1 - TIME_WEIGHT)*distributions[i]->mRays) ); #if 1 distributions[i]->mRatio = sqr(distributions[i]->mRatio); #endif } } bool RssPreprocessor::ComputeVisibility() { Debug << "type: rss" << endl; cout<<"Rss Preprocessor started\n"<SetFilled(); Halton<4> halton; // for (int i=1; i < 7; i++) // cout<PrintStatistics(Debug); } int rssPass = 0; int rssSamples = 0; // now decode distribution string char buff[1024]; Environment::GetSingleton()->GetStringValue("RssPreprocessor.distributions", buff); char *curr = buff; mUseRssTree = false; while (1) { char *e = strchr(curr,'+'); if (e!=NULL) { *e=0; } if (strcmp(curr, "rss")==0) { mDistributions.push_back(new RssBasedDistribution(*this)); mUseRssTree = true; } else if (strcmp(curr, "object")==0) { mDistributions.push_back(new ObjectBasedDistribution(*this)); } else if (strcmp(curr, "spatial")==0) { mDistributions.push_back(new SpatialBoxBasedDistribution(*this)); } else if (strcmp(curr, "global")==0) { mDistributions.push_back(new GlobalLinesDistribution(*this)); } else if (strcmp(curr, "direction")==0) { mDistributions.push_back(new DirectionBasedDistribution(*this)); } else if (strcmp(curr, "object_direction")==0) { mDistributions.push_back(new ObjectDirectionBasedDistribution(*this)); } else if (strcmp(curr, "reverse_object")==0) { mDistributions.push_back(new ReverseObjectBasedDistribution(*this)); } else if (strcmp(curr, "reverse_viewspace_border")==0) { mDistributions.push_back(new ReverseViewSpaceBorderBasedDistribution(*this)); } if (e==NULL) break; curr = e+1; } mMixtureDistribution = new MixtureDistribution(*this); mMixtureDistribution->mDistributions = mDistributions; mMixtureDistribution->Init(); bool oldGenerator = false; const int batch = 100000; if (mLoadInitialSamples) { cout << "Loading samples from file ... "; LoadSamples(mVssRays, mObjects); cout << "finished\n" << endl; } else { SimpleRayContainer rays; if (oldGenerator) { cout<<"Generating initial rays..."<mType != SamplingStrategy::RSS_BASED_DISTRIBUTION) count++; for (i=0; i < mDistributions.size(); i++) if (mDistributions[i]->mType != SamplingStrategy::RSS_BASED_DISTRIBUTION) GenerateRays(mInitialSamples/count, *mDistributions[i], rays); cout<<"Casting initial rays..."<ComputeSampleContributions(mVssRays, true, false); cout<<"done.\n"<GenerateSamples(batch, rays); CastRays(rays, mVssRays, true, pruneInvalidRays); mMixtureDistribution->ComputeContributions(mVssRays); } } } cout << "#totalRayStackSize=" << (int)mVssRays.size() << endl <UpdatePVS(newVssRays); Debug<<"Valid viewcells before set validity: "<CountValidViewcells()< median (0.5f) //mViewCellsManager->SetValidityPercentage(0, 0.5f); // mViewCellsManager->SetValidityPercentage(0, 1.0f); Debug<<"Valid viewcells after set validity: "<CountValidViewcells()<PrintPvsStatistics(mStats); if (0) { char str[64]; sprintf(str, "tmp/v-"); // visualization const bool exportRays = true; const bool exportPvs = true; ObjectContainer objects; mViewCellsManager->ExportSingleViewCells(objects, 1000, false, exportPvs, exportRays, 10000, str); } if (renderer) { ComputeRenderError(); } rssPass++; // mDistributions.resize(1); mRssTree = new RssTree; mRssTree->SetPass(mPass); /// compute view cell contribution of rays if view cells manager already constructed // mViewCellsManager->ComputeSampleContributions(mVssRays, true, false); if (mUseRssTree) { mRssTree->Construct(mObjects, mVssRays); mRssTree->stat.Print(mStats); cout<<"RssTree root PVS size = "<GetRootPvsSize()<mRatio != 0) { GenerateRays(int(mRssSamplesPerPass*mDistributions[i]->mRatio), *mDistributions[i], rays); rays.NormalizePdf((float)rays.size()); CastRays(rays, tmpVssRays, true, pruneInvalidRays); castRays += (int)rays.size(); cout<<"Computing sample contributions..."<ComputeSampleContributions(tmpVssRays, true, false); #else float contribution = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true); #endif mDistributions[i]->mContribution = contribution; mDistributions[i]->mTotalContribution += contribution; cout<<"done."<mTime = TimeDiff(t1, GetTime()); // mDistributions[i]->mRays = (int)rays.size(); mDistributions[i]->mRays = (int)tmpVssRays.size(); mDistributions[i]->mTotalRays = (int)tmpVssRays.size(); // mStats<<"#RssRelContrib"<AddSampleContributions(vssRays); #endif totalSamples += castRays; rssSamples += (int)vssRays.size(); cout<<"Generated "<PrintPvsStatistics(mStats); Debug<<"done.\n"< 0) { Debug<<"Computing render errror..."<SetSnapPrefix(buf); renderer->SetSnapErrorFrames(true); ComputeRenderError(); Debug<<"done."< some of them can be deleted if (mExportRays) { Debug<<"Exporting rays..."<AddRays(vssRays); Debug<<"done.\n"<UpdateSubdivision(); Debug<<"done.\n"<= mRssSamples + mInitialSamples) break; rssPass++; mPass++; mRssTree->SetPass(mPass); } if(0) { VssRayContainer selectedRays; int desired = mViewCellsManager->GetVisualizationSamples(); mVssRays.SelectRays(desired, selectedRays); mViewCellsManager->Visualize(mObjects, selectedRays); } // view cells after sampling mViewCellsManager->PrintStatistics(Debug); EvalViewCellHistogram(); //-- render simulation after merge cout << "\nEvaluating view cells render time after sampling ... "; mRenderSimulator->RenderScene(); SimulationStatistics ss; mRenderSimulator->GetStatistics(ss); cout << " finished" << endl; cout << ss << endl; Debug << ss << endl; if (useRayBuffer && mExportRays) { char filename[64]; sprintf(filename, "rss-rays-i.x3d"); rayBuffer.resize(mPass); ExportRayAnimation(filename, rayBuffer); } // do not delete rss tree now - can be used for visualization.. #if 0 Debug<<"Deleting RSS tree...\n"; delete mRssTree; Debug<<"Done.\n"; #endif return true; } }