Ogre Tutorial 1: Creating a sample application

In this page you will be presented with the required tasks to create a simple application based on the Reference Application Layer. It is a simplified version of the BSPCollision example that ships with Ogre.

IMPORTANT NOTE: It is assumed that you have been through the Ogre 3D Introduction and know about Ogre's Example Reference Application Layer. You should also look into Setting up Ogre3D (Windows) and make sure you have ogre correctly installed and configured, and that you are able to compile and run the Demos.

The following steps are described here:

  • Preparing the project
  • Create the GameApplication class: where the engine is setup and the scene is described
  • Create the GameFrameListener class: the class that will handle user input and scene update
  • Create the main entry point: the standard code that instantiates a GameApplication and starts its main loop

Preparing the project

Assuming that you have tried to compile and run at least one of the demos shipped with Ogre and succeeded, your new project will be placed at a similar level of the demos, for the sake of simplicity.

  • Navigate to the “samples” folder in the OgreSDK home folder
  • Extract the OgreGameSlnTemplate.zip file in that folder. You should end up with a “Game” folder contain a .sln file, a .vcproj file and a .user file.
  • Go inside the “Game” folder and open the .sln file in MSVC
  • At this point you have the project set up, now you must add the files with the code, as described in the following sections.

If you are interested, click here for additional details on these configurations

If you are interested, click here for additional details on these configurations

In case you wonder or need to build or integrate your own project, the important parts you should configure are the additional include and lib directories, additional lib files, and the output and working directories for debugging. In the project properties, under “Configuration Properties”, these are the parameters that should be confirmed:

  • General
    • OutputDirectory=“..\..\bin\$(ConfigurationName)”
    • IntermediateDirectory=“..\obj\$(ConfigurationName)”
  • C++
    • AdditionalIncludeDirectories=“..\include;$(OGRE_HOME)\include;$(OGRE_HOME)\include;$(OGRE_HOME)\include;..\refapp\include”
  • Linker
    • AdditionalDependencies=“OgreMain_d.lib OIS_d.lib ReferenceAppLayer_d.lib”
    • AdditionalLibraryDirectories=“$(OGRE_HOME)\lib;..\..\..\Dependencies\lib\$(ConfigurationName)”
  • Debugging
    • Command=“..\..\bin\$(ConfigurationName)\$(TargetFileName)”
    • WorkingDirectory=“..\..\bin\$(ConfigurationName)”

Game Application Class: Lights, camera, scenario (world and objects)

  • Create a GameApplication class extending ExampleRefAppApplication, and overriding the createScene method to:
    • setup lights and shadows
    • setup the physics world parameters (gravity)
    • setup the camera
    • create a collidable Ball to be thrown
    • create four walls using collidable FinitePlane's
    • create a shelf using a collidable Box
    • create a set of collidable Box's
GameApplication.h
#pragma once
 
#include "GameFrameListener.h"
 
#include "OgreReferenceAppLayer.h"
 
#include "ExampleRefAppApplication.h"
#include "OgreStringConverter.h"
 
class GameApplication : public ExampleRefAppApplication
{
public:
    GameApplication() { }
    ~GameApplication() { }
 
protected:
	ApplicationObject *ball;
 
	void createScene(void)
    {
        mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);
 
	// Set ambient light
        mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
 
		// Create a point light
        Light* l = mSceneMgr->createLight("MainLight");
        l->setPosition(-100,50,100);
        l->setAttenuation(8000,1,0,0);
 
 
        // Setup World
        mWorld->setGravity(Vector3(0, 0, -60));
 
        // modify camera for close work
        mCamera->setNearClipDistance(10);
        mCamera->setFarClipDistance(20000);
 
        // Also change position, and set Quake-type orientation
        // Get random player start point
        ViewPoint vp = mSceneMgr->getSuggestedViewpoint(true);
        mCamera->setPosition(vp.position);
        mCamera->pitch(Degree(90)); // Quake uses X/Y horizon, Z up
        mCamera->rotate(vp.orientation);
 
        // Don't yaw along variable axis, causes leaning
        mCamera->setFixedYawAxis(true, Vector3::UNIT_Z);
 
	// Look at the boxes
	mCamera->lookAt(-150,40,30);
 
	// create ball
        ball = mWorld->createBall("ball", 7, vp.position + Vector3(0,0,80));
        ball->setDynamicsEnabled(true);
        ball->getEntity()->setMaterialName("Ogre/Eyes");
 
