Skip to main content

History: Basic Ogre Framework

Source of version: 9

Copy to clipboard
            {maketoc}

!!Introduction
Once upon a time a young programmer started discovering the great world of Ogre. He went through the ((Ogre Tutorials|#Basic Tutorials|first tutorials)) and was happy that everything worked without lots of code as there was the ''ExampleApplication.h'' that made the Ogre beginner's life rather easy. But, suddenly he read somewhere that the way it is done in this example application, isn't the way it is meant to be done (at least not in more advanced applications). So he started searching on the wiki and in the forums and piece-by-piece, he put together his own BasicOgreFramework.

This magic piece of code was capable of starting Ogre, loading the basic resources, reacting to standard keyboard and mouse input by moving the camera, making screen shots as well as showing the standard Ogre overlays with the logo and the ((FPS)) counter. From this day on, he always used this Framework when he needed a simple base for a test case or whatever.

As many people have the same problem (as he recognized by following most of the forum threads), he finally decided to put his solution in this great wiki, as his solution was much more complete than the other versions already available. However, he decided not to explain the code that much as it is self-explanatory for everyone that read the first ((Ogre Tutorials|Ogre tutorials)).

{DIV(class="Layout_box13")}{img src="img/wiki_up/Forum_icon_question2.gif" alt="Forum icon question2.gif"} However: If you have any problems, please post in the [http://www.ogre3d.org/forums/viewtopic.php?f=5&t=48491|forum thread for this article].{DIV}

{IMG(src="img/wiki_up/BasicOgreFramework.jpg",thumb="y",rel="box",width="200",align="center",stylebox="border",alt="thumb|Basic Ogre Framework")}{IMG}
%clear%
{DIV(class="Bloody_box1")}An example that runs out-of-the-box (without any compiling) can be downloaded [http://www.spacegaier.de/Ogre/BasicOgreFramework.rar|here] from my webspace. Of course it comes with the source, the needed media as well as with a Microsoft ((VisualStudio)) solution file.

''If this file shouldn't be available anymore (due to a possible restructuring of my website), just [http://www.ogre3d.org/forums/ucp.php?i=pm&mode=compose&u=16228|send me a PM] in the forum.''

File has been attached to this page: {ATTACH(id=>20, icon=>1, showdesc=>1, dls=>1)} {ATTACH}{DIV}
!!Architecture
Well, the architecture is rather simple: There is one class, called OgreFramework, that does most of the magic. Just add it to your project. Then you need a second class that is the real application. It calls several functions from the OgreFramework class and also implements the main loop. If you want, you can also make it handle additional input to extend the input handling already implemented.

__Note:__ Don't be scared by the code that looks probably quite a lot to a beginner. However, it is quite easy to understand.

!!OgreFramework.hpp
{DIV(class="Spacegaier_box1")}That is the header for our OgreFramework class. It contains all the Ogre related variables: 
* Ogre Root
* Camera
* RenderWindow
* Viewport
* SceneManager
* Log
* Timer
* Input stuff
* ... 

It also has the input handler function (e.g. ''keyPressed()'' or ''mouseMoved()'' ), that are used to capture some keys for basic camera movement. Apart from that, there are some other members such as a counter for the number of screenshots done while running the application or a variable indicating whether the application is to be shut down.{DIV}

{CODE(wrap="1", colors="c++")}//|||||||||||||||||||||||||||||||||||||||||||||||

#ifndef OGRE_FRAMEWORK_HPP
#define OGRE_FRAMEWORK_HPP

//|||||||||||||||||||||||||||||||||||||||||||||||

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

//|||||||||||||||||||||||||||||||||||||||||||||||

class OgreFramework : public Ogre::Singleton, OIS::KeyListener, OIS::MouseListener
{
public:
	OgreFramework();
	~OgreFramework();

	void initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener = 0, OIS::MouseListener *pMouseListener = 0);
	void updateOgre(double timeSinceLastFrame);
	void updateStats();
	void moveCamera();
	void getInput();

	bool isOgreToBeShutDown()const{return m_bShutDownOgre;}

	bool keyPressed(const OIS::KeyEvent &keyEventRef);
	bool keyReleased(const OIS::KeyEvent &keyEventRef);

	bool mouseMoved(const OIS::MouseEvent &evt);
	bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id); 
	bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
	
	Ogre::Root*				m_pRoot;
	Ogre::SceneManager*			m_pSceneMgr;
	Ogre::RenderWindow*			m_pRenderWnd;
	Ogre::Camera*				m_pCamera;
	Ogre::Viewport*				m_pViewport;
	Ogre::Log*				m_pLog;
	Ogre::Timer*				m_pTimer;
	
	OIS::InputManager*			m_pInputMgr;
	OIS::Keyboard*				m_pKeyboard;
	OIS::Mouse*				m_pMouse;

private:
	OgreFramework(const OgreFramework&);
	OgreFramework& operator= (const OgreFramework&);

	Ogre::Overlay*				m_pDebugOverlay;
	Ogre::Overlay*				m_pInfoOverlay;
	int					m_iNumScreenShots;

	bool					m_bShutDownOgre;
	
	Ogre::Vector3				m_TranslateVector;
	Ogre::Real				m_MoveSpeed; 
	Ogre::Degree				m_RotateSpeed; 
	float					m_MoveScale; 
	Ogre::Degree				m_RotScale;
};

//|||||||||||||||||||||||||||||||||||||||||||||||

#endif 

//|||||||||||||||||||||||||||||||||||||||||||||||{CODE}

!!OgreFramework.cpp
The following code parts form together the OgreFramework.cpp. I'll give some information on the functions:
{DIV(class="Spacegaier_box1")}* __First line__: Needed for the ((Singleton))
* __OgreFramework()__: It just sets some default values for the variables
{DIV}

{CODE(wrap="1", colors="c++")}
#include "OgreFramework.hpp"

using namespace Ogre; 

template<> OgreFramework* Ogre::Singleton::ms_Singleton = 0;

OgreFramework::OgreFramework()
{
	m_MoveSpeed			= 0.1;
	m_RotateSpeed		        = 0.3;

	m_bShutDownOgre		        = false;
	m_iNumScreenShots	        = 0;

	m_pRoot				= 0;
	m_pSceneMgr			= 0;
	m_pRenderWnd		        = 0;
	m_pCamera			= 0;
	m_pViewport			= 0;
	m_pLog				= 0;
	m_pTimer			= 0;

	m_pInputMgr			= 0;
	m_pKeyboard			= 0;
	m_pMouse			= 0;

	m_pDebugOverlay		        = 0;
	m_pInfoOverlay		        = 0;
}{CODE}

{DIV(class="Spacegaier_box1")}* __initOgre()__:
# instantiates the log manager class
# creates a new Ogre root
# creates the scene manager and set some ambient light
# creates the camera and sets its position and clip planes
# creates the viewport and sets the background color
# creates the input devices
# loads the resources
# creates the timer
# creates the debug overlay
# sets the render window active
{DIV}

{CODE(wrap="1", colors="c++")}
void OgreFramework::initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener, OIS::MouseListener *pMouseListener)
{
	Ogre::LogManager* logMgr = new Ogre::LogManager();
	
	m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, false);
	m_pLog->setDebugOutputEnabled(true);
	
	m_pRoot = new Ogre::Root();

	m_pRoot->showConfigDialog();
	m_pRenderWnd = m_pRoot->initialise(true, wndTitle);

	m_pSceneMgr = m_pRoot->createSceneManager(ST_GENERIC, "SceneManager");
	m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7, 0.7, 0.7));
	
	m_pCamera = m_pSceneMgr->createCamera("Camera");
	m_pCamera->setPosition(Vector3(0, 60, 60));
	m_pCamera->lookAt(Vector3(0,0,0));
	m_pCamera->setNearClipDistance(1);

	m_pViewport = m_pRenderWnd->addViewport(m_pCamera);
	m_pViewport->setBackgroundColour(ColourValue(0.8, 0.7, 0.6, 1.0));

	m_pCamera->setAspectRatio(Real(m_pViewport->getActualWidth()) / Real(m_pViewport->getActualHeight()));
	
	m_pViewport->setCamera(m_pCamera);

	unsigned long hWnd = 0;
        OIS::ParamList paramList;
        m_pRenderWnd->getCustomAttribute("WINDOW", &hWnd);

	paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));

	m_pInputMgr = OIS::InputManager::createInputSystem(paramList);

        m_pKeyboard = static_cast(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));
	m_pMouse = static_cast(m_pInputMgr->createInputObject(OIS::OISMouse, true));
    
	m_pMouse->getMouseState().height = m_pRenderWnd->getHeight();
	m_pMouse->getMouseState().width	 = m_pRenderWnd->getWidth();

	if(pKeyListener == 0)
		m_pKeyboard->setEventCallback(this);
	else
		m_pKeyboard->setEventCallback(pKeyListener);

	if(pMouseListener == 0)
		m_pMouse->setEventCallback(this);
	else
		m_pMouse->setEventCallback(pMouseListener);

	Ogre::String secName, typeName, archName;
	Ogre::ConfigFile cf;
        cf.load("resources.cfg");

	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
        while (seci.hasMoreElements())
        {
            secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
            Ogre::ConfigFile::SettingsMultiMap::iterator i;
            for (i = settings->begin(); i != settings->end(); ++i)
            {
                typeName = i->first;
                archName = i->second;
                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
            }
        }
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

	m_pTimer = new Ogre::Timer();
	m_pTimer->reset();
	
	m_pDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
	m_pDebugOverlay->show();

	m_pRenderWnd->setActive(true);
}{CODE}

