Evènements liés à la gestion de la caméra

 

Il s'agit ici d'expliquer le code par défaut des évènements permettant la gestion de la caméra. Je ne rentrais pas ici dans le détail concernant la gestion du clavier ou de la souris, cela concerne deux autres chapitres vus par la suite (Evènements clavier, souris).

Dans la classe glWindows qui est la classe principale, il y a la gestion de tous les évènements Windows/X Window ou GLUT. Nous trouverons donc naturellement des évènements concernant la gestion du clavier ou de la souris.

 

La souris

Je suis parti sur le principe que la caméra pouvait subir des rotations de tangage ou de lacet à partir de la souris (rien de révolutionnaire me direz-vous...), il faut donc:

Placer du code sur l'évènement bool onPosMouseGLW (POINT xyScrSouris, POINT xySourisClt) de la classe glWindows;

Dans ce code:

- Lire les nouvelles positions de la souris

- Si elles sont au centre de notre fenêtre, considérer qu'il n'y a rien à faire et sortir, car le centre de notre fenêtre est pour nous l'origine donc la souris n'a pas bougé.

- Sinon, par rapport au centre de la fenêtre, déterminer le déplacement à droite ou à gauche, ou vers le haut ou vers le bas, et déclencher les méthodes de rotations ChangeTangageX et/ou ChangeLacetY en passant le nombre de degrés correspondant.

- Et repositionner la souris au centre de la fenêtre. Obligatoire pour deux raisons:

- Permettre de déterminer les degrés de rotations lors du prochain déplacement de la souris toujours par rapport au centre de la fenêtre qui, pour rappel, correspond à notre origine.

- Eviter que la souris ne sorte de notre fenêtre au risque de perdre la capture de notre souris.

Image non trouvée !Le fait de repositionner la souris au centre de la fenêtre va déclencher à nouveau l'évènement onPosMouseGLW. Il est donc impératif de contrôler les positions de la souris. Si elles sont au centre, il ne faut vraiment rien faire et surtout ne pas la repositionner de nouveau ! Sinon, nous rentrerions en boucle infinie !!!

 

Cette méthode retournera true pour indiquer à Windows que nous avons bien pris en compte le déplacement de la souris et qu'il ne faudra donc plus traiter cet évènement.

 

Le clavier

Mais le clavier peut aussi servir à piloter la caméra...

Dans ce cas, il faut coder l'évènement bool onKeyUpGLW (GLWPARAM wKey) et/ou onKeyDownGLW (GLWPARAM wKey). (Pour rappel, une application Windows ou X Window peut recevoir un key Down ou un key Up d'une touche et pas systématiquement les deux sur une touche. Il suffit pour cela que la fenêtre perde la capture du clavier après un appui sur une touche sans que l'utilisateur ne la relache, ou que la fenêtre récupère le focus lors d'une phase de relachement de touche...). Enfin, l'évènement onKeyUpGLW n'est pas exploitable sous GLUT.

Dans cet évènement, je controle les touches du clavier numérique:

2 ou 8 permettent le tangage

4 ou 6 le lacet

7 ou 9 le roulis

+ ou - pour la vélocité

Evidemment, les degrès de rotations ou la vélocité correspondant au sens de la touche préssée...

J'ai aussi implémenté du code sur la touche F1 dans onKeyDown de la classe glWindows qui permet simplement d'activer ou non l'affichage lors d'un évènement onPaint de glWindows d'informations concernant la position de la caméra (méthode AffInfoCam de la classe camera).

Enfin, je retourne true si la touche nous a servi à déplacer la caméra. false pour laisser windows gérer sinon...

 

La mise en oeuvre du déplacement

Un autre évènement, et pas des moindre, est celui qui va permettre de "positionner" notre caméra dans le monde virtuel.

Il s'agit donc de l'évènement permettant l'affichage du monde 3D.

Soit l'évènement bool onPaintGLW().

Il faudra placer la caméra avant de dessiner les objets. On pourra placer la caméra via la matrice modelisation des objets ou via la matrice de projection.

Dans mon exemple, j'utilise le premier cas, le second étant pour moi plus lourd ...

 

Que fait-on dans mon cas:

- On passe sur la matrice modelview

- On l'initialise normalement...soit:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Effaçons l'écran et le DEPTH buffer
glLoadIdentity(); // Initialisation de la matrice

- Puis on effectue les rotations/translations pour placer la caméra (CamLookAt).

- On dessine l'objet, ici un cube par défaut.

- Pour gérer l'affichage des informations de la caméra, on réinitialise la matrice via glLoadIdentity(); car les informations ne doivent pas subir le déplacement/rotation de la caméra.

- On échange les buffers pour voir le rendu.

C'est tout !!!

 

Que fairait-on dans le second cas:

- On passe sur la matrice projection

- On mémorise la matrice via pushMatrix(), nécessaire, car il faudra la restaurer après avoir mis en place la caméra, sinon on cumulerai les différents placements de la caméra (on ne verrai plus rien, ou plutôt tout défilerai !!!)

- Puis on effectue les rotations/translations pour placer la caméra (méthode CamLookAt).

- On passe sur la matrice modelview

- On l'initialise normalement...soit:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Effaçons l'écran et le DEPTH buffer
glLoadIdentity(); // Initialisation de la matrice

- On dessine l'objet, ici un cube par défaut.

- On restaure la matrice de projection, il faut donc repasser en projection

- puis restaurer via popMatrix()

- Pour gérer l'affichage des informations de la caméra, on repasse dans la matrice modelview; car les informations doivent être dessinées dans cette matrice.

Ce qui est en gras corerspond aux ajouts par rapport au premier cas qui sont nécessaires pour faire fonctionner le code dans ce second cas...

Par rapport au premier cas, il y a quand même un glLoadIdentity(); en moins...ou plutôt remplacé devrais-je dire par le popMatrix()

Bref, c'est plus lourd !!!