/** \file TestCullingTerrainApplication.cpp \brief Tests the visibility culling algorithm */ #include #include #include <../CEGUIRenderer/include/OgreCEGUIRenderer.h> #include <../CEGUIRenderer/include/OgreCEGUIResourceProvider.h> #include <../CEGUIRenderer/include/OgreCEGUITexture.h> #include #include #include "OgreReferenceAppLayer.h" //#include "OgreRefAppWorld.h" #include "TestCullingTerrainApplication.h" #define WIN32_LEAN_AND_MEAN #include #define VIZ_VIEWPORT_Z_ORDER 10 const char* frame_outfile = "frame.out"; const char* objects_outfile = "objects.out"; /*******************************************************/ /* TestCullingTerrainApplication implementation */ /*******************************************************/ //----------------------------------------------------------------------- TestCullingTerrainApplication::~TestCullingTerrainApplication() { if(mTerrainContentGenerator) delete mTerrainContentGenerator; //if(mRenderTargetListener) delete mRenderTargetListener; } //----------------------------------------------------------------------- void TestCullingTerrainApplication::createCamera() { // create the camera mCamera = mSceneMgr->createCamera("PlayerCam"); /** set a nice viewpoint * we use a camera node here and apply all transformations on it instead * of applying all transformations directly to the camera * because then the camera is displayed correctly in the visualization */ mCamNode = mSceneMgr->getRootSceneNode()->createChildSceneNode( "CamNode1", Vector3(707, 5000, 528)); //mCamera->setPosition(707, 5000, 528); mCamNode->setOrientation(Quaternion(-0.3486, 0.0122, 0.9365, 0.0329)); mCamNode->attachObject(mCamera); //-- create visualization camera mVizCamera = mSceneMgr->createCamera("VizCam"); mVizCamera->setPosition(mCamNode->getPosition()); mVizCamera->setNearClipDistance(1); mCamera->setNearClipDistance(1); // infinite far plane? if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE)) { mVizCamera->setFarClipDistance(0); mCamera->setFarClipDistance(0); } else { mVizCamera->setFarClipDistance(20000); mCamera->setFarClipDistance(20000); } } //----------------------------------------------------------------------- bool TestCullingTerrainApplication::setup() { bool result = ExampleApplication::setup(); createRenderTargetListener(); return result; } //----------------------------------------------------------------------- void TestCullingTerrainApplication::createRenderTargetListener() { mWindow->addListener(new VisualizationRenderTargetListener(mSceneMgr)); } //----------------------------------------------------------------------- void TestCullingTerrainApplication::createScene() { // Set ambient light mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5)); // Create a light Light* l = mSceneMgr->createLight("MainLight"); // Accept default settings: point light, white diffuse, just set position // NB I could attach the light to a SceneNode if I wanted it to move automatically with // other objects, but I don't l->setPosition(20,80,50); // --Fog // NB it's VERY important to set this before calling setWorldGeometry // because the vertex program picked will be different ColourValue fadeColour(0.93, 0.86, 0.76); mWindow->getViewport(0)->setBackgroundColour(fadeColour); //mSceneMgr->setFog( FOG_LINEAR, fadeColour, .001, 500, 1000); // Create a skybox mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox", 5000, false); std::string terrain_cfg("terrain.cfg"); #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE terrain_cfg = mResourcePath + terrain_cfg; #endif mSceneMgr->setWorldGeometry(terrain_cfg); //-- CEGUI setup setupGui(); //-- terrain content setup // HACK: necessary to call once before the content creation for // terrain initialisation mSceneMgr->_renderScene(mCamera, mWindow->getViewport(0), true); mTerrainContentGenerator = new TerrainContentGenerator(mSceneMgr); // if no objects file generate yourself //if (!mTerrainContentGenerator->LoadObjects("objects.out")) //{ // the objects are generated on the whole terrain // height is restricted to 50, so no objects appear on peaks // => there is much occlusion mTerrainContentGenerator->SetMaxPos(Vector3(3000.0f, 50.0f, 3000.0f)); mTerrainContentGenerator->GenerateScene(1500, "robot"); // mTerrainContentGenerator->GenerateScene(500, "ninja"); //} // no limitations needed anymore: the user can set // objects also on peaks of terrain mTerrainContentGenerator->SetMaxPos(Vector3(3000.0f, 5000.0f, 3000.0f)); //-- create light mSunLight = mSceneMgr->createLight("SunLight"); mSunLight->setType(Light::LT_SPOTLIGHT); mSunLight->setPosition(1000,1250,500); mSunLight->setSpotlightRange(Degree(30), Degree(50)); Vector3 dir; dir = -mSunLight->getPosition(); dir.normalise(); mSunLight->setDirection(dir); mSunLight->setDiffuseColour(0.35, 0.35, 0.38); mSunLight->setSpecularColour(0.9, 0.9, 1); mSunLight->setCastShadows(true); } //----------------------------------------------------------------------- void TestCullingTerrainApplication::setupGui() { mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, ST_EXTERIOR_CLOSE); mGUISystem = new CEGUI::System(mGUIRenderer); // Mouse CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLook.scheme"); CEGUI::MouseCursor::getSingleton().setImage("TaharezLook", "MouseArrow"); mGUISystem->setDefaultMouseCursor( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8*)"MouseArrow"); CEGUI::MouseCursor::getSingleton().show(); } //----------------------------------------------------------------------- void TestCullingTerrainApplication::createFrameListener() { mFrameListener= new MouseQueryListener(mWindow, mCamera, mSceneMgr, mGUIRenderer, mTerrainContentGenerator, mVizCamera, mCamNode); mFrameListener->showDebugOverlay(true); mRoot->addFrameListener(mFrameListener); } //----------------------------------------------------------------------- void TestCullingTerrainApplication::chooseSceneManager() { mSceneMgr = mRoot->getSceneManager(ST_EXTERIOR_CLOSE); } /***********************************************/ /* MouseQueryListener implementation */ /***********************************************/ //----------------------------------------------------------------------- MouseQueryListener::MouseQueryListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager, CEGUI::Renderer *renderer, TerrainContentGenerator *sceneGenerator, Camera *vizCamera, SceneNode *camNode): ExampleFrameListener(win, cam, false, true), mGUIRenderer(renderer), mShutdownRequested(false), mLMouseDown(false), mRMouseDown(false), mSceneMgr(sceneManager), mCurrentObject(NULL), mTerrainContentGenerator(sceneGenerator), mVisibilityThreshold(0), mCurrentAlgorithm(GtpVisibility::VisibilityEnvironment::COHERENT_HIERARCHICAL_CULLING), mShowOctree(false), mUseVisibilityCulling(true), mUseOptimization(true), mVizCamera(vizCamera), mShowVisualization(false), mRenderNodesForViz(false), mVizCameraHeight(Real(2500.0)), mCamNode(camNode), mCullCamera(false), mAppState(WALKTHROUGH), mCurrentFrame(0), mRecord(false), mTimeElapsed(0) { // Reduce move speed mMoveSpeed = 50; mRotateSpeed *= 2; // Register this so that we get mouse events. mEventProcessor->addMouseListener(this); mEventProcessor->addMouseMotionListener(this); mEventProcessor->addKeyListener(this); mRayQueryExecutor = new RayQueryExecutor(mSceneMgr); // show overlay Overlay* pOver = OverlayManager::getSingleton().getByName("Example/VisibilityDemoOverlay"); mAlgorithmInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/AlgorithmInfo"); mThresholdInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/ThresholdInfo"); mFrustumCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/FrustumCulledNodesInfo"); mQueryCulledNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/QueryCulledNodesInfo"); mTraversedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/TraversedNodesInfo"); mHierarchyNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/HierarchyNodesInfo"); mRenderedNodesInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/RenderedNodesInfo"); mObjectsInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/ObjectsInfo"); mUseOptimizationInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/UseOptimizationInfo"); mQueriesIssuedInfo = OverlayManager::getSingleton().getOverlayElement("Example/Visibility/QueriesIssuedInfo"); mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]); mThresholdInfo->setCaption(": 0"); mFrustumCulledNodesInfo->setCaption(": 0"); mQueryCulledNodesInfo->setCaption(": 0"); mTraversedNodesInfo->setCaption(": 0"); mHierarchyNodesInfo->setCaption(": 0"); mRenderedNodesInfo->setCaption(": 0"); mObjectsInfo->setCaption(": 0"); mUseOptimizationInfo->setCaption(": true"); mQueriesIssuedInfo->setCaption(": 0"); setAlgorithm(mCurrentAlgorithm); mSceneMgr->setOption("UseOptimization", &mUseOptimization); mSceneMgr->setOption("UseVisibilityCulling", &mUseVisibilityCulling); mSceneMgr->setOption("ShowOctree", &mShowOctree); mSceneMgr->setOption("CullCamera", &mCullCamera); mSceneMgr->setOption("ShowVisualization", &mShowVisualization); mSceneMgr->setOption("RenderNodesForViz", &mRenderNodesForViz); pOver->show(); } //----------------------------------------------------------------------- MouseQueryListener::~MouseQueryListener() { delete mRayQueryExecutor; } //----------------------------------------------------------------------- void MouseQueryListener::mouseMoved(MouseEvent *e) { // Update CEGUI with the mouse motion CEGUI::System::getSingleton().injectMouseMove(e->getRelX() * mGUIRenderer->getWidth(), e->getRelY() * mGUIRenderer->getHeight()); } //----------------------------------------------------------------------- void MouseQueryListener::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()); Vector3 queryResult; // Get results, create a node/entity on the position mCurrentObject = mTerrainContentGenerator->GenerateSceneObject( mouseRay.getOrigin(), Vector3(0,0,0), "robot.mesh"); mLMouseDown = true; } // Right mouse button down else if (e->getButtonID() & InputEvent::BUTTON1_MASK) { CEGUI::MouseCursor::getSingleton().hide(); mRMouseDown = true; } } // mousePressed //----------------------------------------------------------------------- void MouseQueryListener::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 MouseQueryListener::mouseDragged(MouseEvent *e) { // If we are dragging the left mouse button. if (mLMouseDown) { Vector3 queryResult; Ray mouseRay = mCamera->getCameraToViewportRay(e->getX(), e->getY()); if (mRayQueryExecutor->executeRayQuery(&queryResult, mouseRay)) { if (mCurrentObject) { mCurrentObject->setPosition(queryResult); } } } // If we are dragging the right mouse button. if (mRMouseDown) { //mCamera->yaw(-e->getRelX() * mRotateSpeed); //mCamera->pitch(-e->getRelY() * mRotateSpeed); mCamNode->yaw(-e->getRelX() * mRotateSpeed); mCamNode->pitch(-e->getRelY() * mRotateSpeed); } } //----------------------------------------------------------------------- bool MouseQueryListener::frameStarted(const FrameEvent &evt) { switch (mAppState) { case REPLAY: setCurrentFrameInfo(evt.timeSinceLastFrame); break; case WALKTHROUGH: if (mRecord) { addFrameInfo(mCamNode, evt.timeSinceLastFrame); // print recording message mWindow->setDebugText("Recording frame " + StringConverter::toString(mFrameInfo.size() - 1)); } Clamp2Terrain(); break; default: break; }; if (mShowVisualization) { // important for visualization => draw octree bounding boxes mSceneMgr->setOption("ShowOctree", &mShowVisualization); // also render geometry? mSceneMgr->setOption("RenderNodesForViz", &mRenderNodesForViz); // -- 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)); } return ExampleFrameListener::frameStarted(evt); } //----------------------------------------------------------------------- void MouseQueryListener::Clamp2Terrain() { // clamp to terrain Vector3 camPos = mCamNode->getPosition(); Vector3 queryResult; if (mRayQueryExecutor->executeRayQuery(&queryResult, Vector3(camPos.x, 5000.0f, camPos.z), Vector3::NEGATIVE_UNIT_Y)) { mCamNode->setPosition(camPos.x, queryResult.y + 10, camPos.z); } } //----------------------------------------------------------------------- bool MouseQueryListener::frameEnded(const FrameEvent& evt) { if (mShutdownRequested) return false; if (timeDelay >= 0) timeDelay -= evt.timeSinceLastFrame; KEY_PRESSED(KC_SPACE, 0.3, nextAlgorithm()); KEY_PRESSED(KC_O, 0.3, toggleUseOptimization()); KEY_PRESSED(KC_T, 0.3, toggleShowOctree()); KEY_PRESSED(KC_C, 0.3, toggleUseVisibilityCulling()); KEY_PRESSED(KC_1, 0.3, toggleShowViz()); KEY_PRESSED(KC_2, 0.3, toggleRenderNodesForViz()); KEY_PRESSED(KC_SUBTRACT, 0, changeThreshold(-10)); KEY_PRESSED(KC_ADD, 0, changeThreshold(10)); KEY_PRESSED(KC_3, 0, zoomVizCamera(50)); KEY_PRESSED(KC_4, 0, zoomVizCamera(-50)); KEY_PRESSED(KC_F1, 0.3, nextAppState()); KEY_PRESSED(KC_F2, 0.3, toggleRecord()); KEY_PRESSED(KC_F3, 0.3, mTerrainContentGenerator->WriteObjects(objects_outfile)); //KEY_PRESSED(KC_F3, 0.3, writeFrames()); //KEY_PRESSED(KC_F4, 0.3, loadFrames()); updateStats(); //return ExampleFrameListener::frameStarted(evt) && ExampleFrameListener::frameEnded(evt); return ExampleFrameListener::frameEnded(evt); } //----------------------------------------------------------------------- void MouseQueryListener::moveCamera() { mCamNode->yaw(mRotX); mCamNode->pitch(mRotY); mCamNode->translate(mCamNode->getLocalAxes(), mTranslateVector); } //----------------------------------------------------------------------- void MouseQueryListener::writeFrames() { std::ofstream ofstr(frame_outfile); 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 MouseQueryListener::loadFrames() { std::ifstream ifstr(frame_outfile); 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); /* std::stringstream d; d << StringConverter::toString(info.position) << " " << StringConverter::toString(info.orientation); LogManager::getSingleton().logMessage(d.str()); */ } ifstr.close(); } //----------------------------------------------------------------------- void MouseQueryListener::setAppState(int state) { mAppState = state; } //----------------------------------------------------------------------- void MouseQueryListener::nextAppState() { mCurrentFrame = 0; // if last state was replay state if (mAppState == REPLAY) { // reset debug text and write frame info to file mWindow->setDebugText(""); writeFrames(); //-- write out stats std::stringstream d; d << "Algorithm: " << mCurrentAlgorithmCaptions[mCurrentAlgorithm] << "\n" << "avg. FPS: " << mWindow->getAverageFPS() << "\n" << "best FPS: " << mWindow->getBestFPS() << "\n" << "worst FPS: " << mWindow->getWorstFPS() << "\n" << "best frame time: " << mWindow->getBestFrameTime() << "\n" << "worst frame time: " << mWindow->getWorstFrameTime(); 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 mRecord = 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 mWindow->resetStatistics(); //-- initialise frame data mTimeElapsed = 0; mCamNode->setPosition(mFrameInfo[0].position); mCamNode->setOrientation(mFrameInfo[0].orientation); } } } //----------------------------------------------------------------------- void MouseQueryListener::toggleRecord() { mRecord = !mRecord; // clear previous camera path if (mRecord) mFrameInfo.clear(); else mWindow->setDebugText(""); } //----------------------------------------------------------------------- void MouseQueryListener::changeThreshold(int incr) { mVisibilityThreshold += incr; if(mVisibilityThreshold < 0) mVisibilityThreshold = 0; char str[100]; sprintf(str,": %d", mVisibilityThreshold); mSceneMgr->setOption("Threshold", &mVisibilityThreshold); mThresholdInfo->setCaption(str); } //----------------------------------------------------------------------- bool MouseQueryListener::processUnbufferedKeyInput(const FrameEvent& evt) { if (mInputDevice->isKeyDown(KC_RIGHT)) { mCamNode->yaw(-mRotScale); return true; } if (mInputDevice->isKeyDown(KC_LEFT)) { mCamNode->yaw(mRotScale); return true; } return ExampleFrameListener::processUnbufferedKeyInput(evt); } //----------------------------------------------------------------------- void MouseQueryListener::zoomVizCamera(int zoom) { mVizCameraHeight += zoom; if(mVizCameraHeight < 0) mVizCameraHeight = 0; } //----------------------------------------------------------------------- void MouseQueryListener::nextAlgorithm() { mCurrentAlgorithm = (mCurrentAlgorithm + 1) % GtpVisibility::VisibilityEnvironment::NUM_CULLING_MANAGERS, setAlgorithm(mCurrentAlgorithm); } //----------------------------------------------------------------------- void MouseQueryListener::setAlgorithm(int algorithm) { mAlgorithmInfo->setCaption(": " + mCurrentAlgorithmCaptions[mCurrentAlgorithm]); mSceneMgr->setOption("Algorithm", &mCurrentAlgorithm); } //----------------------------------------------------------------------- void MouseQueryListener::updateStats() { unsigned int opt = 0; char str[100]; mSceneMgr->getOption("NumFrustumCulledNodes", &opt); sprintf(str,": %d", opt); mFrustumCulledNodesInfo->setCaption(str); mSceneMgr->getOption("NumQueriesIssued", &opt); sprintf(str,": %d", opt); mQueriesIssuedInfo->setCaption(str); mSceneMgr->getOption("NumQueryCulledNodes", &opt); sprintf(str,": %d", opt); mQueryCulledNodesInfo->setCaption(str); mSceneMgr->getOption("NumTraversedNodes", &opt); sprintf(str,": %d", opt); mTraversedNodesInfo->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()); mObjectsInfo->setCaption(str); } //----------------------------------------------------------------------- void MouseQueryListener::toggleUseOptimization() { mUseOptimization = !mUseOptimization; mSceneMgr->setOption("UseOptimization", &mUseOptimization); if (mUseOptimization) mUseOptimizationInfo->setCaption(": true"); else mUseOptimizationInfo->setCaption(": false"); } //----------------------------------------------------------------------- void MouseQueryListener::toggleShowOctree() { mShowOctree = !mShowOctree; mSceneMgr->setOption("ShowOctree", &mShowOctree); } //----------------------------------------------------------------------- void MouseQueryListener::toggleUseVisibilityCulling() { mUseVisibilityCulling = !mUseVisibilityCulling; mSceneMgr->setOption("UseVisibilityCulling", &mUseVisibilityCulling); } //----------------------------------------------------------------------- void MouseQueryListener::toggleShowViz() { 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())); //vizvp->setClearEveryFrame(false); // Create a skyplane (for visualization background) /* Plane plane; plane.d = -1000; plane.normal = Vector3::UNIT_Y; mSceneMgr->setSkyPlane(true, plane, "Examples/TransparentTest", 4000, 75, false); */ } else { mWindow->removeViewport(VIZ_VIEWPORT_Z_ORDER); // if octree was enabled for visualization purpose mSceneMgr->setOption("ShowOctree", &mShowOctree); } } //----------------------------------------------------------------------- void MouseQueryListener::toggleRenderNodesForViz() { mRenderNodesForViz = !mRenderNodesForViz; mSceneMgr->setOption("RenderNodesForViz", &mRenderNodesForViz); } //----------------------------------------------------------------------- void MouseQueryListener::keyPressed(KeyEvent* e) { if(e->getKey() == KC_ESCAPE) { mShutdownRequested = true; e->consume(); return; } CEGUI::System::getSingleton().injectKeyDown(e->getKey()); CEGUI::System::getSingleton().injectChar(e->getKeyChar()); e->consume(); } //----------------------------------------------------------------------- void MouseQueryListener::keyReleased(KeyEvent* e) { CEGUI::System::getSingleton().injectKeyUp(e->getKey()); e->consume(); } //----------------------------------------------------------------------- void MouseQueryListener::keyClicked(KeyEvent* e) { // Do nothing e->consume(); } //----------------------------------------------------------------------- void MouseQueryListener::addFrameInfo(SceneNode *camNode, Real timeElapsed) { frame_info info; info.orientation = mCamNode->getOrientation(); info.position = mCamNode->getPosition(); info.timeElapsed = timeElapsed; mFrameInfo.push_back(info); } //----------------------------------------------------------------------- void MouseQueryListener::setCurrentFrameInfo(Real timeElapsed) { //-- find current frame relative to elapsed frame time mTimeElapsed -= timeElapsed; while ((mTimeElapsed <= 0) && (mCurrentFrame < (int)mFrameInfo.size() - 1)) { mTimeElapsed += 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 = mTimeElapsed / 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(); } } /**************************************************************/ /* VisualizationRenderTargetListener implementation */ /**************************************************************/ //----------------------------------------------------------------------- VisualizationRenderTargetListener::VisualizationRenderTargetListener(SceneManager *sceneMgr) :RenderTargetListener(), mSceneMgr(sceneMgr) { } //----------------------------------------------------------------------- void VisualizationRenderTargetListener::preViewportUpdate(const RenderTargetViewportEvent &evt) { const bool showViz = evt.source->getZOrder() == VIZ_VIEWPORT_Z_ORDER; // visualization viewport const bool nShowViz = !showViz; mSceneMgr->setOption("ShowVisualization", &showViz); mSceneMgr->setOption("SkyBoxEnabled", &nShowViz); //mSceneMgr->setOption("SkyPlaneEnabled", &showViz); RenderTargetListener::preViewportUpdate(evt); } //----------------------------------------------------------------------- void VisualizationRenderTargetListener::postRenderTargetUpdate(const RenderTargetEvent &evt) { RenderTargetListener::postRenderTargetUpdate(evt); } //----------------------------------------------------------------------- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) { // Create application object TestCullingTerrainApplication app; try { app.go(); } catch( Ogre::Exception& e ) { MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); } return 0; }