{DIV(class="Spacegaier_box1")}* __~OgreFramework()__: Just clears up the whole thing{DIV}

{CODE(wrap="1", colors="c++")}
OgreFramework::~OgreFramework()
{
	if(m_pInputMgr)
	{
		delete m_pKeyboard;
		delete m_pMouse;
		OIS::InputManager::destroyInputSystem(m_pInputMgr);
	}

	delete m_pRoot;
}{CODE}

{DIV(class="Spacegaier_box1")}* __keyPressed()__: Implements the basic keyboard input handling
# leave the application when ''escape'' is pressed
# make a screenshot when ''print'' is hit
# change polygon mode when M is hit
# toggle the overlay when O is pressed
{DIV}

{CODE(wrap="1", colors="c++")}
bool OgreFramework::keyPressed(const OIS::KeyEvent &keyEventRef)
{
	m_pLog->logMessage("OgreFramework::keyPressed");
	
	if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
	{
			m_bShutDownOgre = true;
			return true;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_SYSRQ))
	{
		std::ostringstream ss;
		ss << "screenshot_" << ++m_iNumScreenShots << ".png";
		m_pRenderWnd->writeContentsToFile(ss.str());
		return true;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_M))
	{
		static int mode = 0;
		
		if(mode == 2)
		{
			m_pCamera->setPolygonMode(PM_SOLID);
			mode = 0;
		}
		else if(mode == 0)
		{
			 m_pCamera->setPolygonMode(PM_WIREFRAME);
			 mode = 1;
		}
		else if(mode == 1)
		{
			m_pCamera->setPolygonMode(PM_POINTS);
			mode = 2;
		}
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_O))
	{
		if(m_pDebugOverlay)
		{
			if(!m_pDebugOverlay->isVisible())
				m_pDebugOverlay->show();
			else
				m_pDebugOverlay->hide();
		}
	}

	return true;
}{CODE}

