Framework Ogre Básico Un Joven programador del Framework Ogre Básico


Introducción


Érase una vez un joven programador que comenzó a descubrir el gran mundo de Ogre. Fue a traves de los primeros tutorial y fue feliz de que todo funcionaba sin mucho código como el que hubo en ExampleApplication.h que hizo la vida de los nuevos en Ogre más fácil. Pero, de repente leyó que el modo de en que se hacen las cosas con el ejemplo de aplicación, no es el modo en que deben ser hechas (al menos no en las aplicaciones más avanzadas). Asi que comenzó a buscar en el wiki y en los foros y pieza a pieza, puso todo junto en su propio BasicOgreFramework.

Esta mágica pieza de código fue capaz de comenzar Ogre, cargar los recursos básicos, reaccionar al teclado estándar y a la entrada de ratón moviendo la cámara, haciendo instantáneas además de mostrar Superposiciones de Ogre con el logotipo y el contador FPS. Desde ese día, él siempre usó este Framework cuando necesitaba una base simple para probar un caso.

Como mucha gente tiene el mismo problema (que se reconoció siguiendo la mayoría de los hilos del foro), se decidió poner esta solución en el gran wiki, como una solución más completa que otras versiones ya existentes. Sin embargo, no se decidió explicar el código por ser autoexplicativo para que todo el mundo leyera los primeros tutoriales.

Si tienes algun problema: ya sabes consúltalo en el foro.

Framework Básico Ogre


Actualización 2010/04/14: Reorganizado y renovado media como previamente use el de la version anterior del SDK, resultando en cuelgues cuando estaba intentando ejecutarse con Ogre 1.7. Así la vieja cabeza de Ogre fue sustituida y todas las superposiciones fueron eliminadas en favor de SdkTrays.

Actualización 2010/01/11: El framework fue actualizado para trabajar con Ogre 1.7

Un ejemplo que funciona (sin compilación) puede ser descargado de aquí. Viene con el código fuente, el media necesitado y con un archivo de solución de VisualStudio.
external image dl1692&display&x=150&y=112


Si este archivo no estuviera disponible se podría reconstruir, mándame un mensaje al foro.

Arquitectura


Bien, la arquitectura es bastante simple: Hay una clase, llamada OgreFramework, que hace la mayor parte de la magia. Añádela a tu proyecto. Entonces necesitas una segunda clase que sea la aplicación real. Llama a varias funciones desde la clase OgreFramework y también implementa el bucle principal. Si quieres, puedes también hacer que se maneje una entrada adicional para extender el manejo de la entrada ya implementada.

external image Forum_icon_info.gifNota informativa: No te preocupes por el código. Sin embargo, es muy sencillo de comprender.

OgreFramework.hpp


Esta es la cabecera para nuestra clase OgreFramework. Contiene todas las variables relacionadas con Ogre:

  • Ogre Root
  • Camera
  • RenderWindow
  • Viewport
  • SceneManager
  • Log
  • Timer
  • Input stuff
  • ...

También tiene la función de manejo de la entrada (ej: keyPressed() o mouseMoved()), que es usada para capturar algunas teclas para el movimiento básico de la cámara. Aparte de eso, hay algunos otros miembros tales como counter para el número de pantallazos hechos mientras se ejecuta la aplicación o una variable indicando si la aplicación ha finalizado.

// |||||||||||||||||||||||||||||||||||||||||||||||
 
#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 <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


El siguiente codigo forma parte de OgreFramework.cpp. Te dara algo de informacion de las funciones:

* Primera linea: necesitada para el [Singleton]
* OgreFramework(): solo establece algunos valores por defecto para las variables

#include "OgreFramework.hpp"
 
using namespace Ogre;
 
template<> OgreFramework* Ogre::Singleton<OgreFramework>::ms_Singleton = 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. instancia una clase log manager
  2. crea un root de Ogre
  3. crea el manejador de escena y establece alguna luz ambiental
  4. crea la camara y establece su posicion y los planos de recorte
  5. crea el viewport y establece el color de fondo
  6. crea los dispositivos de entrada
  7. carga los recursos
  8. crea un timer
  9. crea una superposicion de depuracion
  10. establece la ventana de renderizado activa

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);
 
      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<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():Sólo limpia todo.

OgreFramework::~OgreFramework()
{
     if(m_pInputMgr) OIS::InputManager::destroyInputSystem(m_pInputMgr);
     if(m_pTrayMgr) delete m_pTrayMgr;
     if(m_pRoot) delete m_pRoot;
}


  • keyPressed(): Implementa el manejo basico de la entrada de teclado
  1. deja la aplicacion cuando escape se ha presionado
  2. hace un pantallazo cuando imprimir es presionado
  3. cambia el modo de poligono cuando "M" es presionado
  4. cambia a estadisticas de frame y logotivo cuando "O" es presionado

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(): No hace nada. Solo tiene que estar alli cuando la clase sea heredada del OIS::MouseListener y OIS::KeyboardListener.

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

  • mouseMoved(): Esta funcion se llama cuando el raton se mueve y cambia la orientacion de la camara.

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(): No hace nada. Solo tiene que estar aqui cuando la clase sea heredada desde OIS::MouseListener and OIS::KeyboardListener
  • mouseReleased(): lo mismo que antes.

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(): La funcion sera llamada por nuestra propia clase demo en el bucle principal (asi para cada frame). Calcula el movimiento y escala de rotacion para tener en cuanta el tiempo transcurrido desde el ultimo frame. Tambien llama a getInput() y moveCamera() al igual que inyecta y actualiza el evento en el 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(): Esta funcion cambia la posicion de la camara de acuerdo al vector m_TranslateVector que es cambiado por la entrada de teclado. Si shift se presiona, se movera 10 veces mas rapido que sin el.

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


  • getInput(): Esta funcion cambia el vector de traslacion de la camara m_TranslateVector de acuerdo a la entrada de teclado.

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

