Now, create a blank project in your favorite IDE and proceed…
Our first application will show you Irrlicht basic features we will use later. They are:
mesh handling - loading, rendering, animating, etc.
user input handling - reacting to keyboard and mouse events
*user interface (UI) - displaying some information within the application window
The good start for that is standard example from Irrlicht pack, the 04 - Movement one.
Let’s take a look over its code:
Paste the code from above to your blank project in your IDE, in the source/main.cpp file.
This may differ, but is not critical. Now, add the CMakeLists.txt file to your project
and fill it with these commands:
Note: for those of you, guys, running MacOS X I prepared a bit more complicated
CMakeLists.txt file - just to make our application run everywhere:
CMake file details
But what happens in all that code? First two lines of our CMakeLists.txt file define the project:
Then we modify the variable CMAKE_CXX_FLAGS, which will be used to set compiler flags.
This is how we add items to lists or modify string variables with CMake: we set it the new
value, consisting of the old one and the new elements / parts:
Then we tell CMake not to build Newton demo sandbox subproject and set a few path variables -
we will use them to point compiler to the header and library files of our third-party libraries
(like Newton itself, Irrlicht and others).
Remember: these are only plain variables, they have no effect on compiler themselves.
Next, we point CMake to our sub-projects, which are by the fact our third-party libraries:
These tell CMake to build sub-projects before building our application. Because our sub-projects
are nothing but libraries, we can then look for the built libraries, required by our project
in the sub-projects’ output directories like this:
Same way we look for system libraries:
These commands set compile-ready variables like X11_LIBRARIES.
Some sub-projects may set CMake variables too, providing us with paths to include files or
library files. If Irrlicht did not do this, we try to find its paths with CMake:
Note the environment variables CMake provides us with: UNIX, APPLE, WIN32, MSVC
and many others. They describe which operating system CMake was ran under and which
compiler it was told to use.
And the most important part of our CMakeLists.txt file:
This actually runs the compiler with the include directories, source files and
output file specified.
After that, we may run linker to link the intermediate object files, provided by
compiler, and end up with the application executable:
For OSX users there is a small hack, needed to build the application:
Note the order the commands are specified in: having include path variables definitions
placed before sub-projects commands may be no harmful, but more “effective” commands,
like compiling sub-projects (add_subdirectory) depend on other CMake commands, so
be sure to keep the order sane and clean.
Running the build
Now that you are ready, run the following commands from your project directory
(you will need cmake to be installed in your system):
Warning: do not forget to replace path_to_directory_where_you_unpacked_irrlicht with
the actual path to the directory, where your Irrlicht files lay!
This will build our first Irrlicht application. Not obvious how handy it is right now,
but you will see the power of CMake in our later sessions.
Before you run the application, copy the whole media directory from the Irrlicht
dir to the parent dir of your project. You should end up with directory structure like this:
Note: If you now just run the irrlicht_newton_game1 binary on OSX, you will see
your application does not react to keyboard events. This is tricky, but you need
to pack your application as OSX application. This is easy, though: just create
a directory tree mkdir -p irrlicht_newton_game1.app/Contents/MacOS/ and move
your binary file there:
Open Finder and run the application from there. On other operating systems run
the executable file in your build directory.
Buuuuut, since we have CMake, we may simplify this task because this is a part of
application build process. So we need to create a usual binary file, when we are
running Linux or Windows or create a directory structure with binary on its deepest
level, when running OSX. CMake allows to do it in a really easy way:
You should see something like this:
To end the process you may consider switching to a terminal and running
Decrypting the code
Here are some basics we could extract from application’ code:
Each 3D model is a scene node
Primitive scene nodes (such as cube or sphere) could be easily created with built-in functions:
Animated 3D models (such as character models) could be loaded from file:
Hint: if mesh is animated, animation could be started with:
Hint: animation could be stopped with setting its speed to zero:
Node could be described not only by its vertices and indices (forming a set of triangles which are drawn
in 3D forming a model, called mesh) but by its position, rotation and scale
Those could be set with:
Hint: rotation is a set of angles relatively to the corresponding axes, the node will be rotated
around. E. g., vector3df(45, 90, 0) sets the rotation by 45 deg around X axis, 90 deg around Y axis
and no rotation aroung Z axis. All those axes are relative to the node itself.
Graphics User Interface’ (GUI) widgets for information output are labels; they are created with
Hint: its text could be set with:
User input is handled by an external IEventReceiver class object.
defines the logic of handling events like mouse events, keyboard events, joystick events,
GUI events, etc.
The type of event is passed with the event.EventType field. The corresponding field is filled
with the event parameters.
Hint:EventReceiver object has nothing in common with our main game loop. So we should create
some interface, some architecture trick to link those two. Because they are strongly related!
Main game loop should contain rendering call, GUI rendering call and other game logic processing
The simplest main loop could look like this:
There is no simple (or at least, built-in) way to get the delta time between two rendered frames.
This is an important variable! We’ll need that later, when we inject physics engine. And Newton GD
is not the only engine requiring this variable!
But that could be easily done with this workaround:
That was some short introduction to the Irrlicht engine. And that’s basically everything we will use
for the next few sections.