#include "SceneGraph.h" #include "Exporter.h" #include "UnigraphicsParser.h" #include "X3dParser.h" #include "Preprocessor.h" #include "ViewCell.h" #include "Environment.h" #include "ViewCellsManager.h" #include "ViewCellBsp.h" #include "VspBspTree.h" #include "VspKdTree.h" #include "RenderSimulator.h" #include "GlRenderer.h" Preprocessor *preprocessor; Preprocessor::Preprocessor(): mKdTree(NULL), mBspTree(NULL), mVspKdTree(NULL), mVspBspTree(NULL), mViewCellsManager(NULL) { environment->GetBoolValue("Preprocessor.useGlRenderer", mUseGlRenderer); // renderer will be constructed when the scene graph and viewcell manager will be known renderer = NULL; environment->GetBoolValue("Preprocessor.useGlDebugger", mUseGlDebugger); } Preprocessor::~Preprocessor() { Debug<<"Deleting view cells manager...\n"; DEL_PTR(mViewCellsManager); Debug<<"done.\n"; Debug<<"Deleting bsp tree...\n"; DEL_PTR(mBspTree); Debug<<"done.\n"; Debug<<"Deleting kd tree...\n"; DEL_PTR(mKdTree); Debug<<"done.\n"; Debug<<"Deleting vspkd tree...\n"; DEL_PTR(mVspKdTree); Debug<<"done.\n"; Debug<<"Deleting vspbsp tree...\n"; DEL_PTR(mVspBspTree); Debug<<"done.\n"; } int SplitFilenames(const string str, vector &filenames) { int pos = 0; while(1) { int npos = (int)str.find(';', pos); if (npos < 0 || npos - pos < 1) break; filenames.push_back(string(str, pos, npos - pos)); pos = npos + 1; } filenames.push_back(string(str, pos, str.size() - pos)); return (int)filenames.size(); } bool Preprocessor::LoadScene(const string filename) { // use leaf nodes of the original spatial hiearrchy as occludees mSceneGraph = new SceneGraph; Parser *parser; vector filenames; int files = SplitFilenames(filename, filenames); cout<ParseFile(filename, &mSceneGraph->mRoot); delete parser; } else { // root for different files mSceneGraph->mRoot = new SceneGraphNode; for (int i= 0; i < filenames.size(); i++) { if (strstr(filenames[i].c_str(), ".x3d")) parser = new X3dParser; else parser = new UnigraphicsParser; SceneGraphNode *node; if (parser->ParseFile(filenames[i], &node)) { mSceneGraph->mRoot->mChildren.push_back(node); // at least one file parsed result = true; } delete parser; } } if (result) { mSceneGraph->AssignObjectIds(); int intersectables, faces; mSceneGraph->GetStatistics(intersectables, faces); cout<CollectObjects(&mObjects); mSceneGraph->mRoot->UpdateBox(); } return result; } bool Preprocessor::ExportPreprocessedData(const string filename) { return false; } bool Preprocessor::BuildKdTree() { mKdTree = new KdTree; // add mesh instances of the scene graph to the root of the tree KdLeaf *root = (KdLeaf *)mKdTree->GetRoot(); mSceneGraph->CollectObjects(&root->mObjects); mKdTree->Construct(); return true; } void Preprocessor::KdTreeStatistics(ostream &s) { s<GetStatistics(); } void Preprocessor::BspTreeStatistics(ostream &s) { s << mBspTree->GetStatistics(); } bool Preprocessor::Export( const string filename, const bool scene, const bool kdtree, const bool bsptree ) { Exporter *exporter = Exporter::GetExporter(filename); if (exporter) { if (scene) exporter->ExportScene(mSceneGraph->mRoot); if (kdtree) { exporter->SetWireframe(); exporter->ExportKdTree(*mKdTree); } if (bsptree) { //exporter->SetWireframe(); exporter->ExportBspTree(*mBspTree); } delete exporter; return true; } return false; } bool Preprocessor::PrepareViewCells() { //-- parse type of view cell container char viewCellsStr[64]; environment->GetStringValue("ViewCells.type", viewCellsStr); mViewCellsManager = CreateViewCellsManager(viewCellsStr); float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0; environment->GetFloatValue("Simulation.objRenderCost",objRenderCost); environment->GetFloatValue("Simulation.vcOverhead", vcOverhead); environment->GetFloatValue("Simulation.moveSpeed", moveSpeed); mRenderSimulator = new RenderSimulator(mViewCellsManager, objRenderCost, vcOverhead, moveSpeed); mViewCellsManager->SetRenderer(mRenderSimulator); //-- parse view cells construction method environment->GetBoolValue("ViewCells.loadFromFile", mLoadViewCells); char buf[100]; if (mLoadViewCells) { environment->GetStringValue("ViewCells.filename", buf); mViewCellsFilename = buf; } if (mUseGlRenderer || mUseGlDebugger) { // NOTE: render texture should be power of 2 and square // renderer must be initialised renderer = new GlRendererBuffer(1024, 768, mSceneGraph, mViewCellsManager, mKdTree); // renderer->makeCurrent(); } environment->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace); return true; } ViewCellsManager *Preprocessor::CreateViewCellsManager(const char *name) { if (strcmp(name, "kdTree") == 0) { mViewCellsManager = new KdViewCellsManager(mKdTree); } else if (strcmp(name, "bspTree") == 0) { mBspTree = new BspTree(); Debug << "view cell type: Bsp" << endl; mViewCellsManager = new BspViewCellsManager(mBspTree); } else if (strcmp(name, "vspBspTree") == 0) { mVspBspTree = new VspBspTree(); Debug << "view cell type: VspBsp" << endl; mViewCellsManager = new VspBspViewCellsManager(mVspBspTree); } else if (strcmp(name, "vspKdTree") == 0) { mVspKdTree = new VspKdTree(); mViewCellsManager = new VspKdViewCellsManager(mVspKdTree); } else if (strcmp(name, "sceneDependent") == 0) { //TODO mBspTree = new BspTree(); Debug << "view cell type: Bsp" << endl; mViewCellsManager = new BspViewCellsManager(mBspTree); } else { cerr<<"Wrong view cells type" << name << endl; exit(1); } return mViewCellsManager; } // use ascii format to store rays #define USE_ASCII 0 inline bool ilt(Intersectable *obj1, Intersectable *obj2) { return obj1->mId < obj2->mId; } bool Preprocessor::LoadSamples(VssRayContainer &samples, ObjectContainer &objects) const { std::stable_sort(objects.begin(), objects.end(), ilt); char fileName[100]; environment->GetStringValue("Preprocessor.samplesFilename", fileName); Vector3 origin, termination; // HACK: needed only for lower_bound algorithm to find the // intersected objects MeshInstance sObj(NULL); MeshInstance tObj(NULL); #if USE_ASCII ifstream samplesIn(fileName, ios::binary); if (!samplesIn.is_open()) return false; string buf; while (!(getline(samplesIn, buf)).eof()) { sscanf(buf.c_str(), "%f %f %f %f %f %f %d %d", &origin.x, &origin.y, &origin.z, &termination.x, &termination.y, &termination.z, &(sObj.mId), &(tObj.mId)); Intersectable *sourceObj = NULL; Intersectable *termObj = NULL; if (sObj.mId >= 0) { ObjectContainer::iterator oit = lower_bound(objects.begin(), objects.end(), &sObj, ilt); sourceObj = *oit; } if (tObj.mId >= 0) { ObjectContainer::iterator oit = lower_bound(objects.begin(), objects.end(), &tObj, ilt); termObj = *oit; } samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); } #else ifstream samplesIn(fileName, ios::binary); if (!samplesIn.is_open()) return false; while (1) { samplesIn.read(reinterpret_cast(&origin), sizeof(Vector3)); samplesIn.read(reinterpret_cast(&termination), sizeof(Vector3)); samplesIn.read(reinterpret_cast(&(sObj.mId)), sizeof(int)); samplesIn.read(reinterpret_cast(&(tObj.mId)), sizeof(int)); if (samplesIn.eof()) break; Intersectable *sourceObj = NULL; Intersectable *termObj = NULL; if (sObj.mId >= 0) { ObjectContainer::iterator oit = lower_bound(objects.begin(), objects.end(), &sObj, ilt); sourceObj = *oit; } if (tObj.mId >= 0) { ObjectContainer::iterator oit = lower_bound(objects.begin(), objects.end(), &tObj, ilt); termObj = *oit; } samples.push_back(new VssRay(origin, termination, sourceObj, termObj)); } #endif samplesIn.close(); return true; } bool Preprocessor::ExportSamples(const VssRayContainer &samples) const { char fileName[100]; environment->GetStringValue("Preprocessor.samplesFilename", fileName); VssRayContainer::const_iterator it, it_end = samples.end(); #if USE_ASCII ofstream samplesOut(fileName); if (!samplesOut.is_open()) return false; for (it = samples.begin(); it != it_end; ++ it) { VssRay *ray = *it; int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1; int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1; samplesOut << ray->GetOrigin().x << " " << ray->GetOrigin().y << " " << ray->GetOrigin().z << " " << ray->GetTermination().x << " " << ray->GetTermination().y << " " << ray->GetTermination().z << " " << sourceid << " " << termid << "\n"; } #else ofstream samplesOut(fileName, ios::binary); if (!samplesOut.is_open()) return false; for (it = samples.begin(); it != it_end; ++ it) { VssRay *ray = *it; Vector3 origin(ray->GetOrigin()); Vector3 termination(ray->GetTermination()); int sourceid = ray->mOriginObject ? ray->mOriginObject->mId : -1; int termid = ray->mTerminationObject ? ray->mTerminationObject->mId : -1; samplesOut.write(reinterpret_cast(&origin), sizeof(Vector3)); samplesOut.write(reinterpret_cast(&termination), sizeof(Vector3)); samplesOut.write(reinterpret_cast(&sourceid), sizeof(int)); samplesOut.write(reinterpret_cast(&termid), sizeof(int)); } #endif samplesOut.close(); return true; } bool Preprocessor::GenerateRays( const int number, const int sampleType, SimpleRayContainer &rays ) { Vector3 origin, direction; int startSize = rays.size(); for (int i=0; rays.size() - startSize < number; i++) { // now get the direction switch (sampleType) { case OBJECT_BASED_DISTRIBUTION: { mViewCellsManager->GetViewPoint(origin); Vector3 point; Vector3 normal; int i = RandomValue(0, mObjects.size() - 1); Intersectable *object = mObjects[i]; object->GetRandomSurfacePoint(point, normal); direction = point - origin; } break; case OBJECT_DIRECTION_BASED_DISTRIBUTION: { int i = RandomValue(0, mObjects.size() - 1); Intersectable *object = mObjects[i]; Vector3 normal; object->GetRandomSurfacePoint(origin, normal); direction = UniformRandomVector(normal); origin += 0.1f*direction; } break; case DIRECTION_BASED_DISTRIBUTION: mViewCellsManager->GetViewPoint(origin); direction = UniformRandomVector(); break; case DIRECTION_BOX_BASED_DISTRIBUTION: { mViewCellsManager->GetViewPoint(origin); float alpha = RandomValue(0.0f, 2*M_PI); float beta = RandomValue(-M_PI/2, M_PI/2); direction = VssRay::GetDirection(alpha, beta); break; } case SPATIAL_BOX_BASED_DISTRIBUTION: mViewCellsManager->GetViewPoint(origin); direction = mKdTree->GetBox().GetRandomPoint() - origin; break; default: // unsuported distribution type return false; } // $$ jb the pdf is yet not correct for all sampling methods! float pdf = 1.0f; float c = Magnitude(direction); if (c > Limits::Small) { direction*=1.0f/c; rays.AddRay(SimpleRay(origin, direction, pdf)); } } return true; }