I. Configuration du projet▲
Commençons comme l'exemple « Hello World » : nous incluons l'en-tête Irrlicht et un fichier supplémentaire pour être capable de demander à l'utilisateur un type de pilote via la console.
#include
<irrlicht.h>
#include
<iostream>
Comme déjà écrit dans l'exemple « Hello World », dans le moteur Irrlicht tout peut être trouvé dans le namespace « irr ». Pour avoir « irr:: » devant tous les noms de classes, nous disons au compilateur d'utiliser ce namespace dès maintenant et nous n'aurons plus à écrire « irr:: ». Il y a cinq autres sous-namespaces : « core », « scene », « video », « io » et « gui ». Contrairement à l'exemple « Hello World », nous n'utiliserons pas « using namespace » pour ces cinq namespaces, car ainsi, nous pourrons connaître l'emplacement de ces éléments. Mais si vous voulez, vous pouvez aussi inclure ces namespaces comme dans le précédent exemple.
using
namespace
irr;
Une fois encore, pour être capable d'utiliser le fichier Irrlicht.DLL nous devons le lier avec Irrlicht.lib. Nous pouvons mettre ces options dans la configuration du projet, mais pour le faire plus simplement, nous pouvons utiliser un « pragma comment lib » :
#ifdef _MSC_VER
#pragma comment(lib,
"Irrlicht.lib"
)
#endif
Bon, commençons. Une fois encore, nous utilisons la méthode main() et non WinMain().
int
main()
{
II. Choix du pilote vidéo▲
Comme dans l'exemple « Hello World », nous créons un IrrlichtDevice avec createDevice().
Mais maintenant nous demandons à l'utilisateur de choisir le pilote vidéo à utiliser. Le programme peut être lent à dessiner une grande carte Quake, mais juste pour tester nous rendons cette décision possible. Au lieu de copier tout ce code dans votre application, vous pouvez simplement inclure driverChoice.h du dossier « include » d'Irrlicht. La fonction driverChoiceConsole() fait exactement la même chose.
// demande à l'utilisateur un driver à utiliser
video::
E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:
\n
"
\
" (a) OpenGL 1.5
\n
(b) Direct3D 9.0c
\n
(c) Direct3D 8.1
\n
"
\
" (d) Burning's Software Renderer
\n
(e) Software Renderer
\n
"
\
" (f) NullDevice
\n
(otherKey) exit
\n\n
"
);
char
i;
std::
cin >>
i;
switch
(i)
{
case
'a'
: driverType =
video::
EDT_OPENGL; break
;
case
'b'
: driverType =
video::
EDT_DIRECT3D9;break
;
case
'c'
: driverType =
video::
EDT_DIRECT3D8;break
;
case
'd'
: driverType =
video::
EDT_BURNINGSVIDEO;break
;
case
'e'
: driverType =
video::
EDT_SOFTWARE; break
;
case
'f'
: driverType =
video::
EDT_NULL; break
;
default
:
return
1
;
}
// créé le système et sort si la création échoue.
IrrlichtDevice *
device =
createDevice(driverType, core::
dimension2d<
u32>
(640
, 480
));
if
(device ==
0
)
return
1
; // on ne peut pas créer le driver sélectionné.
Récupérons un pointeur sur le pilote vidéo, ainsi nous n'aurons pas à appeler à chaque fois irr::IrrlichtDevice::getVideoDriver() et irr::IrrlichtDevice::getSceneManager().
video::
IVideoDriver*
driver =
device->
getVideoDriver();
scene::
ISceneManager*
smgr =
device->
getSceneManager();
III. Chargement et affichage de la carte▲
Pour afficher la carte Quake 3, nous devons d'abord la charger. Les cartes Quake 3 sont stockées dans des fichiers .pk3 qui ne sont autres que des fichiers .zip. Nous ajoutons alors le fichier .pk3 à notre irr::io::IFileSystem. Après l'avoir ajouté, nous sommes capables de lire les fichiers de cette archive comme s'ils étaient directement stockés dans le disque.
device->
getFileSystem()->
addFileArchive("../../media/map-20kdm2.pk3"
);
Maintenant nous pouvons charger les meshs en appelant irr::scene::ISceneManager::getMesh(). Nous obtenons un pointeur sur un irr::scene::IAnimatedMesh. Comme vous pouvez le savoir, les cartes Quake 3 ne sont pas réellement animées, elles possèdent seulement une très grande partie de géométrie statique avec quelques matériels attachés. L'IAnimatedMesh est donc constitué d'une seule image, nous obtenons donc la « première image » de « l'animation » qui est notre carte Quake et créons un nœud de l'octree(2) pour la scène en utilisant irr::scene::ISceneManager::addOctreeSceneNode(). L'octree optimise un peu la scène en essayant de dessiner seulement la géométrie visible. Une alternative à l'octree pourrait être un irr::scene::IMeshSceneNode qui dessinera toujours entièrement la géométrie du mesh sans optimisation. Essayons-le, utilisez irr::scene::ISceneManager::addMeshSceneNode() à la place d'addOctreeSceneNode() et comparez-les primitives(3) dessinées par le pilote vidéo. (Il y a une méthode irr::video::IVideoDriver::getPrimitiveCountDrawn() dans la classe irr::video::IVideoDriver). Notez que cette optimisation avec l'octree est utile seulement quand on dessine des grands meshs constitués de nombreuse géométrie.
scene::
IAnimatedMesh*
mesh =
smgr->
getMesh("20kdm2.bsp"
);
scene::
ISceneNode*
node =
0
;
if
(mesh)
node =
smgr->
addOctreeSceneNode(mesh->
getMesh(0
), 0
, -
1
, 1024
);
// node = smgr->addMeshSceneNode(mesh->getMesh(0));
Parce que la carte n'était pas modélisée à l'origine (0,0,0) nous la déplaçons légèrement. Ceci est fait au niveau de irr::scene::ISceneNode en utilisant les méthodes irr::scene::ISceneNode::setPosition() (dans notre cas), irr::scene::ISceneNode::setRotation(), et irr::scene::ISceneNode::setScale().
if
(node)
node->
setPosition(core::
vector3df(-
1300
,-
144
,-
1249
));
IV. Création de la caméra▲
Maintenant, nous avons juste besoin d'une caméra pour regarder la carte Quake 3. Nous voulons créer une caméra contrôlée par l'utilisateur. Il y a plusieurs caméras disponibles dans le moteur Irrlicht. Par exemple, la « MayaCamera » peut être contrôlée comme une caméra Maya : rotation en pressant le bouton droit de la souris, zoom avec deux boutons pressés, translation en pressant le bouton gauche. Ceci peut être créé avec irr::scene::ISceneManager::addCameraSceneNodeMaya(). Mais pour cet exemple, nous voulons créer une caméra qui se comporte comme celles des jeux de tir à la première personne (FPS(4)), nous utiliserons donc irr::scene::ISceneManager::addCameraSceneNodeFPS().
smgr->
addCameraSceneNodeFPS();
Nous n'avons pas besoin de voir le curseur de la souris, donc nous le cachons via irr::IrrlichtDevice::ICursorControl.
device->
getCursorControl()->
setVisible(false
);
Nous avons tout fini, maintenant dessinons-le. Nous écrivons aussi le nombre d'images par seconde ainsi que les primitives dessinées dans le titre de la fenêtre. Le test avec irr::IrrlichtDevice::isWindowActive() est optionnel, mais évite le moteur d'attraper le curseur de la souris après un changement de tâche lorsque d'autres programmes sont actifs. L'appel de irr::IrrlichtDevice::yield() va éviter la boucle principale de prendre tous les cycles CPU quand la fenêtre n'est pas active.
int
lastFPS =
-
1
;
while
(device->
run())
{
if
(device->
isWindowActive())
{
driver->
beginScene(true
, true
, video::
SColor(255
,200
,200
,200
));
smgr->
drawAll();
driver->
endScene();
int
fps =
driver->
getFPS();
if
(lastFPS !=
fps)
{
core::
stringw str =
L"Irrlicht Engine - Quake 3 Map example ["
;
str +=
driver->
getName();
str +=
"] FPS:"
;
str +=
fps;
device->
setWindowCaption(str.c_str());
lastFPS =
fps;
}
}
else
device->
yield();
}
À la fin, détruisons le système Irrlicht.
device->
drop();
return
0
;
}
Voilà, compilons et expérimentons le programme.
V. Conclusion▲
Vous pouvez désormais charger une carte Quake 3 en utilisant Irrlicht.
Dans le prochain tutoriel « Nœud de scène personnalisé », nous verrons comment créer un nœud de scène personnalisé et comment l'utiliser.
VI. Remerciements▲
Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.
Merci à LittleWhite pour sa relecture technique ainsi qu'à zoom61 pour sa relecture orthographique.