Basic Ogre Framework         A young Ogre programmers Basic Framework
Print


Introduction

Once upon a time a young programmer started discovering the great world of Ogre. He went through the 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.

help However: If you have any problems, please post in the forum thread for this article(external link).

 

BasicOgreFramework.jpg
Basic Ogre Framework

 

An example that runs out-of-the-box (without any compiling) can be downloaded from my BasicOgreFramework BitBucket Hg repository(external link). Of course it comes with the source, the needed media as well as with a Microsoft VisualStudio solution file.

 

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.

Info 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

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.

 

//|||||||||||||||||||||||||||||||||||||||||||||||
 
#ifndef OGRE_FRAMEWORK_HPP
#define OGRE_FRAMEWORK_HPP
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
#include <OgreCamera.h>
#include <OgreEntity.h>
#include <OgreLogManager.h>
#include <OgreOverlay.h>
#include <OgreOverlayElement.h>
#include <OgreOverlayManager.h>
#include <OgreRoot.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>
#include <OgreConfigFile.h>
#include <OgreFrameListener.h>
 
#include <OISEvents.h>
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h>
 
#include <SdkTrays.h>
 
//|||||||||||||||||||||||||||||||||||||||||||||||
 
class OgreFramework : public Ogre::Singleton<OgreFramework>, OIS::KeyListener, OIS::MouseListener, OgreBites::SdkTrayListener
{
public:
	OgreFramework();
	~OgreFramework();
 
	bool initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener = 0, OIS::MouseListener *pMouseListener = 0);
	void updateOgre(double timeSinceLastFrame);
	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&);
 
	OgreBites::SdkTrayManager*	        m_pTrayMgr;
        Ogre::FrameEvent                        m_FrameEvent;
	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 
 
//|||||||||||||||||||||||||||||||||||||||||||||||

 

OgreFramework.cpp

The following code parts form together the OgreFramework.cpp. I'll give some information on the functions:

  • First line: Needed for the [[Singleton]]
  • OgreFramework(): It just sets some default values for the variables

 

#include "OgreFramework.hpp"
 
#include <OgreTextureManager.h>
 
using namespace Ogre; 
 
template<> OgreFramework* Ogre::Singleton<OgreFramework>::msSingleton = 0;
 
OgreFramework::OgreFramework()
{
	m_MoveSpeed			= 0.1f;
	m_RotateSpeed		        = 0.3f;
 
	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_pTrayMgr                      = 0;
        m_FrameEvent                    = Ogre::FrameEvent();
}

 

  • initOgre():
  1. instantiates the log manager class
  2. creates a new Ogre root
  3. creates the scene manager and set some ambient light
  4. creates the camera and sets its position and clip planes
  5. creates the viewport and sets the background color
  6. creates the input devices
  7. loads the resources
  8. creates the timer
  9. creates the debug overlay
  10. sets the render window active
bool 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();
 
	if(!m_pRoot->showConfigDialog())
		return false;
	m_pRenderWnd = m_pRoot->initialise(true, wndTitle);
 
	m_pSceneMgr = m_pRoot->createSceneManager(ST_GENERIC, "SceneManager");
	m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));
 
	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.8f, 0.7f, 0.6f, 1.0f));
 
	m_pCamera->setAspectRatio(Real(m_pViewport->getActualWidth()) / Real(m_pViewport->getActualHeight()));
 
	m_pViewport->setCamera(m_pCamera);
 
	size_t 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<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));
	m_pMouse = static_cast<OIS::Mouse*>(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_pTrayMgr = new OgreBites::SdkTrayManager("TrayMgr", m_pRenderWnd, m_pMouse, this);
        m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
        m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
        m_pTrayMgr->hideCursor();
 
	m_pRenderWnd->setActive(true);
 
	return true;
}

 

  • ~OgreFramework(): Just clears up the whole thing
OgreFramework::~OgreFramework()
{
    if(m_pInputMgr) OIS::InputManager::destroyInputSystem(m_pInputMgr);
    if(m_pTrayMgr)  delete m_pTrayMgr;
    if(m_pRoot)     delete m_pRoot;
}

 

  • keyPressed(): Implements the basic keyboard input handling
  1. leave the application when escape is pressed
  2. make a screenshot when print is hit
  3. change polygon mode when 'M' is hit
  4. toggle the frame stats and logo when 'O' is pressed

 

bool OgreFramework::keyPressed(const OIS::KeyEvent &keyEventRef)
{
	if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
	{
			m_bShutDownOgre = true;
			return true;
	}
 
	if(m_pKeyboard->isKeyDown(OIS::KC_SYSRQ))
	{
		m_pRenderWnd->writeContentsToTimestampedFile("BOF_Screenshot_", ".png");
		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_pTrayMgr->isLogoVisible())
                {
                        m_pTrayMgr->hideLogo();
                        m_pTrayMgr->hideFrameStats();
                }
                else
                {
                        m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
                        m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
                }
	}
 
	return true;
}

 

  • 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.
bool OgreFramework::keyReleased(const OIS::KeyEvent &keyEventRef)
{
	return true;
}

 

  • mouseMoved(): This function gets called when the mouse is move and then changes the camera's orientation.

 

bool OgreFramework::mouseMoved(const OIS::MouseEvent &evt)
{
	m_pCamera->yaw(Degree(evt.state.X.rel * -0.1f));
	m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1f));
 
	return true;
}

 

  • 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.
bool OgreFramework::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return true;
}
 
bool OgreFramework::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
	return true;
}

 

  • 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 inject an update event into the SdkTrayManager.

 

void OgreFramework::updateOgre(double timeSinceLastFrame)
{
	m_MoveScale = m_MoveSpeed   * (float)timeSinceLastFrame;
	m_RotScale  = m_RotateSpeed * (float)timeSinceLastFrame;
 
	m_TranslateVector = Vector3::ZERO;
 
	getInput();
	moveCamera();
 
	m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;
        m_pTrayMgr->frameRenderingQueued(m_FrameEvent);
}

 

  • 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.

 

void OgreFramework::moveCamera()
{
	if(m_pKeyboard->isKeyDown(OIS::KC_LSHIFT)) 
		m_pCamera->moveRelative(m_TranslateVector);
	else
		m_pCamera->moveRelative(m_TranslateVector / 10);
}

 

  • getInput(): This function changes the camera translation vector m_TranslateVector accordingly to the keyboard input.

 

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;
}

 



Contributors to this page: spacegaier6073 points  , Spacegaier6073 points  , masterfalcon435 points  and jacmoe180265 points  .
Page last modified on Friday 28 of February, 2014 23:41:48 UTC by spacegaier6073 points .


The content on this page is licensed under the terms of the Creative Commons Attribution-ShareAlike License.
As an exception, any source code contributed within the content is released into the Public Domain.