Tutorial Básico 6 La Secuencia de Comienzo de Ogre


external image dl1773

Introducción de Tutorial


En este tutorial aprenderemos a como escribir una aplicación simple de Ogre desde cero.

external image help.gifLos problemas que encuentres mientras trabajes en este tutorial deberías consultarlos en los Foros de Ayuda.

Prerrequisitos


  • Este tutorial asume que tienes conocimientos sobre programación en C++ y eres capaz de compilar e instalar una aplicación de Ogre.
  • Este tutorial también asume que has creado un proyecto usando el Tutorial Framework Ogre Wiki, manualmente, usando CMake o el AppWizard de Ogre - mirar Creando una aplicación para más instrucciones.
  • Este tutorial se compila sobre la versión anterior de los tutoriales básicos, así que se asume que has trabajado con ellos.

Cuando mires el tutorial deberías ir lentamente añadiendo código a tu proyecto y mirando los resultados. Puedes ver el código fuente para ver el estado final del tutorial aquí. Si tienes problemas con el código, deberías comparar tu fuente del proyecto al resultado final.


Comenzando


El código Inicial


En este tutorial, usaremos un grupo de huesos (bones) de código como punto de partida.

Peligro
external image dl1761
Antes de continuar, asegúrate de que tienes un proyecto, y que sólo tiene dos archivos: una cabecera y un cpp.
Si has usado el Framework Tutorial Ogre Wiki, elimina BaseApplication.h y BaseApplication.cpp de él.

Cabecera BasicTutorial6
class BasicTutorial6
{
public:
 BasicTutorial6(void);
 virtual ~BasicTutorial6(void);
 bool go(void);
};
Implementación BasicTutorial6
#include "BasicTutorial6.h"
 
#include <OgreException.h>
 
// -------------------------------------------------------------------------------------
BasicTutorial6::BasicTutorial6(void)
{
}
//-------------------------------------------------------------------------------------
BasicTutorial6::~BasicTutorial6(void)
{
}
 
bool BasicTutorial6::go(void)
{
 return true;
}
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
 int main(int argc, char *argv[])
#endif
{
 // crea un objeto de aplicacion
 BasicTutorial6 app;
 
 try {
 app.go();
 } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
 std::cerr << "An exception has occured: " <<
 e.getFullDescription().c_str() << std::endl;
#endif
 }
 
 return 0;
 }
 
#ifdef __cplusplus
}
#endif

Asegúrate de poder compilar este código antes de continuar.
El código no hará nada en absoluto - sólo saldrá inmediatamente después de ejecutarlo.

No te preocupes, piensa:
Después de pasar por este tutorial, daremos una aplicación en Ogre llena de características.

El proceso de comienzo


Una vez que comprendas el proceso, comenzar a usar Ogre será muy sencillo. El ejemplo del framework parece como si quisieramos hacer muchas cosas de una sola vez. Después de finalizar este tutorial, serás capaz de coger y seleccionar lo que es necesario para tu aplicación y puedes construir una clase con eso exactamente. Antes de meternos en esto, primero echaremos un vistazo rápido a como funciona el proceso de comienzo a alto nivel.

El ciclo de vida básico de un programa Ogre es así:

  1. Crea el objeto Root.
  2. Define los recursos que Ogre usará.
  3. Elige y establece el RenderSystem (esto es, DirectX, OpenGL, etc).
  4. Crea la RenderWindow (la ventana en la que Ogre reside).
  5. Inicializa los recursos que vas a usar.
  6. Crea una escena usando estos recursos.
  7. Establece las librerías de terceros y los plugins.
  8. Crea un número de frame listeners.
  9. Comienza el bucle de renderizado.

Trataremos cada uno de estos temas en profundidad en este tutorial.

Nota que mientras deberías seguir los pasos 1-4 en orden, los pasos 5 y 6 (inicialización de recursos y creación de la escena) pueden ser mucho después de tu proceso de creación si lo deseas.
Podrías inicializar los plugins de terceros y crear los frame listeners antes de los pasos 5 y 6 si lo prefieres, pero no deberías hacerlo antes de finalizar el paso 4.
También, los frame listeners de las librerías de terceros no pueden acceder a cualquier recurso del juego (como cámaras, entidades, etc) hasta que los recursos son inicializados y la escena es creada.
En resumen, puedes hacer alguno de estos pasos en orden distinto si crees que es mejor para tu aplicación, pero no te recomendamos que los hagas a menos que estes seguro de comprender las consecuencias de lo que estas haciendo.

