FAQ mathématiques pour les jeuxConsultez toutes les FAQ

Nombre d'auteurs : 7, nombre de questions : 82, dernière mise à jour : 16 mai 2017 

 
OuvrirSommaireMatricesTransformations

Une matrice de rotation est utilisée pour tourner un ensemble de points dans un système de coordonnées. Chaque point a de nouvelles coordonnées, mais leur distance relative reste inchangée.

Toutes les rotations sont définies à l'aide des fonctions trigonométriques sinus et cosinus.

Pour un système de coordonnées à deux dimensions, la matrice de rotation est la suivante :

Image non disponible

Quand l'angle A est nul, on génère la matrice identité :

Image non disponible

Si A vaut +90 degrés, on a la matrice :

Image non disponible

Si l'angle vaut -90 degrés :

Image non disponible

Prendre l'opposé de l'angle revient à transposer la matrice.

Si la matrice de rotation est multipliée par sa transposée, le résultat est la matrice identité.

Créé le 13 novembre 2005  par Hexapod

Utilisez la matrice 4x4 suivante :

Image non disponible
Créé le 13 novembre 2005  par Hexapod

Utilisez la matrice 4x4 suivante :

Image non disponible
Créé le 13 novembre 2005  par Hexapod

Utilisez la matrice 4x4 suivante :

Image non disponible
Créé le 13 novembre 2005  par Hexapod

Les angles d'Euler sont le nom donné à un triplet d'angles de rotation (x, y, z) représentant respectivement les rotations autour des axes X, Y et Z.

Exemples :

 
Sélectionnez
(0, 0, 0) génèrera la matrice identité (aucune rotation)
(90, 0, 0) est une rotation de 90° autour de X
(30, 0, 55) est une rotation de 30° autour de X, suivie d'une rotation de 55° autour de Z
(0, 80, 90) est une rotation de 80° autour de Y, suivie d'une rotation de 90° autour de Z
Créé le 13 novembre 2005  par Hexapod

Ces termes sont d'origine aéronautique et correspondent aux rotations à l'aide des angles d'Euler (système de coordonnées euclidien), relativement à la base locale d'un avion.

Imaginez-vous un avion.

L'axe Z passe par la queue et l'avant de l'appareil.
L'axe X part de l'aile gauche à l'aile droite.
L'axe Y pointe vers le haut de l'appareil.

Ainsi le tangage devient la rotation autour de l'axe X, le lacet devient la rotation autour de l'axe Y, et le roulis la rotation autour de l'axe Z.

Créé le 13 novembre 2005  par Hexapod

Les matrices de rotations se combinent en les multipliant entre elles. Attention à l'ordre dans lequel vous les multipliez ! Sinon…

Créé le 13 novembre 2005  par Hexapod

Le problème de la perte d'un degré de liberté, le gmbal lock, arrive quand on utilise les angles d'Euler. Comme la matrice de rotation finale dépend de l'ordre des multiplications, il est possible que parfois, l'une des rotations autour d'un axe soit confondue avec un autre axe de rotation.

Pire encore, il est devient parfois impossible de tourner l'objet suivant un certain axe. C'est le gimbal lock !

Par exemple, supposons qu'un objet est tourné dans l'ordre Z, Y et X et que la rotation autour de Y soit de 90°.

Dans ce cas, la rotation suivant Z se fait correctement, puisque c'est la première. L'axe Y tourne également correctement. Néanmoins, après cette rotation, l'axe X et l'axe Z sont confondus.

Du coup, toute rotation autour de l'axe X tourne l'objet suivant Z ! Pire encore, il est devenu impossible de tourner l'objet autour de l'axe X.

Créé le 13 novembre 2005  par Hexapod

La seule solution à ce problème est de transformer les axes de rotation suivants avec les rotations précédentes. Ces transformations requièrent un outil de combinaison de rotations quelconques, ce qui s'avère plus facile avec des quaternions qu'avec des matrices.

On ne peut pas dire que ce sont les quaternions qui à eux seuls permettent d'éviter le gimbal lock, il est tout à fait possible de reproduire ce problème avec des quaternions.

Autrement dit, si on note R[0x,a](objet) la rotation autour de l'axe 0x et d'angle a de l'objet, R[Oy,b] la rotation autour de l'axe Oy et d'angle b et R[Oz,c] la rotation autour de l'axe Oz d'angle c, pour combiner les trois rotations axiales, on fait :

 
Sélectionnez
R(objet)=R[R[R[Ox,a](Oy),b]R[Ox,a](Oz),c](R[R[Ox,a](Oy),b](R[Ox,a](objet)))