{DIV(class="Spacegaier_box1")}* __keyReleased()__: Doesn't do anything. It just has to be in there due to the class being inherited from the ''OIS::MouseListener'' and ''OIS::KeyboardListener''.
{DIV}
{CODE(wrap="1", colors="c++")}
bool OgreFramework::keyReleased(const OIS::KeyEvent &keyEventRef)
{
	return true;
}{CODE}

{DIV(class="Spacegaier_box1")}* __mouseMoved()__: This function gets called when the mouse is move and then changes the camera's orientation.
{DIV}

{CODE(wrap="1", colors="c++")}bool OgreFramework::mouseMoved(const OIS::MouseEvent &evt)
{
	m_pCamera->yaw(Degree(evt.state.X.rel * -0.1));
	m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1));
	
	return true;
}{CODE}

{DIV(class="Spacegaier_box1")}* __mousePressed()__: Doesn't do anything. It just has to be in there due to the class being inherited from the ''OIS::MouseListener'' and ''OIS::KeyboardListener'' 
* __mouseReleased()__: Same here as above.
{DIV}
{CODE(wrap="1", colors="c++")}bool OgreFramework::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return true;
}

bool OgreFramework::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return true;
}{CODE}

{DIV(class="Spacegaier_box1")}
* __updateOgre()__: The function will be called by our own demo class in the main loop (so for every frame). It calculates the move and rotation scale in order to take into account the time passed since the last frame. It also calls ''getInput()'' and ''moveCamera()'' as well as ''updateStats()''.
{DIV}
{CODE(wrap="1", colors="c++")}void OgreFramework::updateOgre(double timeSinceLastFrame)
{
	m_MoveScale = m_MoveSpeed   * timeSinceLastFrame;
	m_RotScale  = m_RotateSpeed * timeSinceLastFrame;
		
	m_TranslateVector = Vector3::ZERO;

	getInput();
	moveCamera();

	updateStats();
}{CODE}