Comenzando Ogre


Creando el Objeto Root


El objeto Root es el núcleo de la librería Ogre, y debe ser creado antes de que puedas hacer algo con el motor.

Necesitamos añadir los siguientes miembros de clase a nuestra clase BasicTutorial6:
private:
Ogre::Root* mRoot;
Ogre::String mPluginsCfg;
También añade lo siguiente a las inclusiones de la cabecera:
#include <OgreRoot.h>
Entonces, ajusta el constructor y el destructor para tratar con ellos:

BasicTutorial6::BasicTutorial6(void)
: mRoot(0),
mPluginsCfg(Ogre::StringUtil::BLANK)
{
}
//-----------------------------------------------------------------------------------
BasicTutorial6::~BasicTutorial6(void)
{
 delete mRoot;
}
en entonces, en BasicTutorial6::go, creamos un nuevo Ogre::Root:
bool BasicTutorial6::go(void)
{
#ifdef _DEBUG
 mPluginsCfg = "plugins_d.cfg";
#else
 mPluginsCfg = "plugins.cfg";
#endif
 // constructor Ogre::Root
 mRoot = new Ogre::Root(mPluginsCfg);
 
 return true;
}
El constructor de Ogre::Root toma tres parámetros:

parámetro (Ogre::String) valor por defecto descripción

pluginFileName "plugins.cfg" el nombre y posición del archivo de configuración de los plugins.

configFileName "ogre.cfg" el nombre y posición del archivo de configuración (que dice a ogre que cosas le gustan de la tarjeta de video, opciones visuales, etc)

logFileName "Ogre.log" el nombre y posición del archivo de log donde Ogre escribirá todo

Podríamos dejarlo a sus valores por defecto, pero para hacer que esta aplicación compile contra el SDK precompilado, donde el nombre del archivo de configuración difiere entre debug y release, necesitamos pasar nuestro parametro mPluginsCfg al constructor, asi que el nombre del archivo de configuración es "plugins_d.cfg" cuando lo corramos en modo debug.

Compila y ejecuta la aplicación. :-)
Todavía parecerá que no hace nada, pero si abres el archivo "Ogre.log" verás que Ogre se lanzó, se inicializó y entonces se apagó.
Deberías ver también que comprobó e instaló los plugins de Ogre listados en "plugins.cfg"

Recursos


Nota: Esta sección tiene mucho más sentido si abrimos "resources.cfg" y echamos un vistazo antes de continuar.
Puedes encontrar esto en la carpeta bin/release de tu SDK.

La siguiente cosa que tenemos que hacer es definir los recursos que la aplicacion usará. Esto incluye las texturas, modelos, scripts, y demás.

No hablaremos de todos los recursos en este tutorial.
Por ahora, sólo tendremos en cuenta que debemos definir primero todos los recursos que debamos usar durante la aplicación, entonces debemos inicializar los recursos especificados que necesitemos antes de poder usarlos.
En este paso tenemos que definir todos los recursos que nuestra aplicación puede usar.

Para hacer esto, tenemos que añadir cada carpeta a ese recurso que reside en ResourceGroupManager.

Anadir el siguiente miembro de clase a nuestra clase BasicTutorial6:
Ogre::String mResourcesCfg;
Entonces ponlo en la lista del inicializador en el constructor, al igual que hicimos con "mPluginsCfg".
Necesitamos incluir Ogre::ConfigFile para hacer uso de la clase de utilidad de comprobación de la configuración de Ogre.

Poner los siguiente en lo alto de "BasicTutorial6.cpp":
#include <OgreConfigFile.h>

