Foreword.
If you prefer tutorials that come with a framework => check the other wiki tutorial series.
If you prefer tutorials that go step by step without a framework => this page should be ok.
I assume you know C++. If not, this tutorial will probably be hard to understand !
This tutorial presents only a few elements of Ogre3D.
You can download the code and media for this tutorial at the bottom of this wiki page.
This little tutorial is an extract of a bigger project which contains more tutorials & helper classes.
This bigger project is avaible there :
https://sourceforge.net/projects/so3dtools/
Also, make sure you read these tutorials in order!
Table of contents
Tutorial Description
In this program, I create a texture, in which I will render the scene.
I create a material that uses this texture, and I apply it on a mesh.
This technique is called a Render-To-Texture (RTT).
Please note that depending on your video card driver, you might get very different results.
For example, on my nvidia Geforce 9600M, RTT fails with 'FBO'.
So I modified the SimpleOgreInit.cpp (at the 'step 3'), so that it uses "Copy" instead of FBO.
Before root initialisation
¤ const Ogre::RenderSystemList& lRenderSystemList = mRoot->getAvailableRenderers(); if( lRenderSystemList.size() == 0 ) { MWARNING("Sorry, no rendersystem was found."); return result; } Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);
In order to have a working RTT, I check if I can select another mode than "FBO".
I suppose that the 'Copy' mode works for everyone under opengl.
¤ Ogre::ConfigOptionMap& lConfigMap = lRenderSystem->getConfigOptions(); if(lConfigMap.find("RTT Preferred Mode") != lConfigMap.end()) { lRenderSystem->setConfigOption("RTT Preferred Mode","Copy");
¤ } mRoot->setRenderSystem(lRenderSystem);
Don't forget the includes
¤#include "OGRE/OgreRoot.h" #include "OGRE/OgreRenderSystem.h" #include "OGRE/OgreRenderWindow.h" #include "OGRE/OgreWindowEventUtilities.h" #include "OGRE/OgreManualObject.h" #include "OGRE/OgreEntity.h" #include "OGRE/OgreMaterialManager.h" #include "OGRE/OgreHardwarePixelBuffer.h"
After resource loading & viewport creation
Now I create a special texture. This texture allows to do what is called a
'render to texture'. Which means that you can render your scene into
it, and then use this texture as any other in a material.
In order to keep a good framerate, I set its number of mipmaps to 0.
¤ Ogre::TextureManager& lTextureManager = Ogre::TextureManager::getSingleton(); Ogre::String lTextureName = "MyFirstRtt"; bool lGammaCorrection = false; unsigned int lAntiAliasing = 0; unsigned int lNumMipmaps = 0; Ogre::TexturePtr lTextureWithRtt = lTextureManager.createManual(lTextureName, lNameOfResourceGroup, Ogre::TEX_TYPE_2D, 512, 512, lNumMipmaps, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, lGammaCorrection, lAntiAliasing);
now I will link this texture to a camera, by creating a viewport in the texture.
¤ Ogre::RenderTexture* lRenderTarget = NULL; { Ogre::HardwarePixelBufferSharedPtr lRttBuffer = lTextureWithRtt->getBuffer(); lRenderTarget = lRttBuffer->getRenderTarget(); lRenderTarget->setAutoUpdated(true);
I create a camera so that it has a beautiful '1' aspect ratio.
¤ Ogre::Camera * lRttCamera = lScene->createCamera("RttCamera"); lRttCamera->setNearClipDistance(1.5f); lRttCamera->setFarClipDistance(3000.0f); lRttCamera->setAspectRatio(1.0f);
I attach this camera to the same node than main camera.
¤ lCameraNode->attachObject(lRttCamera);
In the texture I will draw first a Big Blue Viewport.
¤ Ogre::Viewport* lRttViewport1 = lRenderTarget->addViewport(lRttCamera, 50, 0.00f, 0.00f, 1.0f, 1.0f); lRttViewport1->setAutoUpdated(true); Ogre::ColourValue lBgColor1(1.0,0.0,0.0,1.0); lRttViewport1->setBackgroundColour(lBgColor1);
In the texture I will draw then a more little red Viewport.
The previous viewport with the ZOrder at 50 will be drawn first (50 < 100).
¤ Ogre::Viewport* lRttViewport2 = lRenderTarget->addViewport(lRttCamera, 100, 0.05f, 0.05f, 0.9f, 0.9f); lRttViewport2->setAutoUpdated(true); Ogre::ColourValue lBgColor2(0.0,0.0,1.0,1.0); lRttViewport2->setBackgroundColour(lBgColor2);
This will draw a scene, within a scene, within a scene etc...
Because the quad that will be drawn is contained 'inside' the texture!
¤ }
now I create a material using this texture.
¤ Ogre::String lMaterialName = "MyRttMaterial"; {
I get a reference on the material manager, which is a singleton.
¤ Ogre::MaterialManager& lMaterialManager = Ogre::MaterialManager::getSingleton(); Ogre::MaterialPtr lMaterial = lMaterialManager.create(lMaterialName, lNameOfResourceGroup); Ogre::Technique * lTechnique = lMaterial->getTechnique(0); Ogre::Pass* lPass = lTechnique->getPass(0); Ogre::TextureUnitState* lTextureUnit = lPass->createTextureUnitState(); lTextureUnit->setTextureName(lTextureName);
I use no mipmap, and I just use some bilinear filtering on the result.
¤ lTextureUnit->setNumMipmaps(0); lTextureUnit->setTextureFiltering(Ogre::TFO_BILINEAR);
I make the texture rotate.
The material can handle 'special effects' on the texture coordinates.
Here I rotate the texture coordinates.
¤ float lRotateSpeed = 0.01f; lTextureUnit->setRotateAnimation(lRotateSpeed);
Uncomment the following line to see something funnier. .
lTextureUnit->setTransformAnimation(Ogre::TextureUnitState::TT_SCALE_U, Ogre::WFT_SINE, 0.9f, 0.5f, 0.0f, 0.2f);
¤ }
Now I will create a manualobject quad, and convert it to a mesh...
¤ Ogre::String lNameOfTheMesh = "MyQuad"; { Ogre::ManualObject * lManualObject = NULL; Ogre::String lManualObjectName = "SomeQuad"; lManualObject = lScene->createManualObject(lManualObjectName);
Always tell if you want to update the 3D (vertex/index) later or not.
¤ bool lDoIWantToUpdateItLater = false; lManualObject->setDynamic(lDoIWantToUpdateItLater);
BaseWhiteNoLighting is the name of a material that already exist inside Ogre.
Ogre::RenderOperation::OT_TRIANGLE_LIST is a kind of primitive.
¤ float lSize = 0.7f; lManualObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST); { float cp = 1.0f * lSize ; float cm = -1.0f * lSize; float lNumberOfTiles = 1.0f; lManualObject->position(cm, cp, 0.0f);// a vertex lManualObject->textureCoord(0.0f, 0.0f); lManualObject->position(cp, cp, 0.0f);// a vertex lManualObject->textureCoord(lNumberOfTiles, 0.0f); lManualObject->position(cp, cm, 0.0f);// a vertex lManualObject->textureCoord(lNumberOfTiles, lNumberOfTiles); lManualObject->position(cm, cm, 0.0f);// a vertex lManualObject->textureCoord(0.0, lNumberOfTiles); lManualObject->triangle(2,1,0); lManualObject->triangle(0,3,2); } lManualObject->end(); lManualObject->convertToMesh(lNameOfTheMesh); lScene->destroyManualObject(lManualObject); }
Now I will create the corresponding entity, and its scenenode.
¤ { Ogre::Entity* lEntity = lScene->createEntity(lNameOfTheMesh); lEntity->setMaterialName(lMaterialName);
Now I attach it to a scenenode, so that it becomes present in the scene.
¤ Ogre::SceneNode* lNodeWithEntity = lNodeWithEntity = lRootSceneNode->createChildSceneNode(); lNodeWithEntity->attachObject(lEntity);
I move the SceneNode so that it is visible to the camera.
¤ lNodeWithEntity->setPosition(0.0f, 0.0f, -1.8f); }
main.cpp , main.cs
NOTE This is a quick semiautomatic convert from C++ and it works with MOGRE SDK 1.7.1 r72
Any problems you encounter while working with MOGRE should be posted to the MOGRE Forum.
//TODO Fix accessViolation error on close window (Dispose correctly). Surround prt with using(){} does not fix this using System; using Mogre; using System.Collections.Generic; namespace OgreTutorials { public static class GlobalMembersMain { // In this program, I create a texture, in which I will render the scene. // I create a material that uses this texture, and I apply it on a mesh. // This technique is called a Render-To-Texture (RTT). // Please note that depending on your video card driver, you might get very different results. // For example, on my nvidia Geforce 9600M, RTT fails with 'FBO'. // So I modified the SimpleOgreInit.cpp (at the 'step 3'), so that it uses "Copy" instead of FBO. // I declare a function in which I will make my whole application. // This is easy then to add more things later in that function. // The main will call this function and take care of the global try/catch. public static void AnOgreApplication() { // I construct my object that will allow me to initialise Ogre easily. OgreEasy.SimpleOgreInit lOgreInit = new OgreEasy.SimpleOgreInit(); if (!lOgreInit.initOgre()) { Console.Write("Impossible to init Ogre correctly."); Console.Write("\n"); return; } //I prefer to be able to access my variables directly. Root lRoot = lOgreInit.mRoot; RenderWindow lWindow = lOgreInit.mWindow; // I create a scenemanager. This is like a 'Scene', in which I can put lights, 3d objects, etc... // The scenemanager contains an arborescent graph of 'SceneNodes'. To manage elements of the scene, // I will create SceneNodes in the SceneManager, and attach the elements to the scenenodes. // First parameter : I select a kind of SceneManager. This may have a huge impact on performance. // Depending on your scene, some are better than other. The default one does no optimization at all. // Second parameter : I give a name to the scenemanager. // Note : It is easy to have more than one scenemanager (If you got 2 different scenes for example). SceneManager lScene = lRoot.CreateSceneManager(SceneType.ST_GENERIC, "MyFirstSceneManager"); // The 'root SceneNode' is the only scenenode at the beginning in the SceneManager. // The SceneNodes can be seen as 'transformation' containers <=> it contains scale/position/rotation // of the objects. There is only 1 root scenenode, and all other scenenode are // its direct or indirect children. SceneNode lRootSceneNode = lScene.RootSceneNode; // I create a camera. It represent a 'point of view' in the scene. Camera lCamera = lScene.CreateCamera("MyFirstCamera"); // I attach the camera to a new SceneNode. It will be easier then to move it in the scene. SceneNode lCameraNode = lRootSceneNode.CreateChildSceneNode("MyFirstCameraNode"); lCameraNode.AttachObject(lCamera); // We create a viewport on a part of the window. // A viewport is the link between 1 camera and 1 drawing surface (here the window). // I can then call 'update();' on it to make it draw the Scene from the camera. // You can have several viewports on 1 window. // Check API for details on parameters. ushort lMainViewportZOrder = 100; Viewport vp = lWindow.AddViewport(lCamera, lMainViewportZOrder); // I want the viewport to draw the scene automatically // when I will call lWindow->update(); vp.SetAutoUpdated(true); // I choose a color for this viewport. // I prefer to have a bright color, to detect holes in geometry etc... vp.BackgroundColour = new ColourValue(1, 0, 1); // I choose the visual ratio of the camera. To make it looks real, I want it the same as the viewport. float ratio = vp.ActualWidth / vp.ActualHeight; lCamera.AspectRatio = ratio; // I choose the clipping far& near planes. if far/near>2000, you can get z buffer problem. // eg : far/near = 10000/5 = 2000 . it's ok. // If (far/near)>2000 then you will likely get 'z fighting' issues. lCamera.NearClipDistance = 1.5f; lCamera.FarClipDistance = 3000.0f; // I want my window to be active lWindow.IsActive = true; // I want to update myself the content of the window, not automatically. lWindow.IsAutoUpdated = false; // Here I choose a name for a resource group. Then I create it. // Often, a resourcegroup is a good way to store the data corresponding // to a level in a game. string lNameOfResourceGroup = "Mission 1 : Deliver Tom"; { ResourceGroupManager lRgMgr = ResourceGroupManager.Singleton; lRgMgr.CreateResourceGroup(lNameOfResourceGroup); // The function 'initialiseResourceGroup' parses scripts if any in the locations. lRgMgr.InitialiseResourceGroup(lNameOfResourceGroup); // Files that can be loaded are loaded. lRgMgr.LoadResourceGroup(lNameOfResourceGroup); } // Now I create a special texture. This texture allows to do what is called a // 'render to texture'. Which means that you can render your scene into // it, and then use this texture as any other in a material. // In order to keep a good framerate, I set its number of mipmaps to 0. TextureManager lTextureManager = TextureManager.Singleton; string lTextureName = "MyFirstRtt"; bool lGammaCorrection = false; uint lAntiAliasing = 0; int lNumMipmaps = 0; TexturePtr lTextureWithRtt = lTextureManager.CreateManual(lTextureName, lNameOfResourceGroup, TextureType.TEX_TYPE_2D, 512, 512, lNumMipmaps, PixelFormat.PF_R8G8B8, (int)TextureUsage.TU_RENDERTARGET, null, lGammaCorrection, lAntiAliasing); // now I will link this texture to a camera, by creating a viewport in the texture. RenderTexture lRenderTarget = null; { HardwarePixelBufferSharedPtr lRttBuffer = lTextureWithRtt.GetBuffer(); lRenderTarget = lRttBuffer.GetRenderTarget(); lRenderTarget.IsAutoUpdated = true; // I create a camera so that it has a beautiful '1' aspect ratio. Camera lRttCamera = lScene.CreateCamera("RttCamera"); lRttCamera.NearClipDistance = 1.5f; lRttCamera.FarClipDistance = 3000.0f; lRttCamera.AspectRatio = 1.0f; // I attach this camera to the same node than main camera. lCameraNode.AttachObject(lRttCamera); // In the texture I will draw first a Big Blue Viewport. Viewport lRttViewport1 = lRenderTarget.AddViewport(lRttCamera, 50, 0.00f, 0.00f, 1.0f, 1.0f); lRttViewport1.SetAutoUpdated(true); lRttViewport1.BackgroundColour = new ColourValue(1.0f, 0.0f, 0.0f, 1.0f); // In the texture I will draw then a more little red Viewport. // The previous viewport with the ZOrder at 50 will be drawn first (50 < 100). Viewport lRttViewport2 = lRenderTarget.AddViewport(lRttCamera, 100, 0.05f, 0.05f, 0.9f, 0.9f); lRttViewport2.SetAutoUpdated(true); lRttViewport2.BackgroundColour = new ColourValue(0.0f, 0.0f, 1.0f, 1.0f); // This will draw a scene, within a scene, within a scene etc... // Because the quad that will be drawn is contained 'inside' the texture! } // now I create a material using this texture. string lMaterialName = "MyRttMaterial"; { // I get a reference on the material manager, which is a singleton. MaterialManager lMaterialManager = MaterialManager.Singleton; MaterialPtr lMaterial = lMaterialManager.Create(lMaterialName, lNameOfResourceGroup); Technique lTechnique = lMaterial.GetTechnique(0); Pass lPass = lTechnique.GetPass(0); TextureUnitState lTextureUnit = lPass.CreateTextureUnitState(); lTextureUnit.SetTextureName(lTextureName); //I use no mipmap, and I just use some bilinear filtering on the result. lTextureUnit.NumMipmaps = 0; lTextureUnit.SetTextureFiltering(TextureFilterOptions.TFO_BILINEAR); // I make the texture rotate. // The material can handle 'special effects' on the texture coordinates. // Here I rotate the texture coordinates. float lRotateSpeed = 0.01f; lTextureUnit.SetRotateAnimation(lRotateSpeed); // Uncomment the following line to see something funnier. :-D. //NOTE lTextureUnit.SetTransformAnimation(TextureUnitState.TextureTransformType.TT_SCALE_U,WaveformType.WFT_SINE, 0.9f, 0.5f, 0.0f, 0.2f); } // Now I will create a manualobject quad, and convert it to a mesh... string lNameOfTheMesh = "MyQuad"; { ManualObject lManualObject = null; string lManualObjectName = "SomeQuad"; lManualObject = lScene.CreateManualObject(lManualObjectName); // Always tell if you want to update the 3D (vertex/index) later or not. bool lDoIWantToUpdateItLater = false; lManualObject.Dynamic = lDoIWantToUpdateItLater; // BaseWhiteNoLighting is the name of a material that already exist inside // Ogre::RenderOperation::OT_TRIANGLE_LIST is a kind of primitive. float lSize = 0.7f; lManualObject.Begin("BaseWhiteNoLighting", RenderOperation.OperationTypes.OT_TRIANGLE_LIST); { float cp = 1.0f * lSize; float cm = -1.0f * lSize; float lNumberOfTiles = 1.0f; lManualObject.Position(cm, cp, 0.0f); // a vertex lManualObject.TextureCoord(0.0f, 0.0f); lManualObject.Position(cp, cp, 0.0f); // a vertex lManualObject.TextureCoord(lNumberOfTiles, 0.0f); lManualObject.Position(cp, cm, 0.0f); // a vertex lManualObject.TextureCoord(lNumberOfTiles, lNumberOfTiles); lManualObject.Position(cm, cm, 0.0f); // a vertex lManualObject.TextureCoord(0.0f, lNumberOfTiles); lManualObject.Triangle(2, 1, 0); lManualObject.Triangle(0, 3, 2); } lManualObject.End(); lManualObject.ConvertToMesh(lNameOfTheMesh); lScene.DestroyManualObject(lManualObject); } // Now I will create the corresponding entity, and its scenenode. { Entity lEntity = lScene.CreateEntity(lNameOfTheMesh); lEntity.SetMaterialName(lMaterialName); // Now I attach it to a scenenode, so that it becomes present in the scene. SceneNode lNodeWithEntity = lRootSceneNode.CreateChildSceneNode(); lNodeWithEntity.AttachObject(lEntity); // I move the SceneNode so that it is visible to the camera. lNodeWithEntity.Position = new Vector3(0.0f, 0.0f, -1.8f); } // cleaning of windows events managed by Ogre::WindowEventUtilities::... // I call it after a 'pause in window updating', in order to maintain smoothness. // Explanation : if you clicked 2000 times when the windows was being created, there are // at least 2000 messages created by the OS to listen to. This is made to clean them. lRoot.ClearEventTimes(); // I wait until the window is closed. // The "message pump" thing is something you will see in most GUI application. // It allow the binding of messages between the application and the OS. // These messages are most of the time : keystroke, mouse moved, ... or window closed. // If I don't do this, the message are never caught, and the window won't close. while (!lOgreInit.mWindow.IsClosed) { // Drawings // the window update its content. // each viewport that is 'autoupdated' will be redrawn now, // in order given by its z-order. lWindow.Update(false); // The drawn surface is then shown on the screen // (google "double buffering" if you want more details). // I always use vertical synchro. bool lVerticalSynchro = true; lWindow.SwapBuffers(lVerticalSynchro); // This update some internal counters and listeners. // Each render surface (window/rtt/mrt) that is 'auto-updated' has got its 'update' function called. lRoot.RenderOneFrame(); WindowEventUtilities.MessagePump(); } // Let's cleanup! { lWindow.RemoveAllViewports(); } { lScene.DestroyAllCameras(); lScene.DestroyAllManualObjects(); lScene.DestroyAllEntities(); lScene.DestroyAllLights(); lRootSceneNode.RemoveAndDestroyAllChildren(); } { RenderSystem lRenderSystem = lRoot.RenderSystem; lRenderSystem.DestroyRenderTarget(lTextureName); } { ResourceGroupManager lRgMgr = ResourceGroupManager.Singleton; lRgMgr.DestroyResourceGroup(lNameOfResourceGroup); } return; } public static void Main() { try { AnOgreApplication(); } catch (Exception e) { OgreEasy.SimpleOgreInit.ShowOgreException(); } } } } // The classes of this tutorial are put in a namespace called OgreEasy. // So that it can be reused without difficulty. namespace OgreEasy { /// \brief This class contains a function that help to initialise Ogre3d in one go. /// the code of this function is inspired by the first tutorial of OgreEasy. /// It was written for tutorial purpose. public class SimpleOgreInit { // The constructor does nothing but initialisation to NULL or empty values. // the constructor uses the initialisation list to have a proper state. public SimpleOgreInit() { mRoot = null; mWindow = null; } // the destructor frees memory allocated by the class. //public void Dispose() //TODO //{ // mRoot.Dispose(); // mRoot = null; // mWindow = null; // //mRoot.Reset(); // I was not obliged to do that... //} ///\brief This function will create 1 ogre root and 1 window and store them in its members mRoot and mWindow. ///\return false if an error occurs, true otherwise. public bool initOgre() { bool result = false; // This try/catch will catch potential exception launched by ogre or by my program. // Ogre can launch 'Ogre::Exception' for example. try { // STEP 1/ First, we will need to create the Ogre::Root object. // It is an object that must be created to use ogre correctly, and delete once we are finished using // This is the name of an optionnal textual configuration file for the rendersystem. // I won't use it. string lConfigFileName = ""; // This is the name of an optionnal textual configuration file, which lists the available plugins. // I won't use it. string lPluginsFileName = ""; // This is the name of the log file. A log file is a file in which you can write things during the program execution. // Ogre use it to display general informations about the rendersystem. // You are not obliged to generate one, and ogre can even transmit the log data to you own class if you want. // Here we only ask the root to create the file. string lLogFileName = "Ogre.log"; mRoot = new Root(lConfigFileName, lPluginsFileName, lLogFileName); // STEP 2/ Then we need to load plugins. It means that there are functions that are stored inside dynamic libraries. // These libraries are .dll or .so files. Most projects Ogre Project do not need all functions to be usable. // That way, only a subset of all function can be loaded. It also means you can create your own plugins if you want. // If you want to know more on the subject, you 'll need to dig into a C++ tutorial. // Anyway, for our use, we will need to load at least a 'RenderSystem' plugin, which means something to drive opengl or directx. // The basic plugins you are the most likely to use are the RenderSystems, the particle FX and the Cgprogram. { // Here I list all the plugins I want to load. // I let those I don't want to use in comments. // Opengl rendersystem is supposed to work everywhere. // But in reality a rendersystem may fail on your computer. // It is likely do to bad/old graphic card driver/installation, // or too old directx version on windows (try update). // Often, when one rendersystem fail, the other at least kind-a-work. // I put them in a std::vector, because then I can factorise operations and calls (do a 'for'). List<string> lPluginNames = new List<string> { "RenderSystem_GL", //"RenderSystem_Direct3D9", "Plugin_ParticleFX", "Plugin_CgProgramManager", //"Plugin_PCZSceneManager", //"Plugin_OctreeZone", "Plugin_OctreeSceneManager", //"Plugin_BSPSceneManager" }; { foreach (var lPluginName in lPluginNames) { //TODO if (OGRE_DEBUG_MODE) lPluginName + "_d" mRoot.LoadPlugin(lPluginName); } } } // STEP 3/ Then, we can select from the loaded plugins the unique RenderSystem we want to use. { // the root provide a method if you want to select // the rendersystem and its options visually (lRoot->showConfigDialog()). // in that case, you don't need to set the render system manually Const_RenderSystemList lRenderSystemList = mRoot.GetAvailableRenderers(); if (lRenderSystemList.Count == 0) { System.Windows.Forms.MessageBox.Show("Sorry, no rendersystem was found."); return result; } RenderSystem lRenderSystem = lRenderSystemList[0]; // In order to have a working RTT, I check if I can select another mode than "FBO". // I suppose that the 'Copy' mode works for everyone under opengl. ConfigOptionMap lConfigMap = lRenderSystem.GetConfigOptions(); if (lConfigMap.Find("RTT Preferred Mode") != lConfigMap.End()) { lRenderSystem.SetConfigOption("RTT Preferred Mode", "Copy"); //lRenderSystem.SetConfigOption("RTT Preferred Mode","PBuffer"); //lRenderSystem.SetConfigOption("RTT Preferred Mode","FBO"); } mRoot.RenderSystem = lRenderSystem; } // STEP 4/ When the RenderSystem is selected, we can initialise the Root. The root can be initialised only when a rendersystem has been selected. { // I can create a window automatically, but I won't do it. bool lCreateAWindowAutomatically = false; // name of the automatically generated window. empty for me. string lWindowTitle = ""; // custom capabilities of the rendersystem. It's a feature for advanced use. string lCustomCapacities = ""; mRoot.Initialise(lCreateAWindowAutomatically, lWindowTitle, lCustomCapacities); } // STEP 5/ Then we can ask to the RenderSystem to create a window. { string lWindowTitle = "Hello Ogre World"; uint lSizeX = 800; uint lSizeY = 600; //I don't want to use fullscreen during development. bool lFullscreen = false; // This is just an example of parameters that we can put. Check the API for more details. NameValuePairList lParams = new NameValuePairList(); // fullscreen antialiasing. (check wikipedia if needed). lParams["FSAA"] = "0"; // vertical synchronisation will prevent some image-tearing, but also // will provide smooth framerate in windowed mode.(check wikipedia if needed). lParams["vsync"] = "true"; mWindow = mRoot.CreateRenderWindow(lWindowTitle, lSizeX, lSizeY, lFullscreen, lParams); } result = true; } catch (Exception e) //TODO { ShowOgreException(); result = false; } return result; } // I put the member in public because there is no need to put them private in these tutorials. // It will allow very simple access to these useful members. ///\brief the root of ogre will be contained in this member. /// it will be initialised in initOgre(). public Root mRoot = new Root(); ///\brief the window created in the initOgre(). NULL otherwise. /// This is just a handle, not a real aggregation. /// The destruction of the Root will imply its destruction. public RenderWindow mWindow; public static void ShowOgreException() { if (OgreException.IsThrown) System.Windows.Forms.MessageBox.Show(OgreException.LastException.FullDescription, "An exception has occured!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); } } }