void Statistics::endFrame() { setValue(frameDurationCounter, frameTimer.getMilliseconds()); { // IO static Util::Timer ioTimer; static size_t lastBytesRead = 0; static size_t lastBytesWritten = 0; const uint64_t duration = ioTimer.getNanoseconds(); // Update every second. if(duration > 1000000000) { const size_t bytesRead = Util::Utils::getIOBytesRead(); const size_t bytesWritten = Util::Utils::getIOBytesWritten(); const double MebiPerSecond = 1024.0 * 1024.0 * 1.0e-9 * static_cast<double>(duration); const double readRate = static_cast<double>(bytesRead - lastBytesRead) / MebiPerSecond; const double writeRate = static_cast<double>(bytesWritten - lastBytesWritten) / MebiPerSecond; ioTimer.reset(); lastBytesRead = bytesRead; lastBytesWritten = bytesWritten; setValue(ioRateReadCounter, readRate); setValue(ioRateWriteCounter, writeRate); } } pushEvent(EVENT_TYPE_FRAME_END, 1); }
void RasterizationPrim::rasterize(const BBox &vsBounds, VoxelBuffer::Ptr buffer) const { FieldMapping::Ptr mapping(buffer->mapping()); DiscreteBBox dvsBounds = Math::discreteBounds(vsBounds); dvsBounds.min -= Imath::V3i(1); dvsBounds.max += Imath::V3i(1); DiscreteBBox bufferBounds = buffer->dataWindow(); dvsBounds = Math::clipBounds(dvsBounds, bufferBounds); V3i size = dvsBounds.size(); size_t numVoxels = size.x * size.y * size.z; Util::Timer interruptTimer; ProgressReporter progress(2.5f, " Rasterization: "); size_t count = 0; // Iterate over voxels for (VoxelBuffer::iterator i = buffer->begin(dvsBounds), end = buffer->end(dvsBounds); i != end; ++i, ++count) { RasterizationState rState; RasterizationSample rSample; // Check if user terminated if (interruptTimer.elapsed() > 1.0) { Sys::Interrupt::throwOnAbort(); interruptTimer.reset(); } // Print progress if (count % 100 == 0) { progress.update(static_cast<float>(count) / numVoxels); } // Get sampling derivatives/voxel size rState.wsVoxelSize = mapping->wsVoxelSize(i.x, i.y, i.z); // Transform voxel position to world space Vector vsP = discToCont(V3i(i.x, i.y, i.z)); mapping->voxelToWorld(vsP, rState.wsP); // Sample the primitive this->getSample(rState, rSample); if (Math::max(rSample.value) > 0.0f) { if (rSample.wsVelocity.length2() == 0.0) { *i += rSample.value; } else { Vector vsEnd; Vector wsMotion = rSample.wsVelocity * RenderGlobals::dt(); mapping->worldToVoxel(rState.wsP + wsMotion, vsEnd); writeLine<true>(vsP, vsEnd, rSample.value, buffer); } } } }
void OnlineFileRequest::schedule(optional<Timestamp> expires) { if (impl.isPending(this) || impl.isActive(this)) { // There's already a request in progress; don't start another one. return; } // If we're not being asked for a forced refresh, calculate a timeout that depends on how many // consecutive errors we've encountered, and on the expiration time, if present. Duration timeout = std::min( http::errorRetryTimeout(failedRequestReason, failedRequests, retryAfter), http::expirationTimeout(expires, expiredRequests)); if (timeout == Duration::max()) { return; } // Emulate a Connection error when the Offline mode is forced with // a really long timeout. The request will get re-triggered when // the NetworkStatus is set back to Online. if (NetworkStatus::Get() == NetworkStatus::Status::Offline) { failedRequestReason = Response::Error::Reason::Connection; failedRequests = 1; timeout = Duration::max(); } timer.start(timeout, Duration::zero(), [&] { impl.activateOrQueueRequest(this); }); }
TriangleTree * ABTreeBuilder::buildTriangleTree(Rendering::Mesh * mesh) { #ifdef MINSG_PROFILING std::cout << "Profiling: Creating ABTree(triangles=" << trianglesPerNode << ", enlargement=" << allowedBBEnlargement << ")" << std::endl; Util::Utils::outputProcessMemory(); Util::Timer timer; timer.reset(); #endif auto k = new ABTree(mesh, trianglesPerNode, allowedBBEnlargement); #ifdef MINSG_PROFILING timer.stop(); std::cout << "Profiling: Construction of root node: " << timer.getMilliseconds() << " ms" << std::endl; Util::Utils::outputProcessMemory(); timer.reset(); #endif if (k->shouldSplit()) { k->split(); } #ifdef MINSG_PROFILING timer.stop(); std::cout << "Profiling: Construction of tree structure: " << timer.getMilliseconds() << " ms" << std::endl; Util::Utils::outputProcessMemory(); #endif return k; }
void Engine::setFPS(float dt) { static Util::Timer delay; static float sumDelta = 0.f; sumDelta += dt; if(!delay.running()) delay.start(); static std::ostringstream str; if(delay.isElapsed(200)) { str.str(""); str << "Trace Engine - " << (int)(1.f/dt) << " FPS"; renderSystem_->setWindowTitle(str.str().c_str()); str.str(""); str << (int)(1.f/dt); delay.stop(); } // fontRenderer_->renderText(str.str(), glm::vec3(10.f, 20.f, 50.f), "consola.ttf", glm::vec4(1.f, 1.f, 1.f, 1.f), 20); // fontRenderer_->renderText(Util::Str::formatTime(static_cast<int>(sumDelta)), glm::vec3(renderSystem_->resolution().x-100, 20.f, 50.f), "consola.ttf", glm::vec4(1.f, 1.f, 1.f, 1.f), 20); }
Test::TestResult TimeTest::timeMonotonicTest() { const int intervalNanos = 50 * 1000 * 1000; struct timespec interval = { 0, intervalNanos }; const int limitSec = 10 * 60; Util::Timer timer; timer.set(); double prev = timer.get(); while (prev <= limitSec) { nanosleep(&interval, NULL); double curr = timer.get(); if (curr < prev + 1.0e-9 * intervalNanos) { Log::test << "prev=" << prev << '\n'; Log::test << "curr=" << curr << '\n'; return TEST_RESULT(false); } prev = curr; } return TEST_RESULT(true); }
/*! * \brief Constructor * \param procedure Procedure to analyze */ LiveVariables::LiveVariables(const IR::Procedure &procedure, const FlowGraph &flowGraph) : mProcedure(procedure) { Util::Timer timer; timer.start(); // Construct the set of all variables in the procedure std::set<const IR::Symbol*> all; for(const std::unique_ptr<IR::Symbol> &symbol : mProcedure.symbols()) { all.insert(symbol.get()); } // Construct gen/kill sets for data flow analysis. std::map<const IR::Entry*, std::set<const IR::Symbol*>> gen; std::map<const IR::Entry*, std::set<const IR::Symbol*>> kill; for(const IR::Entry *entry : mProcedure.entries()) { for(const IR::Symbol *symbol : all) { std::set<const IR::Symbol*> &g = gen[entry]; if(entry->uses(symbol)) { // An entry which uses a symbol adds that symbol to the set of live symbols g.insert(symbol); } const IR::Symbol *assign = entry->assign(); if(assign && g.find(assign) == g.end()) { // An entry which assigns to a symbol and does not use it kills that symbol // from the live symbol set kill[entry].insert(assign); } } } // Perform a backwards data flow analysis on the procedure, using the gen and kill sets // constructed above. DataFlow<const IR::Symbol*> dataFlow; mMap = dataFlow.analyze(flowGraph, gen, kill, all, DataFlow<const IR::Symbol*>::Meet::Union, DataFlow<const IR::Symbol*>::Direction::Backward); Util::log("opt.time") << " LiveVariables(" << mProcedure.name() << "): " << timer.stop() << "ms" << std::endl; }
int test_statistics() { std::ofstream output("test_statistics.tsv"); output << "class\tnumEventTypes\tnumEventsOverall\tduration\n"; Util::Timer timer; for(uint32_t numRuns = 1; numRuns < 5; ++numRuns) { for(uint32_t numEventsOverall = 1; numEventsOverall <= 1000000; numEventsOverall *= 10) { for(uint32_t numEventTypes = 1; numEventTypes <= 32; numEventTypes *= 2) { timer.reset(); testStatistics(numEventTypes, numEventsOverall); timer.stop(); output << "Statistics\t" << numEventTypes << '\t' << numEventsOverall << '\t' << timer.getNanoseconds() << '\n'; timer.reset(); testProfiler(numEventTypes, numEventsOverall); timer.stop(); output << "Profiler\t" << numEventTypes << '\t' << numEventsOverall << '\t' << timer.getNanoseconds() << '\n'; } } } return EXIT_SUCCESS; }
//! ---|> Evaluator void OccOverheadEvaluator::measure(FrameContext & context,Node & node,const Geometry::Rect & /*r*/) { //float currentRenderingTime=0; //int numTests=0; //int numVBO=0; int numPoly=0; Util::Color4f clearColor(0.5f, 0.5f, 0.9f, 1.0f); { // 1. normal render pass // rc.clearScreen(0.5,0.5,0.9); // context.getRenderingContext().finish(); // node.display(rc,renderingFlags); context.getRenderingContext().clearScreen(clearColor); node.display(context,renderingFlags|USE_WORLD_MATRIX); context.getRenderingContext().clearScreen(clearColor); context.getRenderingContext().finish(); context.getStatistics().beginFrame(); node.display(context,renderingFlags|USE_WORLD_MATRIX); context.getRenderingContext().finish(); context.getStatistics().endFrame(); numPoly=static_cast<int>(context.getStatistics().getValueAsDouble(context.getStatistics().getTrianglesCounter())); } // 2. test all group nodes if their bb is visible and collect them std::deque<GroupNode *> visibleGroupNodes; { // collect geometry nodes in frustum const auto groupNodesInVFList = collectNodesInFrustum<GroupNode>(&node,context.getCamera()->getFrustum()); // setup occlusion queries int numQueries=groupNodesInVFList.size(); if (numQueries==0) { values->push_back(nullptr); // TODO!!! return; // TODO?? } auto queries = new Rendering::OcclusionQuery[numQueries]; // test bounding boxes context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::LEQUAL)); int i=0; // start queries Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext()); for(const auto & groupNode : groupNodesInVFList) { queries[i].begin(); // queries[i].fastBoxTest((*it)->getWorldBB()); Rendering::drawAbsBox(context.getRenderingContext(), groupNode->getWorldBB() ); queries[i].end(); ++i; } Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext()); i=0; // get results for(const auto & groupNode : groupNodesInVFList) { Geometry::Box extendedBox=groupNode->getWorldBB(); extendedBox.resizeAbs(context.getCamera()->getNearPlane()); if (queries[i].getResult() > 0 || extendedBox.contains(context.getCamera()->getWorldOrigin()) ) { visibleGroupNodes.push_back(groupNode); } ++i; } context.getRenderingContext().popDepthBuffer(); delete [] queries; } std::deque<GeometryNode *> geoNodesInVisibleGroupNodes; // 3. collect all direct geometry-node children { struct GeoChildrenCollector:public NodeVisitor { GeoChildrenCollector(std::deque<GeometryNode*> & _geoNodes,FrameContext & _context): geoNodes(_geoNodes),firstNode(true),frameContext(_context) {} virtual ~GeoChildrenCollector() {} std::deque<GeometryNode*> & geoNodes; bool firstNode; FrameContext & frameContext; // ---|> NodeVisitor NodeVisitor::status enter(Node * _node) override { // if this is the first call, continue... if(firstNode) { firstNode=false; return CONTINUE_TRAVERSAL; } // else collect the geometry children and break the traversal. GeometryNode * gn=dynamic_cast<GeometryNode *>(_node); if(gn){ if(frameContext.getCamera()->testBoxFrustumIntersection( _node->getWorldBB()) != Geometry::Frustum::intersection_t::OUTSIDE) geoNodes.push_back(gn); } return BREAK_TRAVERSAL; } }; for (auto & visibleGroupNode : visibleGroupNodes) { GeoChildrenCollector vis(geoNodesInVisibleGroupNodes,context); (visibleGroupNode)->traverse(vis); } } // 4. clear screen and measure time drawing children float perfectRenderingTime=0; { context.getRenderingContext().clearScreen(clearColor); context.getRenderingContext().finish(); Util::Timer timer; timer.reset(); for (auto & geoNodesInVisibleGroupNode : geoNodesInVisibleGroupNodes) { context.displayNode((geoNodesInVisibleGroupNode),renderingFlags|USE_WORLD_MATRIX); } context.getRenderingContext().finish(); timer.stop(); perfectRenderingTime=timer.getMilliseconds(); } // // Test-costs: // float result=numTests!=0?(currentRenderingTime-perfectRenderingTime)/numTests:0; // currentRenderingTime-perfRendering: // float result=currentRenderingTime-perfectRenderingTime; float result=numPoly>0?perfectRenderingTime*1000/numPoly:0; // std::cout <<currentRenderingTime<<"-"<<perfectRenderingTime<<"="<<result<<"\t"<<numTests<<"\n"; // std::cout <<numVBO<<":"<<geoNodesInVisibleGroupNodes.size()<<"\n"; // float result=perfectRenderingTime; // values.push_back(currentRenderingTime); // values.push_back(perfectRenderingTime); values->push_back(new Util::_NumberAttribute<float>(result)); // if(mode==SINGLE_VALUE){ // if(result>renderingTime || renderingTime==0) // renderingTime=result; // }else{ // values.push_back(result); // } // renderingTime=0; }
int test_spherical_sampling_serialization() { #ifdef MINSG_EXT_SVS std::cout << "Test serialization of SVS objects ... "; Util::Timer timer; timer.reset(); using namespace MinSG::SVS; MinSG::SceneManagement::SceneManager sceneManager; const uint32_t count = 10; std::array<Util::Reference<MinSG::GeometryNode>, count> nodes; for(uint_fast32_t i = 0; i < count; ++i) { nodes[i] = new MinSG::GeometryNode; sceneManager.registerNode(std::string("Node") + Util::StringUtils::toString(i), nodes[i].get()); } MinSG::VisibilitySubdivision::VisibilityVector vv; for(uint_fast32_t i = 0; i < count; ++i) { vv.setNode(nodes[i].get(), i); } std::vector<SamplePoint> samples; { using namespace Rendering::MeshUtils::PlatonicSolids; Util::Reference<Rendering::Mesh> mesh = createEdgeSubdivisionSphere(createIcosahedron(), 4); auto accessor = Rendering::PositionAttributeAccessor::create(mesh->openVertexData(), Rendering::VertexAttributeIds::POSITION); for(std::size_t i = 0; accessor->checkRange(i); ++i) { samples.emplace_back(accessor->getPosition(i)); } } { std::stringstream stream; stream.precision(std::numeric_limits<long double>::digits10); // Serialize for(const auto & sample : samples) { stream << sample.getPosition() << ' '; sample.getValue().serialize(stream, sceneManager); stream << ' '; } // Unserialize std::vector<SamplePoint> newSamples; for(std::size_t s = 0; s < samples.size(); ++s) { Geometry::Vec3f pos; stream >> pos; SamplePoint sample(pos); sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager)); newSamples.push_back(sample); } for(std::size_t s = 0; s < samples.size(); ++s) { const SamplePoint & oldSample = samples[s]; const SamplePoint & newSample = newSamples[s]; if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } const auto & oldVV = oldSample.getValue(); const auto & newVV = newSample.getValue(); for(uint_fast32_t n = 0; n < count; ++n) { if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } } } } VisibilitySphere visibilitySphere(Geometry::Sphere_f(Geometry::Vec3f(1.0f, 2.0f, 3.0f), 17.0f), samples); { std::stringstream stream; stream.precision(std::numeric_limits<long double>::digits10); // Serialize stream << visibilitySphere.getSphere() << ' ' << samples.size(); for(const auto & sample : samples) { stream << ' ' << sample.getPosition() << ' '; sample.getValue().serialize(stream, sceneManager); stream << ' '; } // Unserialize Geometry::Sphere_f sphere; stream >> sphere; std::size_t sampleCount; stream >> sampleCount; std::vector<SamplePoint> newSamples; for(std::size_t s = 0; s < sampleCount; ++s) { Geometry::Vec3f pos; stream >> pos; SamplePoint sample(pos); sample.setValue(MinSG::VisibilitySubdivision::VisibilityVector::unserialize(stream, sceneManager)); newSamples.push_back(sample); } VisibilitySphere newVisibilitySphere(sphere, newSamples); if(!(visibilitySphere.getSphere() == newVisibilitySphere.getSphere())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } for(std::size_t s = 0; s < samples.size(); ++s) { const SamplePoint & oldSample = visibilitySphere.getSamples()[s]; const SamplePoint & newSample = newVisibilitySphere.getSamples()[s]; if(oldSample.getPosition().distance(newSample.getPosition()) > std::numeric_limits<float>::epsilon()) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } const auto & oldVV = oldSample.getValue(); const auto & newVV = newSample.getValue(); for(uint_fast32_t n = 0; n < count; ++n) { if(oldVV.getBenefits(nodes[n].get()) != newVV.getBenefits(nodes[n].get())) { std::cout << "Serialization/unserialization failed." << std::endl; return EXIT_FAILURE; } } } } timer.stop(); std::cout << "done (duration: " << timer.getSeconds() << " s).\n"; #endif /* MINSG_EXT_SVS */ return EXIT_SUCCESS; }
// Sets the timeout period for the play in seconds inline void startTimer(void) { timer.start(); int tm = timer.split(); lastRoleReassignTime = tm - 2*roleReassignPeriod; //so that 1st call to timedOut gives shouldRolesReassign = true. 2* just to be safe }
/*! * \brief Optimize a program * \param program Program to optimize */ void Optimizer::optimize(IR::Program &program) { std::vector<Transform::Transform*> startingTransforms; std::map<Transform::Transform*, std::vector<Transform::Transform*>> transformMap; // Build the list of all transforms startingTransforms.push_back(Transform::CopyProp::instance()); startingTransforms.push_back(Transform::ConstantProp::instance()); startingTransforms.push_back(Transform::DeadCodeElimination::instance()); startingTransforms.push_back(Transform::ThreadJumps::instance()); startingTransforms.push_back(Transform::LoopInvariantCodeMotion::instance()); startingTransforms.push_back(Transform::CommonSubexpressionElimination::instance()); // Transforms to run after CopyProp transformMap[Transform::CopyProp::instance()].push_back(Transform::DeadCodeElimination::instance()); // Transforms to run after Constant Prop transformMap[Transform::ConstantProp::instance()].push_back(Transform::DeadCodeElimination::instance()); // Transforms to run after DeadCodeElimination transformMap[Transform::DeadCodeElimination::instance()].push_back(Transform::ConstantProp::instance()); transformMap[Transform::DeadCodeElimination::instance()].push_back(Transform::CopyProp::instance()); // Transforms to run after CommonSubexpressionElimination transformMap[Transform::CommonSubexpressionElimination::instance()].push_back(Transform::CopyProp::instance()); // Optimize each procedure in turn for(std::unique_ptr<IR::Procedure> &procedure : program.procedures()) { Analysis::Analysis analysis(*procedure); // Queue of transformations to run Util::UniqueQueue<Transform::Transform*> transforms; // Start by running each optimization pass once for(Transform::Transform *transform : startingTransforms) { transforms.push(transform); } Util::log("opt") << "Optimizations (" << procedure->name() << "):" << std::endl; // Run optimization passes until there are none left while(!transforms.empty()) { Transform::Transform *transform = transforms.front(); transforms.pop(); // Run the transform Util::Timer timer; timer.start(); bool changed = transform->transform(*procedure, analysis); Util::log("opt.time") << transform->name() << ": " << timer.stop() << "ms" << std::endl; if(changed) { procedure->print(Util::log("opt.ir")); Util::log("opt.ir") << std::endl; // If the transform changed the IR, add its follow-up transformations to the queue std::vector<Transform::Transform*> &newTransforms = transformMap[transform]; for(Transform::Transform *newTransform : newTransforms) { transforms.push(newTransform); } } } Util::log("opt") << std::endl; } }
int test_large_scene(Util::UI::Window * window, Util::UI::EventContext & eventContext) { // texture registry std::map<std::string, Util::Reference<Rendering::Texture> > textures; std::cout << "Create FrameContext...\n"; FrameContext fc; unsigned int renderingFlags = /*BOUNDING_BOXES|SHOW_META_OBJECTS|*/FRUSTUM_CULLING/*|SHOW_COORD_SYSTEM*/;//|SHOW_COORD_SYSTEM; std::cout << "Create scene graph...\n"; Util::Reference<GroupNode> root = new MinSG::ListNode(); /// Skybox SkyboxState * sb = SkyboxState::createSkybox("Data/texture/?.bmp"); root->addState(sb); /// Some shperes... { std::default_random_engine engine; std::uniform_real_distribution<float> coordinateDist(0.0f, 200.0f); std::vector<Util::Reference<Rendering::Mesh> > spheres; Util::Reference<Rendering::Mesh> icosahedron = Rendering::MeshUtils::PlatonicSolids::createIcosahedron(); for(int i=0;i<6;++i) spheres.push_back(Rendering::MeshUtils::PlatonicSolids::createEdgeSubdivisionSphere(icosahedron.get(), i)); // 6... 81920 triangles each for (int i = 0; i < 1000; i++) { // create a real clone inclusive internal data! MinSG::GeometryNode * gn = new GeometryNode(spheres[std::uniform_int_distribution<std::size_t>(0, spheres.size() - 1)(engine)]->clone()); gn->moveRel(Geometry::Vec3(coordinateDist(engine), coordinateDist(engine), coordinateDist(engine))); root->addChild(gn); gn->scale(0.1 + std::uniform_real_distribution<float>(0.0f, 1000.0f)(engine) / 400.0); } } /// Camera Node * schwein = loadModel(Util::FileName("Data/model/Schwein.low.t.ply"), MESH_AUTO_CENTER | MESH_AUTO_SCALE); ListNode * camera = new ListNode(); CameraNode * camNode = new CameraNode(); camNode->setViewport(Geometry::Rect_i(0, 0, 1024, 768)); camNode->setNearFar(0.1, 2000); camNode->applyVerticalAngle(80); camNode->moveRel(Geometry::Vec3(0, 4, 10)); camera->addChild(camNode); camera->addChild(schwein); schwein->moveRel(Geometry::Vec3(0, 0, 0)); schwein->rotateLocal_deg(180, Geometry::Vec3(0, 1, 0)); LightNode * myHeadLight = LightNode::createPointLight(); myHeadLight->scale(1); myHeadLight->moveRel(Geometry::Vec3(0, 0, 0)); camera->addChild(myHeadLight); LightingState * lightState = new LightingState; lightState->setLight(myHeadLight); root->addState(lightState); root->addChild(camera); /// Eventhandler MoveNodeHandler * eh = new MoveNodeHandler(); MoveNodeHandler::initClaudius(eh, camera); // --------------------------------------------------------------------------------------------- Rendering::RenderingContext::clearScreen(Util::Color4f(0.5f, 0.5f, 0.5f, 0.5f)); // ---- GET_GL_ERROR(); uint32_t fpsFrameCounter = 0; Util::Timer fpsTimer; std::cout << "\nEntering main loop...\n"; // program main loop bool done = false; while (!done) { ++fpsFrameCounter; double seconds = fpsTimer.getSeconds(); if (seconds > 1.0) { double fps = static_cast<double> (fpsFrameCounter) / seconds; std::cout << "\r " << fps << " fps "; std::cout.flush(); fpsTimer.reset(); fpsFrameCounter = 0; } // message processing loop eventContext.getEventQueue().process(); while (eventContext.getEventQueue().getNumEventsAvailable() > 0) { Util::UI::Event event = eventContext.getEventQueue().popEvent(); // check for messages switch (event.type) { // exit if the window is closed case Util::UI::EVENT_QUIT: done = true; break; // check for keypresses case Util::UI::EVENT_KEYBOARD: { if(event.keyboard.pressed && event.keyboard.key == Util::UI::KEY_ESCAPE) { done = true; } break; } } // end switch } // end of message processing // apply translation eh->execute(); // clear screen Rendering::RenderingContext::clearScreen(Util::Color4f(0.0f, 0.0f, 0.0f, 1.0f)); // enable Camera fc.setCamera(camNode); // render Scene root->display(fc, renderingFlags); window->swapBuffers(); GET_GL_ERROR(); } // end main loop // destroy scene graph MinSG::destroy(root.get()); root = nullptr; // all is well ;) std::cout << "Exited cleanly\n"; //system("pause"); return EXIT_SUCCESS; }
int test_OutOfCore() { #ifdef MINSG_EXT_OUTOFCORE const bool verbose = true; // Tests for MinSG::OutOfCore::CacheObjectPriority if(sizeof(MinSG::OutOfCore::CacheObjectPriority) != 8) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(1, 2, 3) == MinSG::OutOfCore::CacheObjectPriority(1, 2, 3))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(1, 100, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 0, 0))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(2, 1, 100) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 0))) { return EXIT_FAILURE; } if(!(MinSG::OutOfCore::CacheObjectPriority(2, 2, 1) < MinSG::OutOfCore::CacheObjectPriority(2, 2, 2))) { return EXIT_FAILURE; } std::default_random_engine engine; std::uniform_int_distribution<std::size_t> vertexCountDist(10, 1000); const uint32_t numMeshes = 30000; const Util::TemporaryDirectory tempDir("MinSGTest_OutOfCore"); // Create empty meshes and save them into a subdirectory. { Rendering::VertexDescription vertexDesc; vertexDesc.appendPosition3D(); for(uint_fast32_t i = 0; i < numMeshes; ++i) { Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, vertexCountDist(engine), 64); Rendering::MeshVertexData & vertexData = mesh->openVertexData(); std::fill_n(vertexData.data(), vertexData.dataSize(), 0); vertexData.markAsChanged(); Rendering::MeshIndexData & indexData = mesh->openIndexData(); std::fill_n(indexData.data(), indexData.getIndexCount(), 0); indexData.markAsChanged(); const std::string numberString = Util::StringUtils::toString<uint32_t>(i); Rendering::Serialization::saveMesh(mesh.get(), Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf")); } } // Set up the OutOfCore system. MinSG::FrameContext frameContext; MinSG::OutOfCore::setUp(frameContext); MinSG::OutOfCore::CacheManager & manager = MinSG::OutOfCore::getCacheManager(); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILE_SYSTEM, 0); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::FILES, 512 * kibibyte); manager.addCacheLevel(MinSG::OutOfCore::CacheLevelType::MAIN_MEMORY, 256 * kibibyte); Util::Timer addTimer; addTimer.reset(); std::cout << "Adding meshes ..." << std::flush; // Add the meshes to the OutOfCore system. std::vector<Util::Reference<Rendering::Mesh> > meshes; meshes.reserve(numMeshes); static const Geometry::Box boundingBox(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); for(uint_fast32_t i = 0; i < numMeshes; ++i) { const std::string numberString = Util::StringUtils::toString<uint32_t>(i); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); } manager.trigger(); addTimer.stop(); std::cout << " done (" << addTimer.getSeconds() << " s)" << std::endl; Util::Timer displayTimer; Util::Timer assureLocalTimer; Util::Timer overallTimer; overallTimer.reset(); uint32_t frame = 0; { // Simulate frames to get the OutOfCore system working. std::uniform_int_distribution<std::size_t> indexDist(0, meshes.size() - 1); for(; frame < 10; ++frame) { std::cout << "Executing frame " << frame << " ..." << std::flush; frameContext.beginFrame(); displayTimer.reset(); // Simulate display of meshes to change the priorities of the system. for(uint32_t i = 0; i < meshes.size() / 2; ++i) { const uint32_t meshIndex = indexDist(engine); Rendering::Mesh * mesh = meshes[meshIndex].get(); manager.meshDisplay(mesh); } manager.trigger(); displayTimer.stop(); assureLocalTimer.reset(); for(uint32_t i = 0; i < 10; ++i) { const uint32_t meshIndex = indexDist(engine); Rendering::Mesh * mesh = meshes[meshIndex].get(); const Rendering::MeshVertexData & vd = mesh->openVertexData(); const Rendering::MeshIndexData & id = mesh->openIndexData(); if (!vd.hasLocalData() || !id.hasLocalData()) { std::cout << "Error: Mesh has no local data." << std::endl; return EXIT_FAILURE; } } assureLocalTimer.stop(); frameContext.endFrame(); std::cout << " done (display: " << displayTimer.getSeconds() << " s, assureLocal: " << assureLocalTimer.getSeconds() << " s)" << std::endl; if(verbose) { outputCacheLevelInformation(); } } } for(uint32_t round = 0; round < 10; ++round) { Util::Timer addAgainTimer; addAgainTimer.reset(); std::cout << "Adding additional meshes ..." << std::flush; // Simulate loading a second scene by adding meshes again. meshes.reserve(meshes.size() + 3 * numMeshes); for(uint_fast32_t i = 0; i < numMeshes; ++i) { const std::string numberString = Util::StringUtils::toString<uint32_t>(i); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); meshes.push_back(MinSG::OutOfCore::addMesh(Util::FileName(tempDir.getPath().getDir() + numberString + ".mmf"), boundingBox)); } manager.trigger(); addAgainTimer.stop(); std::cout << " done (" << addAgainTimer.getSeconds() << " s)" << std::endl; // Simulate frames to get the OutOfCore system working. std::normal_distribution<double> indexDist(meshes.size() / 2, std::sqrt(meshes.size() / 2)); const auto untilFrame = frame + 5; for(; frame < untilFrame; ++frame) { std::cout << "Executing frame " << frame << " ..." << std::flush; frameContext.beginFrame(); displayTimer.reset(); // Simulate display of meshes to change the priorities of the system. for(uint32_t i = 0; i < meshes.size() / 10; ++i) { const std::size_t meshIndex = std::max(static_cast<std::size_t>(0), std::min(static_cast<std::size_t>(indexDist(engine)), meshes.size() - 1)); Rendering::Mesh * mesh = meshes[meshIndex].get(); manager.meshDisplay(mesh); } manager.trigger(); displayTimer.stop(); frameContext.endFrame(); std::cout << " done (display: " << displayTimer.getSeconds() << " s)" << std::endl; if(verbose) { outputCacheLevelInformation(); } } } overallTimer.stop(); std::cout << "Overall duration: " << overallTimer.getSeconds() << " s" << std::endl; MinSG::OutOfCore::shutDown(); return EXIT_SUCCESS; #else /* MINSG_EXT_OUTOFCORE */ return EXIT_FAILURE; #endif /* MINSG_EXT_OUTOFCORE */ }
int main(int argc, char** argv) { // LOAD OBJ Manifold m; if(argc>1) { ArgExtracter ae(argc, argv); do_aabb = ae.extract("-A"); do_obb = ae.extract("-O"); ae.extract("-x", vol_dim[0]); ae.extract("-y", vol_dim[1]); ae.extract("-z", vol_dim[2]); do_ray_tests = ae.extract("-R"); flip_normals = ae.extract("-f"); string file = ae.get_last_arg(); cout << "loading " << file << "... " << flush; load(file, m); cout << " done" << endl; } else { string fn("../../data/bunny-little.x3d"); x3d_load(fn, m); } cout << "Volume dimensions " << vol_dim << endl; if(!valid(m)) { cout << "Not a valid manifold" << endl; exit(0); } triangulate_by_edge_face_split(m); Vec3d p0, p7; bbox(m, p0, p7); Mat4x4d T = fit_bounding_volume(p0,p7,10); cout << "Transformation " << T << endl; for(VertexIDIterator v = m.vertices_begin(); v != m.vertices_end(); ++v) m.pos(*v) = T.mul_3D_point(m.pos(*v)); RGridf grid(vol_dim,FLT_MAX); Util::Timer tim; float T_build_obb=0, T_build_aabb=0, T_dist_obb=0, T_dist_aabb=0, T_ray_obb=0, T_ray_aabb=0; if(do_obb) { cout << "Building OBB Tree" << endl; tim.start(); OBBTree obb_tree; build_OBBTree(m, obb_tree); T_build_obb = tim.get_secs(); cout << "Computing distances from OBB Tree" << endl; tim.start(); DistCompCache<OBBTree> dist(&obb_tree); for_each_voxel(grid, dist); T_dist_obb = tim.get_secs(); cout << "Saving distance field" << endl; save_raw_float("obb_dist.raw", grid); if(do_ray_tests) { cout << "Ray tests on OBB Tree" << endl; tim.start(); RayCast<OBBTree> ray(&obb_tree); for_each_voxel(grid, ray); T_ray_obb = tim.get_secs(); cout << "Saving ray volume" << endl; save_raw_float("obb_ray.raw", grid); } } if(do_aabb) { cout << "Building AABB Tree" << endl; tim.start(); AABBTree aabb_tree; build_AABBTree(m, aabb_tree); T_build_aabb = tim.get_secs(); cout << "Computing distances from AABB Tree" << endl; tim.start(); DistCompCache<AABBTree> dist(&aabb_tree); for_each_voxel(grid, dist); T_dist_aabb = tim.get_secs(); cout << "Saving distance field" << endl; save_raw_float("aabb_dist.raw", grid); if(do_ray_tests) { cout << "Ray tests on AABB tree" << endl; tim.start(); RayCast<AABBTree> ray(&aabb_tree); for_each_voxel(grid, ray); T_ray_aabb = tim.get_secs(); cout << "Saving ray volume" << endl; save_raw_float("aabb_ray.raw", grid); } } cout.width(10); cout << "Poly"; cout.width(11); cout <<"build_obb"; cout.width(12); cout << "build_aabb"; cout.width(10); cout << "dist_obb" ; cout.width(10); cout << "dist_aabb"; cout.width(10); cout << "ray_obb" ; cout.width(10); cout << "ray_aabb"; cout << endl; cout.precision(4); cout.width(10); cout << m.no_faces() << " "; cout.width(10); cout << T_build_obb; cout.width(12); cout << T_build_aabb; cout.width(10); cout << T_dist_obb; cout.width(10); cout << T_dist_aabb; cout.width(10); cout << T_ray_obb; cout.width(10); cout << T_ray_aabb; cout << endl; }
int test_spherical_sampling() { #ifdef MINSG_EXT_SVS std::cout << "Test SVS ... "; Util::Timer timer; timer.reset(); MinSG::SceneManagement::SceneManager sceneManager; MinSG::FrameContext frameContext; Rendering::VertexDescription vertexDesc; vertexDesc.appendPosition3D(); Util::Reference<Rendering::Mesh> boxMesh = Rendering::MeshUtils::MeshBuilder::createBox(vertexDesc, Geometry::Box(Geometry::Vec3f(0.5f, 0.5f, 0.5f), 1)); /* * Create a 1D array of n unit-size boxes in the x axis * * / * ..L2 * / / * ......L1 / * / / / * ...L0.... / / * / / / / / * ------------------------- ... ----- * | 0 | 1 | 2 | 3 | 4 | 5 | | n | * | | | | | | | | | * ------------------------- ... ----- * ^ ^ ^ * | | | * x=0 x=4 x=n * * The first three boxes are put into the first list node L0. * L0 together with the fourth box are put into the second list node L1. */ const uint32_t count = 512; std::vector<Util::Reference<MinSG::ListNode>> listNodes; std::vector<Util::Reference<MinSG::GeometryNode>> boxNodes; for(uint_fast32_t x = 0; x < count; ++x) { MinSG::GeometryNode * geoNode = new MinSG::GeometryNode(boxMesh); geoNode->moveLocal(Geometry::Vec3f(x, 0, 0)); sceneManager.registerNode(std::string("Node") + Util::StringUtils::toString(x), geoNode); boxNodes.push_back(geoNode); if(x != 1 && x != 2) { listNodes.push_back(new MinSG::ListNode); } if(x < 3) { listNodes.front()->addChild(geoNode); } else { listNodes[x - 2]->addChild(listNodes[x - 3].get()); listNodes[x - 2]->addChild(geoNode); } } // Debug output of created scene graph //MinSG::GraphVizOutput::treeToFile(listNodes.back().get(), &sceneManager, Util::FileName("output.dot")); // Perform the sampling std::vector<Geometry::Vec3f> positions; positions.emplace_back(-1, 0, 0); // left positions.emplace_back(1, 0, 0); // right positions.emplace_back(0, 1, 0); // top positions.emplace_back(0, 0, 1); // back // The resolution has to be at least the number of boxes. Otherwise, boxes will be missed during visibility testing. MinSG::SVS::PreprocessingContext preprocessingContext(sceneManager, frameContext, listNodes.back().get(), positions, count, false, false); while(!preprocessingContext.isFinished()) { preprocessingContext.preprocessSingleNode(); } // Validate the results for(uint_fast32_t listIndex = 0; listIndex < count - 2; ++listIndex) { MinSG::ListNode * listNode = listNodes[listIndex].get(); const MinSG::SVS::VisibilitySphere & visibilitySphere = MinSG::SVS::retrieveVisibilitySphere(listNode); { // Because the geometry is built of axis-aligned bounding boxes only, the sphere has to contain the group's bounding box. assert(visibilitySphere.getSphere().distance(listNode->getBB().getMin()) < 1.0e-9); assert(visibilitySphere.getSphere().distance(listNode->getBB().getMax()) < 1.0e-9); } { // left => only first box must be visible const auto vv = visibilitySphere.queryValue(positions[0], MinSG::SVS::INTERPOLATION_NEAREST); assert(vv.getBenefits(boxNodes.front().get()) > 0); for(uint_fast32_t boxIndex = 1; boxIndex < count; ++boxIndex) { MinSG::GeometryNode * geoNode = boxNodes[boxIndex].get(); assert(vv.getBenefits(geoNode) == 0); } } { // right => only last box inside the subtree must be visible const auto vv = visibilitySphere.queryValue(positions[1], MinSG::SVS::INTERPOLATION_NEAREST); const uint32_t lastBoxIndex = listIndex + 2; assert(vv.getBenefits(boxNodes[lastBoxIndex].get()) > 0); for(uint_fast32_t boxIndex = 0; boxIndex < count; ++boxIndex) { if(boxIndex != lastBoxIndex) { MinSG::GeometryNode * geoNode = boxNodes[boxIndex].get(); assert(vv.getBenefits(geoNode) == 0); } } } // top, back => all boxes in the subtree must be visible for(uint_fast32_t posIndex = 2; posIndex <= 3; ++posIndex) { const auto vv = visibilitySphere.queryValue(positions[posIndex], MinSG::SVS::INTERPOLATION_NEAREST); const auto geoNodes = MinSG::collectNodes<MinSG::GeometryNode>(listNode); for(const auto & geoNode : geoNodes) { assert(vv.getBenefits(geoNode) > 0); } } } boxNodes.clear(); MinSG::destroy(listNodes.back().get()); listNodes.clear(); timer.stop(); std::cout << "done (duration: " << timer.getSeconds() << " s).\n"; #endif /* MINSG_EXT_SVS */ return EXIT_SUCCESS; }
// Sets the timeout period for the play in seconds inline void startTimer(void) { timer.start(); }