Loading...
Searching...
No Matches
Tutorial 12: Terrain Rendering

This tutorial will briefly show how to use the terrain renderer of Irrlicht. It will also show the terrain renderer triangle selector to be able to do collision detection with terrain.

Note that the Terrain Renderer in Irrlicht is based on Spintz' GeoMipMapSceneNode, lots of thanks go to him. DeusXL provided a new elegant simple solution for building larger area on small heightmaps -> terrain smoothing.

In the beginning there is nothing special. We include the needed header files and create an event listener to listen if the user presses a key: The 'W' key switches to wireframe mode, the 'P' key to pointcloud mode, and the 'D' key toggles between solid and detail mapped material.

#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(scene::ISceneNode* terrain, scene::ISceneNode* skybox, scene::ISceneNode* skydome) :
Terrain(terrain), Skybox(skybox), Skydome(skydome), showBox(true), showDebug(false)
{
Skybox->setVisible(showBox);
Skydome->setVisible(!showBox);
}
bool OnEvent(const SEvent& event)
{
// check if user presses the key 'W' or 'D'
if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
{
switch (event.KeyInput.Key)
{
case irr::KEY_KEY_W: // switch wire frame mode
Terrain->setMaterialFlag(video::EMF_WIREFRAME,
!Terrain->getMaterial(0).Wireframe);
Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false);
return true;
case irr::KEY_KEY_P: // switch wire frame mode
Terrain->setMaterialFlag(video::EMF_POINTCLOUD,
!Terrain->getMaterial(0).PointCloud);
Terrain->setMaterialFlag(video::EMF_WIREFRAME, false);
return true;
case irr::KEY_KEY_D: // toggle detail map
Terrain->setMaterialType(
Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ?
video::EMT_DETAIL_MAP : video::EMT_SOLID);
return true;
case irr::KEY_KEY_S: // toggle skies
showBox=!showBox;
Skybox->setVisible(showBox);
Skydome->setVisible(!showBox);
return true;
case irr::KEY_KEY_X: // toggle debug information
showDebug=!showDebug;
Terrain->setDebugDataVisible(showDebug?scene::EDS_BBOX_ALL:scene::EDS_OFF);
return true;
default:
break;
}
}
return false;
}
private:
scene::ISceneNode* Terrain;
scene::ISceneNode* Skybox;
scene::ISceneNode* Skydome;
bool showBox;
bool showDebug;
};
irr::IEventReceiver
Interface of an object which can receive events.
Definition IEventReceiver.h:434
irr::scene::ISceneNode
Scene node interface.
Definition ISceneNode.h:41
driverChoice.h
irrlicht.h
Main header file of the irrlicht, the only file needed to include.
irr::scene::EDS_OFF
@ EDS_OFF
No Debug Data ( Default ).
Definition EDebugSceneTypes.h:17
irr::scene::EDS_BBOX_ALL
@ EDS_BBOX_ALL
EDS_BBOX | EDS_BBOX_BUFFERS.
Definition EDebugSceneTypes.h:38
irr::video::EMF_POINTCLOUD
@ EMF_POINTCLOUD
Draw as point cloud or filled triangles? Default: false.
Definition EMaterialFlags.h:20
irr::video::EMF_WIREFRAME
@ EMF_WIREFRAME
Draw as wireframe or filled triangles? Default: false.
Definition EMaterialFlags.h:17
irr::video::EMT_DETAIL_MAP
@ EMT_DETAIL_MAP
Detail mapped material.
Definition EMaterialTypes.h:68
irr::video::EMT_SOLID
@ EMT_SOLID
Standard solid material.
Definition EMaterialTypes.h:19
irr
Everything in the Irrlicht Engine can be found in this namespace.
Definition aabbox3d.h:13
irr::KEY_KEY_P
@ KEY_KEY_P
Definition Keycodes.h:81
irr::KEY_KEY_X
@ KEY_KEY_X
Definition Keycodes.h:89
irr::KEY_KEY_D
@ KEY_KEY_D
Definition Keycodes.h:69
irr::KEY_KEY_S
@ KEY_KEY_S
Definition Keycodes.h:84
irr::KEY_KEY_W
@ KEY_KEY_W
Definition Keycodes.h:88
irr::EET_KEY_INPUT_EVENT
@ EET_KEY_INPUT_EVENT
A key input event.
Definition IEventReceiver.h:35
irr::SEvent::SKeyInput::Key
EKEY_CODE Key
Key which has been pressed or released.
Definition IEventReceiver.h:322
irr::SEvent::SKeyInput::PressedDown
bool PressedDown
If not true, then the key was left up.
Definition IEventReceiver.h:325
irr::SEvent
SEvents hold information about an event. See irr::IEventReceiver for details on event handling.
Definition IEventReceiver.h:263
irr::SEvent::EventType
EEVENT_TYPE EventType
Definition IEventReceiver.h:414
irr::SEvent::KeyInput
struct SKeyInput KeyInput
Definition IEventReceiver.h:419

