Irrlicht Manual Chapter 2

<< Chapter 1 Back To Index Chapter 3 >>

Chapter 2: Learning the Basics

Table of Contents

  1. 2.1 How to read the Documentation
  2. 2.2 Learning About Meshes
  3. 2.3 Learning About Nodes
  4. 2.4 Camera Basics
  5. 2.5 Initializing
  6. 2.6 The Game Loop
  7. 2.7 Skybox/Skydome
  8. 2.8 Cursor
  9. 2.9 Creating your Second Program (Tutorial 2)
  10. 2.10 Chapter Conclusion
  11. 2.11 Exercises

2.1 How To Read The Documentation

Documentation is a form of communicational material in which is used to explain some entity or object and its workings. The Irrlicht Engine API Documentation, communicates information about the Irrlicht Engine via a collection of text documents,graphical diagrams and source code. The Irrlicht Engine API Documentation can be found Here. A copy of the Irrlicht Documentation may also be found within the doc subdirectory of your Irrlicht folder irrlicht/doc in a compressed .chm format. The understanding of the proper use of the Irrlicht Engine API Documentation is a key skill in which will help you progress, and act as a constant resource / pool of information which can constantly be accessed should you require to query a section of the Irrlicht API.

Upon entering the Irrlicht Documentation you will be greeted by the index page, here you will find some information about the Irrlicht API, some links and source code for a demonstration of the simple capabilities of the Irrlicht engine. Under the Link section you will find:
Links
Namespaces: A very good place to start reading the documentation.
Class list: List of all classes with descriptions.
Class members: Good place to find forgotten features.

The first link, allows you to access the Namespace section of the Documentation. This is a very good place to start weaving your way through the Irrlicht Engine API. Simply click the link and within here you will be able to navigate your way through the Irrlicht engine fairly efficiently. Click the first link Irr and you will be able to access information on all the objects/items within the Irrlicht Engine. From here you will be able to select individual namespaces and then be able to explore certain functions within these namespaces, allowing you to see the functionality of these sections of the Irrlicht engine and how they are interlinked.(More Information)

2.1.1 Namespaces

Namespaces allow to group entities like classes, objects and functions under a name. This way the global scope can be divided in "sub-scopes", each one with its own name.
The format of namespaces is:
namespace identifier { entities }

Within the Irrlicht Engine the namespaces are ordered as follows:

NameDescription
irrEverything in the Irrlicht Engine can be found in this namespace
irr::coreIn this namespace can be found basic classes like vectors, planes, arrays, lists and so on
irr::guiThe gui namespace contains useful classes for easy creation of a graphical user interface
irr::ioThis namespace provides interfaces for input/output: Reading and writing files, accessing zip archives, xml files, ...
irr::sceneAll scene management can be found in this namespace: Mesh loading, special scene nodes like octrees and billboards, ...
irr::scene::quake3
irr::videoThe video namespace contains classes for accessing the video driver. All 2d and 3d rendering is done here

2.2 Learning About Meshes

A mesh consists of a list of vertices and a list of triangular facets (="triangles"). Vertices are basically 3D points (plus additional information for normals,texture and color) and the triangles are formed as 3-tuple of indices in the vertices list. Note that the triangle list is just called "indices" in the code which is a good example for non optimal naming. If you try to use the meshbuffer append method be aware that:

  • all facets have to be triangles (There is no absence of a feature here. It optimizes mesh performance)
  • the type must be compatible to "u16" (in my case that is "unsigned short")
  • the number of indices must be the number of triangles * 3

Its not incredibly important to learn about 3d meshes but if you want to do some extra research on the matter you can read all about it here http://en.wikipedia.org/wiki/Polygon_mesh

2.2.1 File formats

One of the advantages of using Irrlicht is that it supports file formats that almost any 3d software can produce. The following list is a summary of all the formats for static meshes that Irrlicht can open, and their advantages/disadvantages.

  • Irrlicht scenes (.irr, r/w)

Irrlicht has its own scene file format which can hold all sorts of data such as the positions of lights. This format can save you a whole ton of time. See irredit for a great modeling tool made for Irrlicht that saves with this format.

  • Irrlicht static meshes (.irrmesh, r/w)