Ahora que hemos añadido mResourcesCfg a debug/release la lógica al comienzo de nuestra función "go":
bool BasicTutorial6::go(void)
{
#ifdef _DEBUG
 mResourcesCfg = "resources_d.cfg";
 mPluginsCfg = "plugins_d.cfg";
#else
 mResourcesCfg = "resources.cfg";
 mPluginsCfg = "plugins.cfg";
#endif
Esto es necesario porque el nombre de los recursos del archivo de configuración difieren entre debug y release.

Ahora estamos listo para comprobar algunos recursos de Ogre.

Añadir el siguiente código a BasicTutorial6::go:
// instalar recursos
 // Cargar las rutas de recursos desde el archivo de configuracion
Ogre::ConfigFile cf;
cf.load(mResourcesCfg);
Esto usa la clase ConfigFile de Ogre para comprobar todos los recursos de "resources.cfg", pero no son cargados en Ogre (tienes que hacer esto manualmente).
Ten en cuenta que en tu aplicación eres libre de usar tu propio comprobador y formatos de archivo de configuración si lo deseas, sólo reemplaza el comprobador ConfigFile de Ogre con el tuyo.
El método para la carga de recursos no tiene que ver con los recursos que has añadido a ResourceGroupManager.

Ahora que hemos comprobado el archivo de configuración, necesitamos añadir las secciones al ResourceGroupManager.
El siguiente código itera a traves del archivo de configuración comprobado y añade cada entrada al ResourceGroupManager mediante el significado de la función addResourceLocation:
 //Va a traves de todas las secciones y ajustes en el archivo
Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
 
Ogre::String secName, typeName, archName;
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);
}
}
Esta función ha añadido todos los recursos desde el archivo de configuración, pero no se dice a Ogre donde estan.
Antes de que puedas usarlos tienes que inicializar el grupo que vayas a usar, o inicializarlos todos.
Discutiremos esto más adelante en la función "Initializing Resources"

Si compilas y ejecutas ahora, puedes ver en "Ogre.log" que Ogre crea un grupo de recursos y comprueba los recursos.

Creando el RenderSystem


Siguiente, necesitamos elegir el RenderSystem (sistema de renderizado) (normalmente DirectX u OpenGL en una máquina Windows) y configurarlo.
La mayoría de las aplicaciones de demostración usan el diálogo de configuración de Ogre, lo cual es un modo perfectamente razonable de establecer tu aplicación.
Ogre ofrece un modo de restablecer la configuración que un usuario ha establecido, lo que significa que nunca tendrás que configurarlo después de la primera vez.

Primero, necesitamos añadir un nuevo miembro de clase a nuestra clase BasicTutorial para guardar nuestra Ogre::RenderWindow:
Ogre::RenderWindow* mWindow;
Entonces, añade el siguiente código a BasicTutorial6::go:
// configure
// Muestra el dialogo de configuracion e inicializa el sistema
if(!(mRoot->restoreConfig() || mRoot->showConfigDialog()))
{
return false;
}
En la primera parte de la sentencia del if, intentamos restaurar el archivo de configuración. Si la función devuelve falso significa que el archivo no existe asi que deberiamos mostrar el diálogo de configuración, que es la segunda porción de la sentencia del if.
Si eso también devuelve falso significa que el usuario cancelo el diálogo de configuración (lo que significa que quiere salir del programa).

En este ejemplo devolvemos false , y salimos del programa. También podríamos lanzar una excepción. Si usas esta técnica en la práctica recomendaría que si atrapas una excepción durante el comienzo de Ogre que borres el archivo ogre.cfg en el bloque catch.
Es posible que los ajustes que hayan escogido en el diálogo de configuración hayan causado un problema y necesiten ser cambiados.
Incluso si no usas esto en tu aplicación puede ayudarte a ahorra tiempo de desarrollo en pequeñas cantidades ya que no tienes que guardar la confirmación de los ajustes gráficos cuando el programa se ejecuta.

Tu aplicación puede también instalar manualmente el RenderSystem si eliges usar algún otro distinto del diálogo de configuración de Ogre. Un ejemplo básico de esto podría ser como sigue...
// No anyadas esto a la aplicacion
RenderSystem *rs = mRoot->getRenderSystemByName("Direct3D9 Rendering Subsystem");
// o usa "El Subsistema de Renderizado OpenGL"
mRoot->setRenderSystem(rs);
rs->setConfigOption("Full Screen", "No");
rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit colour");
Puedes usar la función Root::getAvailableRenderers para encontrar que sistemas de renderizado estan disponibles para el uso con tu aplicación.
Una vez que has elegido un RenderSystem, puedes usar RenderSystem::getConfigOptions para ver que opciones estan disponibles para el usuario. Combinando estas dos funciones de llamadas, puedes crear tu propio diálogo de configuración para tu aplicación.

Creando una RenderWindow

Ahora que hemos escogido el RenderSystem, necesitamos una ventana para Ogre renderice en ella.
Hay actualmente muchas opciones para como hacer esto, pero sólo cubriremos un par.