The start of the main function starts like in most other example. We ask the user for the desired renderer and start it up. This time with the advanced parameter handling.

int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
// create device with full flexibility over creation parameters
// you can add more parameters if desired, check irr::SIrrlichtCreationParameters
irr::SIrrlichtCreationParameters params;
params.DriverType=driverType;
params.WindowSize=core::dimension2d<u32>(640, 480);
IrrlichtDevice* device = createDeviceEx(params);
if (device == 0)
return 1; // could not create selected driver.
irr::IrrlichtDevice
The Irrlicht device. You can create it with createDevice() or createDeviceEx().
Definition IrrlichtDevice.h:44
irr::core::dimension2d
Specifies a 2 dimensional size.
Definition dimension2d.h:21
irr::video::E_DRIVER_TYPE
E_DRIVER_TYPE
An enum for all types of drivers the Irrlicht Engine supports.
Definition EDriverTypes.h:15
irr::video::EDT_COUNT
@ EDT_COUNT
No driver, just for counting the elements.
Definition EDriverTypes.h:56
irr::createDeviceEx
IRRLICHT_API IrrlichtDevice *IRRCALLCONV createDeviceEx(const SIrrlichtCreationParameters &parameters)
Creates an Irrlicht device with the option to specify advanced parameters.
irr::SIrrlichtCreationParameters
Structure for holding Irrlicht Device creation parameters.
Definition SIrrCreationParameters.h:20
irr::SIrrlichtCreationParameters::WindowSize
core::dimension2d< u32 > WindowSize
Size of the window or the video mode in fullscreen mode. Default: 800x600.
Definition SIrrCreationParameters.h:103
irr::SIrrlichtCreationParameters::DriverType
video::E_DRIVER_TYPE DriverType
Type of video driver used to render graphics.
Definition SIrrCreationParameters.h:100

