SlideShare a Scribd company logo
1 of 17
Download to read offline
1
Transformations affines
But: fixer le positionnement et l’orientation des objets de la scène.
2
Transformations de modélisation
Les transformations sur les objets permettent de déplacer les objets,
de les orienter différemment et / ou de changer leur forme.
En particulier, les transformations affines nous ont permis de passer
du système de coordonnées du « monde » à celui de l’écran.
Une transformation peut être vue soit comme un changement de
repère ou soit comme une transformation des sommets de l’objet.
La transformation vient modifier les points de l’objet sans changer
le repère de l’objet.
Cela définit un nouveau repère: les points des objets sont alors
redéfinis selon ce nouveau repère.
3
Transformation affine des sommets d’un objet
Ces transformations sont représentées aussi sous forme matricielle :
v = M u
où M est une matrice d’ordre 4 : | 11 12 13 14|
M = | 21 22 23 24|
| 31 32 33 34|
| 0 0 0 1 |
Nous avons 12 degrés de liberté pour une transformation sur un point p
quelconque : p  | 1|
| 2|
| 3|
| 1 |
Pour une transformation sur un vecteur, 9 éléments ont une influence :
v = M u où u  | 1|
| 2|
| 3|
| 0 |
4
Transformation via un changement de repère
Au lieu d’appliquer une transformation aux sommets d’un objet
tout en conservant le système de coordonnées utilisé intact, on
effectue un changement de repère.
Soit le repère R1  (u, v, w, O),
soit une transformation affine représentée par la matrice M1,
le nouveau repère après transformation est :
R2  (M1 u, M1 v, M1 w, M1 O).
Soit un point P défini dans le repère R1, ce même point dans le repère
R2 est défini par M1
-1 P.
5
Implantation en OpenGL des transformations
Dans OpenGL, il existe 2 matrices pour stocker la résultante des transformations
qui interviennent dans une application :
GL_MODELVIEW : (par défaut)
elle est unique même si on peut la voir comme le produit de 2 matrices :
° les transformations affines à appliquer aux objets,
° celles permettant de passer du repère des objets à celui de la caméra.
GL_PROJECTION :
° les transformations permettant de définir la forme et l’orientation
du volume de visualisation.
La primitive glMatrixMode permet de choisir la matrice où les transformations
s’appliqueront :
void glMatrixMode(GLenum mode);
Spécifie laquelle des matrices sera modifiée par la suite selon la valeur
de mode : GL_MODELVIEW ou GL_PROJECTION.
Il n’est possible de modifier qu’une seule matrice à la fois.
6
Soit Q la matrice associée au mode GL_MODELVIEW, cette matrice est appliquée
à n’importe quel sommet d’un objet qui est défini après l’initialisation de Q.
Soit p un tel sommet, alors la transformation suivante s’applique : Qp.
En modifiant Q, nous changeons l’état du système.
À n’importe quel objet qui est défini après la modification de Q, la transformation
modifiée s’applique :
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0);
glEnd();
glTranslatef(25.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0);
glEnd();
Note : On ne peut pas insérer glTranslatef à l’intérieur
de glBegin() / glEnd().
7
Lorsque vous écrivez un programme en OpenGL, vous devez vous assurer que
la matrice MODEL_VIEW est initialisée correctement :
void glLoadIdentity();
Initialise la matrice active à la matrice identité d’ordre 4.
void glLoadMatrix{fd}(const TYPE * m);
Initialise la matrice active à partir d’un vecteur à 16 éléments
où ceux-ci sont rangés colonne par colonne.
void glMultMatrix{fd}(const TYPE * m);
Post-multiplie la matrice active à partir d’un vecteur à 16 éléments
où ceux-ci sont rangés colonne par colonne.
Si C est la matrice active et M la matrice passée
en paramètre, alors la matrice active devient CM.
Dans les 2 primitives précédentes,
l’élément m[i][j] se trouve dans la
colonne i et sur la ligne j :
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15
m4 m8 m12 m16
8
Des transformations élémentaires peuvent aussi être effectuées (post-multiplication)
à la matrice courante.
void glRotate{fd}(TYPE angle, TYPE vx, TYPE vy, TYPE vz);
Rotation dans le sens contraire des aiguilles d’une montre d’un angle en
degré autour d’un axe de rotation (qui passe par l’origine) dont la direction
est (vx, vy, vz).
void glTranslate{fd}(TYPE dx, TYPE dy, TYPE dz);
Déplacement d’un objet selon le vecteur (dx, dy, dz).
void glScale{fd}(TYPE sx, TYPE sy, TYPE sz);
Mise à l’échelle d’un objet selon les facteurs sx, sy et sz.
9
Exemple :
glMatrixMode(GL_MODELVIEW)
glLoadIdentity(); Q  I
glTranslatef(4.0, 5.0, 6.0); Q  QT(4.0, 5.0, 6.0)
glRotatef(45.0, 1.0, 2.0, 3.0) Q  QR(45.0, 1.0, 2.0, 3.0)
glTranslatef(-4.0, -5.0, -6.0); Q  QT(-4.0, -5.0, -6.0)
ce qui donne
q = Q p équivaut à :
q = T(4.0, 5.0, 6.0) R(45.0, 1.0, 2.0, 3.0) T(-4.0, -5.0, -6.0) p.
Ordre selon lequel il vous faut spécifier une série de transformations
La dernière primitive de transformation que votre programme appelle est en réalité
la première appliquée aux sommets.
En réalité, il ne se produit qu’une seule multiplication d’un sommet par la matrice
MODEL_VIEW car les matrices sont déjà multipliées en une seule matrice avant
d’être appliquées à p.
10
Sauvegarde de la matrice de transformation courante
À une étape donnée de notre programme, il se peut que l’on veuille sauvegarder la
matrice de transformation courante pour y avoir accès ultérieurement.
OpenGL permet ceci en gérant des piles de transformations.
Les fonctions suivantes sont disponibles :
glPushMatrix();
Sachant que la matrice de transformation courante est sur le dessus de la
pile, cette fonction effectue une copie de cette matrice et la place sur le
dessus de la pile.
Cette copie sera modifiée dès que la matrice de transformation courante est
modifiée dans le programme.
glPopMatrix();
Cette fonction enlève du dessus de la pile la copie de la matrice de
transformation courante.
La matrice de transformation courante devient alors la dernière matrice
sauvegardée.
11
void Affichage( void )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glLoadIdentity();
glRotatef(theta, vx, vy, vz); glTranslatef(2.0, 2.0, 2.0);
glutSolidSphere(0.5, 10, 20);
glLoadIdentity();
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_LINES);
glVertex3f(0, 0, 0); glVertex3f(vx, vy, vz);
glEnd();
/* Cela force le système à afficher les points aussitôt que possible. */
glFlush();
/* Permet de transférer l'image à l'écran. */
glutSwapBuffers(); }
Exemple I : Affichage d’un axe et d’une sphère laquelle a subi une rotation autour
de cet axe.
sphère
axe
12
Exemple I (suite) :
void sphere_en_rotation()
{
theta += 0.05;
if (theta > 360.0) theta -= 360.0;
Affichage();
}
Permet de changer la direction de l’axe selon le bouton de la souris choisi.
void souris(int bouton, int etat, int x, int y)
{
if ( (bouton == GLUT_LEFT_BUTTON) &
(etat == GLUT_DOWN)) vx = vx + 1.0;
if ( (bouton == GLUT_MIDDLE_BUTTON) &
(etat == GLUT_DOWN)) vy = vy + 1.0;
if ( (bouton == GLUT_RIGHT_BUTTON) &
(etat == GLUT_DOWN)) vz = vz + 1.0;
}
Permet d’afficher une sphère en rotation autour d’un axe de direction (vx, vy, vz).
13
Exemple I (suite et fin) :
void main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(800, 500);
glutInitWindowPosition(500, 100);
glutCreateWindow("Transformations");
glutDisplayFunc(Affichage);
Initialisation();
/* La fonction sphere_en_rotation sera exécutée lorsque tous les
événements générés ont déjà été pris en compte. Cette fonction
est particulièrement utile pour créer des effets d'animation. */
glutIdleFunc(sphere_en_rotation);
glutReshapeFunc(reconfiguration);
glutMouseFunc(souris);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
14
Exemple II :
void Affichage( void )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Le système de coordonnées se trouve initialement au centre du cube.
// Vous devez déplacer le système de coordonnées vers une extrémité du cube.
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
// Translation de (1, 0, 0) pour établir le point d'articulation.
// Rotation autour de l'axe des z d'un angle "epaule".
glRotatef((GLfloat) epaule, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutSolidCube(1.0);
glPopMatrix();
Affichage d’un bras articulé.
static int epaule = 0, coude = 0, doigt = 0;
static GLint w = 100, h = 100;
15
Exemple II (suite) :
glColor3f(0.0, 1.0, 0.0);
// Translation de (1.5, 0, 0) pour établir le point d'articulation.
// Rotation autour de l'axe des z d'un angle "coude".
// Translation de (1, 0, 0) pour se déplacer vers la prochaine articulation.
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat) coude, 0.0, 0.0, 1.0);
glTranslatef(1.5, 0.0, 0.0);
glPushMatrix();
glScalef(3.0, 0.2, 1.0);
glutSolidCube(1.0);
glPopMatrix();
glColor3f(0.0, 0.0, 1.0);
16
Exemple II (suite) :
// Translation de (0.5, 0, 0) pour établir le point d'articulation.
// Rotation autour de l'axe des z d'un angle "doigt".
// Translation de (1.5, 0, 0) pour se déplacer vers la prochaine
// articulation.
glTranslatef(1.5, 0.0, 0.0);
glRotatef((GLfloat) doigt, 0.0, 0.0, 1.0);
glTranslatef(0.5, 0.0, 0.0);
glPushMatrix();
glScalef(1.0, 0.1, 0.1);
glutSolidCube(1.0);
glPopMatrix();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
17
Exemple II (suite et fin) :
void clavier(unsigned char cle, int x, int y)
{
switch(cle)
{
case 'e' : // Rotation à l'épaule.
epaule = (epaule + 5) % 360; glutPostRedisplay(); break;
case 'E' :
epaule = (epaule - 5) % 360; glutPostRedisplay(); break;
case 'c' : // Rotation au coude.
coude = (coude + 5) % 360; glutPostRedisplay(); break;
case 'C' :
coude = (coude - 5) % 360; glutPostRedisplay(); break;
case 'd' : // Rotation au doigt.
doigt = (doigt + 5) % 360; glutPostRedisplay(); break;
case 'D' :
doigt = (doigt - 5) % 360; glutPostRedisplay(); break;
default: break;
}
}

