Classe GLWindows pour X Windows
Un classe pour gérer OpenGL dans une fenêtre X Window
Je pense que si vous êtes ici, il y a du code que vous connaissez maintenant très bien. Il s'agit de celui qui permet d'intialiser OpenGL dans une fenêtre GLUT. Et vous devez sans doute en avoir marre de devoir tout le temps le refaire...
C'est pour cette raison que nous allons regrouper dans une classe (que je nommerai GLWindows) la création d'une fenêtre et l'initialisation d'OpenGL, la gestion des évènements GLUT, ainsi que la gestion d'une caméra suivant vos déplacements. Pas de panique, voici les explications...
Il s'agit d'une classe, il y aura donc un constructeur et un destructeur.
Initialiser votre projet pour GLUT
Par défaut, cette classe fonctionne soit avec les méthodes de développement en C sous Windows soit sous X Window. Développer sous GLUT doit donc être précisé. Pour cela, il y a un fichier nommé defaut.h à paramétrer:
Dans ce fichier,il faut retirer le commentaire de la ligne #define USEGLUT 1
Si vous laissez cette variable prépo. avec la valeur 1, alors le projet cherchera à inclure <gl\glut.h>
Si l'include n'est pas dans ce répertoire, vous pouvez positionner USEGLUT à 2 et indiquer le répertoire de GLUT dans la variable prépo. INCLUDEUSEGLUT avec par exemple "glut.h"
Constructeur/destructeur
Le constructeur va initialiser des variables et initialiser GLUT. Comme GLUT a besoin d'arguments qui sont en principe passés lors du lancement d'un programme (En fait, je vois que je n'ai jamais réellement expliqué cela sur mon site, ou alors en partie dans la gestion des processus sous Unix et l'initialisation de GLUT), nous allons construire un tableau d'argument qui sera vide. La classe ne traitant pas d'arguments en ligne de commandes.
Le constructeur va aussi lancer (éventuellement si pas encore lancé) un singleton gérant une liste nommé GLListe. Cette liste sera composée d'un identifiant de fenêtre GLUT et d'une instance GLWindow.
Pourquoi ?
Parce que GLUT n'est pas prévu pour être lancé en C++, mais en C. Par conséquent, toutes les procédures de GLUT (Gestion de la souris, clavier, affichage, ...) doivent être déclarées en static dans notre classe. Ce qui signifie aussi qu'une procédure GLUT ne peut pas connaître l'instance GLWindow à laquelle elle est associée. Seule chose qui peut permettre de retrouver qui va avec qui est une liste de données croisées qui stockera l'identifiant de la fenêtre GLUT et l'instance correspondantes. En recherchant dans la liste l'identifiant de la fenêtre, nous retrouverons l'identifiant de notre instance GLWindows. Voilà pour le principe.
Le destructeur se limitera à retirer la ligne référençant notre fenêtre GLUT à notre instance GLWindows de notre liste GLListe.
Initialisation fenêtre et OpenGL
Notre classe aura besoin de créer une instance de fenêtre GLUT. Pas spécialement besoin de faire plus entre OpenGL et la fenêtre GLUT, puisque c'est automatiquement fait. Cette fenêtre pourra occuper la totalité de l'écran (fullscreen) ou non. Mais impossible de préciser la résolution, GLUT ne le permettant pas à la base.
openWindowGLW(char* title, int x, int y, int width, int height, int bits, bool fullscreenflag) dans glWindows.cpp
Cette méthode attend en entrée:
char *title qui est le titre de la windows
int x,y qui sont les coordonnées de la fenêtre sachant que ce paramètre ne sert à rien si le mode fullscreen est positionné et qu'en mode fenêtré, le window manager fera bien ce qu'il lui plait !
Les valeurs pouvant être 0, pour indiquer à X Window qu'il peut positionner la fenêtre où il veut. -1 ou CW_DEFAULT marcherons aussi pour rester compatible avec Windows
int width et height qui sont respectivement la largeur et la hauteur de la zone cliente. J'ai bien dit client et nom de la fenêtre, donc sans les bordures, ... La fenêtre occupera donc une taille plus importante.
int bits : Nombre de bits à utiliser pour la couleur.
fullscreenflag : Vrai pour essayer de passer en mode plein écran, à faux pour le mode fenêtré.
En sortie:
vrai si tout est ok, sinon problème lors de la création et toutes les ressources initialisées durant ce traitement seront refermées.
Cette méthode met en oeuvre pas mal de choses, et déclenchera donc à son tour d'autres méthodes
Voici les explications un peu plus détaillées:
La méthode createWinExGLW(char* title, int x, int y, int width, int height, int bits, bool fullscreenflag), qui reprendra les mêmes paramètres. C'est ici que la fenêtre sera créée et paramétrée avec les procédures de gestions diverses (affichage, souris, clavier, ...)
- OpenGL en fullscreen sous GLUT
La méthode initOpenGLGLW(int bits) est ensuite appelée pour initialiser OpenGL sur la fenêtre précédemment créée. Là encore, rien de bien transcendant, puisqu'il s'agit de paramétrer OpenGL pour permettre d'afficher et de gérer les couleurs, ... comme nous le désirons.
La méthode termine son travail en affichant la fenêtre à l'écran et en lui donnant le focus...
Boucle de traitement
Il s'agit ici d'effectuer tous les traitements liés à notre instance.
trtMsgGLW (bool bBcl);
bBcl qui ne servira pas dans le cas d'une utilisation GLUT. Normalement, elle permet d'indiquer que l'on veut récupérer la main après traitement d'un message ou non. Or dans le cas de GLUT, la gestion des messages est bloquantes.
La fonction de cette procédure est en fait très basique, puisqu'il s'agit de lancer la procédure de gestion des messages GLUT. La complexité vient plutôt des procédures standard de GLUT qui sont lancées lorsqu'un évènement arrive. Comme indiqué ci-dessus, ces procédures sont statiques et ne connaissanet donc pas l'instance GLWindows. Elles utiliseront donc notre liste pour retrouver l'instance GLWindows à partir de l'identifiant de la fenêtre GLUT.
Cette procédure des messages va à son tour traiter les messages et déclencher des évènements dans notre instance glWindows.
- Voir la liste des évènements
A chaque évènement, il y a un code par défaut. Ces évènements étant virtuels, il sera possible de les redéfinir dans vos classes dérivées (Voir Polymorphisme/Fonctions virtuelles et classes abstraites et Fonction virtuelle pour les classes dérivées).
Classe GLWindows
Voici le code !
Je reviendrai plus en détail sur certains points de cette classe par la suite...