Irrlicht's inbuilt static object file.

  • 3D Studio meshes (.3ds, r)

.3ds is the file format used by Autodesk's 3DS Max modeling and animation software. It was the native file format of the old 3DS Max but was replaced by the newer 3D Studio Max in 1996. Ever since, the format has become almost universal for exporting and importing among animation/modeling software. The format is binary based instead of human readable text which optimizes its performance for 3D games, however, there are a few minor restrictions on the format. The mesh can not contain more than 65,536 triangles and material names must be no longer than 16 characters. The format supports no quads but that is OK because Irrlicht doesn't support them anyways.

  • Alias Wavefront Maya (.obj, r/w)

Another extremely universal format that can be made in almost any 3D software. This format was created by Wavefront technology as an open format. It is a very simple format that holds mesh data and UV coordinates.

  • Lightwave Objects (.lwo, r)
  • COLLADA 1.4 (.xml, .dae, r/w)

Originally created by Sony Computer Entertainment, the COLLADA format has grown to support almost all attributes of a 3D model and has been used in dozens of video games and countless 3D animation/modeling programs. It has a very bright future with discussion about incorporating even more attributes of the 3D model such as physics attributes.

  • OGRE meshes (.mesh, r)

Ogre meshes are the native format for the Ogre graphic rendering engine (another open source project similar to Irrlicht). This format is open source and so it can be exported from many 3D programs simply go to their home page and grab the corresponding exporter for your software. The file itself is human readable and is therefore slightly less efficient than the .obj or .3ds. The format does support many features and is used by Ogre for animation so it is probably best used for Ogre and not static Irrlicht meshes.

  • My3DTools 3 (.my3D, r)
  • Pulsar LMTools (.lmts, r)
  • Quake 3 levels (.bsp, r)

The Quake format was originally built for the Doom engine and is nothing more than a huge zip file built for worlds and 3d environments. Basically it is a very fast format for making your scenes, it can store lights, textures, etc. The format uses a special algorithm that called binary space partitioning which minimizes the load time and draw time of 3D scenes. This special algorithm has only one main disadvantage; it will sometimes render open areas in a buggy way, however for buildings and room based worlds this is a great format.

  • DeleD (.dmf, r)

This is the Native file format for the deleD world builder/Modeler. The software itself either is open source or will be soon, anyway. It is free and looks like a great tool for Irrlicht, it even has a plug-in to export .X formats and a plug-in to preview your world in Irrlicht.

  • FSRad oct (.oct, r)
  • Cartography shop 4 (.csm, r)
  • STL 3D files (.stl, r/w)

The STL file format (native to the stereo-lithography CAD software) was originally designed only to hold CAD data and therefore has poor support for colors and textures.

  • PLY 3D files (.ply, r/w)

PLY is a computer file format known as the Polygon File Format or the Stanford Triangle Format. It was originally inspired to be like the .obj file format but a few new unique features such as the ability to assign different properties to the two different sides of the same polygon were introduced.

The following table supports information about Irrlicht animation file formats.

FormatBasic DescriptionSkeleton animationMorph Animation
B3D files (.b3d)Blitz 3D is a lightweight format built by the BlitzBasic companyYesNo
Microsoft DirectX (.x).X is Microsoft's 3D file format built for the Direct X SDK. The format is available in both binary form and human readable text formyesno
Milkshape (.ms3d)Milk shapes animation file formatyesno
Quake 2 models (.md2)The files are very small and therefore load very fast in your scene. The meshes are very light weight and efficientnoyes
Quake 3 models (.md3)basically just a newer md3noyes

2.3 Learning About Nodes

To quote Wikipedia "A node is an abstract basic unit used to build linked data structures such as trees, linked lists, and computer-based representations of graphs. Each node contains some data and possibly links to other nodes. Links between nodes are often implemented by pointers or references.

A node can be thought of as a logical placeholder for some data. It is a memory block which contains some data unit and perhaps references to other nodes, which in turn contain data and perhaps references to yet more nodes. By forming chains of interlinked nodes, very large and complex data structures can be formed. Nodes are conceptually similar to vertices, which are elements of a graph."