On conserve ainsi le repère local associé à l'objet qui change après chaque rotation appliqué à celui-ci, on garde ainsi tous les degrés de liberté.

Créé le 11 septembre 2008  par loka, gouessej

En réalité, il n'y a pas de façon correcte de combiner les matrices de rotation. Néanmoins, afin de prédire les résultats de la combinaison des matrices, un peu d'organisation est nécessaire.

Le moyen le plus simple de tourner un objet est de multiplier les matrices dans cet ordre :

Image non disponible

Où M est la matrice de rotation finale, et X, Y, Z les matrices de rotations individuelles.

Néanmoins, quand la vue de la caméra est évaluée, l'ordre et le signe des rotations sont inversés.

Par exemple, si vous êtes debout, et que vous vous tournez vers la droite, tout ce que vous voyez dans votre champ de vision semblera tourner vers la gauche.

Par conséquent, le point de vue de la caméra est modélisé à l'aide de l'ordre suivant :

Image non disponible

Ceci est l'inverse (ou la transposée) de la matrice de rotation de l'objet.

Créé le 13 novembre 2005  par Hexapod

À première vue, la méthode la plus évidente pour générer une matrice de rotation à partir d'un ensemble d'angles d'Euler est de générer chaque matrice individuellement et de les multiplier ensemble :

 
Sélectionnez

                    m3_rotx(mat_x,     vec -> angle_x);
                    m3_roty(mat_y,     vec -> angle_y);
                    m3_rotz(mat_z,     vec -> angle_z);
                    m3_mult(mat_tmp,   mat_z, mat_y);
                    m3_mult(mat_final, mat_tmp, mat_x);
                

Cet ensemble d'appels peut être placé dans une routine séparée :

 
Sélectionnez

                    m3_fromeuler(MATRIX *mat_final, VECTOR3 *euler)
                

Néanmoins, la réalisation de cette séquence d'appels est vraiment très inefficace en termes de temps de calcul. Étant donné que chaque matrice de rotation 4x4 doit avoir 10 éléments avec la valeur 0, 2 autres avec la valeur 1, et 4 autres avec des valeurs arbitraires, près de 75 % de chaque opération matricielle est fait en pure perte ! Ceci n'inclut pas l'initialisation des matrices…

Un moyen plus efficace doit être trouvé. Heureusement, il existe un autre moyen d'aboutir à la matrice finale.

Si nos trois matrices sont combinées dans un format algébrique, l'expression suivante est définie :

Image non disponible

Où :
M est la matrice finale
X est la matrice de rotation autour de l'axe X
Y est la matrice de rotation autour de l'axe Y
Z est la matrice de rotation autour de l'axe Z

Soit les matrices associées :

Image non disponible
Image non disponible
Image non disponible

Où A, B sont le cosinus et le sinus de la rotation autour de l'axe X,
C, D sont le cosinus et le sinus de la rotation autour de l'axe Y,
E, F sont le cosinus et le sinus de la rotation autour de l'axe Z.

Alors, l'expression :

Image non disponible

Peut se partager en 2 multiplications de matrices :

Image non disponible
Image non disponible

Évaluons M' :

Image non disponible
Image non disponible
Image non disponible

D'où M devient :

Image non disponible
Image non disponible
Image non disponible

C'est la matrice de rotation finale. En tant que matrice 4x4 :

Image non disponible

Les valeurs individuelles de A,B,C,D,E et F sont évaluées en premier. Ensuite, on évalue BD et AD puisqu'ils sont fréquents.

Donc, voici l'algorithme final :

 
Sélectionnez

A       = cos(angle_x);
B       = sin(angle_x);
C       = cos(angle_y);
D       = sin(angle_y);
E       = cos(angle_z);
F       = sin(angle_z);

AD      =   A * D;
BD      =   B * D;

mat[0]  =   C * E;
mat[1]  =  -C * F;
mat[2]  =  D;
mat[4]  =  BD * E + A * F;
mat[5]  =  -BD * F + A * E;
mat[6]  =  -B * C;
mat[8]  = -AD * E + B * F;
mat[9]  =  AD * F + B * E;
mat[10] =   A * C;

mat[3]  =  mat[7] = mat[11] = mat[12] = mat[13] = mat[14] = 0;
mat[15] =  1;

À l'aide des multiplications de matrices, on aurait dû faire 128 multiplications, 96 additions et 80 affectations.

Avec cet algorithme, on a fait seulement 12 multiplications, 6 soustractions et 18 affectations !

Donc, par l'utilisation de l'algorithme optimisé, on réalise un gain de 1000 % !

Créé le 13 novembre 2005  par Hexapod

Cette opération est exactement l'opposé de celle vue plus haut. Soit une matrice de rotation :