	// Create walls
	OgreRefApp::FinitePlane* walls[4];
 
	//Right
	walls[0] = mWorld->createPlane("Wall0",100,100,Vector3(-150,+100,0),Quaternion(Radian(Degree(90)),Vector3(1,0,0)));
        walls[0]->getEntity()->setMaterialName("Examples/Rocky");
 
	//Left
	walls[1] = mWorld->createPlane("Wall1",100,100,Vector3(-150,-100,0),Quaternion(Radian(Degree(-90)),Vector3(1,0,0)));
        walls[1]->getEntity()->setMaterialName("Examples/Rocky");
 
	//Back
	walls[2] = mWorld->createPlane("Wall2",100,100,Vector3(-250,0,0),Quaternion(Radian(Degree(90)),Vector3(0,1,0)));
        walls[2]->getEntity()->setMaterialName("Examples/Rocky");
 
	//bottom
	walls[3] = mWorld->createPlane("Wall3",100,100,Vector3(-150,0,-100),Quaternion(Radian(Degree(0)),Vector3(1,0,0)));
        walls[3]->getEntity()->setMaterialName("Examples/Rocky");
 
	// Shelf
	OgreRefApp::Box* box = mWorld->createBox("shelf", 75, 125, 5, Vector3(-150, 40, 30));
        box->getEntity()->setMaterialName("Examples/Rocky");
 
	// Cubes
        static const Real BOX_SIZE = 15.0f;
        static const int num_rows = 3;
 
        for (int row = 0; row < num_rows; ++row)
        {
            for (int i = 0; i < (num_rows-row); ++i)
            {
                Real row_size = (num_rows - row) * BOX_SIZE * 1.25;
                String name = "box";
                name += StringConverter::toString((row*num_rows) + i);
                box = mWorld->createBox(name, BOX_SIZE,BOX_SIZE,BOX_SIZE , 
                    Vector3(-150, 
                        40 - (row_size * 0.5) + (i * BOX_SIZE * 1.25) , 
                        32.5 + (BOX_SIZE / 2) + (row * BOX_SIZE)));
                box->setDynamicsEnabled(false, true);
                box->getEntity()->setMaterialName("Examples/10PointBlock");
            }
        }
 
        mCamera->setCollisionEnabled(false);
    }
 
    // Create new frame listener
    void createFrameListener(void)
    {
        mFrameListener= new GameFrameListener(mWindow, mCamera, ball);
        mRoot->addFrameListener(mFrameListener);
    }
};

Game Frame Listener: action (input handling and scene update)

  • Create a GameFrameListener class extending ExampleRefAppFrameListener and overriding the frameEnded method so that it:
    • calls the base class's method (to process general input)
    • if the space key is pressed, throw the ball i.e., set it in the viewer's position and set a velocity vector with a direction equal to the looking direction
GameFrameListener.h
#pragma once
 
#include "OgreReferenceAppLayer.h"
 
#include "ExampleRefAppFrameListener.h"
 
class GameFrameListener : public ExampleRefAppFrameListener
{
protected:
	ApplicationObject *ball;
 
public:
    GameFrameListener(RenderWindow* win, CollideCamera* cam, ApplicationObject *pball)
        : ExampleRefAppFrameListener(win, cam), ball(pball)
    {
    }
 
 
    bool frameEnded(const FrameEvent& evt)
    {
	// Call superclass
        bool ret = ExampleRefAppFrameListener::frameEnded(evt);
 
	// Respond to keyboard: SPACE FIRES
	if (mKeyboard->isKeyDown(OIS::KC_SPACE))
        {
            ball->setPosition(mCamera->getPosition() + 
                mCamera->getDirection() * mCamera->getNearClipDistance() * 2);
            ball->setLinearVelocity(mCamera->getDirection() * 200);
            ball->setAngularVelocity(Vector3::ZERO);
        }
 
        return ret;
    }
};

Main Application Entry Point

  • The application's main entry point consists solely of the creation of a GameApplication object and invoking its go method (plus some minor platform handling code):
GameMain.cpp
#include "GameApplication.h"
 
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
 
 
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
    // Create application object
    GameApplication app;
 
    try {
        app.go();
    } catch( 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();
#endif
    }
 
 
    return 0;
}