Basically A Node can be thought of as a "box" which is related to other nodes in some way that contains data. See the diagram below.

Lets get some terminology straight about nodes. Node number 1 is the master node it is the node that all other nodes are attached to. Nodes number 2 and 3 are referred to as children in relation to node 1. The node from which other node are attached to are called parents in relation to their children. Nodes on the same level with each other in the data (such as nodes 2 and 3 or nodes 4 and 5) are referred to as siblings.

In Irrlicht every thing you see on the screen is a node the camera, the characters, the world ect... so it very important to understand them.

Enough theory lets create a node

     smgr->addCubeSceneNode(); 

This Code creates a new CubeSceneNode and attaches it to the smgr node (which is short for scene manager which will be discussed in the Initializing section on this page)

The result of our new node

2.3.1 Setting Node Properties

The code: smgr->addCubeSceneNode(); is kind of worthless and boring because it attaches our node directly to our scene with no way of manipulating the node. What we need is to make a pointer to the node once it is created so we can assign properties to it. The following code

     smgr->addCubeSceneNode();

does the same thing as

     ISceneNode* Cube = smgr->addCubeSceneNode();

With on crucial difference, we can edit our new scene node with the pointer "Cube" that we created. Now we can add new properties to the node Cube.

     Cube->setPosition(vector3df(10,0,0));

We have now moved the Cube node over 10 Irrlicht units on the positive X axis.

All sorts of properties can be added to nodes to find them all you will have to look through the Irrlicht API. For now you will learn the 3 fundamental node manipulation properties.

Scaling a node

     MyNodeHere->setScale(vector3df(0,0,0));

Rotating a node

     MyNodeHere->setRotation(vector3df(0,0,0));

Translating a node

     MyNodeHere->setPosition(vector3df(0,0,0));

2.3.2 Accessing Node Properties

Through out your 3D programming there will come times were you must access different attributes about the nodes you have created. To give you an example lets find the position of a cube that we will create.

     ISceneNode* Cube = smgr->addCubeSceneNode(); // adds our cube scene node
     Cube->setPosition(vector3df(10,5,-3)); //place the Cube node over 10 Irrlicht units on the positive X axis 5 over on the positive Y and over 3 on the negative Z axis.

We have now created our Cube node and have positioned it. Now lets print the position of the node in the console window. First we need to create 3 variables to hold the different positions of the cube the following code will do the trick.

     //f32 is floating point value

     f32 PosX = Cube->getPosition().X;
     f32 PosY = Cube->getPosition().Y;
     f32 PosZ = Cube->getPosition().Z;

Now we have three variable that can easily be printed in the console window (or in a GUI system but we will get to that later) Like so. Note: we are using iostream which is found in the C++ STL.

     std::cout <<"\nThe X Position is:  "<<PosX <<std::endl;
     std::cout <<"The Y Position is:  "<<PosY <<std::endl;
     std::cout <<"The Z Position is:  \n"<<PosZ <<std::endl;

Of course we could extend this to hold the scale or rotation data with getRotation() or getScale(). If we wanted to we could also store the data in an array like so

     f32 CubePos[] = {Cube->getPosition().X,Cube->getPosition().Y,Cube->getPosition().Z};

But that is all up to you.

Now that you understand the basics of nodes you should definitely start looking through the API if you have not done so already.

2.4 Camera Basics

By now, you should have understood the basics of setting up scene nodes with Irrlicht. Now we move to adding camera's to the scenes. A camera is basically a viewport that allows the users to view the entire scene that is rendered on the screen. Like a real camera takes pictures of things in the real world, the Irrlicht cameras show(render on screen) the things in the virtual world.

In Irrlicht a camera is also another scene node, and hence a member of the ISceneNode class. Irrlicht (ver 1.4) has three inbuilt cameras that users can make use of:

  • A normal camera
  • An FPS camera
  • A Maya camera

These cameras are implemented as public functions of the ISceneManager class.

You might wonder why there are so many different cameras when each one of them does the same thing - render the scene on the screen, well because they behave differently to user input. Like each camera in real world has different buttons so does each camera in Irrlicht, e.g. the FPS camera changes what it is pointing at by moving the mouse but doesn't change it's position while the Maya camera keeps pointing at the same location when mouse is moved but rotates itself around the point it is looking at when mouse is moved.

