Histoire de complexifier un peu la chose, nous allons maintenant dessiner une pyramide à l'intérieur de cette boite. Et comme il n'existe évidement aucune fonction permettant de le faire simplement, il va falloir mettre les mains dans le cambouis (ô joie). Avant tout, un petit rappel (ou une découverte pour certains) sur la composition et la formation des meshs.
Vous le savez un mesh est un maillage, à savoir un assemblage de points (sommets, vertex en anglais) qui reliés d'une certaine manière forment des faces, qui forment elles mêmes au final une forme plus ou moins complexe. Pour faire simple, il faut deux choses pour créer un mesh :
- Une liste de points
- Une liste de valeurs expliquant comment les relier
Pour mieux comprendre ce qui va suivre, je vous ai fait un petit schéma maison (le losange ne sert qu'à saisir plus facilement la perspective du cube) :
Les sommets, qui sont représentés par des lettres, ont donc des coordonnées en 3D. Maintenant imaginons que nous ayons un tableau de 8 cases contenant chacune une coordonnée en 3D, qu'on peut donc assimiler à un sommet. On aimerait bien pouvoir construire le cube ci-dessus à partir de ces 8 sommets. C'est faisable bien sûr, à condition d'indiquer quel sommet fait parti de quelle face. La face du haut par exemple contient les points A,B,C et D. La face de droite les points C,D,E et F, etc...
Le driver, qui va se charger de dessiner tout ça
uniquement avec des triangles, a donc besoin d'une liste qui lui permette de comprendre dans quel ordre relier les points pour former les triangles. En fait, du point de vue de la syntaxe on se contente de lui passer une liste ininterrompue de valeurs correspondant aux sommets, qu'il va regrouper par paquets de 3 pour dessiner les triangles. Ce qui nous donne pour dessiner la face du haut :
Code : Autre
Et la liste complète pour le cube entier :
Code : Autre1
2
3
4
5
6
| A,B,C, C,D,A, // face du haut
E,F,G, G,H,E, // face du bas
C,D,E, E,F,C, // face de droite
B,A,H, H,G,B, // face de gauche
A,D,E, E,H,A, // face dernier plan
C,F,B, B,G,C // face premier plan |
Maintenant que nous avons compris ça, je pense qu'on peut attaquer le code. Pour commencer, il faut rajouter un attribut à notre classe :
Code : C++ | irr::video::S3DVertex m_vertices[5]; // contient les sommets du mesh
|
S3DVertex est une classe d'Irrlicht permettant comme son nom l'indique de stocker les coordonnées d'un sommet en 3D. On utilise donc un tableau contenant 5 sommets, 4 pour la base et 1 pour le sommet de la pyramide. Ensuite il faut modifier le constructeur pour ajouter l'initialisation de ces sommets :
Code : C++ | m_vertices[0] = irr::video::S3DVertex(-20,-20,-20,0,0,0, irr::video::SColor(255,0,255,255), 0, 0);
m_vertices[1] = irr::video::S3DVertex(-20,-20,20,0,0,0, irr::video::SColor(255,255,0,255), 0, 0);
m_vertices[2] = irr::video::S3DVertex(20,-20,20,0,0,0, irr::video::SColor(255,255,255,0), 0, 0);
m_vertices[3] = irr::video::S3DVertex(20,-20,-20,0,0,0, irr::video::SColor(255,0,0,255), 0, 0);
m_vertices[4] = irr::video::S3DVertex(0,20,0,0,0,0, irr::video::SColor(255,0,255,0), 0, 0);
|
Quelques explications sur les valeurs indiquées. Les 3 premières correspondent à la position du point respectivement sur les axes X, Y, et Z (Y représentant l'axe vertical par défaut dans Irrlicht). Les 3 suivantes permettent d'indiquer un vecteur normal au sommet. Si vous ne savez pas ce que c'est pas de panique, nous n'en avons pas besoin dans l'immédiat (d'ailleurs je les ai laissés à 0). Sachez simplement que c'est très utile pour l'éclairage par exemple. Les deux dernières valeurs (là aussi laissées à 0) servent à faire correspondre une texture avec le mesh. En gros ces deux valeurs indiquent un point sur une image 2D (texture) et qui correspond au sommet 3D.
Toujours dans le constructeur, il y a une autre ligne à ajouter :
Code : C++ | m_material.BackfaceCulling = false;
|
Cela va désactiver le backface culling, c'est à dire que toutes les faces seront visibles des deux cotés. Nous n'auront ainsi pas à nous soucier de l'ordre dans lequel les sommets d'une même face sont reliés. Et nous arrivons d'ailleurs au moment de créer la liste dont nous parlions plus haut. Dans la fonction
render :
Code : C++ | u16 indices[] = { 0,1,4, 1,2,4, 2,3,4, 3,0,4, 0,1,2, 0,2,3 };
|
Si vous reprenez les coordonnées 3D des sommets que nous avons déclarés plus haut, vous vous rendrez compte que les 4 premiers groupes de 3 correspondent aux cotés de la pyramide, et les 2 derniers aux deux triangles composant la base. Ensuite il ne reste plus qu'à ajouter cette ligne, toujours dans la fonction
render :
Code : C++ | driver->drawIndexedTriangleList(&m_vertices[0], 5, &indices[0], 6);
|
Le premier paramètre sert à indiquer le tableau contenant les sommets. Le deuxième indique sa taille, ou du moins le nombre de cases à prendre à compte. Le troisième indique la liste que nous venons de créer juste au dessus. Et enfin le dernier indique le nombre de paquets de 3 contenus dans la liste. Donc le nombre de faces que nous allons dessiner.
Vous savez ce qu'il reste à faire. Mélangez, compilez, et admirez le résultat sur le screen de droite si vous ne l'avez pas déjà sous les yeux.