Creando tu clase demo


Solo lo que falta es tu clase demo que solo necesita algunos contenidos. Se parecera a esto:

  • algunas funciones para comenzar, instalar y ejecutar el Demo
  • un puntero a la instancia de OgreFramework
  • una entity y un nodo de escena
  • una variable boleana para mostrar si la demo deberia para

Nota: La herencia de OIS::KeyListener y nuestra clase de demo pasada como parametro al metodo initOgre(), podemos extender el manejo de la entrada desde la clase OgreFramework reaccionando a los eventos de entrada en las funciones keyPressed() y keyReleased(). La funcion keyPressed() y keyReleased() de OgreFramework no son llamadas por OIS en este caso, debemos llamarlas desde keyPressed() y keyReleased() en DemoApp en su lugar.

// |||||||||||||||||||||||||||||||||||||||||||||||
 
#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
 
// |||||||||||||||||||||||||||||||||||||||||||||||

Implementando nuestra clase demo


Asi es como deberia ser la implementacion de la clase demo:

  • DempApp(): Constructor
  • ~DemoApp(): Destructor
  • startDemo():

  1. crea un nuevo OgreFramework
  2. establece el indicador de apagado a false (porque ya queremos que pare?)
  3. llama a setupDemo() y runDemo()
  • setupDemoScene(): pon algunos contenidos en nuestra escena
  1. añade una caja celeste
  2. crea una luz
  3. añade una malla de cubo simple
  • runDemo(): el bucle principal de nuestra aplicacion
  1. deja la aplicacion si m_Shutdown esta a false o si el OgreFramework quiero apagarnos por alguna razon
  2. calcula el tiempo pasado desde el ultimo frame
  3. ordena los dispositivos de entrada para que el teclado y el raton miren pro nuevos eventos de entrada
  4. llama a la funcion updateOgre()
  5. renderiza un frame
  6. Si la ventana de renderizado no esta activa (no tiene el foco), la aplicacion duerme por un segundo

  • keyPressed(): puedes definir aqui nuestro manejo de entrada, como ej: mover el cubo en nuestra escena
  • keyReleased(): igual que como se vio antes

DemoApp::DemoApp()
{
       m_pCubeNode = 0;
       m_pCubeEntity = 0;
}
 
// |||||||||||||||||||||||||||||||||||||||||||||||
 
DemoApp::~DemoApp()
{
       delete OgreFramework::getSingletonPtr();
}
 
// |||||||||||||||||||||||||||||||||||||||||||||||
 
void DemoApp::startDemo()
{
       new OgreFramework();
       if(!OgreFramework::getSingletonPtr()->initOgre("DemoApp v1.0", this, 0))
                return;
 
       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))
         {
              // hacer algo
         }
 
         return true;
}
 
// |||||||||||||||||||||||||||||||||||||||||||||||
 
bool DemoApp::keyReleased(const OIS::KeyEvent &keyEventRef)
{
         OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
 
         return true;
}
 
// |||||||||||||||||||||||||||||||||||||||||||||||


La última cosa: main.cpp


  • lo primero de todo: no tienes que comprender esto!
  • las únicas partes importantes son las dos líneas donde una instancia de nuestra DemoApp es creada y la función startDemo() se llama.

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


Notas


1. Si quieres, que puedas declarar todos los miembros Ogre en la clase OgreFramework (Root, Camera, RenderWindow, SceneManager, ...) privados y implementar sus metodos. Esto es mas bien un estilo de código y una preferencia. Podrías eliminar totalmente la mayoría de ellos como tiene singletons(ej: Ogre::Root, Ogre::Log) y conseguirlos por medio de las funciones singleton. A tu elección!

2. Si Ogre::WindowEventUtilities::messagePump() no funciona, prueba esto en su lugar:

#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

3. En Mac, la función Sleep esta escrita con una s en minúsculas al comienzo, tienes que cambiar esto (si quieres ambos en tu código) usa esto en su lugar:

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    Sleep(1000);
#elif OGRE_PLATFORM == OGRE_PLATFORM_APPLE
    sleep(1000);
#endif

4. Si estas usando Linux y sólo consigues una pantalla en negro que no responde a la entrada del teclado y del ratón, sustituye:

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
Ogre::WindowEventUtilities::messagePump();
con
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_LINUX
Ogre::WindowEventUtilities::messagePump();
en DemoApp.cpp y añade #include "OgreWindowEventUtilities.h" a los includes en lo alto del archivo.

5. En esta nota del foro encontrarás una lista de todos los cambios necesarios para conseguir que funcione con XCode sobre Mac.

Conclusión


Eso es todo! No es tan mágico. De hecho no es mágico. Sólo un posible punto de partida simple y limpio.

De acuerdo, deberías alterarlo y modificarlo segun tus necesidades. El joven programador de Ogre desde la parte superior de la página te desea suerte.