The Irrlicht Engine is an open source high performance realtime 3D engine written and usable in C++ and also available for .NET languages. It is completely cross-platform, using D3D, OpenGL and its own software renderer, and has all of the state-of-the-art features which can be found in commercial 3d engines.
Irrlicht has a huge active community, and there are lots of projects in development that use the engine. You can find enhancements for Irrlicht all over the web, like alternative terrain renderers, portal renderers, exporters, world layers, tutorials, editors, language bindings for java, perl, ruby, basic, python, lua, and so on. And best of all: It’s completely free.
In this tutorial series we will look at how to use Irrlicht to create some simple 3D application while exploring some of the basic, and not so basic, features available in the Irrlicht 3D engine.
You can find a good, step by step tutorial that shows you how to get a simple Irrlicht application up and running here. If you don’t have a copy of Visual Studio, Microsoft has released Visual Studio Express, which is a free copy of their flagship IDE, and Visual Studio Express C++ has everything you need to get started.
We will start with a class called IrrlichtEngineManager
The IrrlichtEngineManager class is designed as a singleton, which means only one instance of the class can exist at any one time. That instance is accessed via the static Instance function, or through the ENGINEMANAGER definition, which is just a shorthand way of accessing the Instance function.
The code to initialise the Irrlicht 3D engine is contained in a function called Startup. The first thing we do is create an IrrlichtDevice by calling the createDevice function.
The first paramater is the rendering system that will be used. This is defined in a header file called ConfigurationValues.h, which serves as a central location for all the constants that define how the application will work. You can choose from a number of rendering systems like OpenGL, DirectX and software. We have choosen OpenGL, which is the only rendering system that can use the power of the video card across multiple operating systems.
The next paramater defines the screen resultion. Again these values come from the ConfigurationValues.h file.
The retruned IrrlichtDevice, which the device variable points to, is the root object for using the engine. It contains most of the objects we will use when dealing the underlying 3D engine. The createDevice function also creates the window that will display the 3D scene we will (eventually) create.
The title of the window is set by calling the IrrlichtDevice setWindowCaption function.
Next we need to get some pointers to the video driver and scene manager held by the IrrlichtDevice. This is really just for convenience: we are not creating these objects, just getting a pointer to them from the IrrlichtDevice.
The Shutdown function essentially does the reverse of the Startup function. We call the IrrlichtDevice drop function, which will delete the IrrlichtDevice. As a rule, any Irrlicht object that is instantiated with a function that starts with the word “create” (like createDevice) needs to be destroyed by calling its drop function. Irrlicht maintains a reference counter behind the scenes, which gives it a very basic form of garbage collection, and the create and drop functions let Irrlicht know when there are no more references to an object. The InitialiseVariables function is then called to set all the variables back to NULL.
Almost every 3D application you will make (with Irrlicht or otherwise) has what is called a render loop. This is a loop that updates the application (by moving objects around, firing bullets, updating particle systems etc) and then renders the result of that frame to the screen. The StartRenderLoop function contains our render loop.
The loop will run until device->run() returns false. Inside the loop we call driver->beginScene(…), which has to be called before any rendering is done. The first two paramaters indicate that we want to clear the back buffer and the z buffer, which essentially clears away any information from the last frame. The third paramater defines what colour the back buffer will be cleared with.
Next we draw the scene manager. As its name suggests, a scene manager contains all the objects in a scene, so when we call smgr->drawAll() all of the 3d objects in a scene will be drawn.
Finally we call driver->endScene(), which will display the rendered scene on the screen.
The render loop is essentially an infinite loop unless we have a way for device->run() to return false. A call to device->closeDevice() does exactly that, and that code is contained in the function called EndRenderLoop.
As was mentioned above, the ConfigurationValues.h file defines the constants that are used to by the application.
The IrrlichtEngineManager now has all the code we need to initialise the Irrlicht 3D engine. To run this code we need an entry point for our application. For Windows application this is the WinMain function, which is in the Main.cpp file. In this function we start the 3D engine by calling the IrrlichtEngineManager Startup function, we then run the render loop by calling the StartRenderLoop function, and when the render loop is exited (in this case by the user closing the window rather than a manual call to the EndRenderLoop function) we shutdown the engine and clean up the memory by calling Shutdown.
At this point we now have an application that displays a blank screen. While it is not terribly exciting, this does give us a place to start displaying some cool 3d models and effects.