Si quieres que Ogre cree una ventana de renderizado para ti, entonces esto es muy fácil de hacer.
Añade el siguiente código a BasicTutorial6::go:
mWindow = mRoot->initialise(true, "BasicTutorial6 Render Window");
Esta llamada inicializa el RenderSystem que hemos establecido en la sección previa.
El primer parámetro es si debería Ogre crear una RenderWindow para nosotros.

Alternativamente, puedes crear una ventana de renderizado tu mismo usando la API win32, wxWidgets, o uno de los muchos sistemas GUI Windows o Linux.
Un rápido ejemplo de como hacer esto bajo Windows debería ser como esto:
// No anyadir esto a la aplicacion
mRoot->initialise(false);
HWND hWnd = 0; // Conseguir el hWnd de la aplicacion!
NameValuePairList misc;
misc["externalWindowHandle"] = StringConverter::toString((int)hWnd);
RenderWindow *win = mRoot->createRenderWindow("Main RenderWindow", 800, 600, false, &misc);
Date cuenta que todavía tienes que llamar a Root::initialise, pero el primer parámetro se establece a false.
Entonces, debes conseguir el HWND de la ventana en la que quieres que Ogre renderice. Como conseguir esto estará determinado por el toolkit GUI que uses al crear la ventana (y bajo Linux puedo imaginar que esto puede ser diferente también).
Después de que tengas esto, usa NameValuePairList para asignar el handle (manejador) a "externalWindowHandle". (manejador externo de ventana)
La función Root::createRenderWindow puede ser usada entonces para crear la clase RenderWindow desde la ventana que has creado.
Consulta la documentación del API sobre esta función para más información.

Inicializando Recursos


Ahora que tenemos nuestro objeto Root y nuestros objetos RenderSystem y RenderWindow creados y listos, estamos muy cerca de poder crear nuestra escena.

La única cosa que nos falta es inicializar los recursos que vamos a usar. En un juego largo o aplicación, tendremos cientos o incluso miles de recursos que nuestro juego usará - todo desde las mallas a las texturas y los scripts. En un momento dado, probablemente sólo se usa un pequeño subconjunto de estos recursos.
Para mantener bajos los requerimientos de memoria, podemos cargar sólo los recursos que nuestra aplicación este usando.
Podemos hacer esto dividiendo nuestros recursos en secciones y solo inicializarlos cuando se necesiten.
No abordaremos eso en este tutorial, sin embargo. Mirar Recursos y ResourceManagers (Manejadores de recursos) para un tutorial centrado en los recursos.

Antes de que inicialicemos los recursos, deberiamos también establecer el número por defecto de mipmaps que las texturas usan.
Debemos establecer esto antes de que inicialicemos los recursos para que tenga efecto.

Añade el siguiente código a BasicTutorial6::go:
// Establece el nivel de mipmap por defecto (NB algunas APIs ignoran esto)
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
// Inicializa todos los grupos de recursos
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
La aplicación tiene ahora todos los grupos de recursos inicializados y listos para ser usados.

Creando una Escena


Siguiente, necesitamos crear la escena.

Necesitas saber que hay tres cosas que debes hacer antes de comenzar a añadir cosas a una escena:

  1. crear el SceneManager
  2. crear la Camara
  3. crear el viewport

Antes de seguir, añade algunos includes a lo alto de nuestro archivo BasicTutorial6.cpp :
#include <OgreCamera.h>
#include <OgreViewport.h>
#include <OgreSceneManager.h>
#include <OgreRenderWindow.h>

Creando un SceneManager


Primero, añade un nuevo miembro de datos privado a la clase BasicTutorial6:
Ogre::SceneManager* mSceneMgr;
Y entonces añade el siguiente código a BasicTutorial6::go:
// Crea el SceneManager, en este caso uno generico
mSceneMgr = mRoot->createSceneManager("DefaultSceneManager");

Creando la Camara


Primero, añade un miembro de datos privado a la clase BasicTutorial6:
Ogre::Camera* mCamera;
Y entonces añade el siguiente código a BasicTutorial6::go:
// Crea la Camara
mCamera = mSceneMgr->createCamera("PlayerCam");
 
// Posicionala en 500 en la direccion Z
mCamera->setPosition(Ogre::Vector3(0,0,80));
// vuelve sobre -Z
mCamera->lookAt(Ogre::Vector3(0,0,-300));
mCamera->setNearClipDistance(5);

Añadiendo un Viewport

// Crea un viewport, la ventana entera
Ogre::Viewport* vp = mWindow->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
 