First, we add standard stuff to the scene: A nice irrlicht engine logo, a small help text, a user controlled camera, and we disable the mouse cursor.

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* env = device->getGUIEnvironment();
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
// add irrlicht logo
env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
core::position2d<s32>(10,10));
//set other font
env->getSkin()->setFont(env->getFont("../../media/fontlucida.png"));
// add some help text
env->addStaticText(
L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map\nPress 'S' to toggle skybox/skydome",
core::rect<s32>(10,421,250,475), true, true, 0, -1, true);
// add camera
scene::ICameraSceneNode* camera =
smgr->addCameraSceneNodeFPS(0,100.0f,1.2f);
camera->setPosition(core::vector3df(2700*2,255*2,2600*2));
camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
camera->setFarValue(42000.0f);
// disable mouse cursor
device->getCursorControl()->setVisible(false);
irr::IrrlichtDevice::getCursorControl
virtual gui::ICursorControl * getCursorControl()=0
Provides access to the cursor control.
irr::IrrlichtDevice::getSceneManager
virtual scene::ISceneManager * getSceneManager()=0
Provides access to the scene manager.
irr::IrrlichtDevice::getVideoDriver
virtual video::IVideoDriver * getVideoDriver()=0
Provides access to the video driver for drawing 3d and 2d geometry.
irr::IrrlichtDevice::getGUIEnvironment
virtual gui::IGUIEnvironment * getGUIEnvironment()=0
Provides access to the 2d user interface environment.
irr::core::rect
Rectangle template.
Definition rect.h:27
irr::gui::ICursorControl::setVisible
virtual void setVisible(bool visible)=0
Changes the visible state of the mouse cursor.
irr::gui::IGUIEnvironment
GUI Environment. Used as factory and manager of all other GUI elements.
Definition IGUIEnvironment.h:71
irr::gui::IGUIEnvironment::addImage
virtual IGUIImage * addImage(video::ITexture *image, core::position2d< s32 > pos, bool useAlphaChannel=true, IGUIElement *parent=0, s32 id=-1, const wchar_t *text=0)=0
Adds an image element.
irr::gui::IGUIEnvironment::getFont
virtual IGUIFont * getFont(const io::path &filename)=0
Returns pointer to the font with the specified filename.
irr::gui::IGUIEnvironment::addStaticText
virtual IGUIStaticText * addStaticText(const wchar_t *text, const core::rect< s32 > &rectangle, bool border=false, bool wordWrap=true, IGUIElement *parent=0, s32 id=-1, bool fillBackground=false)=0
Adds a static text.
irr::gui::IGUIEnvironment::getSkin
virtual IGUISkin * getSkin() const =0
Returns pointer to the current gui skin.
irr::gui::IGUISkin::setFont
virtual void setFont(IGUIFont *font, EGUI_DEFAULT_FONT which=EGDF_DEFAULT)=0
sets a default font
irr::scene::ICameraSceneNode
Scene Node which is a (controlable) camera.
Definition ICameraSceneNode.h:24
irr::scene::ICameraSceneNode::setTarget
virtual void setTarget(const core::vector3df &pos)=0
Sets the look at target of the camera.
irr::scene::ICameraSceneNode::setFarValue
virtual void setFarValue(f32 zf)=0
Sets the value of the far clipping plane (default: 2000.0f).
irr::scene::ISceneManager
The Scene Manager manages scene nodes, mesh recources, cameras and all the other stuff.
Definition ISceneManager.h:151
irr::scene::ISceneManager::addCameraSceneNodeFPS
virtual ICameraSceneNode * addCameraSceneNodeFPS(ISceneNode *parent=0, f32 rotateSpeed=100.0f, f32 moveSpeed=0.5f, s32 id=-1, SKeyMap *keyMapArray=0, s32 keyMapSize=0, bool noVerticalMovement=false, f32 jumpSpeed=0.f, bool invertMouse=false, bool makeActive=true)=0
Adds a camera scene node with an animator which provides mouse and keyboard control appropriate for f...
irr::scene::ISceneNode::setPosition
virtual void setPosition(const core::vector3df &newpos)
Sets the position of the node relative to its parent.
Definition ISceneNode.h:507
irr::video::IVideoDriver
Interface to driver which is able to perform 2d and 3d graphics functions.
Definition IVideoDriver.h:257
irr::video::IVideoDriver::getTexture
virtual ITexture * getTexture(const io::path &filename)=0
Get access to a named texture.
irr::video::IVideoDriver::setTextureCreationFlag
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled=true)=0
Enables or disables a texture creation flag.
irr::core::vector3df
vector3d< f32 > vector3df
Typedef for a f32 3d vector.
Definition vector3d.h:445
irr::video::ETCF_ALWAYS_32_BIT
@ ETCF_ALWAYS_32_BIT
Definition ITexture.h:41

Here comes the terrain renderer scene node: We add it just like any other scene node to the scene using ISceneManager::addTerrainSceneNode(). The only parameter we use is a file name to the heightmap we use. A heightmap is simply a gray scale texture. The terrain renderer loads it and creates the 3D terrain from it.

To make the terrain look more big, we change the scale factor of it to (40, 4.4, 40). Because we don't have any dynamic lights in the scene, we switch off the lighting, and we set the file terrain-texture.jpg as texture for the terrain and detailmap3.jpg as second texture, called detail map. At last, we set the scale values for the texture: The first texture will be repeated only one time over the whole terrain, and the second one (detail map) 20 times.