Image non disponible

Où A, B sont le cosinus et le sinus de la rotation autour de l'axe X,
C, D sont le cosinus et le sinus de la rotation autour de l'axe Y,
E, F sont le cosinus et le sinus de la rotation autour de l'axe Z.

En utilisant une structure de donnée C pour une matrice 4x4, les valeurs d'index sont les suivants :

Image non disponible

En comparant les deux tables, on constate que l'élément [2] a la valeur de -D, soit -sin(Y). Donc, la rotation autour de l'axe Y peut être calculée à l'aide d'un sinus inverse. Passer le résultat à la fonction cosinus nous donnera la valeur de C.

Si C est non nul, alors la rotation en X et en Z peut être obtenue des termes respectivement sur la troisième et la première colonne :

 
Sélectionnez

/* Axe X */
M[6]  = -B * C;
M[10] = A * C;

/* Axe Z */
M[0] = C * E;
M[1] = C * -F;

Les angles de rotation peuvent être obtenus en prenant chaque paire de valeurs divisées par C et en passant le résultat aux fonctions inverses correspondantes.

Si C est nul, ces calculs sont impossibles. Dans ce cas, l'angle de rotation en Y est de -90 ou de 90°. Donc D vaut 1 ou -1.

Dans ce cas, un gimbal lock s'est produit. Les rotations en X et Z semblent avoir le même axe. Lors du calcul de la matrice, on a :

Image non disponible

D'où :

Image non disponible

En arrangeant :

Image non disponible

On peut voir la matrice sous cette forme :

Image non disponible

Où :
V vaut BE + AF ;
W vaut AE - BF.

Ces deux valeurs peuvent être vues comme le sinus et le cosinus d'une seule rotation.

L'algorithme final est donc :

 
Sélectionnez

angle_y = D =  asin(mat[2]);           /* Calcul de l'Angle Y */
C           =  cos(angle_y);
angle_y    *=  RADIANS;

if (fabs(C) > 0.005)                /* Gimbal lock ? */
{
    trx      =  mat[10] / C;           /* Non, donc calcul de l'angle X */
    try      = -mat[6]  / C;

    angle_x  = atan2(try, trx) * RADIANS;

    trx      =  mat[0] / C;            /* Calcul de l'angle Z */
    try      = -mat[1] / C;

    angle_z  = atan2(try, trx) * RADIANS;
}
else                                   /* Gimbal lock  */
{
    angle_x  = 0;                      /* Angle X à 0 */

    trx      = mat[5];                 /* Calcul de l'angle Z */
    try      = mat[4];

    angle_z  = atan2(try, trx) * RADIANS;
}

angle_x = clamp(angle_x, 0, 360);  /* Modulo ;) */
angle_y = clamp(angle_y, 0, 360);
angle_z = clamp(angle_z, 0, 360);
Créé le 13 novembre 2005  par Hexapod

La seule façon de générer ce type de matrice de rotation est à l'aide des quaternions.

Voir http://jeux.developpez.com/faq/math/?page=quaternions#Q56 et http://jeux.developpez.com/faq/math/?page=quaternions#Q54.

Créé le 13 novembre 2005  par Hexapod

Quand on développe une application d'animation, une requête commune est de trouver la matrice de rotation qui « mappe » un vecteur direction sur un autre.

Ce problème peut être visualisé en considérant deux vecteurs directions attachés à leur base. Donc, la totalité de l'espace de rotation forme une sphère unité.

En théorie, il existe un nombre infini de rotations possibles pour rendre les deux vecteurs colinéaires. Tous ces axes sont dans le plan pour lequel tous les points appartenant au plan sont à égale distance des deux vecteurs.

Néanmoins, une seule solution est intéressante en pratique. C'est le chemin qui couvre la plus petite distance angulaire entre les deux vecteurs.

L'axe de rotation de ce chemin se calcule à l'aide du produit vectoriel entre les deux vecteurs :

Image non disponible

L'angle de rotation est calculé à l'aide du produit scalaire entre les deux vecteurs :

Image non disponible

Attention, si ceux-ci ne sont pas normalisés il faudra tenir compte de leur norme dans le calcul :

Image non disponible

Cependant, l'angle obtenu n'est pas forcément correct : en effet un cosinus peut être obtenu avec deux angles différents (cos(x) = cos(-x)). Il faudra donc trouver un moyen de déterminer s'il s'agit de x ou -x.

Créé le 13 novembre 2005  par Hexapod

De façon similaire au problème précédent, nous avons besoin de « confondre » deux systèmes de coordonnées. Néanmoins, il s'agit de faire correspondre trois axes au lieu d'un seul. Les deux systèmes sont représentés par des matrices 3x3 ou 4x4.