// Altera la relacion de aspecto de la camara para que coincida con el viewport
mCamera->setAspectRatio(
Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));

Creando Escenas


Debes crear los SceneManagers y cámaras que necesites, pero tienes que tener cuidado que cuando quieres renderizar algo sobre la pantalla usando la cámara, tienes que añadir un Viewport para ello.

Añadamos algo a nuestra escena, ahora que tenemos en cuenta lo básico.
Busca la funcion BasicTutorial6::go y añade el siguiente código:
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
 
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
headNode->attachObject(ogreHead);
 
// Establecer la luz de ambiente
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
 
// Crea una luz
Ogre::Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(20,80,50);
Necesitamos incluir OgreEntity para que el codigo compile sin errores, asi que anyade esta linea a lo alto de "BasicTutorial6.cpp":
#include <OgreEntity.h>

Bucle de renderizado - paso 1


Para ver como va nuestro trabajo debemos renderizar nuestra escena.

Las características de Ogre::Root incluyen varios métodos sobre el bucle de renderizado, la más simple de estas es Ogre::Root::renderOneFrame().
Básicamente repite cualquier función dentro del buble hasta que se sale del mismo.

Así es como debe ser:
void Root::startRendering(void)
{
assert(mActiveRenderer != 0);
 
mActiveRenderer->_initRenderTargets();
 
// Limpia los tiempos de eventos
clearEventTimes();
 
// bucle infinito, hasta que es terminado por los frame listeners
// o se sale llamando a queueEndRendering()
mQueuedEnd = false;
 
while( !mQueuedEnd )
{
// Bombear mensajes en todas las ventanas RenderWindow registradas
WindowEventUtilities::messagePump();
 
if (!renderOneFrame())
break;
}
}
No entraremos en detalle sobre la funcion, pero solo senyalaremos la funcion renderOneFrame.
Miramos la funcion en el Tutorial Basico 4, pero volvamos otra vez sobre ella:
bool Root::renderOneFrame(void)
{
 if(!_fireFrameStarted())
 return false;
 
 if (!_updateAllRenderTargets())
 return false;
 
 return _fireFrameEnded();
}
Al contrario que las actualizaciones de todos los objetivos de renderizado, llama a las funciones de los eventos de frame, y si cualquiera de estas devuelve falso, causara que el bucle de renderizado se detenga.

Ya que no hemos usado FrameListeners todavia, necesitamos un bucle de renderizado alternativo.

Anyade esta linea a la lista de includes en lo alto del archivo BasicTutorial6.cpp:
#include <OgreWindowEventUtilities.h>
Pon esto en la funcion BasicTutorial6::go:
while(true)
{
 // Bombeo de mensajes de la ventana
 Ogre::WindowEventUtilities::messagePump();
 
 if(mWindow->isClosed())
 {
 return false;
 }
 
 // Renderiza un frame
 if(!mRoot->renderOneFrame()) return false;
}
Se ejecuta una y otra vez, hasta que la ventana se cierra, o la función renderOneFrame devuelve falso.

Compila y ejecuta tu aplicación. :-)
Deberías ver una ventana con una cabeza de Ogre en ella.
Necesitas hacer click en el boton cerrar para salir de la aplicación, porque no hemos implementado ninguna entrada todavía.

external image dl1874&display&x=400&y=310

OIS


Piensa que no es la única opción de entrada en Ogre, OIS es una de las mejores.
Trataremos brevemente como comenzar con OIS en tu aplicación.
Para los usos actuales de la librería, debes comprobar varios tutoriales aquí (que lo usan extensivamente) y la documentación OIS en si misma.

Pon los siguientes includes en BasicTutorial6.h:
#include <OISEvents.h>
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h>
Añade los siguientes miembros de datos a la clase BasicTutorial6:
<span style="font-family: Arial,sans-serif; font-style: normal; font-weight: normal; margin-bottom: 0cm;"> </span>// Dispositivos de entrada OIS
OIS::InputManager* mInputManager;
OIS::Mouse* mMouse;
OIS::Keyboard* mKeyboard;
Entonces necesitamos añadir OIS a los ajustes de nuestro proyecto:
Directorio include $(OGRE_HOME)/include/OIS
Libreria de entrada OIS_d.lib/OIS.lib

El directorio de la libreria deberia estar ya establecido.

Asegurate que compilas el proyecto despues de anyadir OIS a ello.


Lanzando OIS