// add terrain scene node
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
"../../media/terrain-heightmap.bmp",
0, // parent node
-1, // node id
core::vector3df(0.f, 0.f, 0.f), // position
core::vector3df(0.f, 0.f, 0.f), // rotation
core::vector3df(40.f, 4.4f, 40.f), // scale
video::SColor ( 255, 255, 255, 255 ), // vertexColor
5, // maxLOD
scene::ETPS_17, // patchSize
4 // smoothFactor
);
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0,
driver->getTexture("../../media/terrain-texture.jpg"));
terrain->setMaterialTexture(1,
driver->getTexture("../../media/detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
irr::scene::ISceneManager::addTerrainSceneNode
virtual ITerrainSceneNode * addTerrainSceneNode(const io::path &heightMapFileName, ISceneNode *parent=0, s32 id=-1, const core::vector3df &position=core::vector3df(0.0f, 0.0f, 0.0f), const core::vector3df &rotation=core::vector3df(0.0f, 0.0f, 0.0f), const core::vector3df &scale=core::vector3df(1.0f, 1.0f, 1.0f), video::SColor vertexColor=video::SColor(255, 255, 255, 255), s32 maxLOD=5, E_TERRAIN_PATCH_SIZE patchSize=ETPS_17, s32 smoothFactor=0, bool addAlsoIfHeightmapEmpty=false)=0
Adds a terrain scene node to the scene graph.
irr::scene::ISceneNode::setMaterialTexture
void setMaterialTexture(u32 textureLayer, video::ITexture *texture)
Sets the texture of the specified layer in all materials of this scene node to the new texture.
Definition ISceneNode.h:436
irr::scene::ISceneNode::setMaterialFlag
void setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
Sets all material flags at once to a new value.
Definition ISceneNode.h:425
irr::scene::ISceneNode::setMaterialType
void setMaterialType(video::E_MATERIAL_TYPE newType)
Sets the material type of all materials in this scene node to a new material type.
Definition ISceneNode.h:448
irr::scene::ITerrainSceneNode
A scene node for displaying terrain using the geo mip map algorithm.
Definition ITerrainSceneNode.h:50
irr::scene::ITerrainSceneNode::scaleTexture
virtual void scaleTexture(f32 scale=1.0f, f32 scale2=0.0f)=0
Scales the base texture, similar to makePlanarTextureMapping.
irr::video::SColor
Class representing a 32 bit ARGB color.
Definition SColor.h:202
irr::scene::ETPS_17
@ ETPS_17
patch size of 17, at most, use 5 levels of detail with this patch size.
Definition ETerrainElements.h:20
irr::video::EMF_LIGHTING
@ EMF_LIGHTING
Will this material be lighted? Default: true.
Definition EMaterialFlags.h:26

To be able to do collision with the terrain, we create a triangle selector. If you want to know what triangle selectors do, just take a look into the collision tutorial. The terrain triangle selector works together with the terrain. To demonstrate this, we create a collision response animator and attach it to the camera, so that the camera will not be able to fly through the terrain.

// create triangle selector for the terrain
scene::ITriangleSelector* selector
= smgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
// create collision response animator and attach it to the camera
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
selector, camera, core::vector3df(60,100,60),
core::vector3df(0,0,0),
core::vector3df(0,50,0));
selector->drop();
camera->addAnimator(anim);
anim->drop();
irr::IReferenceCounted::drop
bool drop() const
Drops the object. Decrements the reference counter by one.
Definition IReferenceCounted.h:116
irr::scene::ISceneManager::createTerrainTriangleSelector
virtual ITriangleSelector * createTerrainTriangleSelector(ITerrainSceneNode *node, s32 LOD=0)=0
Creates a triangle selector which can select triangles from a terrain scene node.
irr::scene::ISceneManager::createCollisionResponseAnimator
virtual ISceneNodeAnimatorCollisionResponse * createCollisionResponseAnimator(ITriangleSelector *world, ISceneNode *sceneNode, const core::vector3df &ellipsoidRadius=core::vector3df(30, 60, 30), const core::vector3df &gravityPerSecond=core::vector3df(0,-10.0f, 0), const core::vector3df &ellipsoidTranslation=core::vector3df(0, 0, 0), f32 slidingValue=0.0005f)=0
Creates a special scene node animator for doing automatic collision detection and response.
irr::scene::ISceneNodeAnimator
Animates a scene node. Can animate position, rotation, material, and so on.
Definition ISceneNodeAnimator.h:31
irr::scene::ISceneNode::addAnimator
virtual void addAnimator(ISceneNodeAnimator *animator)
Adds an animator which should animate this node.
Definition ISceneNode.h:348
irr::scene::ISceneNode::setTriangleSelector
virtual void setTriangleSelector(ITriangleSelector *selector)
Sets the triangle selector of the scene node.
Definition ISceneNode.h:635
irr::scene::ITriangleSelector
Interface to return triangles with specific properties.
Definition ITriangleSelector.h:29

If you need access to the terrain data you can also do this directly via the following code fragment.

scene::CDynamicMeshBuffer* buffer = new scene::CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_16BIT);
terrain->getMeshBufferForLOD(*buffer, 0);
video::S3DVertex2TCoords* data = (video::S3DVertex2TCoords*)buffer->getVertexBuffer().getData();
// Work on data or get the IndexBuffer with a similar call.
buffer->drop(); // When done drop the buffer again.
irr::scene::CDynamicMeshBuffer
Definition CDynamicMeshBuffer.h:19
irr::scene::CDynamicMeshBuffer::getVertexBuffer
virtual IVertexBuffer & getVertexBuffer() const
Definition CDynamicMeshBuffer.h:37
irr::scene::ITerrainSceneNode::getMeshBufferForLOD
virtual void getMeshBufferForLOD(IDynamicMeshBuffer &mb, s32 LOD=0) const =0
Gets the meshbuffer data based on a specified level of detail.
irr::scene::IVertexBuffer::getData
virtual void * getData()=0
irr::video::EVT_2TCOORDS
@ EVT_2TCOORDS
Vertex with two texture coordinates, video::S3DVertex2TCoords.
Definition S3DVertex.h:25
irr::video::EIT_16BIT
@ EIT_16BIT
Definition SVertexIndex.h:17
irr::video::S3DVertex2TCoords
Vertex with two texture coordinates.
Definition S3DVertex.h:110