{DIV(class="Spacegaier_box1")}
* __updateStats()__: This function simply updates the overlay with the newest information on the ((FPS)) or the triangle count.
{DIV}
{CODE(wrap="1", colors="c++")}void OgreFramework::updateStats() 
{ 
	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: "; 
        static String batches = "Batch Count: "; 
 
        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 = m_pRenderWnd->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"); 

        OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); 
        guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount)); 

	OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches"); 
        guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount)); 

	OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText"); 
	guiDbg->setCaption("");
}{CODE}

{DIV(class="Spacegaier_box1")}* __moveCamera()__: This function changes the position of the camera accordingly to the vector m_TranslateVector that is changed by the keyboard input. If ''shift'' is pressed, it will move ten times faster than without.
{DIV}
{CODE(wrap="1", colors="c++")}void OgreFramework::moveCamera()
{
	if(m_pKeyboard->isKeyDown(OIS::KC_LSHIFT)) m_pCamera->moveRelative(m_TranslateVector);
	m_pCamera->moveRelative(m_TranslateVector / 10);
}{CODE}

{DIV(class="Spacegaier_box1")}* __getInput()__: This function changes the camera translation vector m_TranslateVector accordingly to the keyboard input.
{DIV}
{CODE(wrap="1", colors="c++")}void OgreFramework::getInput()
{
	if(m_pKeyboard->isKeyDown(OIS::KC_A))
	{
		m_TranslateVector.x = -m_MoveScale;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_D))
	{
		m_TranslateVector.x = m_MoveScale;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_W))
	{
		m_TranslateVector.z = -m_MoveScale;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_S))
	{
		m_TranslateVector.z = m_MoveScale;
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
	{
		m_pCamera->yaw(m_RotScale);
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
	{
		m_pCamera->yaw(-m_RotScale);
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_UP))
	{
		m_pCamera->pitch(m_RotScale);
	}

	if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
	{
		m_pCamera->pitch(-m_RotScale);
	}
}{CODE}

!!Creating your demo class
{DIV(class="Spacegaier_box1")}All that is missing now is your own demo class that only needs some content. It might look like this:
* some functions to start, setup and run the Demo
* a pointer to an OgreFramework instance
* an entity and a scene node
* a boolean variable to show whether the demo should be shut down

__Note:__ By inheriting from ''OIS::KeyListener'' and passing our demo class as a parameter to the ''initOgre()'' method, we can extend the input handling from the ''OgreFramework'' class by reacting to the inputs events in the ''keyPressed()'' and ''keyReleased()'' functions. The ''keyPressed()'' and ''keyReleased()'' function of OgreFramework are not called by OIS in this case, so we must call them from ''keyPressed()'' and ''keyReleased()'' in the DemoApp instead.
{DIV}
{CODE(wrap="1", colors="c++")}//|||||||||||||||||||||||||||||||||||||||||||||||

#ifndef OGRE_DEMO_HPP
#define OGRE_DEMO_HPP

//|||||||||||||||||||||||||||||||||||||||||||||||

#include "OgreFramework.hpp"

//|||||||||||||||||||||||||||||||||||||||||||||||

class DemoApp : public OIS::KeyListener
{
public:
	DemoApp();
	~DemoApp();

	void startDemo();
	
	bool keyPressed(const OIS::KeyEvent &keyEventRef);
	bool keyReleased(const OIS::KeyEvent &keyEventRef);

private:
        void setupDemoScene();
	void runDemo();

	Ogre::SceneNode*			m_pCubeNode;
	Ogre::Entity*				m_pCubeEntity;

	bool					m_bShutdown;
};