OIS usa un InputManager general que es un paso dificil de instalar, pero es facil usarlo una vez lo has creado propiamente. OIS no esta integrado en Ogre; es una libreria empotrada, lo que significa que necesitaras proporcionarle informacion al empezar a trabajar con ella correctamente.
En la practica solo necesita el manejador de ventana que Ogre esta renderizando. Afortunadamente, ya que hemos usado la ventana auto creada, Ogre lo hace sencillo para nosotros.

Ve a la funcion BasicTutorial6::go y anyade este codigo a ello, antes de nuestro bucle de renderizado:
Ogre::LogManager::getSingletonPtr()->logMessage("* Initializing OIS *");
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
 
mWindow->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
 
mInputManager = OIS::InputManager::createInputSystem( pl );
Esto instala el InputManager para su uso, pero actualmente se usa OIS para conseguir la entrada desde teclado, raton, o joystick que elijas, necesitaras crear estos objetos:
mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, false ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, false ));
Estamos pasando "false" a la funcion createInputObject porque queremos raton y teclado sin bufer.
external image Forum_icon_info.gifNota informativa: Si deseas usar entrada con bufer (significa que consigues llamadas sobre evento a mouseMoved, mousePressed, keyReleased, y demas), entonces debes establecer el segundo parametro a createInputObject para que sea true.

Apagando OIS


OIS es un poco complicado para apagarse correctamente.
El modo mas seguro de hacer esto es usando un WindowEventListener.

Primeramente, pon esta linea en tu lista de includes en BasicTutorial6.h:
#include <OgreWindowEventUtilities.h>
Entonces necesitamos cambiar nuestra declaracion de clase para que derive de WindowEventListener:
class BasicTutorial6 : public Ogre::WindowEventListener
Queremos sobreescribir WindowEventListener::windowResized y WindowEventListener::windowClosed, asi que pon esto en la seccion protegida de la declaracion de la clase BasicTutorial6:
// Ogre::WindowEventListener
virtual void windowResized(Ogre::RenderWindow* rw);
virtual void windowClosed(Ogre::RenderWindow* rw);
Ahora, abre BasicTutorial6.cpp y añade lo siguiente:
<span style="font-family: Arial,sans-serif; font-style: normal; font-weight: normal; margin-bottom: 0cm;"> </span>// Ajustar el area de recorte del raton
void BasicTutorial6::windowResized(Ogre::RenderWindow* rw)
{
 unsigned int width, height, depth;
 int left, top;
 rw->getMetrics(width, height, depth, left, top);
 
 const OIS::MouseState &ms = mMouse->getMouseState();
 ms.width = width;
 ms.height = height;
}
 
// Desacoplar OIS antes de apagar la ventana (muy importante bajo Linux)
void BasicTutorial6::windowClosed(Ogre::RenderWindow* rw)
{
 // Cierra solo la ventana que creo el OIS (la ventana principal en estos demos)
 if( rw == mWindow )
 {
 if( mInputManager )
 {
 mInputManager->destroyInputObject( mMouse );
 mInputManager->destroyInputObject( mKeyboard );
 
 OIS::InputManager::destroyInputSystem(mInputManager);
 mInputManager = 0;
 }
 }
}
windowResized se llama si la ventana es redimensionada, necesitamos registrarlo.
Asi que anyade estas lineas a BasicTutorial6::go:
// Establecer el tamanyo de recorte inicial del raton
windowResized(mWindow);
 
 // Registralo como un listener de Ventana
Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
Otra cosa mas que necesitamos hacer.
Encontrar el destructor de BasicTutorial6 y hacer que sea asi:
// Eliminarnos a nosotros mismos como un listener de Window.
Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
windowClosed(mWindow);
delete mRoot;

Construyendo el FrameListener


No tiene en cuenta si estas usando entrada con búfer o sin búfer, en cada frame sólo llama al método de captura de todos los objetos teclado, ratón y joystick que uses.

Para entrada sin búfer, esto es todo lo que necesitas.
En cada frame puedes llamar a varias funciones de teclado y ratón para preguntar por el estado de los objetos.

Así que, necesitamos hacer que nuestra clase BasicTutorial6 sea un FrameListener. :-)

