III.1.4.2 La fonction d'affichage : [26]
glutDisplayFunc(void (*func)(void))
|
spécifie la fonction à appeler pour l'affichage
|
glutPostRedisplay(void)
|
permet de forcer le réaffichage de la fenêtre.
|
Les couleurs : Les couleurs sont
définies en OpenGL de deux manières :
Couleurs indexées :
256 couleurs sont choisies, et on se
réfère au numéro de la couleur (son index). C'est un mode
qui était intéressant lorsque les écrans d'ordinateurs
ne savaient afficher que 256 couleurs simultanées.
Couleurs RVBA :
Une couleur est définie par son intensité sur 3
composantes Rouge, Vert, Bleu. La quatrième composante est
appelée canal Alpha, et code l'opacité.
La couleur d'un objet est spécifiée par l'appel
de glColor (...).
III.1.4.3 Les primitives
géométriques :
Déclaration :
glBegin(GLenum mode) : ouvre la
déclaration des sommets de la primitive
glEnd(void) : termine cette
déclaration
Il y a dix types de primitives différents, qui
correspondent à des points, des lignes, des triangles, des
quadrilatères, et des polygones convexes.
GL_POINTS
|
GL_LINES
|
GL_LINE_STRIP
|
GL_LINE_LOOP
|
GL_TRIANGLE
|
|
|
|
|
|
GL_TRIANGLE_STRIP
|
GL_TRIANGLE_FAN
|
GL_QUADS
|
GL_QUAD_STRIP
|
GL_POLYGON
|
|
|
|
|
|
a. Le vecteur normal en un point :
C'est grâce au vecteur normal que l'on peut
spécifier l'orientation de la surface dans l'espace, et en particulier
l'orientation par rapport aux sources de lumière. L'appel à
glNormal*() donne une valeur à la normale courante.
Elle sera associée aux points spécifiés par les appels
suivants à glVertex*().
b. Le modèle d'ombrage :
Chaque facette d'un objet peut être affichée d'une
unique couleur (ombrage plat) ou à l'aide de plusieurs couleurs (ombrage
lissé). OpenGL implémente une technique de lissage appelée
Ombrage de Gouraud. ce choix s'effectue avec glShadeModel(GLenum
mode).
c. Elimination des surfaces
cachées :
OpenGL utilise la technique du Z buffer (ou buffer de
profondeur) pour éviter l'affichage des surfaces cachées.
On ne voit d'un objet que les parties qui sont devant et pas
celles qui se trouvent derrière. Pour chaque élément de la
scène la contribution qu'il aurait à l'image s'il était
visible est calculée, et est stockée dans le Z buffer avec la
distance de cet élément à la caméra (c'est cette
distance qui est la profondeur). Chaque pixel de l'image garde donc la couleur
de l'élément qui est le plus proche de la caméra. Dans le
cas plus complexe d'un objet transparent, il y a une combinaison des couleurs
de plusieurs éléments.
d. Fonctions utilisées
glutInitDisplayMode(GLUT_DEPTH | ... )
glEnable(GL_DEPTH_TEST)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) Avant
l'affichage d'une scène.
III.1.5 principe de génération d'un MNT
par OpenGL :
On peut résumer la méthodologie suivie par les
différentes étapes suivantes :
1. On charge une image de format BMP , TIFF, JPEG,..
2. Supposant que le pixel qui a une grande
intensité ,est le point le plus haut dans la scène, donc on
peut calculer les changements d'hauteur de chaque pixel en fonction de son
intensité,
3. et enfin, on définit le type de préemptives,
`TRIANGLES `'
III.1.5.1 lecture d'une image
Bitmap :
Pour lire une image BMP, il faut l'ouvrir en lecture binaire,
puis tout simplement récupérer les structures de données.
Puis ; on stocke nos valeurs dans un tableau de pixel de dimensions
précisées plus haut dans les configurations. Ce tableau sera un
tableau d'entiers appelé "map" d'une taille de 80x80
(ce qui fait déjà 6400 points à placer, sachant qu'un
point est lui même composé d'un rectangle composé de 2
triangles ...) et les images qui contiennent l'information de la hauteur ont
des tailles différentes donc il faut tout remettre en
échelle.
Algorithme :
pour j=1 jusqu'àl `hauteur de l'image
pour j=1 jusqu'àl `hauteur de l'image
id=80/h ;
jd=80/w ;
tab[id][jd]=extraction d'hateur d'image;
fin
fin
Avec di et dj, deux variables flottantes pour avoir une mise
à l'échelle.
III.1.5.2 Réalisation du mode filaire du
terrain
Dans un premier temps, il y aura une génération
d'un maillage carré dans le plan XY qui est qu'un ensemble de polygones
carrés composés de deux triangles collés les uns aux
autres pour éviter d'avoir des soucis au niveau de l'affichage de
certaines formes (En cas d'utilisation d'un rectangle simple). De plus ils
permettent une meilleure précision mais évidemment cela à
un coût : 2 sommets supplémentaires ...
Voici la différence de rendu filaire :
On remarque une différence assez flagrante au niveau de la
précision.
L'opération se réalise très facilement
avec deux boucles imbriquées. Une fois le maillage est
créé, il n'y a plus qu'affecter aux sommets de chaque polygone
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.
§ Déclaration des
variables :
int i,j;
double ajout = CONFIG_taille_carre /
CONFIG_max_points,posi,posj;
§ La construction des triangles :
glColor3f(1.0f,0.0f,0.0f); // rouge
for(i=0,posi=0;i<CONFIG_max_points-1;i++, posi += ajout) {
glBegin(GL_TRIANGLES);
for(j=0,
posj=0;j<CONFIG_max_points-1;j++, posj += ajout){
glVertex3d(posi,posj,map[i][j]);
glVertex3d(posi,posj+ajout,map[i][j+1]);
glVertex3d(posi+ajout,posj+ajout,map[i+1][j+1]);
glVertex3d(posi,posj,map[i][j]);
glVertex3d(posi+ajout,posj+ajout,map[i+1][j+1]);
glVertex3d(posi+ajout,posj,map[i+1][j]);
}
glEnd();
}
a. Coloration des traits
On définit la couleur des traits, avec la fonction
glColor3f (R, G, B). On entre alors dans une double boucle dans
laquelle i et j sont incrémentés par un pour parcourir le tableau
des hauteurs. Voir figure (III.12)
b. Ajout des textures
Une texture est une image qui est appliquée à
des vertex puis peinte.
On peut appliquer plusieurs formats d'images (tga, bmp) mais
pour plus de facilité, nous allons utiliser des images de type bitmap
étant pour sa simplicité.
Une fois on a la matrice des pixels, la largeur et la hauteur
de l'image, on doit lui fournir un pointeur vers un entier pour lui assigner
une texture afin de l'appliquer.
On prend donc un tableau de textures qu'on le déclare
comme suit :
GLuint
texture [2];
Notre première texture sera donc texture [0] puis texture
[1] ...
§ Application des textures
Chargement de l'image de texture
if (CONFIG_filaire) {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_TEXTURE_2D);
}
else {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_TEXTURE_2D);
}
Par exemple si on prend deux types de textures (terrain et
eau), on donne donc le numéro "0" au terrain, et le numéro "1"
à l'eau. Ensuite, on teste si nous sommes en mode texturé ou pas,
si c'est le cas on active la texture, et on précise le mode d'affichage
des polygones (filaire ou linéaire).
Maintenant attaquons nous au placement de la texture. Une
texture se place selon 2 points (U et V) que l'on associe à un vertex.
Ce chiffre définit en fait la position à laquelle nous nous
plaçons sur la texture, si ce chiffre est supérieur à
1.00, la texture est alors répétée ou plus affichée
(ce qui dépend du mode texturé appliqué, par défaut
elle est répétée). De plus, les axes sont inversés,
c'est à dire que le U correspond au Y et le V au X. Pour notre terrain,
on ne veut évidemment pas la répéter,
on va donc choisir une valeur comprise entre 0 et 1.
glBegin(GL_TRIANGLES);
for(i=0,posi=-20 ;i<MAX_POINTS-1;i++, posi += ajout)
{
for(j=0, posj=-20;j<MAX_POINTS-1;j++, posj += ajout)
{
glVertex3d(posi,posj,(int)map[i][j]*20/256);
glVertex3d(posi,posj+ajout,(int)map[i][j+1]*20/256);
glVertex3d(posi+ajout,posj+ajout,(int)map[i+1][j+1]*20/256);
glVertex3d(posi,posj,(int)map[i][j]*20/256);
glVertex3d(posi+ajout,posj+ajout,(int)map[i+1][j+1]*20/256);
glVertex3d(posi+ajout,posj,(int)map[i+1][j]*20/256);
}
}
glEnd();
|