Tutoriel Irrlicht 2

Carte Quake 3

| Nikolaus Gebhart | Laurent Alexandre |

Traducteur

Neckara

Ce tutoriel est une traduction de l'anglais des tutoriels officiels d'Irrlicht.

Il explique comment charger une carte Quake 3, créer un SceneNode(1) pour optimiser la vitesse de rendu et comment créer une caméra contrôlée par l'utilisateur.

Avant de lire ce tutoriel, vous devriez lire le premier tutoriel « Hello World » si vous ne l'avez pas encore fait.

Commentez

- Titre : Tutoriel Irrlicht 2

- Auteurs : Nikolaus Gebhart, Laurent Alexandre

- Traducteur : Neckara

- Parution : 3 avril 2013

- Mise à jour : 3 avril 2013

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2012 Neckara. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Configuration du projet

- II. Choix du pilote vidéo

- III. Chargement et affichage de la carte

- IV. Création de la caméra

- V. Conclusion

- VI. Remerciements

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.

(1)« Nœud » de scène.

(2)Un octree est un arbre où chaque nœud peut avoir huit enfants. C'est une structure couramment utilisée pour le partitionnement d'un espace 3D en sous ensemble.

(3)Formes géométriques basique constituant des géométries plus complexes.

(4)First person shooter.