[C++/OpenGL] Génération d'un terrain 3D à partir d'un bitmap
* Principe *
Notre petit programme ira lire une image au format BMP (bitmap) en noir&blanc 24bits (1 octet par pixel donc) et la représentera en 3D en se basant sur les nuances de gris pour faire les changements de hauteur.
On partira du fait que le blanc représente le sommet, et le noir le bas. Dans ce tutoriel, nous représenterons donc notre terrain, nous placerons de l 'eau et on va essayer de placer une petite texture pour faire un peu plus vrai... Allez, on va démarrer.
* Il nous faut quoi ? *
Nous aurons besoin donc d'une fonction permettant de lire un fichier BITMAP et d'en récupérer les informations sur les pixels qui composent l'image, il faut également une fonction pour traiter ces informations afin de les afficher correctement, le reste de l'OpenGL classique.
* Avant de commencer donc *
Nous allons lire un bitmap donc, mais il faut peut être se poser la question de comment ça marche ? Quelle est sa structure ? Quels outils nous avons pour nous faciliter la vie ?
Alors, il existe plusieurs solutions pour lire une image bmp et pour l'étudier, il existe notemment des API comme la SDL mais Windows nous donne également des structures toutes faites qui se remplissent toutes seules ... Alors pourquoi se géner ? De plus nous apprendrons à nous servir de structures pré-remplies, ce qui peut être utile pour la suite.
Structure d'un bitmap
On peut diviser notre image en 3 parties qui sont données dans les définitions de la MSDN :
- Entête de fichier (BITMAPFILEHEADER)
- Entête d'information (BITMAPINFOHEADER)
- Données (pixels)
BITMAPFILEHEADER contient essentiellement la taille en octet de nos données, essentiel pour les allocations et les parcours de l'image.
typedef struct tagBITMAPFILEHEADER { WORD bfType; // le type de fichier DWORD bfSize; // la taille en octect des données WORD bfReserved1; // 0 WORD bfReserved2; // 0 DWORD bfOffBits; // le premier octet des données } BITMAPFILEHEADER, *PBITMAPFILEHEADER;
BITMAPINFOHEADER contient toutes les informations sur l'image, son poids, sa taille, sa méthode de compression ...
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; // taille de la structure LONG biWidth; // largeur en px LONG biHeight; // hauteur en px (peut être négatif attention) WORD biPlanes; // 1 WORD biBitCount; // nombre de bits par pixel DWORD biCompression; // type de compression DWORD biSizeImage; // taille de l'image en octet LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
Les données sont représentées par un tableau de caractères (1 caractère = 1 octet) tout simplement. Par contre, il faut également savoir que l'ordre des couleurs est BVR au lieu de RVB .. Il faudra donc penser à inverser le R et le B avant de l'envoyer à OpenGL pour qu'il en fasse une texture au risque d 'avoir des drôles de couleurs !
Maintenant que nous avons tout ça, pour récupérer ses informations on se servira des fonctions basiques pour traiter les fichiers (fread).