Tutorial 2: Using Ogre's facilities for debugging

screenshot of tutorial2

When you are developping an algorithm you often need to debug it. This requires displaying information either general or on particular object that you selected. You also generally want to know how well it behaves not only qualitatively but also quantitatively. For example, you want to know the framerate or the number of triangles displayed. Ogre offers an overlay mechanism that is very handy to display information above the scene rendered. As far as I understand, it is not generic enough to do complex GUI but sufficient (and very convenient) to display some text and some images (e.g. the Ogre logo). In this tutorial, we will introduce overlays. In the course of that introduction, we will also learn some important notions about resource management. Ogre has a second useful mechanism to intersect a ray with the scene. We will present it and see how to use it for selection.

Step A: resource management

Resources, groups and archives

One boring part of writing applications is data management because it involves a lot of tedious book keeping. By data, I mean eveything that is not coded in the program but you instead feed to the application at run time. In Ogre, this is called a resource. From Ogre's API reference for the Resource class :

Resources are data objects that must be loaded and managed throughout an application. A resource might be a mesh, a texture, or any other piece of data - the key thing is that they must be identified by a name which is unique, must be loaded only once, must be managed efficiently in terms of retrieval, and they may also be unloadable to free memory up when they have not been used for a while and the memory budget is under stress.

As you can see, resource management is quite involving and I am glad Ogre has a mechanim to do it! Let's describe it. As you can expect there is an abstract ResourceManager with sub-classes for different type of resources. You won't normally have to derive resource managers as for the resources you are likely to use it is already done. Yeees! But you still have to do some work. Nooo! Let's see why...

Brute force resource management a.k.a loading everything in memory on startup, is not efficient. In a largescale application, we need to do load on demand, to free unused resources, etc. We might even need some more complex things like progress bar when loading large resources. So a resource has a life and can be in different states. Ogre defines a couple of such states. From the API reference of ResourceGroupManager (a class I'll describe very soon) :

Undefined Nobody knows about this resource yet. It might be in the filesystem, but Ogre is oblivious to it at the moment - there is no Resource instance. This might be because it's never been declared (either in a script, or using ResourceGroupManager::declareResource), or it may have previously been a valid Resource instance but has been removed, either individually through ResourceManager::remove or as a group through ResourceGroupManager::clearResourceGroup.
Declared Ogre has some forewarning of this resource, either through calling ResourceGroupManager::declareResource, or by declaring the resource in a script file which is on one of the resource locations which has been defined for a group. There is still no instance of Resource, but Ogre will know to create this resource when ResourceGroupManager::initialiseResourceGroup is called (which is automatic if you declare the resource group before Root::initialise).
Unloaded There is now a Resource instance for this resource, although it is not loaded. This means that code which looks for this named resource will find it, but the Resource is not using a lot of memory because it is in an unloaded state. A Resource can get into this state by having just been created by ResourceGroupManager::initialiseResourceGroup (either from a script, or from a call to declareResource), by being created directly from code (ResourceManager::create), or it may have previously been loaded and has been unloaded, either individually through Resource::unload, or as a group through ResourceGroupManager::unloadResourceGroup.
Loaded The Resource instance is fully loaded. This may have happened implicitly because something used it, or it may have been loaded as part of a group.

So how does Ogre manages all these states? It uses a ResourceGroupManager. Groups allows you to gather resources that can be loaded / unloaded as a unit. Ogre always have one group named "General" meant to hold all resources which do not need to be unloaded until shutdown. You can create additional groups so that you can control the life of your resources in whichever way you wish. So the ResourceGroupManager manages groups. But not only. Let's see what else it does.

One problem with resources is to locate them. If you are bored of old style Linux environment variables such as TEXINPUTS, you know what I mean! In Ogre, you simply add locations to the ResourceGroupManager and anytime it needs to know something about the resources (to declare or load it for example), it searches the path to find it. Locations in Ogre are represented by the concept of archive. Currently, archive can be either a directory or a zip file, which is handy to bundle a bunch of resources together (e.g. a mesh and its textures).

All these concepts might exhaust you but I thought you might like to understand a bit more the magic behind the chunk of code in previous tutorial. Hopefully, the manipulation of these concepts translates in very few lines of code as we shall see. Let's suppose you have a directory /opt/media/ containing some meshes and a zip file /home/decoret/pack.zip containing a bunch of scripts (we will soon see what scripts are). Here is how you would register them in your application :