1 Transformations affines But: fixer le positionnement et lorientation 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 lobjet. La transformation vient modifier les points de lobjet sans changer le repère de lobjet. 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 dun objet Ces transformations sont représentées aussi sous forme matricielle : v = M u où M est une matrice dordre 4 :| | M =| | | | | 0001 | 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 dappliquer une transformation aux sommets dun objet tout en conservant le système de coordonnées utilisé intact, on effectue un changement de repère. Soit le repère R 1 ( u, v, w, O), soit une transformation affine représentée par la matrice M 1, le nouveau repère après transformation est : R 2 (M 1 u, M 1 v, M 1 w, M 1 O). Soit un point P défini dans le repère R 1, ce même point dans le repère R 2 est défini par M 1 -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 lorientation du volume de visualisation. La primitive glMatrixMode permet de choisir la matrice où les transformations sappliqueront : 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 nest possible de modifier quune seule matrice à la fois.
6 Soit Q la matrice associée au mode GL_MODELVIEW, cette matrice est appliquée à nimporte quel sommet dun objet qui est défini après linitialisation de Q. Soit p un tel sommet, alors la transformation suivante sapplique : Qp. En modifiant Q, nous changeons létat du système. À nimporte quel objet qui est défini après la modification de Q, la transformation modifiée sapplique : 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 à linté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é dordre 4. void glLoadMatrix{fd}(const TYPE * m); Initialise la matrice active à partir dun 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 dun 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 : m 1 m 5 m 9 m 13 m 2 m 6 m 10 m 14 m 3 m 7 m 11 m 15 m 4 m 8 m 12 m 16
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 dune montre dun angle en degré autour dun axe de rotation (qui passe par lorigine) dont la direction est (vx, vy, vz). void glTranslate{fd}(TYPE dx, TYPE dy, TYPE dz); Déplacement dun objet selon le vecteur (dx, dy, dz). void glScale{fd}(TYPE sx, TYPE sy, TYPE sz); Mise à léchelle dun 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 quune seule multiplication dun 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 lon 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 dun axe et dune 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 laxe 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 dafficher une sphère en rotation autour dun 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 dun 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(); 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; }