#include "Ogre.h" #include "OgreConfigFile.h" #include "OgreKeyEvent.h" #include "OgreEventListeners.h" #include "OgreStringConverter.h" #include "OgreException.h" using namespace Ogre; class ExampleFrameListener: public FrameListener, public KeyListener { protected: int mSceneDetailIndex ; Real mMoveSpeed; Degree mRotateSpeed; Overlay* mDebugOverlay; float zoom; void updateStats(void) { static int count = 0; count += 1; if (count % 100 == 0) { const RenderTarget::FrameStats& stats = mWindow->getStatistics(); std::cout << stats.avgFPS << std::endl; } static String currFps = "Current FPS: "; static String avgFps = "Average FPS: "; static String bestFps = "Best FPS: "; static String worstFps = "Worst FPS: "; static String tris = "Triangle Count: "; // update stats when necessary try { GuiElement* guiAvg = GuiManager::getSingleton().getGuiElement("Core/AverageFps"); GuiElement* guiCurr = GuiManager::getSingleton().getGuiElement("Core/CurrFps"); GuiElement* guiBest = GuiManager::getSingleton().getGuiElement("Core/BestFps"); GuiElement* guiWorst = GuiManager::getSingleton().getGuiElement("Core/WorstFps"); const RenderTarget::FrameStats& stats = mWindow->getStatistics(); guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS)); guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS)); guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS) +" "+StringConverter::toString(stats.bestFrameTime)+" ms"); guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS) +" "+StringConverter::toString(stats.worstFrameTime)+" ms"); GuiElement* guiTris = GuiManager::getSingleton().getGuiElement("Core/NumTris"); guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount)); GuiElement* guiDbg = GuiManager::getSingleton().getGuiElement("Core/DebugText"); guiDbg->setCaption(mWindow->getDebugText()); } catch(...) { // ignore } } public: // Constructor takes a RenderWindow because it uses that to determine input context ExampleFrameListener(RenderWindow* win, Camera* cam, bool useBufferedInputKeys = false, bool useBufferedInputMouse = false) { zoom = 170; mDebugOverlay = (Overlay*)OverlayManager::getSingleton().getByName("Core/DebugOverlay"); mUseBufferedInputKeys = useBufferedInputKeys; mUseBufferedInputMouse = useBufferedInputMouse; mInputTypeSwitchingOn = mUseBufferedInputKeys || mUseBufferedInputMouse; mRotateSpeed = 36; mMoveSpeed = 100; if (mInputTypeSwitchingOn) { mEventProcessor = new EventProcessor(); mEventProcessor->initialise(win); OverlayManager::getSingleton().createCursorOverlay(); mEventProcessor->startProcessingEvents(); mEventProcessor->addKeyListener(this); mInputDevice = mEventProcessor->getInputReader(); } else { mInputDevice = PlatformManager::getSingleton().createInputReader(); mInputDevice->initialise(win,true, true); } mCamera = cam; mWindow = win; mStatsOn = true; mNumScreenShots = 0; mTimeUntilNextToggle = 0; mSceneDetailIndex = 0; mMoveScale = 0.0f; mRotScale = 0.0f; mTranslateVector = Vector3::ZERO; mAniso = 1; mFiltering = TFO_BILINEAR; showDebugOverlay(true); } virtual ~ExampleFrameListener() { if (mInputTypeSwitchingOn) { delete mEventProcessor; } else { PlatformManager::getSingleton().destroyInputReader( mInputDevice ); } } virtual bool processUnbufferedKeyInput(const FrameEvent& evt) { if (mInputDevice->isKeyDown(KC_A)) { // Move camera left mTranslateVector.x = -mMoveScale; } if (mInputDevice->isKeyDown(KC_D)) { // Move camera RIGHT mTranslateVector.x = mMoveScale; } /* Move camera forward by keypress. */ if (mInputDevice->isKeyDown(KC_UP) || mInputDevice->isKeyDown(KC_W) ) { mTranslateVector.z = -mMoveScale; } /* Move camera backward by keypress. */ if (mInputDevice->isKeyDown(KC_DOWN) || mInputDevice->isKeyDown(KC_S) ) { mTranslateVector.z = mMoveScale; } if (mInputDevice->isKeyDown(KC_L)) { zoom += 0.1f; } if (mInputDevice->isKeyDown(KC_S)) { zoom -= 0.1f; } if (mInputDevice->isKeyDown(KC_PGUP)) { // Move camera up mTranslateVector.y = mMoveScale; } if (mInputDevice->isKeyDown(KC_PGDOWN)) { // Move camera down mTranslateVector.y = -mMoveScale; } if (mInputDevice->isKeyDown(KC_RIGHT)) { mCamera->yaw(-mRotScale); } if (mInputDevice->isKeyDown(KC_LEFT)) { mCamera->yaw(mRotScale); } if( mInputDevice->isKeyDown( KC_ESCAPE) ) { return false; } // see if switching is on, and you want to toggle if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_M) && mTimeUntilNextToggle <= 0) { switchMouseMode(); mTimeUntilNextToggle = 1; } if (mInputTypeSwitchingOn && mInputDevice->isKeyDown(KC_K) && mTimeUntilNextToggle <= 0) { // must be going from immediate keyboard to buffered keyboard switchKeyMode(); mTimeUntilNextToggle = 1; } if (mInputDevice->isKeyDown(KC_F) && mTimeUntilNextToggle <= 0) { mStatsOn = !mStatsOn; showDebugOverlay(mStatsOn); mTimeUntilNextToggle = 1; } if (mInputDevice->isKeyDown(KC_T) && mTimeUntilNextToggle <= 0) { 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); showDebugOverlay(mStatsOn); mTimeUntilNextToggle = 1; } if (mInputDevice->isKeyDown(KC_SYSRQ) && mTimeUntilNextToggle <= 0) { char tmp[20]; sprintf(tmp, "screenshot_%d.png", ++mNumScreenShots); mWindow->writeContentsToFile(tmp); mTimeUntilNextToggle = 0.5; mWindow->setDebugText(String("Wrote ") + tmp); } if (mInputDevice->isKeyDown(KC_R) && mTimeUntilNextToggle <=0) { 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 ; } mTimeUntilNextToggle = 0.5; } static bool displayCameraDetails = false; if (mInputDevice->isKeyDown(KC_P) && mTimeUntilNextToggle <= 0) { displayCameraDetails = !displayCameraDetails; mTimeUntilNextToggle = 0.5; if (!displayCameraDetails) mWindow->setDebugText(""); } if (displayCameraDetails) { // Print camera details mWindow->setDebugText("P: " + StringConverter::toString(mCamera->getDerivedPosition()) + " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation())); } // Return true to continue rendering return true; } bool 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; } void moveCamera() { // Make all the changes to the camera // Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW (e.g. airplane) mCamera->yaw(mRotX); mCamera->pitch(mRotY); mCamera->moveRelative(mTranslateVector); //std::cout << zoom << std::endl; if (zoom >= 179.9) zoom = 179.9; else if (zoom < 10) zoom = 10; mCamera->setFOVy(Radian(Degree(zoom))); } void showDebugOverlay(bool show) { if (mDebugOverlay) { if (show) { mDebugOverlay->show(); } else { mDebugOverlay->hide(); } } } // Override frameStarted event to process that (don't care about frameEnded) bool frameStarted(const FrameEvent& evt) { if(mWindow->isClosed()) return false; if (!mInputTypeSwitchingOn) { mInputDevice->capture(); } if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys) { // one of the input modes is immediate, so setup what is needed for immediate mouse/key movement if (mTimeUntilNextToggle >= 0) mTimeUntilNextToggle -= 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 (mUseBufferedInputKeys) { // no need to do any processing here, it is handled by event processor and // you get the results as KeyEvents } else { if (processUnbufferedKeyInput(evt) == false) { return false; } } if (mUseBufferedInputMouse) { // no need to do any processing here, it is handled by event processor and // you get the results as MouseEvents } else { if (processUnbufferedMouseInput(evt) == false) { return false; } } if ( !mUseBufferedInputMouse || !mUseBufferedInputKeys) { // one of the input modes is immediate, so update the movement vector moveCamera(); } return true; } bool frameEnded(const FrameEvent& evt) { updateStats(); return true; } void switchMouseMode() { mUseBufferedInputMouse = !mUseBufferedInputMouse; mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse); } void switchKeyMode() { mUseBufferedInputKeys = !mUseBufferedInputKeys; mInputDevice->setBufferedInput(mUseBufferedInputKeys, mUseBufferedInputMouse); } void keyClicked(KeyEvent* e) { if (e->getKeyChar() == 'm') { switchMouseMode(); } else if (e->getKeyChar() == 'k') { switchKeyMode(); } } void keyPressed(KeyEvent* e) {} void keyReleased(KeyEvent* e) {} protected: EventProcessor* mEventProcessor; InputReader* mInputDevice; Camera* mCamera; Vector3 mTranslateVector; RenderWindow* mWindow; bool mStatsOn; bool mUseBufferedInputKeys, mUseBufferedInputMouse, mInputTypeSwitchingOn; unsigned int mNumScreenShots; float mMoveScale; Degree mRotScale; // just to stop toggles flipping too fast Real mTimeUntilNextToggle ; Radian mRotX, mRotY; TextureFilterOptions mFiltering; int mAniso; }; /** Base class which manages the standard startup of an Ogre application. Designed to be subclassed for specific examples if required. */ class ExampleApplication { public: /// Standard constructor ExampleApplication() { mFrameListener = 0; mRoot = 0; } /// Standard destructor virtual ~ExampleApplication() { delete mFrameListener; delete mRoot; } /// Start the example virtual void go(void) { if (!setup()) return; mRoot->startRendering(); } protected: Root *mRoot; Camera* mCamera; SceneManager* mSceneMgr; ExampleFrameListener* mFrameListener; RenderWindow* mWindow; // These internal methods package up the stages in the startup process /** Sets up the application - returns false if the user chooses to abandon configuration. */ virtual bool setup(void) { mRoot = new Root(); setupResources(); bool carryOn = configure(); if (!carryOn) return false; chooseSceneManager(); createCamera(); createViewports(); // Set default mipmap level (NB some APIs ignore this) TextureManager::getSingleton().setDefaultNumMipMaps(5); // Create the scene createScene(); createFrameListener(); return true; } /** Configures the application - returns false if the user chooses to abandon configuration. */ virtual bool configure(void) { // Show the configuration dialog and initialise the system // You can skip this and use root.restoreConfig() to load configuration // settings if you were sure there are valid ones saved in ogre.cfg if(mRoot->showConfigDialog()) { // If returned true, user clicked OK so initialise // Here we choose to let the system create a default rendering window by passing 'true' mWindow = mRoot->initialise(true); return true; } else { return false; } } virtual void chooseSceneManager(void) { // Get the SceneManager, in this case a generic one mSceneMgr = mRoot->getSceneManager(ST_GENERIC); } virtual void createCamera(void) { // Create the camera mCamera = mSceneMgr->createCamera("PlayerCam"); // Position it at 500 in Z direction mCamera->setPosition(Vector3(50,50,50)); // Look back along -Z mCamera->lookAt(Vector3(0,0,0)); mCamera->setNearClipDistance(5); mCamera->setFOVy(Radian(Degree(170))); mCamera->setProjectionType(PT_ORTHOGRAPHIC); } virtual void createFrameListener(void) { mFrameListener= new ExampleFrameListener(mWindow, mCamera); mFrameListener->showDebugOverlay(true); mRoot->addFrameListener(mFrameListener); } virtual void createViewports(void) { // Create one viewport, entire window Viewport* vp = mWindow->addViewport(mCamera); vp->setBackgroundColour(ColourValue(0,0,0)); // Alter the camera aspect ratio to match the viewport mCamera->setAspectRatio( Real(vp->getActualWidth()) / Real(vp->getActualHeight())); } /// Method which will define the source of resources (other than current folder) virtual void setupResources(void) { // Load resource paths from config file ConfigFile cf; cf.load("resources.cfg"); // Go through all settings in the file ConfigFile::SettingsIterator i = cf.getSettingsIterator(); String typeName, archName; while (i.hasMoreElements()) { typeName = i.peekNextKey(); archName = i.getNext(); ResourceManager::addCommonArchiveEx( archName, typeName ); } //Root::addResourceLocation() } void createScene() { // Create a skybox //mSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox"); std::cout << "XXXXXXXXXXXXXXXXXXXX" << std::endl; std::cout << "CCCCCCXXXXXXXXXXXXXXXXXXXX" << std::endl; //Entity* head = mSceneMgr->createEntity("MrFoo", "farm2/Plane.001.mesh"); //mSceneMgr->getRootSceneNode()->attachObject(head); int s = 50; for(int y = 0; y < s; ++y) { for(int x = 0; x < s; ++x) { char str[1024]; snprintf(str, 1024, "foo%d", (y*s+x)); Entity* newentity = mSceneMgr->createEntity(str, "farm2/Plane.001.mesh"); //Entity* newentity = mSceneMgr->createEntity(str, "coalmine/Plane.001.mesh"); SceneNode* mShipNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mShipNode->attachObject(newentity); mShipNode->translate((x-s) * 20, 0, (y-s) * 20); } } mSceneMgr->setAmbientLight(ColourValue(.5, 0.5, .5)); // White light in "off" state Light* mWhiteLight = mSceneMgr->createLight("WhiteFlyingLight"); mWhiteLight->setType(Light::LT_POINT); mWhiteLight->setPosition(Vector3(150,50,50)); mWhiteLight->setDiffuseColour(ColourValue(1.0, 1.0, 1.0)); //mWhiteLight->setCastShadows(true); //mWhiteLight->setAttenuation(8000,1,0.0005,0); mSceneMgr->getRootSceneNode()->attachObject(mWhiteLight); Light* mWhiteLight2 = mSceneMgr->createLight("WhiteFlyingLight2"); mWhiteLight2->setType(Light::LT_POINT); mWhiteLight2->setPosition(Vector3(-150,-50,-50)); mWhiteLight2->setDiffuseColour(ColourValue(1.0, 1.0, 1.0)); mSceneMgr->getRootSceneNode()->attachObject(mWhiteLight2); //mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_ADDITIVE); } }; int main(int argc, char** argv) { // Create application object ExampleApplication app; try { app.go(); } catch( Ogre::Exception& e ) { std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; } return 0; } /* EOF */