Maintenant que nous avons vu ce que sont et à quoi servent les textures, reste à voir comment les appliquer. Mais commençons d'abord par mettre quelques petites choses au point.
Si vous avez déjà fait des applications 3D utilisant OpenGL, vous êtes sûrement passés (à un moment ou un autre) par le mode de déclaration directe des sommets. Celui-ci permet de déclarer plusieurs sommets d'affilée qui définissent au final des primitives de base (triangles, carrés, etc...). Par exemple :
Code : C++1
2
3
4
5
6 | glBegin(GL_QUADS);
glVertex2d(-0.75,-0.75);
glVertex2d(-0.75,0.75);
glVertex2d(0.75,0.75);
glVertex2d(0.75,-0.75);
glEnd();
|
L'un des avantages de ce mode est qu'il permet de déclarer les coordonnées de texture en même temps. On associe une coordonnée de texture à chaque sommet déclaré, et au final tout se retrouve là où il faut lors du rendu. Et bien grande nouvelle :
vous pouvez oublier tout ça ! En effet vous ne trouverez pas ce mode de déclaration des sommets sous Irrlicht.
Mais pourquoi donc ? Encore un complot pour rendre l'informatique inaccessible et mystérieuse ?
Que nenni. Il y a en fait deux bonnes raisons à ce qu'Irrlicht n'intègre pas cette fonctionnalité :
- Elle n'est proposée que par OpenGL, et pas par Direct3D. Etant donné qu'Irrlicht interface indifféremment les deux API, ç'aurait été un véritable casse-tête à implémenter.
- Ce mode est un des (voir le) plus lents qui puissent exister en termes de performances.
Nous (re)verrons dans un prochain chapitre en quoi consistent les autres modes de déclaration des sommets (et comment ils sont implémentés sous Irrlicht), mais si vous êtes vraiment pressés, vous pouvez toujours vous faire les dents sur ces deux tutoriels :
Reste une question en suspens :
Comment fait-on alors pour déclarer les sommets et les coordonnées de texture qui vont avec ?
Et bien malheureusement (ou pas) nous n'allons pas voir comment le faire manuellement pour le moment. Parce que ça implique de connaître beaucoup de choses (qui peuvent se résumer à "savoir comment créer un scene node personnalisé"). Nous y reviendrons lors d'un prochain chapitre, mais en attendant... il va falloir vous en passer. Il existe néanmoins d'autres moyens d'appliquer des textures, le seul "souci" est qu'il faut passer par un modèle 3D.
Coordonnées de texture
La plupart (une grande majorité à vrai dire) des formats de fichiers 3D fonctionne sur le principe des coordonnées de texture. L'idée est la suivante : le modèle 3D en lui même est contenu dans un fichier (MD2, OBJ, etc...), et la texture qui le recouvre dans un autre (BMP, PNG, etc...). A chaque sommet du modèle sont associées 2 valeurs représentant des coordonnées en 2 dimensions. Ces coordonnées désignent un point sur la surface de la texture. L'aire délimitée sur la surface de la texture par tous les sommets d'une face du modèle représente exactement le morceau de la texture qui sera appliqué sur cette face.
Si vous jetez un oeil au modèle Sydney qu'on utilise depuis le début de ce tutoriel, vous vous apercevrez que c'est ce système qui est utilisé. Le modèle 3D en lui même est contenu dans un fichier MD2, et la texture qui le recouvre dans un banal fichier BMP. Basiquement, le code permettant d'assigner une texture à un mesh est le suivant :
Code : C++1 | sceneNode->setMaterialTexture( 0, driver->getTexture("le_nom_de_la_texture") );
|
Le 0 du premier paramètre indique le niveau de cette texture.
En effet, il est possible d'appliquer plusieurs niveaux de textures sur un mesh.
Tout en un
Il existe des formats de fichiers 3D qui contiennent le modèle
et les textures. Là c'est que du bonheur, vous n'avez plus qu'à vous mettre les doigts de pieds en éventail et laisser Irrlicht faire le boulot.

Lorsque vous chargez le fichier dans votre scène, le modèle et les textures sont chargées en même temps.
Le format .bsp utilisé pour les maps de Quake 3 est de ceux-là. Et d'ailleurs si vous avez fait attention, vous aurez remarqué que c'est également le format de la map qu'on a chargée lors du chapitre sur les événements. On ne le voit pas au premier coup d'oeil puisque le fichier est à la base au format .pk3 qui n'est rien de plus qu'un fichier .bsp compressé.
Plaquage répétitif
La dernière solution, qui fait un peu "roue de secours", est de plaquer répétitivement une texture sur le modèle. Pour ce faire il faut passer par le manipulateur de mesh. Il s'agit d'une classe qui, comme son nom l'indique, va nous permettre de... manipuler des meshs. La méthode à appeler est celle-ci :
makePlanarTextureMapping (IMesh *mesh, f32 resolution)
Le premier paramètre est un pointeur vers le mesh à texturer, et le deuxième permet de définir le nombre de répétitions de la texture. Si vous avez bonne mémoire, vous devez vous souvenir qu'on a déjà rencontré cette fonction. Dans le chapitre sur l'éclairage, au moment de texturer la pièce. Je vous remets le code intéressant :
Code : C++1
2
3
4
5
6
7
8
9 | // La salle
scene::IAnimatedMesh *room = scenegraph->getMesh("room.3ds");
scene::IMeshSceneNode *Nroom = scenegraph->addMeshSceneNode(room->getMesh(0));
//On desactive la sensibilite a la lumiere
Nroom->setMaterialFlag(video::EMF_LIGHTING, true);
//On definit le nombre de repetition de la texture
scenegraph->getMeshManipulator()->makePlanarTextureMapping(room->getMesh(0), 0.04f);
//On choisit la texture
Nroom->setMaterialTexture( 0, driver->getTexture("rockwall.bmp") );
|
A dire vrai, la seule difficulté consiste à savoir quelle valeur passer au deuxième paramètre. Vous pouvez toujours tâtonner pour trouver la valeur qui vous plaît le plus. Plus ce chiffre est élevé, et plus la texture sera répétée. Par exemple, sur les images ci-dessous, les valeurs sont (de gauche à droite) 0.0004, 0.004, 0.04 :


La "formule" permettant de calculer le nombre de répétitions est la suivante :
longueur de la plus grande face de la bounding box du mesh * le nombre passé au deuxième paramètre = nombre de répétitions de la texture
Si vous ne savez pas ce qu'est une bounding box, pas de panique. On le verra dans un prochain chapitre. En attendant, imaginez-vous que c'est un grand rectangle qui englobe votre mesh. Donc, prenez en gros la longueur de votre mesh pour faire le calcul.