More Related Content

Similar to Transformations ponctuelles.ppt

Similar to Transformations ponctuelles.ppt (13)

Ds2 informatique
Ds2 informatiqueDs2 informatique
Ds2 informatique
 
ECMASCRIPT6 1partie.pptx
ECMASCRIPT6 1partie.pptxECMASCRIPT6 1partie.pptx
ECMASCRIPT6 1partie.pptx
 
algorithme_simplexe et exercices dans la recherche operationnelle
algorithme_simplexe et exercices dans la recherche operationnellealgorithme_simplexe et exercices dans la recherche operationnelle
algorithme_simplexe et exercices dans la recherche operationnelle
 
Rapport
RapportRapport
Rapport
 
Le langage C
Le langage CLe langage C
Le langage C
 
G1SSCIN03203-sujet1.pdf
G1SSCIN03203-sujet1.pdfG1SSCIN03203-sujet1.pdf
G1SSCIN03203-sujet1.pdf
 
Chapitre 5. Diagramme des activités.pdf
Chapitre 5.       Diagramme des activités.pdfChapitre 5.       Diagramme des activités.pdf
Chapitre 5. Diagramme des activités.pdf
 
Le grafcet
Le grafcetLe grafcet
Le grafcet
 
cours Plsql _ abdelkhalek benhoumine
cours Plsql _ abdelkhalek benhouminecours Plsql _ abdelkhalek benhoumine
cours Plsql _ abdelkhalek benhoumine
 