2.4.1 Normal Camera

A normal camera is setup such that it looks at a particular location in the scene. The camera function is as given below: CODE:

	addCameraSceneNode (
		ISceneNode *parent=0,					  // Camera parent
		const core::vector3df &position=core::vector3df(0, 0, 0), // Look from
		const core::vector3df &lookat=core::vector3df(0, 0, 0),	  // Look to
		s32 id=-1);						  // Camera ID

The first variable specifies the parent of the camera, more on this later. The second variable is the location from where the camera looks onto the scene, specified by the third variable. The fourth variable provides an id for this camera. The simplest way to set up a camera is: CODE:

	addCameraSceneNode (0,0,5) //Sets the camera to look at 5 points, from the scene center.

2.4.2 FPS Camera

An FPS camera is controlled by the mouse and keys just like one finds in normal FPS games.

To add functionality to this camera, you may add an array of type SKeyMap as the last parameter when creating an FPS camera to create more functions for keys.

2.4.3 Maya Camera

A Maya camera is controlled by the mouse and moves the scene in the opposite direction to the movement of the mouse.

2.4.4 Third Person Camera

We are looking for an article about it, some algorithms etc not the code.

2.4.5 Field of view

Irrlicht comes with a few properties that can be passed on to the camera node such as the clipping distance of the camera and the field of view. So first lets create a camera and lets call it cam.

     ICameraSceneNode* cam = smgr->addCameraSceneNode(0, vector3df(0,0,0), vector3df(0,0,0));

Cameras in the real world all have lens values (20mm, 32mm ect...). Different lens sizes determine the cameras focal point. In Irrlicht we can do the same thing with our virtual camera. The following line of code demonstrates how to set the field of view to our camera.

     cam->setFOV(32);

The 32 is the new camera lens and the FOV stands for "field of view" play around with different values. You can dramatically alter your scene with this.

2.4.6 Clipping

The more things the camera has to render at once the slower your game/3D app will render. The Solution to this problem is to set a clipping distance from the camera so that things beyond the clipping distance will not render and thus will only take minimal resources during game play. So you should always try to set clipping as close to the camera as possible considering your applications quality. Lets use our cam node once more to show you how to do this.

     cam->setFarValue(800);

Sets clipping to 800 Irrlicht units. Simple enough? You can also set minimal clipping distances if you want with

     cam->setNearValue(10);

2.5 Initializing

2.6 The Game Loop

Quote from Wikipedia Game Programming: The key component of any game, from a programming standpoint, is the game loop. The game loop allows the game to run smoothly regardless of a user's input or lack thereof.

Most traditional software programs respond to user input and do nothing without it. For example, a word processor formats words and text as a user types. If the user doesn't type anything, the word processor does nothing. Some functions may take a long time to complete, but all are initiated by a user telling the program to do something.