//|||||||||||||||||||||||||||||||||||||||||||||||

#endif 

//|||||||||||||||||||||||||||||||||||||||||||||||{CODE}

!!Implemeting your demo class
{DIV(class="Spacegaier_box1")}This is what your demo class implementation could look like:
* __DempApp()__: Constructor
* __~DemoApp()__: Destructor
* __startDemo()__: 
# creates a new ''OgreFramework''
# set the shutdown indicator to false (why would we want to shut it down right now?)
# calls ''setupDemo()'' and ''runDemo()''
* __setupDemoScene()__: puts some content in our scene
# adds a skyBox
# creates a light
# adds a simple cube mesh
* __runDemo()__: the main loop of our application
# leaves the application if m_Shutdown is false or if the ''OgreFramework'' wants us to shut down for some reason
# calculates the time passed since the last frame
# orders the input devices for the keyboard and the mouse to look for new input events
# calls the ''updateOgre()'' function
# renders one frame
# if the render window is not active (does not have the focus), the application sleeps for a second
* __keyPressed()__: you can define here own input handling stuff, as e.g. move the cube in our scene
* __keyReleased()__: same as above
{DIV}
{CODE(wrap="1", colors="c++")}DemoApp::DemoApp()
{
	m_pCubeNode		= 0;
	m_pCubeEntity		= 0;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

DemoApp::~DemoApp()
{
       delete OgreFramework::getSingletonPtr();
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void DemoApp::startDemo()
{
	new OgreFramework();
	OgreFramework::getSingletonPtr()->initOgre("DemoApp v1.0", this, 0);

	m_bShutdown = false;

	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Demo initialized!");
	
	setupDemoScene();
	runDemo();
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void DemoApp::setupDemoScene()
{
	OgreFramework::getSingletonPtr()->m_pSceneMgr->setSkyBox(true, "Examples/SpaceSkyBox");

	OgreFramework::getSingletonPtr()->m_pSceneMgr->createLight("Light")->setPosition(75,75,75);

	m_pCubeEntity = OgreFramework::getSingletonPtr()->m_pSceneMgr->createEntity("Cube", "ogrehead.mesh");
	m_pCubeNode = OgreFramework::getSingletonPtr()->m_pSceneMgr->getRootSceneNode()->createChildSceneNode("CubeNode");
	m_pCubeNode->attachObject(m_pCubeEntity);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void DemoApp::runDemo()
{
	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop...");
	
	double timeSinceLastFrame = 0;
	double startTime = 0;
	
      OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics();

	while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown()) 
	{
		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		Ogre::WindowEventUtilities::messagePump();
#endif	
		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
		{
			startTime = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU();
					
			OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
			OgreFramework::getSingletonPtr()->m_pMouse->capture();

			OgreFramework::getSingletonPtr()->updateOgre(timeSinceLastFrame);
			OgreFramework::getSingletonPtr()->m_pRoot->renderOneFrame();
		
			timeSinceLastFrame = OgreFramework::getSingletonPtr()->m_pTimer->getMillisecondsCPU() - startTime;
		}
		else
		{
			Sleep(1000);
		}
	}

	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit");
	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool DemoApp::keyPressed(const OIS::KeyEvent &keyEventRef)
{
	OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
	
	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_F))
	{
		 //do something
	}

	return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool DemoApp::keyReleased(const OIS::KeyEvent &keyEventRef)
{
	OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
	
	return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||{CODE}

!!The very last thing: main.cpp
{DIV(class="Spacegaier_box1")}* first of all: you don't have to understand this!
* the only important parts are the two lines where an instance of our DemoApp is created and the ''startDemo()'' function is called
{DIV}
{CODE(wrap="1", colors="c++")}//|||||||||||||||||||||||||||||||||||||||||||||||

#include "DemoApp.hpp"

//|||||||||||||||||||||||||||||||||||||||||||||||

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

//|||||||||||||||||||||||||||||||||||||||||||||||

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
int main(int argc, char **argv)
#endif
{
	try
      {
		DemoApp demo;
		demo.startDemo();
      }
	catch(std::exception& e)
      {
#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBoxA(NULL, e.what(), "An exception has occurred!", MB_OK | MB_IConerror | MB_TASKMODAL);
#else
        fprintf(stderr, "An exception has occurred: %s\n", e.what());
#endif
      }

    return 0;
}

//|||||||||||||||||||||||||||||||||||||||||||||||{CODE}

!!Note
__1.__ If you want to, you can declare all the Ogre members in the OgreFramework class (Root, Camera, RenderWindow, SceneManager, ...) private and implement getter methods for them. This is mostly a matter of code style and one's preferences. You could also totally remove most of them as they are also singletons (e.g. Ogre::Root, Ogre::Log) and retrieve them via the singleton functions. It's up to you!

__2.__ If ''Ogre::WindowEventUtilities::messagePump()'' doesn't work for you, try this instead:

{CODE(wrap="1", colors="c++")}#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
{
   MSG msg;
   while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
   {
       if (msg.message == WM_QUIT)
          m_bShutdown = true;
       else
       {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
   }
}
#endif{CODE}

__3.__ On Mac, the ''Sleep()'' function is written with a lower-case S at the beginning, so you either have to change this or (if you want both in your code) use this instead:
{CODE(wrap="1", colors="c++")}#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
   Sleep(1000);
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
   sleep(1000);
#endif
{CODE}

__4.__ In [http://www.ogre3d.org/forums/viewtopic.php?f=5&t=48491&start=75#p354360|this forum post] you will find a list of all needed changes in order to get this running with XCode on Mac.

!!Conclusion
So that's it! It's not that much magic as it looks like. In fact it's no magic at all... just one possible way to have a simple and clean framework to use as a starting point.

Of course, you may alter and modify it to your needs. The young Ogre programmer from the top of the page wishes you good luck...

        

History

Information Version
Mon 26 of Mar, 2018 09:39 GMT-0000 paroj 36
Sun 25 of Mar, 2018 13:24 GMT-0000 paroj 35
Fri 28 of Feb, 2014 23:41 GMT-0000 spacegaier updated to work with Ogre v1.10 (although the changes are minimal and everything should also run with Ogre v1.9 34
Sun 05 of Feb, 2012 11:06 GMT-0000 spacegaier 33
Fri 30 of Dec, 2011 14:47 GMT-0000 spacegaier added link to new BitBucket repo and did some code changes 32
Mon 01 of Aug, 2011 00:10 GMT-0000 jacmoe 31
Wed 27 of Apr, 2011 14:19 GMT-0000 spacegaier 30
Wed 13 of Apr, 2011 06:54 GMT-0000 masterfalcon Minor spelling error in section header 29
Wed 09 of Feb, 2011 23:51 GMT-0000 spacegaier removed the update list, since it is already present in the support thread 28
Wed 09 of Feb, 2011 23:50 GMT-0000 spacegaier 27
Wed 09 of Feb, 2011 23:37 GMT-0000 spacegaier linux fix: sleep() wants seconds and not milliseconds 26
Wed 09 of Feb, 2011 23:18 GMT-0000 spacegaier removed previous note 3 regarding linux/mac sleep() function with lower case 'S' 25
Wed 09 of Feb, 2011 23:18 GMT-0000 spacegaier added OS check around sleep() 24
Wed 09 of Feb, 2011 23:15 GMT-0000 spacegaier changed #if before messagePump() to also allow Linux in there 23
Wed 09 of Feb, 2011 23:12 GMT-0000 spacegaier removed previous note 4 (so old 5 is now the new 4) 22
Wed 29 of Dec, 2010 13:01 GMT-0000 spacegaier changed note 4 since it also applies for linux, not only MAC 21
Fri 22 of Oct, 2010 08:53 GMT-0000 spacegaier removed memory leak caused by m_pTrayManager 20
Mon 28 of Jun, 2010 20:59 GMT-0000 jacmoe 19
Sun 30 of May, 2010 13:06 GMT-0000 jacmoe 18
Sun 30 of May, 2010 13:04 GMT-0000 jacmoe 17
Thu 06 of May, 2010 08:14 GMT-0000 jacmoe 16
Thu 06 of May, 2010 08:13 GMT-0000 jacmoe 15
Thu 06 of May, 2010 08:10 GMT-0000 jacmoe 14
Thu 06 of May, 2010 08:09 GMT-0000 jacmoe 13
Thu 06 of May, 2010 08:06 GMT-0000 jacmoe 12
  • «
  • 1 (current)
  • 2