TD 1.pdf
TD 1.pdfTD 1.pdf
TD 1.pdf
 
CNC_cours.pdf
CNC_cours.pdfCNC_cours.pdf
CNC_cours.pdf
 
246242769 sequence-1-pdf
246242769 sequence-1-pdf246242769 sequence-1-pdf
246242769 sequence-1-pdf
 
presentation kadimi wahidi.pdf
presentation kadimi wahidi.pdfpresentation kadimi wahidi.pdf
presentation kadimi wahidi.pdf
 

Transformations ponctuelles.ppt

  • 1. 1 Transformations affines But: fixer le positionnement et l’orientation des objets de la scène.
  • 2. 2 Transformations de modélisation Les transformations sur les objets permettent de déplacer les objets, de les orienter différemment et / ou de changer leur forme. En particulier, les transformations affines nous ont permis de passer du système de coordonnées du « monde » à celui de l’écran. Une transformation peut être vue soit comme un changement de repère ou soit comme une transformation des sommets de l’objet. La transformation vient modifier les points de l’objet sans changer le repère de l’objet. Cela définit un nouveau repère: les points des objets sont alors redéfinis selon ce nouveau repère.
  • 3. 3 Transformation affine des sommets d’un objet Ces transformations sont représentées aussi sous forme matricielle : v = M u où M est une matrice d’ordre 4 : | 11 12 13 14| M = | 21 22 23 24| | 31 32 33 34| | 0 0 0 1 | Nous avons 12 degrés de liberté pour une transformation sur un point p quelconque : p  | 1| | 2| | 3| | 1 | Pour une transformation sur un vecteur, 9 éléments ont une influence : v = M u où u  | 1| | 2| | 3| | 0 |
  • 4. 4 Transformation via un changement de repère Au lieu d’appliquer une transformation aux sommets d’un objet tout en conservant le système de coordonnées utilisé intact, on effectue un changement de repère. Soit le repère R1  (u, v, w, O), soit une transformation affine représentée par la matrice M1, le nouveau repère après transformation est : R2  (M1 u, M1 v, M1 w, M1 O). Soit un point P défini dans le repère R1, ce même point dans le repère R2 est défini par M1 -1 P.
  • 5. 5 Implantation en OpenGL des transformations Dans OpenGL, il existe 2 matrices pour stocker la résultante des transformations qui interviennent dans une application : GL_MODELVIEW : (par défaut) elle est unique même si on peut la voir comme le produit de 2 matrices : ° les transformations affines à appliquer aux objets, ° celles permettant de passer du repère des objets à celui de la caméra. GL_PROJECTION : ° les transformations permettant de définir la forme et l’orientation du volume de visualisation. La primitive glMatrixMode permet de choisir la matrice où les transformations s’appliqueront : void glMatrixMode(GLenum mode); Spécifie laquelle des matrices sera modifiée par la suite selon la valeur de mode : GL_MODELVIEW ou GL_PROJECTION. Il n’est possible de modifier qu’une seule matrice à la fois.
  • 6. 6 Soit Q la matrice associée au mode GL_MODELVIEW, cette matrice est appliquée à n’importe quel sommet d’un objet qui est défini après l’initialisation de Q. Soit p un tel sommet, alors la transformation suivante s’applique : Qp. En modifiant Q, nous changeons l’état du système. À n’importe quel objet qui est défini après la modification de Q, la transformation modifiée s’applique : glBegin(GL_POLYGON); glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0); glEnd(); glTranslatef(25.0, 0.0, 0.0); glBegin(GL_POLYGON); glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0); glEnd(); Note : On ne peut pas insérer glTranslatef à l’intérieur de glBegin() / glEnd().
  • 7. 7 Lorsque vous écrivez un programme en OpenGL, vous devez vous assurer que la matrice MODEL_VIEW est initialisée correctement : void glLoadIdentity(); Initialise la matrice active à la matrice identité d’ordre 4. void glLoadMatrix{fd}(const TYPE * m); Initialise la matrice active à partir d’un vecteur à 16 éléments où ceux-ci sont rangés colonne par colonne. void glMultMatrix{fd}(const TYPE * m); Post-multiplie la matrice active à partir d’un vecteur à 16 éléments où ceux-ci sont rangés colonne par colonne. Si C est la matrice active et M la matrice passée en paramètre, alors la matrice active devient CM. Dans les 2 primitives précédentes, l’élément m[i][j] se trouve dans la colonne i et sur la ligne j : m1 m5 m9 m13 m2 m6 m10 m14 m3 m7 m11 m15 m4 m8 m12 m16
  • 8. 8 Des transformations élémentaires peuvent aussi être effectuées (post-multiplication) à la matrice courante. void glRotate{fd}(TYPE angle, TYPE vx, TYPE vy, TYPE vz); Rotation dans le sens contraire des aiguilles d’une montre d’un angle en degré autour d’un axe de rotation (qui passe par l’origine) dont la direction est (vx, vy, vz). void glTranslate{fd}(TYPE dx, TYPE dy, TYPE dz); Déplacement d’un objet selon le vecteur (dx, dy, dz). void glScale{fd}(TYPE sx, TYPE sy, TYPE sz); Mise à l’échelle d’un objet selon les facteurs sx, sy et sz.
  • 9. 9 Exemple : glMatrixMode(GL_MODELVIEW) glLoadIdentity(); Q  I glTranslatef(4.0, 5.0, 6.0); Q  QT(4.0, 5.0, 6.0) glRotatef(45.0, 1.0, 2.0, 3.0) Q  QR(45.0, 1.0, 2.0, 3.0) glTranslatef(-4.0, -5.0, -6.0); Q  QT(-4.0, -5.0, -6.0) ce qui donne q = Q p équivaut à : q = T(4.0, 5.0, 6.0) R(45.0, 1.0, 2.0, 3.0) T(-4.0, -5.0, -6.0) p. Ordre selon lequel il vous faut spécifier une série de transformations La dernière primitive de transformation que votre programme appelle est en réalité la première appliquée aux sommets. En réalité, il ne se produit qu’une seule multiplication d’un sommet par la matrice MODEL_VIEW car les matrices sont déjà multipliées en une seule matrice avant d’être appliquées à p.
  • 10. 10 Sauvegarde de la matrice de transformation courante À une étape donnée de notre programme, il se peut que l’on veuille sauvegarder la matrice de transformation courante pour y avoir accès ultérieurement. OpenGL permet ceci en gérant des piles de transformations. Les fonctions suivantes sont disponibles : glPushMatrix(); Sachant que la matrice de transformation courante est sur le dessus de la pile, cette fonction effectue une copie de cette matrice et la place sur le dessus de la pile. Cette copie sera modifiée dès que la matrice de transformation courante est modifiée dans le programme. glPopMatrix(); Cette fonction enlève du dessus de la pile la copie de la matrice de transformation courante. La matrice de transformation courante devient alors la dernière matrice sauvegardée.
  • 11. 11 void Affichage( void ) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 0.0, 0.0); glLoadIdentity(); glRotatef(theta, vx, vy, vz); glTranslatef(2.0, 2.0, 2.0); glutSolidSphere(0.5, 10, 20); glLoadIdentity(); glColor3f(0.0, 1.0, 0.0); glBegin(GL_LINES); glVertex3f(0, 0, 0); glVertex3f(vx, vy, vz); glEnd(); /* Cela force le système à afficher les points aussitôt que possible. */ glFlush(); /* Permet de transférer l'image à l'écran. */ glutSwapBuffers(); } Exemple I : Affichage d’un axe et d’une sphère laquelle a subi une rotation autour de cet axe. sphère axe
  • 12. 12 Exemple I (suite) : void sphere_en_rotation() { theta += 0.05; if (theta > 360.0) theta -= 360.0; Affichage(); } Permet de changer la direction de l’axe selon le bouton de la souris choisi. void souris(int bouton, int etat, int x, int y) { if ( (bouton == GLUT_LEFT_BUTTON) & (etat == GLUT_DOWN)) vx = vx + 1.0; if ( (bouton == GLUT_MIDDLE_BUTTON) & (etat == GLUT_DOWN)) vy = vy + 1.0; if ( (bouton == GLUT_RIGHT_BUTTON) & (etat == GLUT_DOWN)) vz = vz + 1.0; } Permet d’afficher une sphère en rotation autour d’un axe de direction (vx, vy, vz).
  • 13. 13 Exemple I (suite et fin) : void main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(800, 500); glutInitWindowPosition(500, 100); glutCreateWindow("Transformations"); glutDisplayFunc(Affichage); Initialisation(); /* La fonction sphere_en_rotation sera exécutée lorsque tous les événements générés ont déjà été pris en compte. Cette fonction est particulièrement utile pour créer des effets d'animation. */ glutIdleFunc(sphere_en_rotation); glutReshapeFunc(reconfiguration); glutMouseFunc(souris); glEnable(GL_DEPTH_TEST); glutMainLoop(); }
  • 14. 14 Exemple II : void Affichage( void ) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Le système de coordonnées se trouve initialement au centre du cube. // Vous devez déplacer le système de coordonnées vers une extrémité du cube. glPushMatrix(); glColor3f(1.0, 0.0, 0.0); // Translation de (1, 0, 0) pour établir le point d'articulation. // Rotation autour de l'axe des z d'un angle "epaule". glRotatef((GLfloat) epaule, 0.0, 0.0, 1.0); glTranslatef(1.0, 0.0, 0.0); glPushMatrix(); glScalef(2.0, 0.4, 1.0); glutSolidCube(1.0); glPopMatrix(); Affichage d’un bras articulé. static int epaule = 0, coude = 0, doigt = 0; static GLint w = 100, h = 100;
  • 15. 15 Exemple II (suite) : glColor3f(0.0, 1.0, 0.0); // Translation de (1.5, 0, 0) pour établir le point d'articulation. // Rotation autour de l'axe des z d'un angle "coude". // Translation de (1, 0, 0) pour se déplacer vers la prochaine articulation. glTranslatef(1.0, 0.0, 0.0); glRotatef((GLfloat) coude, 0.0, 0.0, 1.0); glTranslatef(1.5, 0.0, 0.0); glPushMatrix(); glScalef(3.0, 0.2, 1.0); glutSolidCube(1.0); glPopMatrix(); glColor3f(0.0, 0.0, 1.0);
  • 16. 16 Exemple II (suite) : // Translation de (0.5, 0, 0) pour établir le point d'articulation. // Rotation autour de l'axe des z d'un angle "doigt". // Translation de (1.5, 0, 0) pour se déplacer vers la prochaine // articulation. glTranslatef(1.5, 0.0, 0.0); glRotatef((GLfloat) doigt, 0.0, 0.0, 1.0); glTranslatef(0.5, 0.0, 0.0); glPushMatrix(); glScalef(1.0, 0.1, 0.1); glutSolidCube(1.0); glPopMatrix(); glPopMatrix(); glFlush(); glutSwapBuffers(); }
  • 17. 17 Exemple II (suite et fin) : void clavier(unsigned char cle, int x, int y) { switch(cle) { case 'e' : // Rotation à l'épaule. epaule = (epaule + 5) % 360; glutPostRedisplay(); break; case 'E' : epaule = (epaule - 5) % 360; glutPostRedisplay(); break; case 'c' : // Rotation au coude. coude = (coude + 5) % 360; glutPostRedisplay(); break; case 'C' : coude = (coude - 5) % 360; glutPostRedisplay(); break; case 'd' : // Rotation au doigt. doigt = (doigt + 5) % 360; glutPostRedisplay(); break; case 'D' : doigt = (doigt - 5) % 360; glutPostRedisplay(); break; default: break; } }