Games, on the other hand, must continue to operate regardless of a user's input. The game loop allows this. A highly simplified game loop, in pseudocode, might look something like this:

	while( user doesn't exit )
		check for user input
		run AI
		move enemies
		resolve collisions
		draw graphics
		play sounds
	end while

The game loop may be refined and modified as game development progresses, but most games are based on this basic idea.

Adding to this, the game loop in Irrlicht is the repetition of a section of code which controls methods that must be constantly refreshed to keep the game or program updated. Take this example: Each frame of a game must be rendered yet if you do not tell the program to render the scene over and over again how is the program going to know to do this. The game loop generally is looped until a certain condition is met this is called a logical expression. Getting back to the example the loop does not only have to contain looped code about rendering, it is simply the point in which any code that needs to be constantly repeated should be found or a instance to that piece of code should be found there.

Take note that the scene manger (smgr) should be drawn before the Gui Environment otherwise the Scene Manager will flood over the Gui Environment and you will not be able to see anything from the Gui Environment.

CODE:

	// The Basic Irrlicht Loop can be defined as the following
	while (device->run())
	{
		driver->beginScene(true,true, SColor(255,255,255,255));
		smgr->drawAll();
		guienv->drawAll();

	// Other Code that must be repeated
		driver->endScene();
	}

2.7 SkyBoxes / SkyDomes

2.7.1 Skyboxes

Skyboxes allow the user to render textures onto a cube figure each side made of two triangles which in turn gives the appearance of a sky and so thus the name skybox. The easiest recognizable example of such a skybox can be seen in tutorial 9: Mesh Viewer, the code goes as follows:

CODE:

	using namespace irr;
	scene::ISceneNode* SkyBox = smgr->addSkyBoxSceneNode( // Declaration of the skybox note namespace irr::scene etc
	driver->getTexture("../../media/irrlicht2_up.bmp"), // Get Texture for the Up or Top Face of the Cube
	driver->getTexture("../../media/irrlicht2_dn.bmp"), // Get Texture for the Down or Bottom Face of the Cube
	driver->getTexture("../../media/irrlicht2_lf.bmp"), // Get Texture for the Left Face of the Cube
	driver->getTexture("../../media/irrlicht2_rt.bmp"), // Get Texture for the Right Face of the Cube
	driver->getTexture("../../media/irrlicht2_ft.bmp"), // Get Texture for the Front Face of the Cube
	driver->getTexture("../../media/irrlicht2_bk.bmp")); // Get Texture for the Back Face of the Cube

2.7.2 SkyDomes

Skydomes are an easier way to implement Sky or space scenes in your project. example:

CODE:

	// First, this is the path to the texture you want to use for your sphere
	smgr->addSkyDomeSceneNode(driver->getTexture("media/skydomeimage.jpg"),
		16,	// 16 rows from top to bottom
		16,	// rectangles each row
		1.0f,	// percent of the texture used, example 0.9f will only use the top 90% of the image file (range 0.0f-1.0f)
		1.0f);	// percent of the sphere to cover 1.0f covers the top half of the sphere, while 2.0f covers the entire sphere

and put all together:

	smgr->addSkyDomeSceneNode(driver->getTexture("media/skydomeimage.jpg"),16,16,1.0f,1.0f);

Try playing around with the values and increase and decrease the rows and rectangles each row to see the effect it has on your skydome,, also try to adjust the last value from 0.1f to 2.0f to see how the skydome covers which portion of the sky.

Here is an Example of a SkyDome sun light patterns, note skydome covers a entire dome shape made of triangular polygons.

2.8 Cursor

The cursor is a node just like all the other nodes so we can set/get properties to/from it as normal.So lets create the cursor.

     ICursorControl* MyCursor = device->getCursorControl();

So lets say we want to hide the cursor, the following code will do the trick.

     MyCursor->setVisible(false);

This is good but sometimes you might not only want the cursor but you might want to replace the standard cursor image with your own. Lets create something that can do that.

This Creates An image node (We will discuss this more in the GUI section) and places it at the top left corner of the screen.

     MyCursor->setVisible(false);       //hides our cursor    
     IGUIImage* MyImage = device->getGUIEnvironment()->addImage(driver->getTexture("../../media/irrlichtlogoalpha2.tga"),core::position2d<s32>(0,0)); // adds our image

Next we will make the code that up dates the image to follow the cursor. This must be placed in the game loop or it will only be read by the compiler once!

     int X = MyCursor->getPosition().X;
     int Y = MyCursor->getPosition().Y;
     MyImage->setRelativePosition(position2di(X,Y));

So now you should have the Irrlicht logo following your cursor around, of course you can hide the cursor and have only the image as your new cursor. You can get a more complete list of thing you can do with the cursor here in the API.

2.9 Creating your Second Program (Tutorial 2)

2.10 Chapter Conclusion

We have coverd a lot of theory in this chapter and hopefully you learned a few things, in fact By now you should be familiar enough with Irrlicht to look through the API and learn the rest on your own. Happy programming!

2.11 Exercises

By now you should be able to do the following:

  • Use the Irrlicht API
  • Explain what a node is, why is this so important in making 3D applications?
  • Explain why the game loop is so important
  • Make a Cube node move it around, familiarize your self with Irrlicht's 3D coordinates system.
  • Make a program that outputs all the transformation data of a node.
Irrlicht, IrrKlang and Irredit Page Footer