|Read more about this book|
(For more resources on this subject, see here.)
Up until now, the ExampleApplication class has started and initialized Ogre 3D for us; now we are going to do it ourselves.
Time for action – starting Ogre 3D
This time we are working on a blank sheet.
- Start with an empty code file, include Ogre3d.h, and create an empty main function:
int main (void)
- Create an instance of the Ogre 3D Root class; this class needs the name of the “plugin.cfg”:
- If the config dialog can’t be shown or the user cancels it, close the application:
- Create a render window:
Ogre::RenderWindow* window = root->initialise(true,"Ogre3D
- Next create a new scene manager:
Ogre::SceneManager* sceneManager = root-
- Create a camera and name it camera:
Ogre::Camera* camera = sceneManager->createCamera("Camera");
- With this camera, create a viewport and set the background color to black:
Ogre::Viewport* viewport = window->addViewport(camera);
- Now, use this viewport to set the aspect ratio of the camera:
- Finally, tell the root to start rendering:
- Compile and run the application; you should see the normal config dialog and then a black window. This window can’t be closed by pressing Escape because we haven’t added key handling yet. You can close the application by pressing CTRL+C in the console the application has been started from.
Ogre::Root* root = new Ogre::Root("plugins_d.cfg");
What just happened?
We created our first Ogre 3D application without the help of the ExampleApplication. Because we aren’t using the ExampleApplication any longer, we had to include Ogre3D.h, which was previously included by ExampleApplication.h. Before we can do anything with Ogre 3D, we need a root instance. The root class is a class that manages the higher levels of Ogre 3D, creates and saves the factories used for creating other objects, loads and unloads the needed plugins, and a lot more. We gave the root instance one parameter: the name of the file that defines which plugins to load. The following is the complete signature of the constructor:
Root(const String & pluginFileName = "plugins.cfg",const String &
configFileName = "ogre.cfg",const String & logFileName = "Ogre.log")
Besides the name for the plugin configuration file, the function also needs the name of the Ogre configuration and the log file. We needed to change the first file name because we are using the debug version of our application and therefore want to load the debug plugins. The default value is plugins.cfg, which is true for the release folder of the Ogre 3D SDK, but our application is running in the debug folder where the filename is plugins_d.cfg.
ogre.cfg contains the settings for starting the Ogre application that we selected in the config dialog. This saves the user from making the same changes every time he/she start our application. With this file Ogre 3D can remember his choices and use them as defaults for the next start. This file is created if it didn’t exist, so we don’t append an _d to the filename and can use the default; the same is true for the log file.
Using the root instance, we let Ogre 3D show the config dialog to the user in step 3. When the user cancels the dialog or anything goes wrong, we return -1 and with this the application closes. Otherwise, we created a new render window and a new scene manager in step 4. Using the scene manager, we created a camera, and with the camera we created the viewport; then, using the viewport, we calculated the aspect ratio for the camera. After creating all requirements, we tell the root instance to start rendering, so our result would be visible. Following is a diagram showing which object was needed to create the other:
We have now created our first Ogre 3D application, which doesn’t need the ExampleApplication. But one important thing is missing: we haven’t loaded and rendered a model yet.
Time for action – loading the Sinbad mesh
We have our application, now let’s add a model.
- After setting the aspect ratio and before starting the rendering, add the zip archive containing the Sinbad model to our resources:
- We don’t want to index more resources at the moment, so index all added resources now:
- Now create an instance of the Sinbad mesh and add it to the scene:
Ogre::Entity* ent = sceneManager->createEntity("Sinbad.mesh");
- Compile and run the application; you should see Sinbad in the middle of the screen:
What just happened?
We used the ResourceGroupManager to index the zip archive containing the Sinbad mesh and texture files, and after this was done, we told it to load the data with the createEntity() call in step 3.
Adding a new line of code for each zip archive or folder we want to load is a tedious task and we should try to avoid it. The ExampleApplication used a configuration file called resources.cfg in which each folder or zip archive was listed, and all the content was loaded using this file. Let’s replicate this behavior.
Time for action – using resources.cfg to load our models
Using our previous application, we are now going to parse the resources.cfg.
- Replace the loading of the zip archive with an instance of a config file pointing at the resources_d.cfg:
- First get the iterator, which goes over each section of the config file:
Ogre::ConfigFile::SectionIterator sectionIter =
- Define three strings to save the data we are going to extract from the config file and iterate over each section:
Ogre::String sectionName, typeName, dataname;
- Get the name of the section:
sectionName = sectionIter.peekNextKey();
- Get the settings contained in the section and, at the same time, advance the section iterator; also create an iterator for the settings itself:
Ogre::ConfigFile::SettingsMultiMap *settings = sectionIter.
- Iterate over each setting in the section:
for (i = settings->begin(); i != settings->end(); ++i)
- Use the iterator to get the name and the type of the resources:
typeName = i->first;
dataname = i->second;
- Use the resource name, type, and section name to add it to the resource index:
addResourceLocation(dataname, typeName, sectionName);
- Compile and run the application, and you should see the same scene as before.