To make the user be able to switch between normal and wireframe mode, we create an instance of the event receiver from above and let Irrlicht know about it. In addition, we add the skybox which we already used in lots of Irrlicht examples and a skydome, which is shown mutually exclusive with the skybox by pressing 'S'.

// create skybox and skydome
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
scene::ISceneNode* skybox=smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));
scene::ISceneNode* skydome=smgr->addSkyDomeSceneNode(driver->getTexture("../../media/skydome.jpg"),16,8,0.95f,2.0f);
driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
// create event receiver
MyEventReceiver receiver(terrain, skybox, skydome);
device->setEventReceiver(&receiver);
irr::IrrlichtDevice::setEventReceiver
virtual void setEventReceiver(IEventReceiver *receiver)=0
Sets a new user event receiver which will receive events from the engine.
irr::scene::ISceneManager::addSkyBoxSceneNode
virtual ISceneNode * addSkyBoxSceneNode(video::ITexture *top, video::ITexture *bottom, video::ITexture *left, video::ITexture *right, video::ITexture *front, video::ITexture *back, ISceneNode *parent=0, s32 id=-1)=0
Adds a skybox scene node to the scene graph.
irr::scene::ISceneManager::addSkyDomeSceneNode
virtual ISceneNode * addSkyDomeSceneNode(video::ITexture *texture, u32 horiRes=16, u32 vertRes=8, f32 texturePercentage=0.9, f32 spherePercentage=2.0, f32 radius=1000.f, ISceneNode *parent=0, s32 id=-1)=0
Adds a skydome scene node to the scene graph.
irr::video::ETCF_CREATE_MIP_MAPS
@ ETCF_CREATE_MIP_MAPS
Definition ITexture.h:59

That's it, draw everything.

int lastFPS = -1;
while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, 0 );
smgr->drawAll();
env->drawAll();
driver->endScene();
// display frames per second in window title
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Terrain Renderer - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
// Also print terrain height of current camera position
// We can use camera position because terrain is located at coordinate origin
str += " Height: ";
str += terrain->getHeight(camera->getAbsolutePosition().X,
camera->getAbsolutePosition().Z);
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}
irr::IrrlichtDevice::run
virtual bool run()=0
Runs the device.
irr::IrrlichtDevice::setWindowCaption
virtual void setWindowCaption(const wchar_t *text)=0
Sets the caption of the window.
irr::IrrlichtDevice::isWindowActive
virtual bool isWindowActive() const =0
Returns if the window is active.
irr::core::string::c_str
const T * c_str() const
Returns character string.
Definition irrString.h:495
irr::core::vector3d::X
T X
X coordinate of the vector.
Definition vector3d.h:408
irr::core::vector3d::Z
T Z
Z coordinate of the vector.
Definition vector3d.h:414
irr::gui::IGUIEnvironment::drawAll
virtual void drawAll()=0
Draws all gui elements by traversing the GUI environment starting at the root node.
irr::scene::ISceneManager::drawAll
virtual void drawAll()=0
Draws all the scene nodes.
irr::scene::ISceneNode::getAbsolutePosition
virtual core::vector3df getAbsolutePosition() const
Gets the absolute position of the node in world coordinates.
Definition ISceneNode.h:522
irr::scene::ITerrainSceneNode::getHeight
virtual f32 getHeight(f32 x, f32 y) const =0
Get height of a point of the terrain.
irr::video::IVideoDriver::beginScene
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, SColor color=SColor(255, 0, 0, 0), const SExposedVideoData &videoData=SExposedVideoData(), core::rect< s32 > *sourceRect=0)=0
Applications must call this method before performing any rendering.
irr::video::IVideoDriver::getFPS
virtual s32 getFPS() const =0
Returns current frames per second value.
irr::video::IVideoDriver::getName
virtual const wchar_t * getName() const =0
Gets name of this video driver.
irr::video::IVideoDriver::endScene
virtual bool endScene()=0
Presents the rendered image to the screen.
irr::core::stringw
string< wchar_t > stringw
Typedef for wide character strings.
Definition irrString.h:1361

Now you know how to use terrain in Irrlicht.

- Irrlicht Engine Documentation © 2003-2012 by Nikolaus Gebhardt. Generated on for Irrlicht 3D Engine by Doxygen 1.15.0