Le problème est donc de trouver la matrice de rotation qui va réaliser cette tâche. On peut l'exprimer mathématiquement comme :

Image non disponible

Où :
Mfinale est la matrice du système de coordonnées final,
Morig est le système de coordonnées original et
Mrot est la matrice de rotation voulue.

L'objectif est de trouver Mrot. Ceci peut être fait en réécrivant l'équation comme suit :

Image non disponible

Ainsi, la matrice de rotation peut être calculée via la multiplication de la matrice finale avec l'inverse de la matrice de départ.

Une fois calculée, cette matrice de rotation peut être conservée dans un quaternion.

Créé le 13 novembre 2005  par Hexapod

Une matrice de translation sert à positionner un objet dans l'espace sans le tourner. Les translations en 3D sous forme matricielle ne peuvent être réalisées qu'avec des matrices 4x4 (voir http://jeux.developpez.com/faq/math/?page=bases#Q1).

Si la translation se définit par un vecteur (X, Y, Z), alors on a la matrice 4x4 suivante :

Image non disponible

Si le vecteur est (0, 0, 0) alors la matrice correspondante est l'identité, et l'objet n'est pas modifié.

Créé le 13 novembre 2005  par Hexapod

C'est une matrice qui permet de grossir ou de rapetisser un modèle 3D.

Si le vecteur de mise à l'échelle est (X, Y, Z) alors la matrice qui correspond est la suivante :

Image non disponible

Si le vecteur de mise à l'échelle est (1, 1, 1), alors on obtient la matrice identité et l'objet ne change pas.

Créé le 13 novembre 2005  par Hexapod

C'est une matrice qui permet de faire en sorte qu'un modèle 3D apparaisse « penché », comme les caractères italiques par exemple.

En 3 dimensions, 6 directions de déformation existent :

  • Étirer X selon Y ;
  • Étirer X selon Z ;
  • Étirer Y selon X ;
  • Étirer Y selon Z ;
  • Étirer Z selon X ;
  • Étirer Z selon Y.

Ces 6 transformations peuvent se combiner dans une seule matrice :

Image non disponible

Où Sij représente une déformation de l'axe I selon l'axe J.

Créé le 13 novembre 2005  par Hexapod

Étant donné deux matrices de transformation, le problème est de trouver le moyen de déterminer les positions intermédiaires par une variable paramétrique t, avec t variant de 0.0 à 1.0.

Ceci peut se faire en convertissant les deux matrices en angles d'Euler ou sphériques (quaternions) et un vecteur translation.

Dans les deux cas, chaque matrice est convertie en une paire de vecteurs 3D.

L'interpolation entre chacun de ces deux vecteurs peut être réalisée via l'équation d'interpolation linéaire classique :

Image non disponible

Où :
Image non disponible est le vecteur résultant
Image non disponible est le vecteur position de départ
Image non disponible est le vecteur position finale

Cette équation s'applique aussi bien aux vecteurs de la translation qu'à celui de la rotation.

Une fois déterminées, la translation et la rotation résultantes sont converties dans la matrice intermédiaire voulue.

Créé le 13 novembre 2005  par Hexapod

Étant donné quatre matrices, le problème consiste à trouver un moyen pour déterminer les positions intermédiaires spécifiées par la variable paramétrique t.

Ceci peut être réalisé en faisant usage de l'interpolation cubique. Comme pour l'interpolation linéaire, les quatre matrices sont converties dans leurs vecteurs rotations et translations correspondants (Euler ou sphérique).

Chaque ensemble de 4 vecteurs est alors converti en un unique vecteur géométrique G. À l'aide des mathématiques des splines, ce vecteur est converti en une matrice d'interpolation M.

Si G est défini comme tel :

Image non disponible

Alors, la multiplication par la matrice de base :

Image non disponible

Va générer une matrice d'interpolation 3x4 Mi :

Image non disponible

Ceci peut être implémenté à l'aide d'une multiplication standard matrice-vecteur.

L'interpolation peut être faite par l'usage de la variable paramétrique t :

Image non disponible

Le vecteur résultant peut être converti en une matrice de rotation ou de translation.

Il doit être noté que les chemins de rotation générés peuvent sembler quelque peu acrobatiques. C'est normal dans le sens que l'algorithme essaye de trouver le chemin avec le minimum de rotations entre les 4 vecteurs.

Des angles d'Euler ou sphériques, ces derniers semblent en général être plus « propres » pour cette interpolation.

Créé le 13 novembre 2005  par Hexapod
  

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 © 2005-2014 Developpez LLC et al. 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.