#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" namespace GtpVisibilityPreprocessor { static bool useViewSpaceBox = false; static bool use2dSampling = false; // not supported anymore! static bool fromBoxVisibility = 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.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); mStats.open("stats.log"); mRssTree = NULL; } bool RssPreprocessor::GenerateRays( const int number, const int sampleType, SimpleRayContainer &rays ) { bool result = false; switch (sampleType) { case SamplingStrategy::RSS_BASED_DISTRIBUTION: case SamplingStrategy::RSS_SILHOUETTE_BASED_DISTRIBUTION: if (mRssTree) { GenerateImportanceRays(mRssTree, number, rays); result = true; } break; default: result = Preprocessor::GenerateRays(number, sampleType, rays); } // rays.NormalizePdf(); return result; } RssPreprocessor::~RssPreprocessor() { // mVssRays get deleted in the tree // CLEAR_CONTAINER(mVssRays); } void RssPreprocessor::ExportObjectRays(VssRayContainer &rays, const int objectId) { ObjectContainer::const_iterator oi; Intersectable *object = NULL; for (oi = mObjects.begin(); oi != mObjects.end(); ++oi) if (objectId == (*oi)->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::ExportRays(const char *filename, const VssRayContainer &vssRays, const int number ) { cout<<"Exporting vss rays..."<SetWireframe(); exporter->ExportKdTree(*mKdTree); } exporter->SetFilled(); // $$JB temporarily do not export the scene if (0) exporter->ExportScene(mSceneGraph->GetRoot()); exporter->SetWireframe(); if (1) { exporter->SetForcedMaterial(RgbColor(1,0,1)); exporter->ExportBox(mViewCellsManager->GetViewSpaceBox()); exporter->ResetForcedMaterial(); } VssRayContainer rays; vssRays.SelectRays(number, rays); exporter->ExportRays(rays, RgbColor(1, 0, 0)); delete exporter; cout<<"done."< &vssRays ) { cout<<"Exporting vss rays..."<SetWireframe(); exporter->ExportKdTree(*mKdTree); } exporter->SetFilled(); // $$JB temporarily do not export the scene if (1) exporter->ExportScene(mSceneGraph->GetRoot()); exporter->SetWireframe(); if (1) { exporter->SetForcedMaterial(RgbColor(1,0,1)); exporter->ExportBox(mViewCellsManager->GetViewSpaceBox()); exporter->ResetForcedMaterial(); } exporter->ExportRaySets(vssRays, RgbColor(1, 0, 0)); delete exporter; cout<<"done."<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 RssPreprocessor::ComputeRenderError() { // compute rendering error if (renderer && renderer->mPvsStatFrames) { // emit EvalPvsStat(); // QMutex mutex; // mutex.lock(); // renderer->mRenderingFinished.wait(&mutex); // mutex.unlock(); renderer->EvalPvsStat(); mStats << "#AvgPvsRenderError\n" <mPvsStat.GetAvgError()<mPvsStat.GetMaxError()<mPvsStat.GetErrorFreeFrames()<mPvsStat.GetAvgPvs()< rayBuffer(50); long startTime = GetTime(); long lastTime; float totalTime; int totalSamples = 0; // if not already loaded, construct view cells from file if (!mLoadViewCells) { // construct view cells using it's own set of samples mViewCellsManager->Construct(this); //-- several visualizations and statistics Debug << "view cells construction finished: " << endl; mViewCellsManager->PrintStatistics(Debug); } int rssPass = 0; int rssSamples = 0; if (mLoadInitialSamples) { cout << "Loading samples from file ... "; LoadSamples(mVssRays, mObjects); cout << "finished\n" << endl; } else { SimpleRayContainer rays; cout<<"Generating initial rays..."<ComputeSampleContributions(mVssRays, true, false); cout<<"done.\n"<PrintPvsStatistics(mStats); // viewcells->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()<SetPass(mPass); /// compute view cell contribution of rays if view cells manager already constructed // mViewCellsManager->ComputeSampleContributions(mVssRays, true, false); if (mUseImportanceSampling) { mRssTree->Construct(mObjects, mVssRays); mRssTree->stat.Print(mStats); cout<<"RssTree root PVS size = "<GetRootPvsSize()<ComputeSampleContributions(tmpVssRays, true, false); #else contributions[0] = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true); #endif times[0] = TimeDiff(t1, GetTime()); nrays[0] = (int)rays.size(); mStats<<"#RssRelContrib"<ComputeSampleContributions(tmpVssRays, true, false); #else contributions[1] = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true); #endif times[1] = TimeDiff(t1, GetTime()); nrays[1] = (int)rays.size(); mStats<<"#SpatialRelContrib"<ComputeSampleContributions(tmpVssRays, true, false); #else contributions[2] = mViewCellsManager->ComputeSampleContributions(tmpVssRays, false, true); #endif times[2] = TimeDiff(t1, GetTime()); nrays[2] = (int)rays.size(); mStats<<"#DirectionalRelContrib"<AddSampleContributions(vssRays); #endif } else { int rayType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION; if (mObjectBasedSampling) rayType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION; else if (mDirectionalSampling) rayType = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION; cout<<"Generating rays..."<ComputeSampleContributions(vssRays, true, false); cout<<"done."<PrintPvsStatistics(mStats); } if (0 && mPass > 0) { char buf[100]; if (mUseImportanceSampling) { sprintf(buf, "snap/i-%02d-", mPass); renderer->SetSnapPrefix(buf); } else { sprintf(buf, "snap/r-%02d-", mPass); renderer->SetSnapPrefix(buf); } renderer->SetSnapErrorFrames(true); } ComputeRenderError(); // epxort rays before adding them to the tree -> some of them can be deleted if (mExportRays) { char filename[64]; if (mUseImportanceSampling) sprintf(filename, "rss-rays-i%04d.x3d", rssPass); else sprintf(filename, "rss-rays-%04d.x3d", rssPass); vssRays.SelectRays(mExportNumRays, rayBuffer[mPass], true); ExportRays(filename, vssRays, mExportNumRays); // now export all contributing rays VssRayContainer contributingRays; vssRays.GetContributingRays(contributingRays, mPass); mStats<<"#NUM_CONTRIBUTING_RAYS\n"<<(int)contributingRays.size()<AddRays(vssRays); if (mUpdateSubdivision) { int updatePasses = 1; if (mPass % updatePasses == 0) { int subdivided = mRssTree->UpdateSubdivision(); cout<<"subdivided leafs = "<= mRssSamples + mInitialSamples) break; rssPass++; mPass++; mRssTree->SetPass(mPass); } if (mUseViewcells) { if(0) { VssRayContainer selectedRays; int desired = mViewCellsManager->GetVisualizationSamples(); mVssRays.SelectRays(desired, selectedRays); mViewCellsManager->Visualize(mObjects, selectedRays); } // view cells after sampling mViewCellsManager->PrintStatistics(Debug); //-- render simulation after merge cout << "\nevaluating bsp view cells render time after sampling ... "; mRenderSimulator->RenderScene(); SimulationStatistics ss; mRenderSimulator->GetStatistics(ss); cout << " finished" << endl; cout << ss << endl; Debug << ss << endl; } if (mExportRays && mUseImportanceSampling) { 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 //mViewCellsManager->ExportViewCells("visibility.xml", // true); return true; } }