I. Contributions

Nous recherchons toujours des traducteurs pour finir ce projet de traduction des articles de NeHe. Votre aide serait appréciée ! Vous êtes intéressé ? Alors contactez-nous à l'adresse suivante : nehe@redaction-developpez.com .

II. Tutoriel

En se basant sur le code de la leçon précédente, nous allons y apporter quelques aménagements. Je vais entièrement réécrire le code ci-dessous, facilitant ainsi la détection de ce qui a été ajouté ou remplacé.

Commençons par ajouter les 2 variables permettant de garder la trace de la rotation pour chaque objet. Nous ferons cela au début de notre programme, à la suite des autres variables. Vous remarquerez 2 nouvelles lignes après 'bool fullscreen=TRUE;'. Ces lignes initialisent 2 variables numériques à virgule flottante que nous pourrons utiliser pour "accrocher" les objets sur l'écran avec une grande précision. Les variables numériques à virgule flottante admettent des valeurs décimales. Ceci signifie que nous ne serons pas limité à l'emploi de valeurs entières (1, 2, 3, etc...) pour les angles, nous pourrons aussi utiliser 1.1, 1.7, 2.3,ou même 1.015 pour une meilleure précision. Vous constaterez que ces valeurs décimales sont incontournables dans la programmation OpenGL. Ces nouvelles variables sont nommées:

  • rtri pour la rotation du triangle
  • rquad pour la rotation du carré

Initialisation et variables globales
Sélectionnez
#include    <windows.h>     // Fichier Header pour Windows
#include    <gl\gl.h>       // Fichier Header pour la librairie OpenGL32 
#include    <gl\glu.h>      // Fichier Header pour la librairie GLu32 
#include    <gl\glaux.h>    // Fichier Header pour la librairie GLaux 

HDC       hDC=NULL;         // Contexte de peripherique GDI prive
HGLRC     hRC=NULL;         // Contexte de rendu permanent
HWND      hWnd=NULL;        // Identificateur pour notre fenetre
HINSTANCE hInstance;        // Identificateur pour l'instance de l'application
bool      keys[256];        // Tableau utilise par la routine du clavier
bool      active=TRUE;      // Indicateur de fenetre active
bool      fullscreen=TRUE;  // Indicateur de plein-ecran a vrai par defaut
GLfloat   rtri;             // Angle pour le Triangle ( NOUVEAU )
GLfloat   rquad;            // Angle pour le carré ( NOUVEAU )

Maintenant, il nous faut modifier le code de DrawGLScene(). Je vais réecrire complètement la procédure; il vous sera ainsi plus facile de repérer les modifications apportées au code initial. J'indiquerai pourquoi les instructions sont modifiées, ainis que le rôle de chaque nouvelle ligne. La portion de code suivante est reprise, sans modification, de la leçon précédente.

Debut de la fonction DrawGLScene
Sélectionnez
int DrawGLScene(GLvoid)                 // C'est ici que tous le rendu sont realises
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // efface l'ecran et le buffer de profondeur
    glLoadIdentity();                   // Reinitialisation de la vue
    glTranslatef(-1.5f,0.0f,-6.0f);     // Deplacement: gauche 1.5 , interieur Six Unites

La ligne de code suivante est nouvelle. glRotatef(Angle,Xvector,Yvector,Zvector) est utilisée pour faire pivoter un objet autour d'un axe. Vous serez amener faire un usage intensif de cette commande... Angle est un nombre, habituellement stocké dans une variable, qui représente le déplacement apporté à l'objet. Les paramètres Xvector, Yvector et Zvector représentent le vecteur mis en oeuvre dans la rotation. Par exemple, le triplet (1,0,0) décrit un vecteur de déplacement d'une unité le long de l'axe des X et vers la droite. Le triplet (-1,0,0,) décrit son opposé: le déplacement se fera vers la gauche.

C'est D. Michael Traub qui m'a fourni l'explication ci-dessus pour ces paramètres Xvector, Yvector and Zvector.

Pour une meilleure compréhension d'une rotation suivant ces axes X, Y et Z, je vais développer ces notions et prendre des exemples

