Daniele Raffo
Projet de Synthèse d'Images, DEA IFA Université
de Marne la Vallée
31 Janvier 2002
Landscape Navigator est un logiciel, programmé en
C avec OpenGl, qui construit et permets d'explorer virtuellement en première
personne un modèle de terrain tridimensionnel décrit par
une image PPM: le niveau de couleur [0 - 255] de chaque pixel de l'image
correspond à l'altitude.
Dans la figure, un exemple d'un plan de terrain et deux capture d'écran
de l'environnement 3D correspondant crée par le programme.
Ce programme est sous les termes de la Licence Publique Génerale
(GPL) GNU.
landnav.cLes fichiers landnav_tx_*.rgb sont les images de texture.
makefile
landnav_tx_skyn.rgb
landnav_tx_moon.rgb
landnav_tx_sea.rgb
terrain1.ppm
terrain2.ppm
terrain3.ppm
Le programme doit être lancé avec la syntaxe suivante
:
landnav <terrain>en lui passant en paramétre l'image source du terrain, en format PPM P5 (en niveaux de gris) ou P6 (en couleurs).
Le terrain possède des différents couleurs selon l'altitude.
La caméra est d'abord placée au centre du terrain. On
peut se tourner, avancer et reculer au moyen des flèches de direction,
ou bien de la souris (bouger la souris en gardant le bouton gauche
enfoncé).
Il y a la possibilité de avancer la caméra automatiquement
à des vitesses différentes en appuyant sur les touches 1
... 9 ; la touche 0 arrête la caméra.
La caméra se déplace en suivant les aspérités
du terrain.
On active/désactive la modalité de vol libre en appuyant
sur J. Dans le vol libre, on peut se déplacer en vertical
au moyen des touches PageUp et PageDown. La caméra
évite automatiquement les aspérités, en s'élevant
au dessus de celle-ci quand nécessaire. (Si on désactive
la modalité de vol libre quand on est plus haut du terrain sous-jacent,
la caméra se baisse jusqu'au sol.)
La touche Majuscule + A permet de changer les couleurs du paysage du mode Normal au mode Antarctique et vice-versa.
On peut changer la taille de la fenêtre, pour s'adapter à
la vitesse de votre machine, avec les touches + et -. De
toute façon je suggère d'utiliser un ordinateur avec carte
accélératrice.
Appuyez sur la touche Esc pour sortir du programme.
L'image PPM source, de dimensions (dx, dy), est d'abord chargée
dans un tableau unidimensionnel nommé image. Ce tableau
est utilisé ensuite pour construire le terrain. La fonction imageval()
prends en paramètre les coordonnées (x,y) d'un pixel, trouve
sa position dans le tableau unidimensionnel et retourne son niveau de gris
[0-255], c'est à dire son altitude. Cette fonction effectue aussi
une transformation de coordonnées - j'avais remarqué, au
moment d'afficher le terrain, que les coordonnées x étaient
inversées par rapport à l'image source.
Le terrain est construit en utilisant des facettes triangulaires.
J'ai décidé d'utiliser de triangles car trois points sont
toujours coplanaires. Pour chaque groupe de 4 points de l'image source
du terrain, deux facettes sont construites: elles auront comme sommets
respectivement les points (i,j), (i+1,j), (i, j+1) et (i+1,j), (i, j+1),
(i+1,j+1). Les facettes qui ont leurs trois sommets tous à 0 ne
sont pas dessinées, pour ne pas couvrir la texture de la mer.
La couleur d'un point dépends de son altitude: j'ai prévu
sept différentes bandes de couleur, de la plage jusqu'au glacier
au sommet des montagnes.
Dés que je n'ai pas mis de lumières dans la scène,
pour éviter que le terrain apparaisse trop uniforme et pour détecter
les variations à l'intérieur d'une même bande d'altitude,
j'ai ajouté une valeur pseudoaléatoire au couleur de certaines
points (en fait, elle dépends de la chiffre moins significative
de l'altitude du point). Je me suis inspiré d'une idée des
mes collègues Jean Laurens et Sophie Creno.
OpenGL ne prévoyant pas à une méthode élémentaire
pour charger une texture d'après un fichier, j'ai fait usage
des méthodes écrits par Roman Podobedov et disponibles sur
l'Internet à l'adresse http://romka.demonews.com/opengl/demos/texture_eng.htm
,qui sont capables de traiter des fichiers en format RGB.
Les textures du ciel et de la mer utilisées dans mon programme
sont de domaine publique et ont été tirées de GRSites.
La texture de la lune est une photo NASA.
J'ai utilisé Gimp pour modifier légèrement et convertir
tous ces images. Les fichiers de texture utilisés par ces méthodes
doivent avoir une dimension qui est une puissance de 2 (64, 128, 256...)
et être sauvés au format RGB (SGI) sans compression.
La mer est un disque de rayon égal à 3 * max(dx, dy). Pour améliorer l'effet esthétique, la mer s'étend au delà du périmètre du terrain, tandis que un contrôle de coordonnées au moyen de la fonction force() assure que la camera ne puisse pas sortir de ce périmètre. Un disque donne mieux l'illusion de l'horizon, car ce dernier ne bouge pas quand on tourne la direction de vue; en outre, le mapping d'une texture carrée sur une surface circulaire engendre des déformations qui sont esthétiquement plus agréables et plus réalistes d'une texture symétrique.
Le ciel est construit avec quatre QUADS au lieu d'un QUAD_STRIP pour avoir un meilleur contrôle sur les coordonnées d'origine de la texture. J'avais pensé d'utiliser une sphère ou un cylindre pour le ciel, ce qui aurait donné l'effet d'un vraisemblable infini; mais le mapping d'une texture d'un ciel étoilé sur une surface quadrique, au contraire de ce qui s'est passé pour la mer, n'aurait pas donné un bon résultat. La texture choisie (des étoiles sur un ciel avec des nébuleuses bleues) ne rends pas trop visibles les arêtes du quadrilatère.
La lune est une sphère texturée qui se déplace
en accord avec la caméra. Elle est toujours à (dx * 1.95,
dy * 2.35) selon le repère de la caméra, et à une
hauteur fixe égale à 2.33 fois la hauteur maximale d'une
montagne. Ces valeurs choisis avec soin assurent que la lune soit toujours
au dehors du terrain mais à l'intérieur des quatre quadrilatères
du ciel.
Cette astuce donne l'impression que la lune soit à l'infini
car elle a toujours la même dimension apparente, en outre elle «paraît
suivre», comme dans la réalité, celui qui regarde.
Une image attachée au ciel, à cause de l'effet de parallaxe,
ne serait pas agréable.
Avec la touche Majuscule + X on désactive les contraintes de position, établies par la fonction force(), et on entre automatiquement dans la modalité vol libre. On peut donc bouger la caméra n'importe où. Cela est très utile pour le déboguage.
J'ai décidé de ne pas utiliser des effets de brouillard
car ils auront empêché de voir la lune et le ciel et auraient
rendu moins réaliste la scène.
Forcément, pour des raisons de temps et de difficultés
techniques, je n'ai pas pu réaliser toutes les idées que
j'avais pour ce programme. Je pensais à réaliser une lune
qui se léve, tourne autour du paysage et se couche, et une lumière
directionnelle à l'infini identifiée avec la direction du
satellite, pour donner l'effet d'un paysage éclairé par la
lune.
(Pour cette raison, j'ai choisi la lune et une texture avec le ciel
étoilé, au lieu du soleil et des nuages en arrière-plan;
ce qui aurait été astronomiquement bizarre....)
J'aurais aussi voulu permettre à l'utilisateur d'effectuer des
rotations de caméra autour des trois axes pour lui permettre de
regarder aussi en haut et en bas.
Celui-ci est mon premier projet en OpenGL; en tant que novice, j'ai
pu apprécier plusieurs cotés de cette bibliothèque
graphique. Même si loin d'être parfait, le programme que j'ai
réalisé m'a donné un premier aperçu sur le
développement d'applications OpenGl. En outre, le fait de
travailler seul à ce projet m'a permis d'explorer toutes les différentes
parties de la création d'un logiciel 3D.