Cambia la declaración de la clase para que sea como esta:
class BasicTutorial6 : public Ogre::WindowEventListener, public Ogre::FrameListener
Entonces añade esta declaración de función a la sección protegida de la declaración de la clase:
// Ogre::FrameListener
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
Y entonces, en BasicTutorial6.cpp, anyade esta definicion de funcion:
bool BasicTutorial6::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
 if(mWindow->isClosed())
 return false;
 
 // Necesita capturar/actualizar cada dispositivo
 mKeyboard->capture();
 mMouse->capture();
 
 if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
 return false;
 return true;
}

Toques finales


Antes de que estemos listos para compilar y ejecutar nuestra aplicación, necesitamos registrar nuestra aplicación como un FrameListener.
Y no necesitamos un bucle personalizado de renderizado.

Busca BasicTutorial6::go y elimina el bucle while.
Entonces añade esto a el:
mRoot->addFrameListener(this);
 
mRoot->startRendering();
Esta primera línea de código añade a BasicTutorial6 a la Root como un FrameListener, lo que significa que recibirá eventos de frame.
Si no lo registramos como un FrameListener con Ogre::Root la función frameRenderingQueued no se llamará.

La segunda línea de código comienza el bucle de renderizado.
No necesitamos un manejo especial del bucle ya que podemos realizar nuestras tareas por frame en la función frameRenderingQueued.

Compila y ejecuta! :-D
Deberías ver la cabeza familiar de Ogre en una renderwindow de Ogre (ventana de renderizado), y deberías ser capaz de salir de la aplicación presionando la tecla Escape.

Mac OSX


Versión Cocoa


La nueva manera para establecer el actual tutorial framework para xcode en Mac OS X es mucho más corto y fácil de comprender.
Asegúrate de que tu proyecto es creado como una aplicación cocoa y cambia la extensión a .mm desde .cpp y copia ambos archivos resources y plugins.cfg a tu fase de copia de recursos en tu objetivo xcode.
Ahora cambia lo siguiente desde:
#ifdef _DEBUG
 mResourcesCfg = "resources_d.cfg";
 mPluginsCfg = "plugins_d.cfg";
#else
 mResourcesCfg = "resources.cfg";
 mPluginsCfg = "plugins.cfg";
#endif
 

a
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 std::string mResourcePath = [[[NSBundle mainBundle] resourcePath] cStringUsingEncoding:NSUTF8StringEncoding];
#endif
#ifdef _DEBUG
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 mResourcesCfg = mResourcePath + "/resources_d.cfg";
 mPluginsCfg = mResourcePath + "/plugins_d.cfg";
#else
 mResourcesCfg = "resources_d.cfg";
 mPluginsCfg = "plugins_d.cfg";
#endif
#else
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 mResourcesCfg = mResourcePath + "/resources.cfg";
 mPluginsCfg = mResourcePath + "/plugins.cfg";
#else
 mResourcesCfg = "resources.cfg";
 mPluginsCfg = "plugins.cfg";
#endif
 

Versión Carbon

Ya que Mac OS X usa paquetes de aplicación, un concepto radicalmente diferente del usado en Windows y Linux, el código descrito anteriormente fallará en Mac OSX.
  • Añade la siguiente función:
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#include <CoreFoundation/CoreFoundation.h>
 
 // Esta funcion localizara la ruta a nuestra aplicacion en OS X,
// a diferencia de windows no puedes buscar en el directorio de trabajo
// actual para encontrar los archivos de configuracion y de recursos.
std::string macBundlePath()
{
 char path[1024];
 CFBundleRef mainBundle = CFBundleGetMainBundle();
 assert(mainBundle);
 
 CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
 assert(mainBundleURL);
 
 CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);
 assert(cfStringRef);
 
 CFStringGetCString(cfStringRef, path, 1024, kCFStringEncodingASCII);
 
 CFRelease(mainBundleURL);
 CFRelease(cfStringRef);
 
 return std::string(path);
}
#endif
  • En createRoot(), cambia
mRoot = new Root();

a
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 mRoot = new Root(macBundlePath() + "/Contents/Resources/plugins.cfg");
#else
 mRoot = new Root();
#endif
  • En defineResources(), cambia
cf.load("resources.cfg");
a
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 cf.load(macBundlePath() + "/Contents/Resources/resources.cfg");
#else
 cf.load("resources.cfg");
#endif
  • también en defineResources(), cambia
Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archName, typeName, secName);

a
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( String(macBundlePath() + "/" + archName), typeName, secName);
#else
 Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archName, typeName, secName);
#endif
Siguiente, Tutorial Básico 7 CEGUI y Ogre