L'axe des X : imaginez que vous travaillez avec une scie circulaire de table. La lame va de gauche à droite (comme pour l'axe des x en OpenGL). Les dents vont donc faire des rotations autour de l'axe X et on aura l'impression que la lame coupe dans le bon sens ou dans le sens contraire. Lorsqu'on fait une rotation sur l'axe des X en OpenGL, cela aura le même effet.

L'axe des Y - Imaginez-vous debout en plein milieu d'un champ. Une énorme tornade arrive droit sur vous. Le centre de la tornade (axe de rotation) va du ciel au sol (en haut et en bas, exactement comme l'axe Y d'OpenGL). La poussière et les débris pris dans la tornade tournent autour de cet axe Y (centre de la tornade) de gauche à droite ou de droite à gauche. Faire défiler un objet sur l'axe Y d'OpenGL permet d'avoir le même effet.

L'axe des Z - Imaginez vous regardant un ventilateur de face. Le centre du ventilateur point vers vous et derrière vous comme s'il vous traversait (exactement comme l'axe z d'OpenGL). Les pales du ventilateur tournent autour de l'axe Z (centre du ventilateur) dans le sens des aiguilles d'une montre (ou dans le sens inverse). C'est la même chose que de faire tourner un objet selon cet axe Z avec OpenGL.

Alors, dans la ligne de code qui suit, si rtri vaut 7, on observera une rotation de 7 unités autour de l'axe Y (de gauche à droite). Vous pouvez expérimenter à votre convenance: par exemple changez le 0.0f en 1.0f, et le 1.0f en 0.0f pour observer la rotation du triangle sur les axes X et Y en même temps.

Il est important de noter que les rotations sont indiquées en degrés. Si rtri a une valeur de 10, la rotation sera de 10 degrés suivant l'axe des Y.

Rotation du triangle
Sélectionnez
glRotatef(rtri,0.0f,1.0f,0.0f);              // Rotation du Triangle sur l'axe Y ( NOUVEAU )

La portion de code suivante n'a pas changé. Elle dessine un triangle aux couleurs mélangées par lissage. Le triangle sera tracé sur le coté gauche de l'écran. On lui appliquera une rotation suivant l'axe Y afin de le faire pivoter de gauche à droite.

Rendu du triangle
Sélectionnez
glBegin(GL_TRIANGLES);               // Debut du tracé du Triangle
    glColor3f(1.0f,0.0f,0.0f);       // Reglage de la couleur : rouge
    glVertex3f( 0.0f, 1.0f, 0.0f);   // Definition du sommet haut
    glColor3f(0.0f,1.0f,0.0f);       // Reglage de la couleur : vert
    glVertex3f(-1.0f,-1.0f, 0.0f);   // Definition du sommet gauche
    glColor3f(0.0f,0.0f,1.0f);       // Reglage de la couleur : bleu 
    glVertex3f( 1.0f,-1.0f, 0.0f);   // Definition du sommet droit
glEnd();                             // Fin du trace

Vous constaterez dans le code ci-dessous, l'ajout d'un appel à glLoadIdentity(). Cela permet de réinitialiser la vue. Si nous ne le faisions pas, un déplacement d'un objet après sa rotation aboutirait à des résultats imprévisibles. En effet, comme l'axe aura bougé, il ne pointe plus dans la direction que l'on pense. Ainsi, un déplacement à gauche suivant l'axe X peut aboutir à déplacement vers le bas, ou vers le haut, selon la rotation appliquée préalablement sur chaque axe. Essayez sans cet appel à glLoadIdentity() pour voir ce que je veux dire...

Une fois la scène réinitialisée, X va de gauche à droite, Y de bas en haut et Z d'avant en arrière, nous pouvons préparer le déplacement. Vous noterez que le déplacement à droite est de 1.5 unité au lieu de 3.0 dans la précédente leçon. En effet, à la réinitialisation de l'écran, le point de référence est repositionné au centre de l'écran. De fait, on n'est plus positionné à 1.5 unité à gauche du centre, on est revenu au point "zéro". En conséquence, pour aller à 1.5 unité à droite du point zéro, le trajet {gauche->centre} ayant déjà été réalisé, le déplacement restant se limite à 1.5 unité vers la droite. Au total, le déplacement aura bien été de 3.0, dont 1.5 à votre charge.

