Landscape Navigator : un navigateur OpenGL dans un environnement 3D

Daniele Raffo
Projet de Synthèse d'Images, DEA IFA Université de Marne la Vallée
31 Janvier 2002



Introduction


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.

                      

Installation

Copiez dans votre répertoire tous les fichiers qui composent le logiciel :
landnav.c
makefile
landnav_tx_skyn.rgb
landnav_tx_moon.rgb
landnav_tx_sea.rgb
terrain1.ppm
terrain2.ppm
terrain3.ppm
Les fichiers landnav_tx_*.rgb sont les images de texture.
Les fichiers terrain*.ppm sont des exemples de plan de terrain.
Compilez enfin le programme avec la commande make.
 
 

Utilisation


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.
 
 

Détails techniques


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.
 
 

Conclusions


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.