Génération de terrain (1/2)
Par Xavier Michelon


 
   
Principe des heightfields

Le principe de champs de hauteur que nous allons mettre en place est relativement simple à comprendre. Dans un premier temps, nous allons générer un maillage carré dans le plan XY. Le maillage est illustré sur la figure 2. Ce n’est en fait ni plus ni moins qu’un ensemble de polygones carrés (on utilisera le terme de patch pour distinguer les petits carrés du maillage complet) collés les uns aux autres. L’opération se réalise très facilement avec deux boucles imbriquées. Une fois le maillage créé, il n’y a plus qu’à affecter aux sommets de chaque patch une coordonnée en Z. En fonction de la position du sommet considéré dans le maillage, on établit une correspondance avec un pixel de l’image en niveaux de gris. Si le pixel correspondant est noir, l’élévation du sommet sera minimale, alors que s’il est blanc, la hauteur sera maximale. Comme vous le voyez, ce n’est pas très compliqué.

Figure 2 : le maillage vu de dessus

 

Des polygones qui dégénèrent

En utilisant le principe que je viens d’énoncer, nous allons être confrontés à un léger problème : nous allons créer des polygones dégénérés. OpenGL définit strictement les propriétés que doit respecter un polygone pour obtenir un rendu correct. Les polygones doivent entre autres être convexes (i.e. toute ligne joignant deux points quelconques du polygone doit être entièrement comprise dans le polygone), non auto-intersectants et tous les points doivent être dans un même plan. Or cette dernière condition n’est pas vérifiée lorsque l’on génère le terrain  puisque les valeurs d’élévation des sommets sont issues d’une image, et il y a finalement peu de chance pour que les 4 sommets de chaque patch soient dans un même plan. Dans le cas d’affichage en mode fil de fer, la dégénérescence des polygones ne pose pas de problème. En revanche, si on éclaire la scène, le rendu des faces en mode plein sera faux. Autant prendre les devants et afficher quelque chose de correct en mode fil de fer.

Figure 3 : le maillage avec les arêtes transversales

 

La solution au problème de dégénérescence est relativement simple : il suffit de décomposer chacun de nos patches en deux triangles. Notre maillage global ressemble donc à la figure 3. Reconnaissez que l’arête transversale est relativement disgracieuse. Nous allons nous en débarrasser en utilisant la fonction glEdgeFlag() d’OpenGL. Le drapeau d’arête (Edge Flag) est une bascule OpenGL qui permet de n’afficher que certaines arêtes d’un polygone. Le prototype de glEdgeFlag est le suivant :

void glEdgeFlag(Glboolean valeur);

‘valeur’ peut valoir TRUE ou FALSE. Les arêtes dont le premier sommet est défini lorsque le drapeau est sur TRUE seront affichées. En revanche si le drapeau est sur FALSE, l’arête n’est pas affichée. Bien sur tout ceci n’a d’intérêt que lors d’un affichage en mode fil de fer. L’exemple ci dessous montre comment dessiner un patch carré en utilisant deux patches triangulaires et la fonction glEdgeFlag() :

/* Dessin du triangle 1 */
glBegin(GL_POLYGON);
  glEdgeFlag(TRUE);
  glVertex3fv(P1);
  glVertex3fv(P2);
  glEdgeFlag(FALSE);
  glVertex3fv(P3);
glEnd();
 
/*Dessin du triangle 2 */
glBegin(GL_POLYGON);
  glVertex3fv(P1);
  glEdgeFlag(TRUE);
  glVertex3fv(P3);
  glVertex3fv(P4);
glEnd();