Après le déplacement aux nouvelles coordonnées sur le coté droit de l'écran, on effectue la rotation du polygone suivant l'axe des X. Cela provoque le défilement vertical du carré.

Debut du rendu pour le carre
Sélectionnez
glLoadIdentity();                 // Reinitialisation de la matrice Current Modelview
glTranslatef(1.5f,0.0f,-6.0f);    // Deplacement: gauche 1.5 , intérieur Six Unites
glRotatef(rquad,1.0f,0.0f,0.0f);  // Pivote le carré sur l'axe des X ( NOUVEAU )

Cette portion du code est inchangée. Elle trace un carré bleu. Ce carré sera dessiné sur la partie droite de l'écran, à l'endroit où il pivotera.

Rendu du carre
Sélectionnez
glColor3f(0.5f,0.5f,1.0f);          // Choisissons une belle teinte bleutee
glBegin(GL_QUADS);                  // Debut du trace du carre
    glVertex3f(-1.0f, 1.0f, 0.0f);  // Angle superieur gauche
    glVertex3f( 1.0f, 1.0f, 0.0f);  // Angle superieur droit
    glVertex3f( 1.0f,-1.0f, 0.0f);  // Angle inferieur droit
    glVertex3f(-1.0f,-1.0f, 0.0f);  // Angle inferieur gauche
glEnd();                            // Fin du trace

Les 2 lignes suivantes sont nouvelles. Pensez à rtri et à rquad comme à des containers. Au début du programme nous les avons créé (GLfloat rtri, et GLfloat rquad). Après leur construction, il n'y a rien dans ces containers. Le première de ces nouvelles lignes AJOUTE 0.2 dans le container concerné. Ainsi, à chaque fois que nous évaluerons la valeur dans le container rtri après le passage dans cette section du code, elle aura été augmentée de 0.2. De la même manière, la valeur du container rquad aura diminué de 0.15. Diminuer plutôt qu'augmenter la valeur d'un container provoque l'inversion du sens de déplacement.

Essayez de changer le signe + en - dans cette ligne, et observez comment l'objet se déplace dans l'autre direction. Essayez aussi de changer les valeurs (0.2 en 1.0 par exemple): plus la valeur est importante et plus le déplacement est rapide; et inversement.

Gestion de la rotation
Sélectionnez
rtri+=0.2f;     // Augmente la variable de rotation du triangle ( NOUVEAU )
rquad-=0.15f;   // Diminue la variable de rotation du carre ( NOUVEAU )
return TRUE;    // On continue
}

Enfin, modification du code pour basculer du mode fenêtré vers le mode plein écran pour que le titre de la fenêtre soit correct.

Gestion de la touche F1
Sélectionnez
if (keys[VK_F1])             // Appui sur la touche F1 ?
{
    keys[VK_F1]=FALSE;       // Si oui, annulation de la touche enfoncee
    KillGLWindow();          // Suppression de la fenetre courante
    fullscreen=!fullscreen;  // Bascule entre les mode plein ecran et fenetre
    // Re-creation de notre fenetre OpenGL ( Modifiée )
    if (!CreateGLWindow("Le Tutoriel sur la Rotation de NeHe",640,480,16,fullscreen))
    {
        return 0;            // Quitter si la fenetre n'a pas ete creee
    }
}

Dans cette partie, j'ai tenté d'expliquer avec le plus de détails possible, comment faire pivoter les objets autour d'un axe. A vous d'expérimenter: tentez de déplacer les objets sur l'axe Z, sur l'axe Y, sur les 3 axes :-) Si vous avez des commentaires ou des interrogations, merci de m'envoyer un mail. Si vous pensez qu'un commentaire est incorrect ou que certaines portions du code peuvent être améliorées, faites le moi savoir. Je désire produire le meilleur tutoriel possible sur OpenGL. Je suis donc intéressé par votre retour d'expérience.

Jeff Molofee ( NeHe )

III. Téléchargements

Compte tenu du nombre de versions de codes sources pour les tutoriels nehe, nous les laissons en anglais. En principe, si vous avez compris le code présenté dans ce tutoriel (et les tutoriels antérieurs), vous n'aurez pas de mal à le comprendre :

IV. Remerciements

Merci à fearyourself et à wichtounet pour leur relecture.

V. Liens