#include "SceneGraph.h" #include "KdTree.h" #include "VssPreprocessor.h" #include "X3dExporter.h" #include "Environment.h" #include "MutualVisibility.h" #include "Polygon3.h" #include "ViewCell.h" #include "VssRay.h" #include "VssTree.h" #include "ViewCellsManager.h" #include "RenderSimulator.h" #include "Beam.h" #include "GlRenderer.h" #include "Intersectable.h" #ifdef GTP_INTERNAL #include "ArchModeler2MLRT.hxx" #endif namespace GtpVisibilityPreprocessor { bool use2dSampling = false; bool useViewspacePlane = false; VssPreprocessor::VssPreprocessor(): mVssRays(), mViewSpaceBox(NULL) { // this should increase coherence of the samples Environment::GetSingleton()->GetIntValue("VssPreprocessor.samplesPerPass", mSamplesPerPass); Environment::GetSingleton()->GetIntValue("VssPreprocessor.initialSamples", mInitialSamples); Environment::GetSingleton()->GetIntValue("VssPreprocessor.vssSamples", mVssSamples); Environment::GetSingleton()->GetIntValue("VssPreprocessor.vssSamplesPerPass", mVssSamplesPerPass); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.useImportanceSampling", mUseImportanceSampling); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.loadInitialSamples", mLoadInitialSamples); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.storeInitialSamples", mStoreInitialSamples); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.useViewSpaceBox", mUseViewSpaceBox); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.testBeamSampling", mTestBeamSampling); Environment::GetSingleton()->GetBoolValue("VssPreprocessor.enlargeViewSpace", mEnlargeViewSpace); Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace); useViewspacePlane = mUseViewSpaceBox; //hack Debug << "*********** vss preprocessor options **************" << endl; Debug << "use view space box=" << mUseViewSpaceBox << endl; Debug << "enlarge view space=" << mEnlargeViewSpace << endl; Debug << "*********** end vss preprocessor options **************" << endl; mStats.open("stats.log"); } VssPreprocessor::~VssPreprocessor() { CLEAR_CONTAINER(mVssRays); DEL_PTR(mViewSpaceBox); } Vector3 VssPreprocessor::GetViewpoint(AxisAlignedBox3 *viewSpaceBox) { AxisAlignedBox3 box; if (viewSpaceBox) box =*viewSpaceBox; else box = mKdTree->GetBox(); // shrink the box in the y direction return box.GetRandomPoint(); } Vector3 VssPreprocessor::GetDirection(const Vector3 &viewpoint, AxisAlignedBox3 *viewSpaceBox ) { Vector3 point; if (!use2dSampling) { if (0) { Vector3 normal; int i = Random((int)mObjects.size()); Intersectable *object = mObjects[i]; object->GetRandomSurfacePoint(point, normal); } else point = mKdTree->GetBox().GetRandomPoint(); // point = viewpoint + UniformRandomVector(); } else { AxisAlignedBox3 box; if (viewSpaceBox) box =*viewSpaceBox; else box = mKdTree->GetBox(); point = box.GetRandomPoint(); point.y = viewpoint.y; } return point - viewpoint; } int VssPreprocessor::GenerateImportanceRays(VssTree *vssTree, const int desiredSamples, SimpleRayContainer &rays ) { int num; if (0) { float minRayContribution; float maxRayContribution; float avgRayContribution; vssTree->GetRayContributionStatistics(minRayContribution, maxRayContribution, avgRayContribution); cout<< "#MIN_RAY_CONTRIB\n"<stat.Leaves()); num = vssTree->GenerateRays(p, rays); } else { int leaves = vssTree->stat.Leaves(); num = vssTree->GenerateRays(desiredSamples, leaves, rays); } cout<<"Generated "<SetWireframe(); exporter->ExportKdTree(*mKdTree); exporter->SetFilled(); exporter->ExportScene(mSceneGraph->GetRoot()); exporter->SetWireframe(); if (mViewSpaceBox) { exporter->SetForcedMaterial(RgbColor(1,0,1)); exporter->ExportBox(*mViewSpaceBox); exporter->ResetForcedMaterial(); } VssRayContainer rays; vssRays.SelectRays(number, rays); //exporter->ExportRays(rays, RgbColor(1, 0, 0)); delete exporter; cout<<"done."<SetFilled(); exporter->ExportScene(mSceneGraph->GetRoot()); // exporter->SetWireframe(); bool result = exporter->ExportVssTree2( *tree, dir ); delete exporter; return result; } bool VssPreprocessor::ExportVssTreeLeaf(char *filename, VssTree *tree, VssTreeLeaf *leaf) { Exporter *exporter = NULL; exporter = Exporter::GetExporter(filename); exporter->SetWireframe(); exporter->ExportKdTree(*mKdTree); if (mViewSpaceBox) { exporter->SetForcedMaterial(RgbColor(1,0,0)); exporter->ExportBox(*mViewSpaceBox); exporter->ResetForcedMaterial(); } 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 VssPreprocessor::ExportVssTreeLeaves(VssTree *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, "vss-leaf-%04d.x3d", num); ExportVssTreeLeaf(filename, tree, leaves[i]); num++; } if (num >= number) break; } } void VssPreprocessor::TestBeamCasting(VssTree *tree, ViewCellsManager *vm, const ObjectContainer &objects) { //debuggerWidget = new GlDebuggerWidget(renderer); // renderer->resize(640, 480); //debuggerWidget->resize(640, 480); vector leaves; tree->CollectLeaves(leaves); Exporter *exporter = Exporter::GetExporter("shafts.x3d"); exporter->SetWireframe(); exporter->ExportGeometry(objects); exporter->SetFilled(); //Randomize(); // §§matt // debuggerWidget = new GlDebuggerWidget(renderer); /*debuggerWidget->mBeam = beam; debuggerWidget->mSourceObject = sourceObj; debuggerWidget->mSamples = 10000; Debug << "showing window" << endl; debuggerWidget->show(); renderer->makeCurrent();*/ for (int i = 0; i < 10; ++ i) { Beam beam; Intersectable *sourceObj = mObjects[5]; const int index = (int)RandomValue(0, (Real)((int)leaves.size() - 1)); VssTreeLeaf *leaf = leaves[index]; AxisAlignedBox3 dirBox = tree->GetDirBBox(leaf); AxisAlignedBox3 box = tree->GetBBox(leaf); beam.Construct(box, dirBox); // collect kd leaves and view cells mKdTree->CastBeam(beam); vm->CastBeam(beam); Debug << "found " << (int)beam.mViewCells.size() << " view cells and " << (int)beam.mKdNodes.size() << " kd nodes" << endl; BeamSampleStatistics stats; // §§matt /* renderer->SampleBeamContributions(sourceObj, beam, 200000, stats); char s[64]; sprintf(s, "shaft%04d.png", i); QImage image = renderer->toImage(); image.save(s, "PNG"); Debug << "beam statistics: " << stats << endl << endl; */ if (1) { AxisAlignedBox3 sbox = mSceneGraph->GetBox(); Vector3 bmin = sbox.Min() - 150.0f; Vector3 bmax = sbox.Max() + 150.0f; AxisAlignedBox3 vbox(bmin, bmax); exporter->ExportBeam(beam, vbox); } bool exportViewCells = false; if (exportViewCells) { ViewCellContainer::const_iterator it, it_end = beam.mViewCells.end(); for (it = beam.mViewCells.begin(); it != beam.mViewCells.end(); ++ it) { BspNodeGeometry geom; AxisAlignedBox3 vbox; vbox.Initialize(); vbox.Include((*it)->GetMesh()); exporter->SetWireframe(); exporter->ExportBox(vbox); exporter->SetFilled(); exporter->ExportViewCell(*it); } /*vector::const_iterator it, it_end = beam.mKdNodes.end(); for (it = beam.mKdNodes.begin(); it != beam.mKdNodes.end(); ++ it) { exporter->ExportBox(mKdTree->GetBox((*it))); }*/ } } /*while (1) { debuggerWidget->repaint(); };*/ delete exporter; } float VssPreprocessor::GetAvgPvsSize(VssTree *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(); } bool VssPreprocessor::ComputeVisibility() { Debug << "type: vss" << endl; long startTime = GetTime(); int totalSamples = 0; AxisAlignedBox3 box(mKdTree->GetBox()); if (!useViewspacePlane) { float size = 0.05f; float s = 0.5f - size; float olds = Magnitude(box.Size()); box.Enlarge(box.Size()*Vector3(-s)); Vector3 translation = Vector3(-olds*0.1f, 0, 0); box.SetMin(box.Min() + translation); box.SetMax(box.Max() + translation); } else { // sample city like heights box.SetMin(1, box.Min(1) + box.Size(1)*0.2f); box.SetMax(1, box.Min(1) + box.Size(1)*0.3f); } if (use2dSampling) box.SetMax(1, box.Min(1)); cout << "use view space box=" << mUseViewSpaceBox << endl; if (mUseViewSpaceBox) { //mViewSpaceBox = ConstructViewSpaceBox(); if (!mEnlargeViewSpace) { mViewSpaceBox = new AxisAlignedBox3(box); } else { mViewSpaceBox = new AxisAlignedBox3(mKdTree->GetBox()); if (0) { // HACK: enlarge in y directon Vector3 size = mViewSpaceBox->Size(); size[1] *= 1.25; Vector3 enlarge(size[0] * 0.25f, size[1] * 0.0f, size[2] * 0.25f); //Vector3 enlarge(size[0] * 4.0f, 0.0f, 0.0f); mViewSpaceBox->Enlarge(enlarge); mViewSpaceBox->SetMax(mViewSpaceBox->Max() + enlarge); } else { AxisAlignedBox3 tbox(*mViewSpaceBox); Vector3 size = mViewSpaceBox->Size(); tbox.SetMax(0, mViewSpaceBox->Max(0) + size[0] * 0.5f); tbox.SetMin(0, mViewSpaceBox->Min(0) + size[0]); *mViewSpaceBox = tbox; // $$ JB temporary /*AxisAlignedBox3 tempbox = *mViewSpaceBox; float s = tempbox.Size(0); tempbox.Scale(0.8f); tempbox.SetMax(0, box.Max(0) + s*0.8f); tempbox.SetMin(0, box.Min(0) + s*0.8f); *mViewSpaceBox = tempbox;*/ } } //Debug << "view space box: " << *mViewSpaceBox << endl; } else { mViewSpaceBox = NULL; } AxisAlignedBox3 vbox = mViewSpaceBox ? *mViewSpaceBox : mKdTree->GetBox(); mSceneGraph->CollectObjects(&mObjects); if (!mLoadViewCells) { //-- generate new view cells or reconstruct them //-- for construction the manager uses it's own set of samples mViewCellsManager->SetViewSpaceBox(vbox); mViewCellsManager->Construct(this); // output visualizations and statistics Debug << "view cells construction finished: " << endl; mViewCellsManager->PrintStatistics(Debug); } #if 1 else { //-- load view cells from file //-- test successful view cells loading by exporting them again VssRayContainer dummies; mViewCellsManager->Visualize(mObjects, dummies); mViewCellsManager->ExportViewCells("test.xml.zip", mViewCellsManager->GetExportPvs(), mObjects); } #endif VssTree *vssTree = NULL; const long initialTime = GetTime(); if (mLoadInitialSamples) { cout << "Loading samples from file ... "; LoadSamples(mVssRays, mObjects); cout << "finished\n" << endl; totalSamples = (int)mVssRays.size(); } else { while (totalSamples < mInitialSamples) { int passContributingSamples = 0; int passSampleContributions = 0; int passSamples = 0; int index = 0; int sampleContributions; int s = Min(mSamplesPerPass, mInitialSamples); for (int k=0; k < s; k++) { // changed by matt Vector3 viewpoint; // viewpoint = GetViewpoint(mViewSpaceBox); mViewCellsManager->GetViewPoint(viewpoint); Vector3 direction = GetDirection(viewpoint, mViewSpaceBox); sampleContributions = CastRay(viewpoint, direction, 1, mVssRays, vbox); if (sampleContributions) { passContributingSamples ++; passSampleContributions += sampleContributions; } passSamples++; totalSamples++; } mPass++; int pvsSize = 0; float avgRayContrib = (passContributingSamples > 0) ? passSampleContributions/(float)passContributingSamples : 0; cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl; cout << "#TotalSamples=" << totalSamples/1000 << "#SampleContributions=" << passSampleContributions << " (" << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS=" << pvsSize/(float)mObjects.size() << endl << "avg ray contrib=" << avgRayContrib << endl; mStats << "#Pass\n" <GetOrigin() << " " << mVssRays[i]->GetTermination() << " " << mVssRays[i]->mOriginObject << " " << mVssRays[i]->mTerminationObject << endl; Debug << dummyRays[i]->GetOrigin() << " " << dummyRays[i]->GetTermination() << " " << dummyRays[i]->mOriginObject << " " << dummyRays[i]->mTerminationObject << endl << endl; }*/ } //int numExportRays = 2000; int numExportRays = 0; if (numExportRays) { char filename[64]; sprintf(filename, "vss-rays-initial.x3d"); ExportRays(filename, mVssRays, numExportRays); } vssTree = new VssTree; // viewcells = Construct(mVssRays); vssTree->Construct(mVssRays, mViewSpaceBox); cout<<"VssTree root PVS size = "<GetRootPvsSize()<UpdatePVS(newVssRays); // get viewcells as kd tree boxes vector kdViewcells; if (0) { vector leaves; mKdTree->CollectLeaves(leaves); vector::const_iterator it; int targetLeaves = 50; float prob = targetLeaves/(float)leaves.size(); for (it = leaves.begin(); it != leaves.end(); ++it) if (RandomValue(0.0f,1.0f) < prob) kdViewcells.push_back(mKdTree->GetBox(*it)); float avgPvs = GetAvgPvsSize(vssTree, kdViewcells); cout<<"Initial average PVS size = "<GetViewPoint(viewpoint); Vector3 direction = GetDirection(viewpoint, mViewSpaceBox); rays.push_back(SimpleRay(viewpoint, direction)); } } else { num = GenerateImportanceRays(vssTree, num, rays); } for (int i=0; i < rays.size(); i++) CastRay(rays[i].mOrigin, rays[i].mDirection, 1, vssRays, vbox); vssTree->AddRays(vssRays); if (0) { int subdivided = vssTree->UpdateSubdivision(); cout<<"subdivided leafs = "<GetAvgPvsSize(); cout<<"*****************************\n"; cout<= mVssSamples) break; pass ++; } if (mTestBeamSampling && mUseGlRenderer) { TestBeamCasting(vssTree, mViewCellsManager, mObjects); } if (0) Debug << vssTree->stat << endl; if (0) { VssRayContainer viewCellRays; // compute rays used for view cells construction const int numRays = mViewCellsManager->GetVisualizationSamples(); vssTree->CollectRays(viewCellRays, numRays); } //-- render simulation after merge cout << "\nevaluating bsp view cells render time after sampling ... "; Debug << "\nStatistics after sampling: " << endl; mRenderSimulator->RenderScene(); SimulationStatistics ss; mRenderSimulator->GetStatistics(ss); cout << " finished" << endl; cout << ss << endl; Debug << ss << endl; delete vssTree; return true; } }