#include #include #include <../CEGUIRenderer/include/OgreCEGUIRenderer.h> #include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h> #include <../CEGUIRenderer/include/OgreCEGUITexture.h> #include #include "IVFrameListener.h" #include "OgreVisibilityOctreeSceneManager.h" #include "VisibilityInfo.h" #include "TestCullingIVApplication.h" //-- captions for overlays String IVFrameListener::msAlgorithmCaptions[] = { "Coherent Hierarchical Culling", "View Frustum Culling", "Stop and Wait Culling" }; // 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"; //----------------------------------------------------------------------- IVFrameListener::IVFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer, Camera *vizCamera, SceneNode *camNode, Light *sunLight, TestCullingIVApplication *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), mVisibilityThreshold(0), mAssumedVisibility(0), //mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING), //mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING), mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::FRUSTUM_CULLING), mNodeVizMode(NODEVIZ_NONE), mVizCameraHeight(Real(2500.0)), mCamNode(camNode), mAppState(WALKTHROUGH), mCurrentFrame(0), mReplayTimeElapsed(0), mRotateSpeed(72), mVizCamera(vizCamera), mStatsOn(true), mShutdownRequested(false), mLMouseDown(false), mRMouseDown(false), mShowOctree(false), mUseDepthPass(false), mUseArbQueries(false), mTestGeometryForVisibleLeaves(false), mShowVisualization(false), mCullCamera(false), mRecordFrames(false), mShowShadows(false), mShowHelp(false), mDisplayCameraDetails(false), mVisualizeCulledNodes(false), mSunLight(sunLight), mShiftPressed(false), mShowQueryStats(false), mVisibilityManager(NULL), mDelayedQueriesIssued(0.0), mDelayedTraversedNodes(0.0), mApplication(app), mMoveSpeed(15), mAccumulatedTris(0), mAccumulatedFps(0) { mRaySceneQuery = mSceneMgr->createRayQuery( Ray(mCamNode->getPosition(), Vector3::NEGATIVE_UNIT_Y)); //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(); //-- 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"); initVisStatsOverlay(); // visibility stats overlay initHelpOverlay(); // help overlay initQueryOverlay(); // visibility query stats overlay // show stats overlays showStats(true); // set culling algorithm type setAlgorithm(mCurrentAlgorithm); // set scene manager options mSceneMgr->setOption("TestGeometryForVisibleLeaves", &mTestGeometryForVisibleLeaves); // apply delayed rendering (i.e., transparents after hierarchical culling pass) // only if optimization is not used bool delayRenderTransparents = !mTestGeometryForVisibleLeaves; mSceneMgr->setOption("DelayRenderTransparents", &delayRenderTransparents); mSceneMgr->setOption("UseDepthPass", &mUseDepthPass); //mSceneMgr->setOption("UseArbQueries", &mUseArbQueries); mSceneMgr->setOption("ShowOctree", &mShowOctree); mSceneMgr->setOption("CullCamera", &mCullCamera); mSceneMgr->setOption("PrepareVisualization", &mShowVisualization); // reset statistics resetStats(); } //----------------------------------------------------------------------- IVFrameListener::~IVFrameListener() { OGRE_DELETE(mEventProcessor); OGRE_DELETE(mRaySceneQuery); } //----------------------------------------------------------------------- void IVFrameListener::mouseMoved(MouseEvent *e) { // Update CEGUI with the mouse motion CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight()); } //----------------------------------------------------------------------- void IVFrameListener::mousePressed(MouseEvent* e) { // Left mouse button down if (e->getButtonID() & InputEvent::BUTTON0_MASK) { CEGUI::MouseCursor::getSingleton().hide(); mLMouseDown = true; } // Right mouse button down else if (e->getButtonID() & InputEvent::BUTTON1_MASK) { CEGUI::MouseCursor::getSingleton().hide(); mRMouseDown = true; } } //----------------------------------------------------------------------- void IVFrameListener::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 IVFrameListener::mouseReleased(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 IVFrameListener::mouseDragged(MouseEvent *e) { // If we are dragging the left mouse button. if (mLMouseDown) { } // If we are dragging the right mouse button. if (mRMouseDown) { mCamNode->yaw(-e->getRelX() * mRotateSpeed); mCamNode->pitch(-e->getRelY() * mRotateSpeed); } } //----------------------------------------------------------------------- bool IVFrameListener::frameStarted(const FrameEvent &evt) { if (mWindow->isClosed()) { return false; } 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 (!processUnbufferedMouseInput(evt)) { return false; }*/ // --- set parameters for visualization if (mShowVisualization) { // important for visualization => draw octree bounding boxes 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)); // move by a constant so view plane is on bottom of viewport mVizCamera->moveRelative(Vector3(0, 800, 0)); } //-- set application state switch (mAppState) { case REPLAY: setCurrentFrameInfo(evt.timeSinceLastFrame); break; case WALKTHROUGH: //-- if we are recording camera status per frame if (mRecordFrames) { addFrameInfo(mCamNode, evt.timeSinceLastFrame); // print recording message mWindow->setDebugText("Recording frame " + StringConverter::toString(mFrameInfo.size() - 1)); } // move camera according to input moveCamera(); // clamp camera so we always walk along the floor plane Clamp2Floor(); break; default: break; }; return true; } //----------------------------------------------------------------------- bool IVFrameListener::Clamp2Floor() { // clamp to floor plane Ray updateRay; updateRay.setOrigin(Vector3(mCamNode->getPosition().x, mCamNode->getPosition().y /*+ 2*/, mCamNode->getPosition().z)); //updateRay.setOrigin(Vector3(0, 100, -200)); updateRay.setDirection(Vector3::NEGATIVE_UNIT_Y); mRaySceneQuery->setRay(updateRay); RaySceneQueryResult& qryResult = mRaySceneQuery->execute(); RaySceneQueryResult::iterator it = qryResult.begin(); while (it != qryResult.end() && it->movable) { if (it->movable->getName() != "PlayerCam") { mCamNode->setPosition(mCamNode->getPosition().x, it->movable->getWorldBoundingBox().getCenter().y + 2, mCamNode->getPosition().z); /*std::stringstream d; d << "World: " << it->movable->getWorldBoundingBox().getCenter().y << ", Object: " << it->movable->getBoundingBox().getCenter().y << ", Camera: " << mCamera->getDerivedPosition(); LogManager::getSingleton().logMessage(d.str());*/ return true; } ++ it; } return false; } //----------------------------------------------------------------------- bool IVFrameListener::frameEnded(const FrameEvent& evt) { if (mShutdownRequested) return false; updateStats(); //-- IMPORTANT mSceneMgr->endFrame(); if (mTimeDelay <= 0) // approx. one second mTimeDelay = 1.0; return true; } //----------------------------------------------------------------------- void IVFrameListener::moveCamera() { // move node rather than camera so orientation is right in the visualization mCamNode->yaw(mRotX); mCamNode->pitch(mRotY); mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector); } //----------------------------------------------------------------------- void IVFrameListener::writeFrames() { std::ofstream ofstr(frames_out_filename); std::vector::const_iterator it, it_end; it_end = mFrameInfo.end(); for (it = mFrameInfo.begin(); it < it_end; ++it) { ofstr << StringConverter::toString((*it).position) << " " << StringConverter::toString((*it).orientation) << " " << StringConverter::toString((*it).timeElapsed) << "\n"; } ofstr.close(); } //----------------------------------------------------------------------- void IVFrameListener::loadFrames() { std::ifstream ifstr(frames_out_filename); char line[256]; frame_info info; // reset current values mFrameInfo.clear(); mCurrentFrame = 0; while (!ifstr.eof()) { ifstr.getline(line, 256); sscanf(line, "%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); mFrameInfo.push_back(info); } ifstr.close(); } //----------------------------------------------------------------------- void IVFrameListener::nextAppState() { mCurrentFrame = 0; // if last state was replay state if (mAppState == REPLAY) { // reset debug text and write frame info to file mWindow->setDebugText(""); writeFrames(); float avgFps = (float)mAccumulatedFps / (float)mFrameCount; float avgTris = (float)mAccumulatedTris / (float)mFrameCount; //-- write out stats for recorded walkthrough std::stringstream d; d << "Algorithm: " << msAlgorithmCaptions[mCurrentAlgorithm] << "\n" //<< "avg. FPS: " << mWindow->getAverageFPS() << "\n" << "avg. FPS: " << avgFps << "\n" << "best FPS: " << mWindow->getBestFPS() << "\n" << "worst FPS: " << mWindow->getWorstFPS() << "\n" << "best frame time: " << mWindow->getBestFrameTime() << "\n" << "worst frame time: " << mWindow->getWorstFrameTime() << "\n" << "avg. #triangles: " << avgTris << " M\n" << "#frames: " << mFrameCount << "\n"; LogManager::getSingleton().logMessage(d.str()); } //-- set the next státe mAppState = (mAppState + 1) % STATE_NUM; // replay recorded walkthrough if (mAppState == REPLAY) { // no recording during replay mRecordFrames = false; // load recorded walkthrough if (mFrameInfo.size() == 0) { loadFrames(); } // if there are no recorded frames => set next state if (mFrameInfo.size() == 0) { nextAppState(); } else { mWindow->setDebugText("Replay"); // reset, because we measure fps stats during walkthrough (warning: average fps broken) mWindow->resetStatistics(); resetStats(); //-- initialise frame data mReplayTimeElapsed = 0; mCamNode->setPosition(mFrameInfo[0].position); mCamNode->setOrientation(mFrameInfo[0].orientation); } } } //----------------------------------------------------------------------- void IVFrameListener::toggleRecord() { mRecordFrames = !mRecordFrames; // clear previous camera path if (mRecordFrames) mFrameInfo.clear(); else mWindow->setDebugText(""); } //----------------------------------------------------------------------- void IVFrameListener::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 IVFrameListener::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 IVFrameListener::zoomVizCamera(int zoom) { mVizCameraHeight += zoom; if(mVizCameraHeight < 0) mVizCameraHeight = 0; } //----------------------------------------------------------------------- void IVFrameListener::nextAlgorithm() { mCurrentAlgorithm = (mCurrentAlgorithm + 1) % GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS; setAlgorithm(mCurrentAlgorithm); } //----------------------------------------------------------------------- void IVFrameListener::setAlgorithm(int algorithm) { mAlgorithmInfo->setCaption(": " + msAlgorithmCaptions[mCurrentAlgorithm]); mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm); } //----------------------------------------------------------------------- void IVFrameListener::resetStats() { mAccumulatedFps = 0; mAccumulatedTris = 0; mFrameCount = 0; } //----------------------------------------------------------------------- void IVFrameListener::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: "; // HACK: compute average fps ourselfs, because ogre avg. fps is wrong // TODO: update only once per second mAccumulatedFps += mWindow->getStatistics().lastFPS; ++ mFrameCount; float avgFps = (float)mAccumulatedFps / (float)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(); //guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS)); if (mTimeDelay < 0) // only update once per second { guiAvg->setCaption(avgFpsString + StringConverter::toString(avgFps) + " ms"); } //std::stringstream d; d << "frame rate :" << stats.lastFPS; //Ogre::LogManager::getSingleton().logMessage(d.str()); guiCurr->setCaption(currFpsString + StringConverter::toString(stats.lastFPS)); 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)); 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.2; sprintf(str,": %d", (int)mDelayedQueriesIssued); mQueriesIssuedInfo->setCaption(str); mSceneMgr->getOption("NumTraversedNodes", &opt); mDelayedTraversedNodes = mDelayedTraversedNodes * 0.8 + (float)opt * 0.2; sprintf(str,": %d", (int)mDelayedTraversedNodes); mTraversedNodesInfo->setCaption(str); } catch (...) { // ignore } } //----------------------------------------------------------------------- void IVFrameListener::toggleTestGeometryForVisibleLeaves() { mTestGeometryForVisibleLeaves = !mTestGeometryForVisibleLeaves; 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 IVFrameListener::toggleShowOctree() { mShowOctree = !mShowOctree; mSceneMgr->setOption("ShowOctree", &mShowOctree); } //----------------------------------------------------------------------- void IVFrameListener::toggleUseArbQueries() { mUseArbQueries = !mUseArbQueries; mSceneMgr->setOption("UseArbQueries", &mUseArbQueries); if (mUseArbQueries) { mUseArbQueriesInfo->setCaption(": ARB"); } else { mUseArbQueriesInfo->setCaption(": NV"); } } //----------------------------------------------------------------------- void IVFrameListener::toggleUseDepthPass() { mUseDepthPass = !mUseDepthPass; mSceneMgr->setOption("UseDepthPass", &mUseDepthPass); if (mUseDepthPass) { mUseDepthPassInfo->setCaption(": true"); } else { mUseDepthPassInfo->setCaption(": false"); } } //----------------------------------------------------------------------- void IVFrameListener::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 IVFrameListener::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 IVFrameListener::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 IVFrameListener::keyPressed(KeyEvent* e) { // hide exact visibility query overlay if (mShowQueryStats) { mQueryOverlay->hide(); mShowQueryStats = false; } switch(e->getKey()) { case KC_ESCAPE: mShutdownRequested = true; e->consume(); return; case KC_SPACE: nextAlgorithm(); break; case KC_F: nextFilter(); break; case KC_R: nextSceneDetailLevel(); break; case KC_P: toggleDisplayCameraDetails(); break; case KC_G: toggleTestGeometryForVisibleLeaves(); break; case KC_T: toggleShowOctree(); break; case KC_X: toggleUseDepthPass(); break; case KC_S: toggleShowShadows(); break; case KC_SUBTRACT: changeThreshold(-10); break; case KC_ADD: changeThreshold(10); break; //-- visualization case KC_1: toggleShowViz(); break; case KC_2: nextNodeVizMode(); break; case KC_F1: toggleShowHelp(); break; case KC_F2: toggleShowStats(); break; case KC_F3: nextAppState(); break; case KC_F4: toggleRecord(); break; case KC_F11: takeScreenshot(); break; case KC_8: changeAssumedVisibility(-1); break; case KC_9: changeAssumedVisibility(1); break; case KC_LSHIFT: mShiftPressed = true; break; case KC_A: toggleUseArbQueries(); break; default: break; } CEGUI::System::getSingleton().injectKeyDown(e->getKey()); CEGUI::System::getSingleton().injectChar(e->getKeyChar()); e->consume(); } //----------------------------------------------------------------------- void IVFrameListener::keyReleased(KeyEvent* e) { if (e->getKey() == KC_LSHIFT) { mShiftPressed = false; } CEGUI::System::getSingleton().injectKeyUp(e->getKey()); e->consume(); } //----------------------------------------------------------------------- void IVFrameListener::keyClicked(KeyEvent* e) { // Do nothing e->consume(); } //----------------------------------------------------------------------- void IVFrameListener::addFrameInfo(SceneNode *camNode, Real timeElapsed) { frame_info info; info.orientation = mCamNode->getOrientation(); info.position = mCamNode->getPosition(); info.timeElapsed = timeElapsed; mFrameInfo.push_back(info); } //----------------------------------------------------------------------- void IVFrameListener::setCurrentFrameInfo(Real timeElapsed) { //-- find current frame relative to elapsed frame time mReplayTimeElapsed -= timeElapsed; while ((mReplayTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1)) { mReplayTimeElapsed += mFrameInfo[mCurrentFrame ++].timeElapsed; } frame_info new_frame = mFrameInfo[mCurrentFrame]; frame_info old_frame = mFrameInfo[mCurrentFrame - 1]; //-- interpolate frames Real factor = 1; if (old_frame.timeElapsed > 0) { factor = mReplayTimeElapsed / old_frame.timeElapsed; } Vector3 camPos = old_frame.position + factor * (new_frame.position - old_frame.position); Quaternion camOrienation = Quaternion::Slerp(factor, old_frame.orientation, new_frame.orientation, true); mCamNode->setPosition(camPos); mCamNode->setOrientation(camOrienation); // stop replay after a full walkthrough if (mCurrentFrame == (int)mFrameInfo.size() - 1) { nextAppState(); } } //----------------------------------------------------------------------- bool IVFrameListener::processUnbufferedKeyInput(const FrameEvent& evt) { bool cursorPressed = false; /* Move camera forward by keypress. */ if (mInputDevice->isKeyDown(KC_UP)) { mTranslateVector.z = -mMoveScale; cursorPressed = true; } /* Move camera backward by keypress. */ if (mInputDevice->isKeyDown(KC_DOWN)) { mTranslateVector.z = mMoveScale; cursorPressed = true; } if (mInputDevice->isKeyDown(KC_RIGHT)) { //mCamNode->yaw(-mRotScale); mRotX = -mRotScale; cursorPressed = true; } if (mInputDevice->isKeyDown(KC_LEFT)) { mRotX = mRotScale; //mCamNode->yaw(mRotScale); cursorPressed = true; } // visualization camera if (mInputDevice->isKeyDown(KC_3)) { zoomVizCamera(50); } if (mInputDevice->isKeyDown(KC_4)) { zoomVizCamera(-50); } // show the results if (cursorPressed && mShowQueryStats) { mQueryOverlay->hide(); mShowQueryStats = false; } // Return true to continue rendering return true; } //----------------------------------------------------------------------- void IVFrameListener::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 IVFrameListener::nextSceneDetailLevel() { 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; } } //----------------------------------------------------------------------- void IVFrameListener::takeScreenshot() { char tmp[20]; sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots); mWindow->writeContentsToFile(tmp); mWindow->setDebugText(String("Wrote ") + tmp); } //----------------------------------------------------------------------- void IVFrameListener::toggleDisplayCameraDetails() { mDisplayCameraDetails = !mDisplayCameraDetails; if (!mDisplayCameraDetails) { mWindow->setDebugText(""); } } //----------------------------------------------------------------------- void IVFrameListener::showStats(bool show) { if (mDebugOverlay && mCullStatsOverlay) { if (show) { mDebugOverlay->show(); mCullStatsOverlay->show(); } else { mDebugOverlay->hide(); mCullStatsOverlay->hide(); } } } //----------------------------------------------------------------------- void IVFrameListener::toggleShowStats() { mStatsOn = !mStatsOn; showStats(mStatsOn); } //----------------------------------------------------------------------- void IVFrameListener::toggleShowHelp() { mShowHelp = !mShowHelp; if (mShowHelp) { mHelpOverlay->show(); } else { mHelpOverlay->hide(); } } //----------------------------------------------------------------------- void IVFrameListener::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 IVFrameListener::initHelpOverlayElement(String name, int top) { OverlayElement *el = OverlayManager::getSingleton().getOverlayElement( "Example/Visibility/Help/" + name); el->setTop(top); } //----------------------------------------------------------------------- void IVFrameListener::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("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("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 IVFrameListener::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(&mUseArbQueriesInfo, ext, "UseArbQueries", top, ": NV"); 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 IVFrameListener::initQueryOverlay() { const int border_height = 10; const int vert_space = 15; //-- visibility culling stats overlay int top = border_height + 25; 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); }