Programming

Here’s a small class I wrote for a quick and easy Ogre config and window. It’s got some inspiration from the some of the classes in the tutorial framework, but I really wanted to write something from scratch just to get a better understanding of set-up and initialization. I might be pulling in a custom config loader to remove the ugly config window and another frame listener with adapters (since I’m not sure I’m sold on OIS yet). Might throw this on my Github once it’s a little more fleshed out, but check it out for now. Pretty straightforward, and I really like the Ogre::FrameListener system now that I’ve figured it out.

#ifndef _SKELETON_APPLICATION_H
#define _SKELETON_APPLICATION_H
 
#include "Ogre.h"
 
namespace Skeleton {
    class Application : public Ogre::FrameListener {
    private:
        Ogre::Root *_root;
        Ogre::RenderWindow *_window;
 
        Ogre::SceneManager *_sceneManager;
        Ogre::Camera *_cam;
        Ogre::Viewport *_viewport;
 
    public:
        Application() {
            // Load resources and config (borrowed from the tutorial framework)
            this->_root = new Ogre::Root("plugins_d.cfg", "resources_d.cfg");
            this->_root->addFrameListener(this);
        }
 
        ~Application() {
	        delete this->_root;
        }
 
        bool init() {
            // Get the settings from the config dialog
            if (!this->_root->showConfigDialog()) return false;
 
            // Auto create the window and store the pointer
            this->_window = this->_root->initialise(true, "Ogre Skeleton");
 
            // Create the scene manager and camera
            this->_sceneManager = this->_root->createSceneManager(Ogre::ST_GENERIC);
            this->_cam = this->_sceneManager->createCamera("MainCamera");
 
	        // Set up the defaults for the camera
            this->_cam->setPosition(Ogre::Vector3(0, 0, 80));
            this->_cam->lookAt(Ogre::Vector3(0, 0, -300));
            this->_cam->setNearClipDistance(5);
 
	        // Add the viewport to the window
            this->_viewport = this->_window->addViewport(this->_cam);
            this->_viewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0)); // Black
 
            return true;
        }
 
        void run() {
            if (this->init()) {
                // Let Ogre handle the render loop
    	        this->_root->startRendering();
            }
        }
 
        virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt) {
            if (this->_window->isClosed()) {
                // Returning false in the frame listener callback triggers shutdown
    	        return false;
            }
 
            return true;
        }
    };
}
 
#endif // _SKELETON_APPLICATION_H

I just had an “oh, that’s how you fix those” moments while playing with some C++ code. I’ve played with C++ a lot in the past (and read some books), but never really dug much deeper than tutorials and trying some simple algorithms. That’s probably why I’ve never come across the following example (though in fact I probably read about it somewhere before).

Say you’ve got a class called Car, and Car has a class called Engine. Now imagine for a moment that Engine has a reference to an instance of a Car, and Engine has a reference back to it’s parent Car instance.

// car.h
 
#include "engine.h"
 
class Car {
private:
    Engine *_engine;
public:
   // ...
};
 
//engine.h
 
#include "car.h"
 
class Engine {
private:
    Car *_car;
public:
    // ...
}

In most programming languages, this just isn’t going to be an issue. But it turns out it’s actually a common problem in compiled languages. We’re talking about C++, and yes, this is an issue despite having proper inclusion guards. This type of code may generate error codes such as C2143 & C4430. But, as it turns out this issue is quite trivial to fix if you know what to do when you recognize this scenario. The fix is called a forward declaration, and it pretty much breaks up the cyclic dependency so the compiler can carry on.

//engine.h
 
#include "car.h"
 
class Car; // <- Forward declaration
class Engine {
    // ...
}

Easy. I hope this helps any noobs stumbling into the same issue.