Rotations

Jeff Molofee (NeHe)

Traducteur

qi130

Dans la leçon précédente, je vous ai montré comment ajouter de la couleur aux triangles ou aux polygones. Dans cette leçon, nous verrons comment faire tourner ces objets colorés autour d'un axe. ♪

- Titre : Rotations

- Auteur : Jeff Molofee (NeHe)

- Traducteur : qi130

- Parution : 23 mars 2007

- Mise à jour : 19 décembre 2012

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2007 Nehe Gamedev.net. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Contributions

- II. Tutoriel

- III. Téléchargements

- IV. Remerciements

- V. Liens

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 deux 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 deux nouvelles lignes après 'bool fullscreen=TRUE;'. Ces lignes initialisent deux 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és à 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

#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éécrire 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, ainsi 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

int DrawGLScene(GLvoid)                 // C'est ici que tous les rendus 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 œuvre 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

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 côté gauche de l'écran. On lui appliquera une rotation suivant l'axe Y afin de le faire pivoter de gauche à droite.

Rendu du triangle

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

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

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 deux lignes suivantes sont nouvelles. Pensez à rtri et à rquad comme à des containers. Au début du programme nous les avons créés (GLfloat rtri, et GLfloat rquad). Après leur construction, il n'y a rien dans ces containers. La 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

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

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 modes plein ecran et fenetre
// Recreation 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. À vous d'expérimenter: tentez de déplacer les objets sur l'axe Z, sur l'axe Y, sur les trois 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 :

- ASM (Conversion par Foolman)

- BeOS (Conversion par Rene Manqueros)

- Borland C++ Builder 6 (Conversion par Christian Kindahl)

- C# (Conversion par Sabine Felsinger)

- Code Warrior 5.3 (Conversion par Scott Lupton)

- CygWin (Conversion par Stephan Ferraro)

- D (Conversion par Familia Pineda Garcia)

- Delphi (Conversion par Michal Tucek)

- Dev C++ (Conversion par Dan)

- Euphoria (Conversion par Evan Marshall)

- Game GLUT (Conversion par Milikas Anastasios)

- Genu (Conversion par Louis-Charles Dumais)

- GLUT (Conversion par Andy Restad)

- Irix (Conversion par Lakmal Gunasekara)

- Java (Conversion par Jeff Kirby)

- Java/SWT (Conversion par Victor Gonzalez)

- Jedi-SDL (Conversion par Dominique Louis)

- JOGL (Conversion par Kevin J. Duling)

- LCC Win32 (Conversion par Robert Wishlaw)

- Linux (Conversion par Richard Campbell)

- Linux GLX (Conversion par Mihael Vrbanec)

- Linux SDL (Conversion par Ti Leggett)

- LWJGL (Conversion par Mark Bernard)

- Mac OS (Conversion par Anthony Parker)

- Mac OS X/Cocoa (Conversion par Bryan Blackburn)

- MASM (Conversion par Nico (Scalp))

- Pelles C (Conversion par Pelle Orinius)

- Perl (Conversion par Cora Hussey)

- Power Basic (Conversion par Angus Law)

- Python (Conversion par John Ferguson)

- REALBasic (Conversion par Thomas J. Cunningham)

- Scheme (Conversion par Jon DuBois)

- Solaris (Conversion par Lakmal Gunasekara)

- VB.NET CsGL (Conversion par X)

- Visual Basic (Conversion par Ross Dawson)

- Visual Fortran (Conversion par Jean-Philippe Perois)

- Visual Studio

- Visual Studio NET (Conversion par Grant James)

IV - Remerciements

Merci à fearyourself et à wichtounet pour leur relecture.

V - Liens

Sommaire

Tutoriel précédent : Coloration

Tutoriel prochain : Première pyramide et premier cube