#include #include #include <../CEGUIRenderer/include/OgreCEGUIRenderer.h> #include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h> #include <../CEGUIRenderer/include/OgreCEGUITexture.h> #include #include "TerrainFrameListener.h" #include "OgrePlatformQueryManager.h" #include "VisibilityInfo.h" #include "OgreOcclusionQueriesQueryManager.h" #include "TestCullingTerrainApplication.h" #include //-- captions for overlays String TerrainFrameListener::msAlgorithmCaptions[] = { "Coherent Hierarchical Culling", "View Frustum Culling", "Stop and Wait Culling", "Standard Rendering" }; //-- captions for overlays String TerrainFrameListener::msApprevAlgorithmCaptions[] = { "CHC", "VFC", "SWC", "DEF" }; String TerrainFrameListener::msQueryTypeCaptions[] = { "from camera", "from viewpoint" }; String TerrainFrameListener::msQueryRelativeVisCaptions[] = { "visible pixels", "relative visibility" }; String TerrainFrameListener::msQueryMethodCaptions[] = { "occlusion queries", "item buffer" }; Real TerrainFrameListener::msObjectTerrainOffsets[] = { 0, -0.1, //7, 0 }; Real TerrainFrameListener::msObjectScales[] = { 0.07, 0.03, //0.1, 0.03 }; String TerrainFrameListener::msObjectCaptions[] = { "robot", "athene", "natFX_Tree1_LOD2", //"tree2", //"HongKong_Tower", "ninja" //"ogrehead" }; // output file for frame info const char* frames_out_filename = "frame.out"; // output file for object positions / orientations const char* objects_out_filename = "objects.out"; std::ofstream video_out("video.lst"); // if we are recording a demo static const bool DEMO_HACK = false; //using namespace GtpVisibility; //----------------------------------------------------------------------- TerrainFrameListener::TerrainFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer, TerrainContentGenerator *sceneGenerator, Camera *vizCamera, SceneNode *camNode, Light *sunLight, TestCullingTerrainApplication *app): mCamera(cam), mWindow(win), mNumScreenShots(0), mTimeDelay(0), mSceneDetailIndex(0), mMoveScale(0.0f), mRotScale(0.0f), mTranslateVector(Vector3::ZERO), mAniso(1), mFiltering(TFO_BILINEAR), mGUIRenderer(renderer), mSceneMgr(sceneManager), mCurrentObject(NULL), mTerrainContentGenerator(sceneGenerator), mVisibilityThreshold(0), mAssumedVisibility(0), mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING), mNodeVizMode(NODEVIZ_NONE), mVizCameraHeight(Real(2000.0)), mCamNode(camNode), mAppState(WALKTHROUGH), mCurrentFrame(0), mReplayTimeElapsed(0), mRotateSpeed(72), mMoveSpeed(50), mVizCamera(vizCamera), mStatsOn(true), mShutdownRequested(false), mLMouseDown(false), mRMouseDown(false), mShowOctree(false), mShowViewCells(false), mUseDepthPass(false), mTestGeometryForVisibleLeaves(false), mShowVisualization(false), mCullCamera(false), mRecordFrames(false), mShowShadows(false), mShowHelp(false), mDisplayCameraDetails(false), mVisualizeCulledNodes(false), mSunLight(sunLight), mShiftPressed(false), mShowQueryStats(false), mQueryManager(NULL), mVisibilityManager(NULL), mDelayedQueriesIssued(0.0), mDelayedTraversedNodes(0.0), mCurrentObjectType(0), mApplication(app), mUseAnimation(false), mDeleteObjects(false), mUseItemBuffer(false), mItemBufferMode(GtpVisibility::QueryManager::PATCH_VISIBILITY), mRecordVideo(false), mPureRenderTimeFps(0.0), mNumVideoFrames(0), mPrecomputedFps(0), mRecordDemo(false), mSavePrecomputedFps(false), mUseBufferedInputMouse(false), mVizScale(25), mUseViewCells(false), mViewCellsLoaded(false), mUseVisibilityFilter(false), mFloorDist(2), mFlushQueue(false) { //mInputDevice = PlatformManager::getSingleton().createInputReader(); //mInputDevice->initialise(win, true, true); mEventProcessor = new EventProcessor(); mEventProcessor->initialise(win); mEventProcessor->startProcessingEvents(); mEventProcessor->addMouseListener(this); mEventProcessor->addMouseMotionListener(this); mEventProcessor->addKeyListener(this); mInputDevice = mEventProcessor->getInputReader(); mInputDevice->setBufferedInput(true, mUseBufferedInputMouse); // create ray query executor, used to place objects in terrain mRayQueryExecutor = new RayQueryExecutor(mSceneMgr); ////////// //-- overlays mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay"); mHelpOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/HelpOverlay"); mQueryOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/QueryOverlay"); mCullStatsOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/CullStatsOverlay"); String ext = "Example/Visibility/"; //-- overlays initVisStatsOverlay(); // visibility stats overlay initHelpOverlay(); // help overlay initQueryOverlay(); // visibility query stats overlay // show stats overlays if (!DEMO_HACK) { showStats(true); } else { mMyStatsOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/MyStatsOverlay"); mMyStatsAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/MyAlgorithmInfo"); mMyStatsAlgorithmInfo->setCaption(""); const int top = 10; mMyStatsAlgorithmInfo->setTop(top); char str[100]; sprintf(str,": %d", 0); mMyStatsFpsInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/MyFpsInfo"); mMyStatsFpsInfo->setCaption(str); mMyStatsOverlay->show(); } // loading view cells overlay mLoadingOverlay = OverlayManager::getSingleton().getByName("Example/Visibility/LoadingOverlay"); mMyLoadingInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Loading/MyLoadingInfo"); mMyLoadingInfo->setCaption("loading view cells ..."); mLoadingOverlay->hide(); // note: larger magnification for terrain to show single objects if (TestCullingTerrainApplication::msShowHillyTerrain) mVizScale = 25; else mVizScale = 1; // the scale factor for the visualized bounding boxes mSceneMgr->setOption("NodeVizScale", &mVizScale); ///////// //-- set the current culling algorithm type //setAlgorithm(mApplication->mAlgorithm); bool isNormalExecution; mSceneMgr->getOption("NormalExecution", &isNormalExecution); if (isNormalExecution) { // no algorithm mCurrentAlgorithm = GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS; } else { mSceneMgr->getOption("Algorithm", &mCurrentAlgorithm); } applyCurrentAlgorithm(); /////////////////////////////// // set scene manager options setTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves); //mSceneMgr->setOption("UseDepthPass", &mUseDepthPass); mSceneMgr->getOption("UseDepthPass", &mUseDepthPass); if (mUseDepthPass) mUseDepthPassInfo->setCaption(": true"); else mUseDepthPassInfo->setCaption(": false"); mSceneMgr->getOption("FlushQueue", &mFlushQueue); if (mFlushQueue) LogManager::getSingleton().logMessage("initial setting: flushing queue"); else LogManager::getSingleton().logMessage("initial setting: not flushing queue"); mSceneMgr->setOption("ShowOctree", &mShowOctree); mSceneMgr->setOption("ShowViewCells", &mShowViewCells); mSceneMgr->setOption("CullCamera", &mCullCamera); mSceneMgr->setOption("PrepareVisualization", &mShowVisualization); applyObjectType(); // initialise timer mTimer = Root::getSingleton().getTimer(); mTimeFrameEnded = mTimeFrameStarted = mTimer->getMilliseconds(); if (0 && (mSceneMgr->getSceneNode("robot Entity1Node")-> getAttachedObject(0)->getMovableType() == "Entity")) Ogre::LogManager::getSingleton().logMessage("found entity"); // init view cell parameters //mSceneMgr->setOption("UseViewCells", &mUseViewCells); mSceneMgr->setOption("UseVisibilityFilter", &mUseVisibilityFilter); // reset statistics mWalkthroughStats.Reset(); } //----------------------------------------------------------------------- void TerrainFrameListener::switchMouseMode() { mUseBufferedInputMouse = !mUseBufferedInputMouse; mInputDevice->setBufferedInput(true, mUseBufferedInputMouse); if (!mUseBufferedInputMouse) CEGUI::MouseCursor::getSingleton().hide(); else CEGUI::MouseCursor::getSingleton().show(); } //----------------------------------------------------------------------- TerrainFrameListener::~TerrainFrameListener() { OGRE_DELETE(mRayQueryExecutor); OGRE_DELETE(mEventProcessor); OGRE_DELETE(mQueryManager); } //----------------------------------------------------------------------- void TerrainFrameListener::mouseMoved(MouseEvent *e) { // Update CEGUI with the mouse motion CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight()); } //----------------------------------------------------------------------- void TerrainFrameListener::mousePressed(MouseEvent* e) { // Left mouse button down if (e->getButtonID() & InputEvent::BUTTON0_MASK) { CEGUI::MouseCursor::getSingleton().hide(); // Setup the ray scene query Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY()); Real val = Math::RangeRandom(0, 360); // random rotation // get results, create a node/entity on the position mCurrentObject = mTerrainContentGenerator->GenerateSceneObject(mouseRay.getOrigin(), Vector3(val, 0, 0), msObjectCaptions[mCurrentObjectType]); mLMouseDown = true; } // Right mouse button down /*else if (e->getButtonID() & InputEvent::BUTTON1_MASK) { CEGUI::MouseCursor::getSingleton().hide(); mRMouseDown = true; }*/ } //----------------------------------------------------------------------- void TerrainFrameListener::mouseDragDropped(MouseEvent* e) { // Left mouse button up if (e->getButtonID() & InputEvent::BUTTON0_MASK) { CEGUI::MouseCursor::getSingleton().show(); mLMouseDown = false; } // Right mouse button up else if (e->getButtonID() & InputEvent::BUTTON1_MASK) { CEGUI::MouseCursor::getSingleton().show(); mRMouseDown = false; } } //----------------------------------------------------------------------- void TerrainFrameListener::mouseReleased(MouseEvent* e) { // Left mouse button up if (e->getButtonID() & InputEvent::BUTTON0_MASK) { CEGUI::MouseCursor::getSingleton().show(); // start animation: only robot has animation phases if (mCurrentObject && (mCurrentObjectType == TestCullingTerrainApplication::ROBOT)) { // HACK: not neccesary the last element Entity *ent = mTerrainContentGenerator->GetGeneratedEntities()->back(); EntityState *entState = new EntityState(ent, EntityState::MOVING, Math::RangeRandom(0.5, 1.5)); mApplication->getEntityStates().push_back(entState); } mLMouseDown = false; } // Right mouse button up else if (e->getButtonID() & InputEvent::BUTTON1_MASK) { CEGUI::MouseCursor::getSingleton().show(); mRMouseDown = false; } } //----------------------------------------------------------------------- void TerrainFrameListener::mouseDragged(MouseEvent *e) { // If we are dragging the left mouse button. if (mLMouseDown) { if (!mCurrentObject) return; Vector3 queryResult; Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY()); if (mRayQueryExecutor->executeRayQuery(&queryResult, mouseRay)) { // apply offset so object is ON terrain queryResult.y += msObjectTerrainOffsets[mCurrentObjectType]; mCurrentObject->setPosition(queryResult); } } } //----------------------------------------------------------------------- bool TerrainFrameListener::frameStarted(const FrameEvent &evt) { if (mWindow->isClosed()) { return false; } if (mDeleteObjects) { mApplication->deleteEntityStates(); mTerrainContentGenerator->RemoveGeneratedObjects(); mDeleteObjects = false; } if (mUseAnimation) { // update animation phases mApplication->updateAnimations(evt.timeSinceLastFrame); } if (mDisplayCameraDetails) // Print camera details { mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) + " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation())); } //-- setup what is needed for immediate mouse/key movement if (mTimeDelay >= 0) { mTimeDelay -= evt.timeSinceLastFrame; } // If this is the first frame, pick a speed if (evt.timeSinceLastFrame == 0) { mMoveScale = 1; mRotScale = 0.1; } // Otherwise scale movement units by time passed since last frame else { // Move about 100 units per second, mMoveScale = mMoveSpeed * evt.timeSinceLastFrame; // Take about 10 seconds for full rotation mRotScale = mRotateSpeed * evt.timeSinceLastFrame; } mRotX = 0; mRotY = 0; mTranslateVector = Vector3::ZERO; if (!processUnbufferedKeyInput(evt)) { return false; } if (!mUseBufferedInputMouse) { if (!processUnbufferedMouseInput(evt)) { return false; } } if (mShowVisualization) { //////////////// //-- set parameters for visualization // important for visualization => draw octree bounding boxes if (0) mSceneMgr->setOption("ShowOctree", &mShowVisualization); /////////////// //-- setup visualization camera mVizCamera->setPosition(0, 0, 0); mVizCamera->setOrientation(Quaternion::IDENTITY); Vector3 camPos = mCamNode->getPosition(); mVizCamera->setPosition(camPos.x, mVizCameraHeight, camPos.z); // point down -Z axis mVizCamera->pitch(Radian(Degree(270.0))); // rotation arounnd X axis mVizCamera->yaw(Math::ATan2(-mCamera->getDerivedDirection().x, -mCamera->getDerivedDirection().z)); const float moveFactor = 200; // move by a constant so view plane is on bottom of viewport mVizCamera->moveRelative(Vector3(0, moveFactor, 0)); } else { // frame start time mTimeFrameStarted = mTimer->getMilliseconds(); } ////////////// //-- set application state switch (mAppState) { case REPLAY: /// set the current camera data to loaded frame information setCurrentFrameInfo(evt.timeSinceLastFrame); // HACK for demo: save new frame rates for different methods on the // same walkthrough if (mSavePrecomputedFps) { addFrameInfo(mPrecomputedFpsFrameInfo, mCamNode, evt.timeSinceLastFrame); } break; case WALKTHROUGH: //-- recording the camera settings per frame if (mRecordFrames) { addFrameInfo(mFrameInfo, mCamNode, evt.timeSinceLastFrame); // print recording message mWindow->setDebugText("Recording frame " + StringConverter::toString((int)mFrameInfo.size() - 1)); } // move camera according to input moveCamera(); // clamp camera so we always walk along the terrain if (TestCullingTerrainApplication::msShowHillyTerrain) { mApplication->Clamp2Terrain(mCamNode, 5); //Ogre::LogManager::getSingleton().logMessage("clamp to terrain"); } else { mApplication->Clamp2FloorPlane(mFloorDist); //Ogre::LogManager::getSingleton().logMessage("clamp to floor"); } break; default: Ogre::LogManager::getSingleton().logMessage("should not come here"); break; }; return true; } //----------------------------------------------------------------------- void TerrainFrameListener::applyVisibilityQuery(bool fromPoint, bool relativeVisibility, bool useItemBuffer) { int itemBufferMode = useItemBuffer ? mItemBufferMode : 0; int queryModes = 0; queryModes |= GtpVisibility::QueryManager::PATCH_VISIBILITY; queryModes |= GtpVisibility::QueryManager::GEOMETRY_VISIBILITY; queryModes |= GtpVisibility::QueryManager::NODE_VISIBILITY; // no visibility manager available => no visibility scene manager, return GtpVisibility::VisibilityManager *visManager = NULL; if (!mSceneMgr->getOption("VisibilityManager", &visManager)) { Ogre::LogManager::getSingleton().logMessage("no vismanager found"); return; } GtpVisibility::HierarchyInterface *hierarchyInterface = NULL; if (!mSceneMgr->getOption("HierarchyInterface", &hierarchyInterface)) { Ogre::LogManager::getSingleton().logMessage("no hierarchy interface found"); return; } const bool approximateVisibility = false; mQueryManager = new OcclusionQueriesQueryManager(hierarchyInterface, mWindow->getViewport(0), queryModes, itemBufferMode); //mQueryManager = new PlatformQueryManager(sm->GetHierarchyInterface(), mWindow->getViewport(0), false); visManager->SetQueryManager(mQueryManager); GtpVisibility::NodeInfoContainer visibleNodes; GtpVisibility::MeshInfoContainer visibleGeometry; GtpVisibility::PatchInfoContainer visiblePatches; if (fromPoint) { mQueryManager->ComputeFromPointVisibility(mCamNode->getPosition(), &visibleNodes, &visibleGeometry, &visiblePatches, relativeVisibility, approximateVisibility); } else { mQueryManager->ComputeCameraVisibility(*mCamera, &visibleNodes, &visibleGeometry, &visiblePatches, relativeVisibility, approximateVisibility); } std::stringstream d; d << "Query mode: " << queryModes << ", " << msQueryTypeCaptions[fromPoint ? 1 : 0].c_str() << " " << msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str() << " " << msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str(); LogManager::getSingleton().logMessage(d.str()); float averageNodeVis = 0, averageGeometryVis = 0, averagePatchVis = 0; int geomSize = 0, nodesSize = 0, patchSize = 0; ///////////////// //-- apply queries on geometry level GtpVisibility::MeshInfoContainer::iterator geomIt, geomIt_end = visibleGeometry.end(); for (geomIt = visibleGeometry.begin(); geomIt != geomIt_end; ++geomIt) { // add if not 0 if ((*geomIt).GetVisiblePixels()) { float vis = relativeVisibility ? (*geomIt).ComputeRelativeVisibility() : (float)(*geomIt).GetVisiblePixels(); averageGeometryVis += vis; ++ geomSize; std::stringstream d; d << "Geometry " << geomSize << " id: " << (*geomIt).GetSource()->getSubEntity(0)->getId() << " visibility: " << (*geomIt).GetVisiblePixels() << ", " << (*geomIt).GetProjectedPixels(); LogManager::getSingleton().logMessage(d.str()); } } //////////////// //-- apply queries on node level GtpVisibility::NodeInfoContainer::iterator nodesIt, nodesIt_end = visibleNodes.end(); for (nodesIt = visibleNodes.begin(); nodesIt != nodesIt_end; ++nodesIt) { // add if not 0 if ((*nodesIt).GetVisiblePixels()) { float vis = relativeVisibility ? (*nodesIt).ComputeRelativeVisibility() : (float)(*nodesIt).GetVisiblePixels(); averageNodeVis += vis; ++ nodesSize; std::stringstream d; d << "Node visibility: " << vis; LogManager::getSingleton().logMessage(d.str()); } } //////////////// //-- apply queries on patch level GtpVisibility::PatchInfoContainer::iterator patchIt, patchIt_end = visiblePatches.end(); for (patchIt = visiblePatches.begin(); patchIt != patchIt_end; ++ patchIt) { // add if not 0 if ((*patchIt).GetVisiblePixels()) { float vis = relativeVisibility ? (*patchIt).ComputeRelativeVisibility() : (float)(*patchIt).GetVisiblePixels(); averagePatchVis += vis; ++ patchSize; std::stringstream d; d << "Patch visibility: " << vis; LogManager::getSingleton().logMessage(d.str()); } } /////////////////////////////////////////////////////////////// //-- update visibility queries stats if (nodesSize) averageNodeVis /= (float)nodesSize; if (geomSize) averageGeometryVis /= (float)geomSize; if (patchSize) averagePatchVis /= (float)patchSize; try { char str[100]; sprintf(str, ": %s, %s, %s", msQueryTypeCaptions[fromPoint ? 1 : 0].c_str(), msQueryRelativeVisCaptions[relativeVisibility ? 1 : 0].c_str(), msQueryMethodCaptions[useItemBuffer ? 1 : 0].c_str()); mQueryTypeInfo->setCaption(str); sprintf(str, ": %d", (int)nodesSize); mQueryVisibleNodesInfo->setCaption(str); sprintf(str,": %d", (int)geomSize); mQueryVisibleGeometryInfo->setCaption(str); sprintf(str,": %d", (int)patchSize); mQueryVisiblePatchInfo->setCaption(str); sprintf(str,": %3.3f", averageNodeVis); mQueryNodeVisibilityInfo->setCaption(str); sprintf(str,": %3.3f", averageGeometryVis); mQueryGeometryVisibilityInfo->setCaption(str); sprintf(str,": %3.3f", averagePatchVis); mQueryPatchVisibilityInfo->setCaption(str); } catch (...) { // ignore } // show the results if (!mShowQueryStats && !mShowHelp) { mQueryOverlay->show(); mShowQueryStats = true; } delete mQueryManager; } bool TerrainFrameListener::processUnbufferedMouseInput(const FrameEvent& evt) { /* Rotation factors, may not be used if the second mouse button is pressed. */ /* If the second mouse button is pressed, then the mouse movement results in sliding the camera, otherwise we rotate. */ if (mInputDevice->getMouseButton(1)) { mTranslateVector.x += mInputDevice->getMouseRelativeX() * 0.13; mTranslateVector.y -= mInputDevice->getMouseRelativeY() * 0.13; } else { mRotX = Degree(-mInputDevice->getMouseRelativeX() * 0.13); mRotY = Degree(-mInputDevice->getMouseRelativeY() * 0.13); } return true; } //----------------------------------------------------------------------- bool TerrainFrameListener::frameEnded(const FrameEvent& evt) { if (mShutdownRequested) return false; // timer end time if (!mShowVisualization) { mTimeFrameEnded = mTimer->getMilliseconds(); } updateStats(); if (mRecordVideo) // record current frame { takeVideoFrame(video_out); } //-- IMPORTANT: must be set, otherwise terrain is not rendered correctly mSceneMgr->endFrame(); if (mTimeDelay <= 0) // simulates approx. one second mTimeDelay = 1.0; return true; } //----------------------------------------------------------------------- void TerrainFrameListener::moveCamera() { // move node rather than camera so orientation is right in the visualization mCamNode->yaw(mRotX, Ogre::Node::TS_WORLD); //mCamNode->rotate(Vector3(0,1,0), mRotX, Ogre::Node::TS_WORLD); mCamNode->pitch(mRotY); mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector); } //----------------------------------------------------------------------- void TerrainFrameListener::writeFrames(const std::string filename, const FrameInfoContainer &frameInfo) const { std::ofstream ofstr(filename.c_str()); std::vector::const_iterator it, it_end; it_end = frameInfo.end(); int i = 0; for (it = frameInfo.begin(); it < it_end; ++ it, ++ i) { ofstr << StringConverter::toString((*it).position) << " " << StringConverter::toString((*it).orientation) << " " << StringConverter::toString((*it).timeElapsed) << " " << StringConverter::toString((*it).fps) << "\n"; } std::stringstream d; d << "saved " << i << " frames to file " << filename; Ogre::LogManager::getSingleton().logMessage(d.str()); ofstr.close(); } //----------------------------------------------------------------------- void TerrainFrameListener::loadFrames(const std::string filename, FrameInfoContainer &frameInfo) { std::ifstream ifstr(filename.c_str()); char line[256]; frame_info info; // reset current values frameInfo.clear(); mCurrentFrame = 0; int i = 0; while (!ifstr.eof()) { ifstr.getline(line, 256); sscanf(line, "%f %f %f %f %f %f %f %f %f", &info.position.x, &info.position.y, &info.position.z, &info.orientation.w, &info.orientation.x, &info.orientation.y, &info.orientation.z, &info.timeElapsed, &info.fps); mFrameInfo.push_back(info); // std::stringstream d; d << StringConverter::toString(info.position) << " " << StringConverter::toString(info.orientation); // LogManager::getSingleton().logMessage(d.str()); ++ i; } std::stringstream d; d << "loaded " << i << " frames from file " << filename; Ogre::LogManager::getSingleton().logMessage(d.str()); ifstr.close(); } //----------------------------------------------------------------------- void TerrainFrameListener::nextAppState() { mCurrentFrame = 0; int lastState = mAppState; // transition to the next state mAppState = (mAppState + 1) % STATE_NUM; // if last state was replay state: post process if (lastState == REPLAY) { // reset debug text mWindow->setDebugText(""); // hack for producing demo: // we produced precomputed fps during the last replay => // save them to file if (mSavePrecomputedFps) //!mPrecomputedFpsFrameInfo.empty()) { std::string filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out"; writeFrames(filename, mPrecomputedFpsFrameInfo); mPrecomputedFpsFrameInfo.clear(); } std::stringstream d; mWalkthroughStats.Print(d, msApprevAlgorithmCaptions[mCurrentAlgorithm]); LogManager::getSingleton().logMessage(d.str()); } //-- replay recorded walkthrough if (mAppState == REPLAY) { // no standard recording during replay mRecordFrames = false; // no stats information mWindow->setDebugText(""); // clear previous walktrough mFrameInfo.clear(); std::string filename; // if recording demo, // we use precomputed fps which corresponds to current method, // e.g., for chc we load precomputed chc fps from disc. if (mRecordDemo) { filename = msApprevAlgorithmCaptions[mCurrentAlgorithm] + "_frames.out"; } else // standard filename { filename = frames_out_filename; } //-- load recorded walkthrough from disk loadFrames(filename, mFrameInfo); // if there are still no recorded frames, // no walkthrough was recorded => set next state if (mFrameInfo.empty()) { nextAppState(); } else // actual replay { mWindow->setDebugText("Replay"); // reset, because we measure fps stats during walkthrough // (warning: average fps broken) mWindow->resetStatistics(); mWalkthroughStats.Reset(); //-- initialise frame data mReplayTimeElapsed = 0; mCamNode->setPosition(mFrameInfo[0].position); mCamNode->setOrientation(mFrameInfo[0].orientation); } } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleRecord() { mRecordFrames = !mRecordFrames; if (mRecordFrames) { // starting new recording => clear old frame info mFrameInfo.clear(); } else // recording just ended => write frame info to file { writeFrames(frames_out_filename, mFrameInfo); mWindow->setDebugText(""); } } //----------------------------------------------------------------------- void TerrainFrameListener::changeThreshold(int incr) { mVisibilityThreshold += incr; if (mVisibilityThreshold < 0) { mVisibilityThreshold = 0; } char str[100]; sprintf(str,": %d", mVisibilityThreshold); mSceneMgr->setOption("Threshold", &mVisibilityThreshold); mThresholdInfo->setCaption(str); } //----------------------------------------------------------------------- void TerrainFrameListener::changeAssumedVisibility(int incr) { mAssumedVisibility += incr; if (mAssumedVisibility < 0) { mAssumedVisibility = 0; } char str[100]; sprintf(str,": %d", mAssumedVisibility); mSceneMgr->setOption("AssumedVisibility", &mAssumedVisibility); mAssumedVisibilityInfo->setCaption(str); } //----------------------------------------------------------------------- void TerrainFrameListener::changeVizScale(const int incr) { mVizScale += incr; if (mVizScale < 1) { mVizScale = 1; } mSceneMgr->setOption("NodeVizScale", &mVizScale); } //----------------------------------------------------------------------- void TerrainFrameListener::changeFloorDist(const float incr) { mFloorDist += incr; if (mFloorDist < 2) { mFloorDist = 2; } } //----------------------------------------------------------------------- void TerrainFrameListener::zoomVizCamera(int zoom) { mVizCameraHeight += zoom; if(mVizCameraHeight < 0) mVizCameraHeight = 0; } //----------------------------------------------------------------------- void TerrainFrameListener::nextAlgorithm() { // possible algorithms: 3 culling algorithms + standard rendering mCurrentAlgorithm = (mCurrentAlgorithm + 1) % (GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS + 1); applyCurrentAlgorithm(); } //----------------------------------------------------------------------- void TerrainFrameListener::applyObjectType() { if (mCurrentObjectType >= 3) // TODO: define a constant mCurrentObjectType = 0; // parameters for new object mTerrainContentGenerator->SetOffset(msObjectTerrainOffsets[mCurrentObjectType]); Real scale = msObjectScales[mCurrentObjectType]; mTerrainContentGenerator->SetScale(Vector3(scale, scale, scale)); mCurrentObjectTypeInfo->setCaption(": " + msObjectCaptions[mCurrentObjectType]); } //----------------------------------------------------------------------- void TerrainFrameListener::applyCurrentAlgorithm() { bool isNormalExecution; if (mCurrentAlgorithm < GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS) { isNormalExecution = false; mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm); } else { // standard rendering without changed render queue flow isNormalExecution = true; } mSceneMgr->setOption("NormalExecution", &isNormalExecution); mAlgorithmInfo->setCaption(": " + msAlgorithmCaptions[mCurrentAlgorithm]); if (1) { std::stringstream d; d << "algorithm: " << msAlgorithmCaptions[mCurrentAlgorithm]; Ogre::LogManager::getSingleton().logMessage(d.str()); } } //----------------------------------------------------------------------- void TerrainFrameListener::updateStats() { unsigned int opt = 0; char str[100]; static String currFpsString = "Current FPS: "; static String avgFpsString = "Average FPS: "; static String bestFpsString = "Best FPS: "; static String worstFpsString = "Worst FPS: "; static String trisString = "Triangle Count: "; int currentFps; // HACK for demo: use precomputed FPS instead of real FPS if (mRecordDemo) { currentFps = mPrecomputedFps; } else { currentFps = mWindow->getStatistics().lastFPS; } #if 0 // HACK: take pure rendering time, only measures the render call long pureRenderTime = mTimeFrameEnded - mTimeFrameStarted; if (pureRenderTime) { mPureRenderTimeFps = 1000.0 / (float) pureRenderTime; } currentFps = mPureRenderRenderTimeFps; //std::stringstream d; d << "Pure render time fps: " << mPureRenderTimeFps << "\n"; //Ogre::LogManager::getSingleton().logMessage(d.str()); #endif unsigned int nodeInfo[3]; mSceneMgr->getOption("NumRenderedNodes", nodeInfo); mSceneMgr->getOption("NumQueryCulledNodes", nodeInfo+1); mSceneMgr->getOption("NumFrustumCulledNodes", nodeInfo+2); mWalkthroughStats.UpdateFrame(currentFps, mWindow->getBestFPS(), mWindow->getWorstFPS(), (int)mWindow->getTriangleCount(), nodeInfo[0], nodeInfo[1], nodeInfo[2]); // HACK: compute average fps ourselfs, because ogre avg. fps is wrong // TODO: update only once per second float avgFps = (float)mWalkthroughStats.mAccFps / (float)(mWalkthroughStats.mFrameCount); // update stats when necessary try { OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps"); OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps"); OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps"); OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps"); const RenderTarget::FrameStats& stats = mWindow->getStatistics(); // HACK: take newly computed avg. fps instead of Ogre avg fps and update only once per second if (mTimeDelay < 0) { guiAvg->setCaption(avgFpsString + StringConverter::toString(avgFps) + " ms"); //guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps)); } if (0) { std::stringstream d; d << "fps: " << StringConverter::toString(currentFps) << ", " << "avg fps: " << StringConverter::toString(avgFps); LogManager::getSingleton().logMessage(d.str()); } //guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS)); guiCurr->setCaption(currFpsString + StringConverter::toString(currentFps)); //std::stringstream d; d << "frame rate :" << stats.lastFPS; //Ogre::LogManager::getSingleton().logMessage(d.str()); guiBest->setCaption(bestFpsString + StringConverter::toString(stats.bestFPS) + " " + StringConverter::toString(stats.bestFrameTime) + " ms"); guiWorst->setCaption(worstFpsString + StringConverter::toString(stats.worstFPS) + " " + StringConverter::toString(stats.worstFrameTime) + " ms"); OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); guiTris->setCaption(trisString + StringConverter::toString(stats.triangleCount)); //LogManager::getSingleton().logMessage(StringConverter::toString(stats.triangleCount)); OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText"); guiDbg->setCaption(mWindow->getDebugText()); //-- culling stats mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); mFrustumCulledNodesInfo->setCaption(str); mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); mQueryCulledNodesInfo->setCaption(str); mSceneMgr->getOption("NumHierarchyNodes", &opt); sprintf(str,": %d", opt); mHierarchyNodesInfo->setCaption(str); mSceneMgr->getOption("NumRenderedNodes", &opt); sprintf(str,": %d", opt); mRenderedNodesInfo->setCaption(str); sprintf(str,": %d", mTerrainContentGenerator->GetObjectCount()); mObjectsCountInfo->setCaption(str); // take old value into account in order to create no sudden changes mSceneMgr->getOption("NumQueriesIssued", &opt); mDelayedQueriesIssued = mDelayedQueriesIssued * 0.8 + (float)opt * 0.2f; sprintf(str,": %d", (int)mDelayedQueriesIssued); mQueriesIssuedInfo->setCaption(str); mSceneMgr->getOption("NumTraversedNodes", &opt); mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2f; sprintf(str,": %d", (int)mDelayedTraversedNodes); mTraversedNodesInfo->setCaption(str); if (mRecordVideo) { // update stats for demo mMyStatsAlgorithmInfo->setCaption(msApprevAlgorithmCaptions[mCurrentAlgorithm]); sprintf(str,": %d", (int)currentFps); mMyStatsFpsInfo->setCaption(str); } } catch (...) { // ignore } } //----------------------------------------------------------------------- void TerrainFrameListener::setTestGeometryForVisibleLeaves(bool testGeometryForVisibleLeaves) { mSceneMgr->setOption("TestGeometryForVisibleLeaves", &mTestGeometryForVisibleLeaves); /* disable optimization which tests geometry instead of aabb * for "delayed" rendering of transparents (i.e., render transparents after all the solids) * because otherwise visible transparents could be skipped */ bool delayedRendering = !mTestGeometryForVisibleLeaves; mSceneMgr->setOption("DelayRenderTransparents", &delayedRendering); if (mTestGeometryForVisibleLeaves) { mTestGeometryForVisibleLeavesInfo->setCaption(": true"); } else { mTestGeometryForVisibleLeavesInfo->setCaption(": false"); } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleShowOctree() { mShowOctree = !mShowOctree; mSceneMgr->setOption("ShowOctree", &mShowOctree); } //----------------------------------------------------------------------- void TerrainFrameListener::toggleShowViewCells() { if (0) // tmp matt { mShowViewCells = !mShowViewCells; mSceneMgr->setOption("ShowViewCells", &mShowViewCells); } else { unsigned int numObjects; mSceneMgr->getOption("VisibleObjects", &numObjects); } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleUseViewCells() { // HACK: no view cells for hilly terrain if (mApplication->msShowHillyTerrain) return; mUseViewCells = !mUseViewCells; // load on demand if (mUseViewCells)// && !mViewCellsLoaded) { LogManager::getSingleton().logMessage("using view cells"); mLoadingOverlay->show(); // call once to load view cell loading overlay mWindow->update(); mViewCellsLoaded = mApplication->LoadViewCells(mApplication->mViewCellsFilename); if (!mViewCellsLoaded) LogManager::getSingleton().logMessage("loading view cells failed"); else LogManager::getSingleton().logMessage("view cells successfully loaded"); mLoadingOverlay->hide(); } if (mUseViewCells) mViewCellsInfo->setCaption(": on"); else mViewCellsInfo->setCaption(": off"); mSceneMgr->setOption("UseViewCells", &mUseViewCells); } //----------------------------------------------------------------------- void TerrainFrameListener::toggleUseVisibilityFilter() { mUseVisibilityFilter = !mUseVisibilityFilter; mSceneMgr->setOption("UseVisibilityFilter", &mUseVisibilityFilter); } //----------------------------------------------------------------------- void TerrainFrameListener::toggleUseDepthPass() { mUseDepthPass = !mUseDepthPass; mSceneMgr->setOption("UseDepthPass", &mUseDepthPass); if (mUseDepthPass) { mUseDepthPassInfo->setCaption(": true"); } else { mUseDepthPassInfo->setCaption(": false"); } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleFlushQueue() { mFlushQueue = !mFlushQueue; mSceneMgr->setOption("FlushQueue", &mFlushQueue); if (mFlushQueue) { LogManager::getSingleton().logMessage("flushing queue"); //mFlushQueueInfo->setCaption(": true"); } else { LogManager::getSingleton().logMessage("not flushing queue"); //mFlushQueueInfo->setCaption(": false"); } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleShowViz() { mVisualizeCulledNodes = mShowVisualization = !mShowVisualization; // create viewport with priority VIZ_VIEWPORT_Z_ORDER: // will be rendered over standard viewport if (mShowVisualization) { Viewport *vizvp = mWindow->addViewport(mVizCamera, VIZ_VIEWPORT_Z_ORDER, 0.6, 0.6, 0.4, 0.4); vizvp->setBackgroundColour(ColourValue(0.0, 0.3, 0.2, 1)); vizvp->setOverlaysEnabled(false); // Alter the camera aspect ratio to match the viewport mVizCamera->setAspectRatio(Real(vizvp->getActualWidth()) / Real(vizvp->getActualHeight())); mSceneMgr->setOption("VisualizeCulledNodes", &mVisualizeCulledNodes); } else { // remove visualization viewport mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER); // octree bounding boxes are shown for visualization purpose, reset now mSceneMgr->setOption("ShowOctree", &mShowOctree); } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleShowShadows() { mShowShadows = !mShowShadows; mSunLight->setCastShadows(mShowShadows); if (mShowShadows) { mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE); //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE); //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE); } else { mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE); } } //----------------------------------------------------------------------- void TerrainFrameListener::nextNodeVizMode() { mNodeVizMode = (mNodeVizMode + 1) % NODEVIZ_MODES_NUM; bool renderNodesForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES) || (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT); bool renderNodesContentForViz = (mNodeVizMode == NODEVIZ_RENDER_NODES_AND_CONTENT); //bool renderNodesContentForViz = mNodeVizMode == NODEVIZ_RENDER_GEOMETRY; mSceneMgr->setOption("RenderNodesForViz", &renderNodesForViz); mSceneMgr->setOption("RenderNodesContentForViz", &renderNodesContentForViz); } //----------------------------------------------------------------------- void TerrainFrameListener::keyPressed(KeyEvent* e) { // hide exact visibility query overlay if (mShowQueryStats) { mQueryOverlay->hide(); mShowQueryStats = false; } switch(e->getKey()) { case KC_SUBTRACT: changeThreshold(-10); break; case KC_ADD: changeThreshold(10); break; case KC_ESCAPE: mShutdownRequested = true; e->consume(); return; case KC_SPACE: nextAlgorithm(); break; case KC_LSHIFT: mShiftPressed = true; break; case KC_DELETE: mDeleteObjects = true; break; case KC_C: if (mItemBufferMode != GtpVisibility::QueryManager::GEOMETRY_VISIBILITY) { mItemBufferMode = GtpVisibility::QueryManager::GEOMETRY_VISIBILITY; } else { mItemBufferMode = GtpVisibility::QueryManager::PATCH_VISIBILITY; } break; case KC_E: // hack for recording demo using precomputed fps mSavePrecomputedFps = !mSavePrecomputedFps; break; case KC_F: nextFilter(); break; case KC_G: mTestGeometryForVisibleLeaves = !mTestGeometryForVisibleLeaves; setTestGeometryForVisibleLeaves(mTestGeometryForVisibleLeaves); break; case KC_H: toggleShowShadows(); break; case KC_L: toggleShowViewCells(); break; case KC_M: // hack for recording demo using precomputed fps mRecordDemo = !mRecordDemo; break; case KC_O: switchMouseMode(); break; case KC_P: toggleDisplayCameraDetails(); break; case KC_V: toggleUseViewCells(); break; case KC_Q: toggleUseVisibilityFilter(); break; case KC_R: nextSceneDetailLevel(); break; case KC_T: toggleShowOctree(); break; case KC_U: mCamNode->resetOrientation(); mCamNode->setPosition(mApplication->mInitialPosition); break; case KC_X: toggleUseDepthPass(); break; case KC_I: toggleFlushQueue(); break; case KC_Z: mCamNode->resetOrientation(); break; /////////////// //-- visualization case KC_1: toggleShowViz(); break; case KC_2: nextNodeVizMode(); break; case KC_7: mTerrainContentGenerator->WriteObjects(objects_out_filename); break; case KC_8: changeAssumedVisibility(-5); // changeAssumedVisibility(-500); break; case KC_9: changeAssumedVisibility(5); // changeAssumedVisibility(500); break; //#if USE_PERFHUD case KC_F1: toggleShowHelp(); break; case KC_F2: mStatsOn = !mStatsOn; showStats(mStatsOn); break; case KC_F3: nextAppState(); break; case KC_F4: toggleRecord(); break; case KC_F5: { unsigned int pixels = 0; mSceneMgr->getOption("VisibleObjects", &pixels); std::stringstream d; d << "visible objects: " << pixels; LogManager::getSingleton().logMessage(d.str()); const bool fromPoint = false; //applyVisibilityQuery(fromPoint, mShiftPressed, mUseItemBuffer); break; } case KC_F6: { const bool fromPoint = true; applyVisibilityQuery(fromPoint, mShiftPressed, mUseItemBuffer); break; } case KC_F7: ++ mCurrentObjectType; applyObjectType(); break; //#endif case KC_F8: { // generate new objects const int objNum = 500; mApplication->generateScene(objNum, mCurrentObjectType); } break; case KC_F9: mUseAnimation = !mUseAnimation; break; case KC_F10: mRecordVideo = !mRecordVideo; case KC_F11: takeScreenshot(); break; case KC_F12: break; //KEY_PRESSED(KC_F3, 0.3, writeFrames()); //KEY_PRESSED(KC_F4, 0.3, loadFrames()); default: break; } CEGUI::System::getSingleton().injectKeyDown(e->getKey()); CEGUI::System::getSingleton().injectChar(e->getKeyChar()); e->consume(); } //----------------------------------------------------------------------- void TerrainFrameListener::keyReleased(KeyEvent* e) { if (e->getKey() == KC_LSHIFT) { mShiftPressed = false; } CEGUI::System::getSingleton().injectKeyUp(e->getKey()); e->consume(); } //----------------------------------------------------------------------- void TerrainFrameListener::keyClicked(KeyEvent* e) { // Do nothing e->consume(); } //----------------------------------------------------------------------- void TerrainFrameListener::addFrameInfo(FrameInfoContainer &frameInfos, SceneNode *camNode, Real timeElapsed) { frame_info info; info.orientation = mCamNode->getOrientation(); info.position = mCamNode->getPosition(); info.timeElapsed = timeElapsed; info.fps = mWindow->getStatistics().lastFPS; frameInfos.push_back(info); } //----------------------------------------------------------------------- void TerrainFrameListener::setCurrentFrameInfo(const Real timeElapsed) { //-- find current frame relative to elapsed frame time mReplayTimeElapsed -= timeElapsed; while ((mReplayTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1)) { mReplayTimeElapsed += mFrameInfo[mCurrentFrame ++].timeElapsed; } // TODO: crashes here if recording / replaying on the same time!! const frame_info new_frame = mFrameInfo[mCurrentFrame]; const frame_info old_frame = mFrameInfo[mCurrentFrame - 1]; ///////////// //-- interpolate frames Real factor = 1; if (old_frame.timeElapsed > 0) { factor = mReplayTimeElapsed / old_frame.timeElapsed; } const Vector3 camPos = old_frame.position + factor * (new_frame.position - old_frame.position); // interpolate the orientation const Quaternion camOrienation = Quaternion::Slerp(factor, old_frame.orientation, new_frame.orientation, true); // HACK for demo: interpolate precomputed fps mPrecomputedFps = old_frame.fps + factor * (new_frame.fps - old_frame.fps); mCamNode->setPosition(camPos); mCamNode->setOrientation(camOrienation); // stop replaying after one full walkthrough if (mCurrentFrame == (int)mFrameInfo.size() - 1) { nextAppState(); } } //----------------------------------------------------------------------- bool TerrainFrameListener::processUnbufferedKeyInput(const FrameEvent& evt) { bool cursorPressed = false; /* Move camera forward by keypress. */ if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W)) { mTranslateVector.z = -mMoveScale; cursorPressed = true; } /* Move camera backward by keypress. */ if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S)) { mTranslateVector.z = mMoveScale; cursorPressed = true; } if (mInputDevice->isKeyDown(KC_A)) { mTranslateVector.x -= mMoveScale; mTranslateVector.y += mMoveScale; cursorPressed = true; } if (mInputDevice->isKeyDown(KC_D)) { mTranslateVector.x += mMoveScale; mTranslateVector.y -= mMoveScale; cursorPressed = true; } if (mInputDevice->isKeyDown(KC_RIGHT)) { mCamNode->yaw(-mRotScale, Ogre::Node::TS_WORLD); cursorPressed = true; } if (mInputDevice->isKeyDown(KC_LEFT)) { mCamNode->yaw(mRotScale, Ogre::Node::TS_WORLD); cursorPressed = true; } // visualization camera if (mInputDevice->isKeyDown(KC_3)) { zoomVizCamera(50); } if (mInputDevice->isKeyDown(KC_4)) { zoomVizCamera(-50); } if (mInputDevice->isKeyDown(KC_5)) { changeVizScale(-1); } if (mInputDevice->isKeyDown(KC_6)) { changeVizScale(1); } if (mInputDevice->isKeyDown(KC_7)) { changeFloorDist(-1); } if (mInputDevice->isKeyDown(KC_8)) { changeFloorDist(1); } // show the results if (cursorPressed && mShowQueryStats) { mQueryOverlay->hide(); mShowQueryStats = false; } // Return true to continue rendering return true; } //----------------------------------------------------------------------- void TerrainFrameListener::nextFilter() { switch (mFiltering) { case TFO_BILINEAR: mFiltering = TFO_TRILINEAR; mAniso = 1; break; case TFO_TRILINEAR: mFiltering = TFO_ANISOTROPIC; mAniso = 8; break; case TFO_ANISOTROPIC: mFiltering = TFO_BILINEAR; mAniso = 1; break; default: break; } MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering); MaterialManager::getSingleton().setDefaultAnisotropy(mAniso); // reload stats showStats(mStatsOn); } //----------------------------------------------------------------------- void TerrainFrameListener::nextSceneDetailLevel() { #if OGRE_103 mSceneDetailIndex = (mSceneDetailIndex + 1) % 3; switch (mSceneDetailIndex) { case 0: mCamera->setDetailLevel(SDL_SOLID); break; case 1: mCamera->setDetailLevel(SDL_WIREFRAME); break; case 2: mCamera->setDetailLevel(SDL_POINTS); break; } #endif } //----------------------------------------------------------------------- void TerrainFrameListener::takeVideoFrame(std::ofstream &ofstr) { char name[50]; sprintf(name, "frame_%05d.tga", ++mNumVideoFrames); mWindow->writeContentsToFile(name); //mWindow->setDebugText(String("Wrote ") + name); ofstr << name << "\n"; } //----------------------------------------------------------------------- void TerrainFrameListener::takeScreenshot() { char name[50]; sprintf(name, "screenshot_%05d.png", ++mNumScreenShots); mWindow->writeContentsToFile(name); //mWindow->setDebugText(String("Wrote ") + name); } //----------------------------------------------------------------------- void TerrainFrameListener::toggleDisplayCameraDetails() { mDisplayCameraDetails = !mDisplayCameraDetails; if (!mDisplayCameraDetails) { mWindow->setDebugText(""); } } //----------------------------------------------------------------------- void TerrainFrameListener::showStats(bool show) { if (mDebugOverlay && mCullStatsOverlay) { if (show) { mDebugOverlay->show(); mCullStatsOverlay->show(); } else { mDebugOverlay->hide(); mCullStatsOverlay->hide(); } } } //----------------------------------------------------------------------- void TerrainFrameListener::toggleShowHelp() { mShowHelp = !mShowHelp; if (mShowHelp) { mHelpOverlay->show(); } else { mHelpOverlay->hide(); } } //----------------------------------------------------------------------- void TerrainFrameListener::initOverlayElement(OverlayElement **elInfo, String ext, String name, int top, String caption) { OverlayElement *el = OverlayManager::getSingleton().getOverlayElement(ext + name); (*elInfo) = OverlayManager::getSingleton().getOverlayElement(ext + name + "Info"); (*elInfo)->setCaption(caption); el->setTop(top); (*elInfo)->setTop(top); } //----------------------------------------------------------------------- void TerrainFrameListener::initHelpOverlayElement(String name, int top) { OverlayElement *el = OverlayManager::getSingleton().getOverlayElement( "Example/Visibility/Help/" + name); el->setTop(top); } //----------------------------------------------------------------------- void TerrainFrameListener::initHelpOverlay() { const int vert_space = 15; int top = 30; initHelpOverlayElement("ShowHelp", top); top += vert_space; initHelpOverlayElement("Stats", top); top += vert_space; initHelpOverlayElement("AppState", top); top += vert_space; initHelpOverlayElement("Recorded", top); top += vert_space; initHelpOverlayElement("Animation", top); top += vert_space; initHelpOverlayElement("Video", top); top += vert_space; initHelpOverlayElement("Screenshots", top); top += vert_space; initHelpOverlayElement("WriteOut", top); top += vert_space; top +=vert_space; initHelpOverlayElement("SceneDetail", top); top += vert_space; initHelpOverlayElement("DisplayCameraDetails", top); top += vert_space; initHelpOverlayElement("DisplayOctree", top); top += vert_space; initHelpOverlayElement("UseShadows", top); top += vert_space; initHelpOverlayElement("Filter", top); top += vert_space; //-- visualization top += vert_space; initHelpOverlayElement("VizSection", top); top += vert_space; initHelpOverlayElement("Viz", top); top += vert_space; initHelpOverlayElement("NextVizMode", top); top += vert_space; initHelpOverlayElement("ZoomViz", top); top += vert_space; //-- visibility queries top += vert_space; initHelpOverlayElement("VisQuery", top); top += vert_space; initHelpOverlayElement("FromCameraQuery", top); top += vert_space; initHelpOverlayElement("FromPointQuery", top); top += vert_space; initHelpOverlayElement("QueryType", top); top += vert_space; initHelpOverlayElement("QueryTarget", top); top += vert_space; //-- object generation top += vert_space; initHelpOverlayElement("SceneObjects", top); top += vert_space; initHelpOverlayElement("PlaceObjects", top); top += vert_space; initHelpOverlayElement("GenerateObjects", top); top += vert_space; initHelpOverlayElement("RemoveObjects", top); top += vert_space; initHelpOverlayElement("DropObject", top); top += vert_space; OverlayElement *helpPanel = OverlayManager::getSingleton().getOverlayElement( "Example/Visibility/Help/HelpPanel"); helpPanel->setHeight(top + 10); } //----------------------------------------------------------------------- void TerrainFrameListener::initVisStatsOverlay() { const int border_height = 10; const int vert_space = 15; //-- visibility culling stats overlay int top = border_height; String ext = "Example/Visibility/"; initOverlayElement(&mAlgorithmInfo, ext, "Algorithm", top, ": " + msAlgorithmCaptions[mCurrentAlgorithm]); top += vert_space; initOverlayElement(&mThresholdInfo, ext, "Threshold", top, ": 0"); top += vert_space; initOverlayElement(&mTestGeometryForVisibleLeavesInfo, ext, "TestGeometryForVisibleLeaves", top, ": true"); top += vert_space; initOverlayElement(&mUseDepthPassInfo, ext, "UseDepthPass", top, ": false"); top += vert_space; initOverlayElement(&mAssumedVisibilityInfo, ext, "AssumedVisibility", top, ": 0"); top += vert_space; initOverlayElement(&mCurrentObjectTypeInfo, ext, "CurrentObjectType", top, ": "); top += vert_space; initOverlayElement(&mViewCellsInfo, ext, "ViewCells", top, ": "); top += vert_space; //initOverlayElement(&mHelpInfo, ext, "Help", top, ": "); top += vert_space; OverlayElement *optionsPanel = OverlayManager::getSingleton(). getOverlayElement("Example/Visibility/VisibilityPanel"); optionsPanel->setHeight(top + border_height); top = border_height; //ext = "Example/Visibility/"; initOverlayElement(&mFrustumCulledNodesInfo, ext, "FrustumCulledNodes", top, ": 0"); top += vert_space; initOverlayElement(&mQueryCulledNodesInfo, ext, "QueryCulledNodes", top, ": 0"); top += vert_space; initOverlayElement(&mTraversedNodesInfo, ext, "TraversedNodes", top, ": 0"); top += vert_space; initOverlayElement(&mHierarchyNodesInfo, ext, "HierarchyNodes", top, ": 0"); top += vert_space; initOverlayElement(&mRenderedNodesInfo, ext, "RenderedNodes", top, ": 0"); top += vert_space; initOverlayElement(&mObjectsCountInfo, ext, "ObjectsCount", top, ": 0"); top += vert_space; initOverlayElement(&mQueriesIssuedInfo, ext, "QueriesIssued", top, ": 0"); top += vert_space; OverlayElement *visPanel = OverlayManager::getSingleton(). getOverlayElement("Example/Visibility/VisibilityStatsPanel"); visPanel->setHeight(top + border_height); } //----------------------------------------------------------------------- void TerrainFrameListener::initQueryOverlay() { const int border_height = 10; const int vert_space = 15; //-- visibility culling stats overlay int top = border_height + 25; const String ext = "Example/Visibility/Query/"; initOverlayElement(&mQueryTypeInfo , ext, "QueryType", top, ": 0"); top += vert_space; initOverlayElement(&mQueryVisibleNodesInfo , ext, "VisibleNodes", top, ": 0"); top += vert_space; initOverlayElement(&mQueryVisibleGeometryInfo , ext, "VisibleGeometry", top, ": 0"); top += vert_space; initOverlayElement(&mQueryVisiblePatchInfo , ext, "VisiblePatches", top, ": 0"); top += vert_space; initOverlayElement(&mQueryNodeVisibilityInfo , ext, "NodeVisibility", top, ": 0"); top += vert_space; initOverlayElement(&mQueryGeometryVisibilityInfo , ext, "GeometryVisibility", top, ": 0"); top += vert_space; initOverlayElement(&mQueryPatchVisibilityInfo , ext, "PatchVisibility", top, ": 0"); top += vert_space; OverlayElement *queryPanel = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/Query/QueryPanel"); queryPanel->setHeight(top + border_height); } //----------------------------------------------------------------------- void TerrainFrameListener::setAlgorithm(const int algorithm) { mCurrentAlgorithm = algorithm; applyCurrentAlgorithm(); }