FAQ Matrices et Quaternions ============================== Version 1.4 Octobre 2000 ------------------------- Traduction : BISMI Mustapha Date de traduction 7/10/2000 Document final;) http://www.javamus.fr.st javamus@hotmail.com Cette FAQ est maintenue par "hexapod@netcom.com". Toutes suggestions ou questions relatives sont les bienvenues. La dernière copie de ce document peut être trouvé sur les pages web suivantes: ftp://ftp.netcom.com/pub/he/hexapod/index.html --> English version http://www.glue.umd.edu/~rsrodger --> English version http://www.javamus.fr.st --> French version La distribution et la copie de ce document est libre ;) Contributions ------------- Introduction I1: steve@mred.bgm.link.com Introduction ------------ I1. Notes Importantes sur ce document et OpenGL. I2. A propos de cette traduction et autres mises en gardes. Questions --------- BASES ===== Q1. Qu'est ce qu'une matrice? Q2. Quel est l'ordre d'une matrice? Q3. Comment représenter une matrice en C/C++? Q4. Quelles sont les avantages à utiliser des matrices? Q5. Comment relier les matrice au système de coordonnées? ARITHMETIQUE ============ Q6. Qu'est ce que la matrice identité? Q7. Qu'est ce que la diagonale d'une matrice? Q8. Qu'est ce que la transposée d'une matrice? Q9. Comment ajouter deux matrices? Q10. Comment soustraire deux matrices? Q11. Comment multiplier deux matrices? Q12. Comment mettre une matrice à une puissance quelconque? Q13. Comment multiplier un ou plusieurs vecteurs par une matrice? DETERMINANTS ET INVERSES ======================== Q14. Qu'est ce que le déterminant d'une matrice? Q15. Comment calculer le déterminant d'une matrice? Q16. Qu'est ce qu'une matrice Isotrope ou Anisotrope? Q17. Qu'est ce que l'inverse d'une matrice? Q18. Comment calculer l'inverse d'une matrice quelconque? Q19. Comment calculer l'inverse d'une matrice identité? Q20. Comment calculer l'inverse d'une matrice de rotation? Q21. Comment calculer l'inverse d'une matrice à l'aide de Kramer? Q22. Comment calculer l'inverse d'une matrice 2x2? Q23. Comment calculer l'inverse d'une matrice 3x3? Q24. Comment calculer l'inverse d'une matrice 4x4? Q25. Comment calculer l'inverse d'une matrice à l'aide d'équations linéaires? TRANSFORMATIONS =============== Q26. Qu'est ce qu'une matrice de rotation? Q27. Comment les matrices de rotations interagissent avec le système de coordonnées? Q28. Comment générer une matrice de rotation d'axe X? Q29. Comment générer une matrice de rotation d'axe Y? Q30. Comment générer une matrice de rotation d'axe Z? Q31. Qu'est ce que les angles d'Euler? Q32. Qu'est ce que le tanguage (yaw), le roulis (roll) et l'orientation (pointer vers le bas/haut, pich)? Q33. Comment combiner les matrices de rotations? Q34. Qu'est ce que la perte d'un degré de liberté? Q35. Quel est la manière correcte de combiner les matrices de rotations? Q36. Comment générer une matrice de rotation à partir d'angles d'Euler? Q37. Comment générer des angles d'Euler à partir d'une matrice de rotation? Q38. Comment générer une matrice de rotation pour un axe et un angle donné? Q39. Comment générer une matrice de rotation pour rendre deux vecteurs colinéaires? Q40. Comment utiliser les matrices pour convertir entre deux systèmes de coordonnées? Q41. Qu'est ce qu'une matrice de translation? Q42. Qu'est ce qu'une matrice de mise à l'échelle? Q43. Qu'est ce que qu'une matrice de déformation? Q44. Comment réaliser une interpolation linéaire entre deux matrices? Q45. Comment réaliser une interpolation cubique entre quatre matrices? Q46. Comment rendre une matrice? QUATERNIONS =========== Q47. Qu'est ce que les quaternions? Q48. Quel est le rapport entre les quaternions et l'animation 3D? Q49. Comment calculer le conjugué d'un quaternion? Q50. Comment calculer l'inverse d'un quaternion? Q51. Comment calculer la norme d'un quaternion? Q52. Comment normaliser un quaternion? Q53. Comment multiplier deux quaternions? Q54. Comment convertir un quaternion en matrice de rotation? Q55. Comment convertir une matrice de rotation en un quaternion? Q56. Comment convertir un axe de rotation et un angle en un quaternion? Q57. Comment convertir un quaternion en un axe de rotation et un angle? Q58. Comment convertir des angles de rotations sphériques en un quaternion? Q59. Comment convertir un quaternion en des angles de rotations sphériques? Q60. Comment convertir des angles d'Euler en un quaternion? Q61. Comment utiliser des quaternions pour réaliser une interpolation linéaire entre matrices? Q62. Comment utiliser les quaternions pour réaliser une interpolation cubique entre matrices? Introduction ------------ I1. Notes Importantes sur ce document et OpenGL. --------------------------------------------------------------- Dans ce document(comme dans la plupart des livres de maths), toutes les matrices sont représentées de la manière standard mathèmatique. Malheureusement, les librairies graphiques comme IrisGL, OpenGL et SGI Performer les représentent tous avec les colonnes et les lignes inversées. Par exemple, vous verrez dans ce document une matrice de translation comme suit : | 1 0 0 X | | | | 0 1 0 Y | M = | | | 0 0 1 Z | | | | 0 0 0 1 | En Performer, elle sera codée comme suit: M[0][1] = M[0][2] = M[0][3] = M[1][0] = M[1][2] = M[1][3] = M[2][0] = M[2][1] = M[2][3] = 0 ; M[0][0] = M[1][1] = M[2][2] = m[3][3] = 1 ; M[3][0] = X ; M[3][1] = Y ; M[3][2] = Z ; cad, la matrice est stockée de cette façon: | M[0][0] M[1][0] M[2][0] M[3][0] | | | | M[0][1] M[1][1] M[2][1] M[3][1] | M = | | | M[0][2] M[1][2] M[2][2] M[3][2] | | | | M[0][3] M[1][3] M[2][3] M[3][3] | OpenGL utilise un tableau à une dimension pour stocker les matrices - mais heureusement, l'ordre de stackage résulte dans le même agencement d'octets en mémoire - du coup, prendre l'adresse d'une pfMatrix et le caster en float* devrait vous permettre de le passer directement dans les routines comme glLoadMatrixf. ( NdT: Je n'ai pas essayé, mais il y a dans cette iddée de quoi dresser les cheveux sur la tête de tous les fans de Génie Logiciel!) Dans les bouts de code dispersés dans ce document, une matrice uni dimensionnel est utilisé pour stocker une matrice. L'ordre des éléments respecte celui d'OpenGL. Document OpenGL | 0 1 2 3 | | 0 4 8 12 | | | | | | 4 5 6 7 | | 1 5 9 13 | M = | | M = | | | 8 9 10 11 | | 2 6 10 14 | | | | | | 12 13 14 15 | | 3 7 11 15 | I2. A propos de cette traduction et autres mises en gardes. --------------------------------------------------------------- Ce document n'est qu'une traduction plus ou moins parfaite. De nombreuses réponses proposées ici peuvent être soumises à des critiques justifiées, et ne parlons pas de la forme. Si vous êtes novices dans le domaine de l'infographie, ce document ne vous sera d'aucune utilité, car en aucun cas il ne vous dispensera de devoir apprendre les bases de l'algébre linéaire. De plus, certains thèmes très importants ne sont pas évoqués ici, comme les coordonnées homogénes... Par contre, si vous connaissez un peu le sujet, peut être trouverez-vous ici un élément de réponse ou une piste pour résoudre un des problèmes qui se pose à vous. Quoiqu'il en soit, amusez-vous bien ;) Mustapha BISMI Réponses -------- BASES ===== Q1. Qu'est ce qu'une matrice? ---------------------- Une matrice est un tableau a deux dimension de données numériques, dans laquelle chaque ligne ou colonnes contient une ou plusieurs valeurs numériques. Les opération arithmétiques que l'on peut réaliser sur les matrices comprenent l'addition, la subtraction, la multiplication et la division. La taille d'une matrice est défini en terme de nombres de lignes et de colonnes. Une matrice avec M lignes et N colonnes est une matrice MxN. Les éléments d'une matrice sont référencés à l'aide de deux valeurs d'index. La notation mathématique "classique" les assignent aux variables 'i' (lignes) et 'j' (colonnes). Par exemple, si on consodère une matrice de taille 4x4, alors les éléments de la matrice sont indéxés par les couples lignes|colonnes : | 00 10 20 30 | M = | 01 11 21 31 | | 02 12 22 32 | | 03 13 23 33 | L'élément en haut à droite de la matrice a i=0 et j=3 On l'identifie comme suit: M = M i,j 0,3 En informatique graphique, les matrices les plus communes ont 2, 3 ou 4 lignes et colonnes. ce sont les matrices 2x2, 3x3 et 4x4. Les matrices 2x2 sont utiles pour les rotations, les découpages et pour différents types de traitement d'images. L'usage génériques des matrices NxN peut être l'application de fonctions de traitement d'images comme la convolotion. Les matrices 3x3 servent pour les "petits" moteurs 3D. Des opérations comme la rotation et la multiplication peuvent être réalisées via ces matrices, mais la projection en perspective est faite via des opérations de divisions. Les matrices 4x4 sont utilisées par les moteurs 3D performants. Des opérations comme la multiplication et la projection perspective peuvent être réalisées à l'aide de ces matrices. Q2. Quel est l'ordre d'une matrice? ------------------------------------- L'ordre d'une matrice est l'autre dénomination de la taille d'une matrice. Une matrice à M lignes et N colonnes est dites d'ordre MxN. Q3. Comment représenter une matrice en C/C++? ----------------------------------------------------------------------- La façon la plus simple pour définir une matrice en C/C++ est d'utiliser le mot clé "typedef". Les matrices 3x3 et 4x4 peuvent par exemple être définies comme suit : typedef float MATRIX3[9]; typedef float MATRIX4[16]; Comme chaque type de matrice est de dimensions 3x3 ou 4x4, il recquiert respectivement 9 et 16 éléments de données. A première vue, l'usage d'un tableau uni dimensionnelle peut sembler contre-nature. L'usage de tableaux bi-dimensionnelle peut donc semble plus simple: typedef float MATRIX3[3][3]; typedef float MATRIX4[4][4]; Néanmoins, l'usage de deux systèmes de références pour chaque élément de la matrice prète souvent à confusion. En effet, l'ordre mathématique pour les lignes et les colonnes est : Mij En C/C++, il devient matrix[j][i] De plus, l'usage de tableaux bi-dimensionnelle provoquent une baisse de performance dans le sens que les compilateurs C font souvent l'usage d'opérations de multiplications pour résoudre les opérations d'index. Du coup, il est plus efficace de travailler avec des tableaux linéaires. Alors, comment mapper un tableaux bi dimensionnelle dans un simple tableau à une dimension? Il n'y a que deux méthodes (lignes d'abord puis colonnes et vice versa). La différence de performance entre les deux est subtil. En effet, le choix peut avoir des conséquence sur des opérations comme les multiplications de matrices. Voici le meilleur ordenancement à utiliser en C/C++: mat[0] = M mat[3] = M 00 03 mat[12] = M mat[15] = M 30 33 | 0 1 2 3 | | | | 0 1 2 | | 4 5 6 7 | | | M = | | M = | 3 4 5 | | 8 9 10 11 | | | | | | 6 7 8 | | 12 13 14 15 | Q4. Quelles sont les avantages à utiliser des matrices? ----------------------------------------------- L'une des premières questions sur les matrices est pourquoi sont elles tellement utilisées en Informatique. Intuitivement, il semble que la surcharge dut aux boucles for-next et aux multiplications de matrices devrait plus ralentir l'application qu'autres choses. Cette objection ne tient pas compte de l'usage des registres CPU pour gérer les compteurs et des caches de données qui optimise l'accès mémoires. De plus, en suivant une approche mathématique pour définir les algorithmes 3D, il est possible de prévoir et de planifier le design d'un système d'animation 3D. Une telle approche permet très simplement d'enviseager l'implémentation de l'animation des personnages, des courbes splines, la cinématique inverse... Néanmoins, une des objection qui revient fréquement est qu'il serait plus rapide de juste multiplier chaque paire de coordonnées par les coéfficients de rotation pour cette axe, au lieu de réaliser une multiplication vecteur/ matrice. ie. Rotation en X transforme Y et Z Rotation en Y transforme X et Z Rotation en Z transforme X et Y Ce qui revient à ceci: Soient un vertex V = (x,y,z), les angles de rotation (A,B et C) et les translations (D,E,F). L'alogorithme est défini comme suit: --------------------------- sx = sin(A) // Setup - une seule fois cx = cos(A) sy = sin(B) cy = cos(B) sz = sin(C) cz = cos(C) x1 = x * cz + y * sz // Rotation de chaque vertex y1 = y * cz - x * sz z1 = z x2 = x1 * cy + z1 * sy y2 = z1 z2 = z1 * cy - x1 * sy x3 = x2 y3 = y2 * cx + z1 * sx z3 = z2 * cx - x1 * sx xr = x3 + D // Translation de chaque vertex yr = y3 + E zr = z3 + F --------------------------- Voici le taux de calcul pris par cette algorithme: Setup Par vertex --------------------------- ------------------------ 6 fonctions trigonometrique 6 operations d'assignement. 12 assignements 12 multiplications 9 additions --------------------------- ------------------------ Admettons qu'il est possible de réaliser la même chose par des multiplication de matrice.. Pour une matrice 4x4, on a: Setup Differ Par vertex Differ -------------------------- ------ ------------------------ ------ 6 fonctions trigonometrique 0 0 18 assignements -12 3 assignements -9 12 multiplications +12 9 multiplications -3 6 soustractions +6 6 additions -3 -------------------------- ------ ------------------------ ------ En comparant les deux tables, on peut constater que la préparation d'une matrice de rotation coute au moins 12 multiplications et 12 appels d'assignement en plus. Néanmoins, alors que cela peut sembler étrange, l'économie vient du calcul de chaque vertex. En utilisant la multiplication de matrice, l'économie faite en calculant juste 4 vertex rattrape la dépense faite plus haut! Q5. Comment relier les matrice au système de coordonnées? -------------------------------------------------- La relation entre les matrices 3x3 ou 4x4 et le système de coordonnées est simple. Les 3 premières colonnes de la matrice définissent les vecteurs direction respectivement des axes X, Y et Z. Si une matrice 4x4 est définie en tant que: | A B C D | M = | E F G H | | I J K L | | M N O P | Alors, le vecteur direction pour chaque axe est le suivant: axe X = [ A E I ] axe Y = [ B F J ] axe Z = [ C G K ] ARITHMETIQUE ============ Q6. Qu'est ce que la matrice identité? --------------------------------- La matrice identité est une matrice qui a autant de colonnes que de lignes, et pour laquelle touts les éléments telles que i=j valent 1 et les autres 0. Par exemple: | 1 0 0 0 | M = | 0 1 0 0 | | 0 0 1 0 | | 0 0 0 1 | Q7. Qu'est ce que la diagonale d'une matrice? -------------------------------------------- La diagonale principale d'une matrice est l'ensemble des éléments pour lesquelles le numéro de la ligne est égale à celui de la colonne. M où i=j ij Dans le cas de la matrice identité, seul les éléments sur la diagonale sont mis à la valeur 1, tandis que les autres sont à 0. Q8. Qu'est ce que la transposée d'une matrice? --------------------------------------- La transposée d'une matrice est la matrice généré par l'inversion des éléments de la matrice d'origine par rapport à la diagonale: M' = M ij ji Néanmaoins, cette opération ne peut être réalisée que sur une matrice carrée. Soit M: | 0.707 -0.866 | M = | | | 0.866 0.707 | La transposé de M est: | 0.707 0.866 | T = | | | -0.866 0.707 | Si la matrice est une matrice de rotation, la transposé est la rotation inverse. Q9. Comment ajouter deux matrices? ---------------------------------------- L'addition peut s'exprimer comme suit: R = M + L ij ij ij Néanmoins, les deux matrices doivent être de taille identique. Par exemple: R = M + L | A B C | | J K L | | | | | = | D E F | + | M N O | | | | | | G H I | | P Q R | | A+J B+K C+L | | | = | D+M E+N F+O | | | | G+P H+Q I+R | Q10. Comment soustraire deux matrices? ------------------------------------- Cette opération est aussi simple que l'addition: R = M - L ij ij ij Néanmoins, les deux matrices doivent être de tailles identiques. Par exemple: R = M - L | A B C | | J K L | | | | | = | D E F | - | M N O | | | | | | G H I | | P Q R | | A-J B-K C-L | | | = | D-M E-N F-O | | | | G-P H-Q I-R | Q11. Comment multiplier deux matrices? --------------------------------------------- Il faut multiplier chaque élément d'une ligne de la première matrice avec chaque élément d'une colonne de la seconde et faire la somme. On peut l'exprimer comme suit: n -- R = \ M x L ij / ij ji -- i=1 Si les deux matrices sont d'ordres : M = AxB et L = CxD alors les deux valeurs B et C doivent être identique. Dans ce cas, la matrice résultante est d'ordre AxD. De plus, il est possible de multiplier une matrice 4x4 par une matrice 4xN, mais pas l'inverse. Par exemple, si M est définie par: | A B C D | M = | E F G H | | I J K L | | M N O P | et L par: L = | Q R | | S T | | U V | | W X | alors, la taille de la matrice résultante est 2x4: R = M x L | A B C D | | Q R | = | E F G H | x | S T | | I J K L | | U V | | M N O P | | W X | | AQ+BS+CU+DW AR+BT+CV+DX | = | EQ+FS+GU+HW ER+FT+GV+HX | | IQ+JS+KU+LW IR+JT+KV+LX | | MQ+NS+OU+PW MR+NT+OV+PX | Q12. Comment elever une matrice à une puissance quelconque? -------------------------------------------------- Une matrice peut être élever à n'importe quel puissance entière. Néanmoins, il y a plusieurs restrictions. Pour chaque puissance, la matrice doit rester orthogonal ie avoir le même nombre de lignes et de colonne. Par example, -1 M est l'inverse de la matrice. 0 M génére la matrice identité. 1 M ne modifie pas la matrice. 2 M Matrice au carré 3 M Matrice au cube Elever une matrice à une puissance supérieur à 1 revient à la multiplier par elle-même un nombre spécifique de fois. Par example, 2 M = M . M 3 M = M . M . M Elever la matrice identité a n'importe quelle puissance conserve la matrice identité. n I = I Q13. Comment multiplier un ou plusieurs vecteurs par une matrice? ------------------------------------------------------- Le meilleur moyen de réaliser cette tache est de traité la liste de vecteurs comme une simple matrice, dont chaque vecteurs representent un vecteur colonne. Si N vecteurs doivent être multiplié par une matrice 4x4, ils peuvent être traitée comme une unique matrice 4xN: Soit la matrice: | A B C D | M = | E F G H | | I J K L | | M N O P | et la liste de vecteurs suivantes: | x1 x2 x3 x4 x5| V = | y1 y2 y3 y4 y5| | z1 z2 z3 z4 z5| | 1 1 1 1 1| Remarquez qu'une ligne de termes constants est ajoutée à la liste de vecteurs, tous à 1.0. Cette ligne ne devrait pas exister. C'est simplement pour permettre la correspondance entre les ordres de M et de V. Exemple de multiplication: M . V = V' | A B C D | | x1 x2 x3 x4 x5 | | A.x1+B.y1+C.z1+D A.x2+B.y2+C.z2+D ... | | E F G H | . | y1 y2 y3 y4 y5 | = | E.x1+F.y1+G.z1+H E.x2+F.y2+G.z2+H ... | | I J K L | | z1 z2 y3 y4 z5 | | I.x1+J.y1+K.z1+L I.x2+J.y2+K.z2+L ... | | M N O P | | 1 1 1 1 1 | | M.x1+N.y1+O.z1+P M.x2+N.y2+O.z2+P ... | Pour chaque vecteur de la liste, il y aura un total de 12 multiplications, 16 additions et 1 division (pour la perspective). Si la matrice est une matrice de rotation ou de translation, la division peut être annulée. DETERMINANTS ET INVERSES ======================== Q14. Qu'est ce que le déterminant d'une matrice? ----------------------------------------- Le déterminant d'une matrice est un réel qui permet de entre autres de savoir si la matrice a ou non un inverse. Si il est nul, aucun inverse n'existe. Par exemple, soit la matrice a un seul élément: M = [ 1 ]. Pour une matrice de cette taille, le déterminant est simplement la valeur de l'élément. Du coup, l'inverse est simplement l'inverse de cet élément: -1 M = [ 1 / M[0][0] ] Si cette valeur est non nul, l'inverse existe. Dans le cas de la matrice identité, l'inverse est la matrice identité. Néanmoins, si la valeur de l'élément est nul, le déterminant est nul également. Essayer de calculer la réciproque de zéro génére l'infini, ce qui entraine que cette matrice n'a pas d'inverse. Pour la matrice identité, le déterminant est toujours 1. Toutes matrices avec un déterminant égal à 1 est dite isotropique. Ainsi, toutes les matrices de rotations sont dites isotropiques, puisque leurs déterminant est toujours égal à 1. Par exemple, soit M une matrice de rotation, et D son déterminant. On a : | A B | | cos X -sin X | M = | | = | | | C D | | sin X cos X | D = AD - BC D = (cos X . cos X) - (-sin X . sin X) 2 2 D = (cos X ) + (sin X) 2 2 Mais, cos X + sin X = 1 Donc, D = 1 Q15. Comment calculer le déterminant d'une matrice? ---------------------------------------------------- Le déterminant d'une matrice se calcul à l'aide des règles de Kramer, qui permet de le calculer en découpant la matrice en des matrices plus petites. Exemple : | A B | M = | | | C D | D = AD - BC Pour une matrice 3x3: | A B C | M = | D E F | | G H I | D = A(EI-HF) - B(FG-DI) + C(DH-GE) Q16. Qu'est ce qu'une matrice Isotrope ou Anisotrope? ------------------------------------------------- Une matrice isotrope est une matrice pour laquelle la somme des carrée des 3 lignes ou colonnes est supérieur à 1. Une matrice qui n'est pas dans ce cas est dites Anisotrope. Quand une matrice 3x3 ou 4x4 est utilisé pour tourner ou mettre à l'échelle un objet, il est parfois nécéssaire d'agrandir ou de rétrécir un axe plus qu'un autre. Par exemple, ca peut être utile de vouloir déformer un personnage de type cartoon vers un axe mais pas dans les autres... Voici une matrice de ce type: | 2 0 0 0 | M = | 0 2 0 0 | | 0 0 0.5 0 | | 0 0 0 1 | Néanmoins, bien que ce type de matrice s'applique bien pour les vertex, il se peut très bien qu'il ait des problème avec les normales, en particulier en ombrage de Gouraud. En effet, les données vertex et les normales sont multipliés par la même matrice, ce qui déforme les normales. N'étant plus normalisé, elles peuvent perturber d'autres calculs comme l'ombrage (shading) ou l'élimination des parties cachées (back-face culling). Q17. Qu'est ce que l'inverse d'une matrice? ------------------------------------- -1 Etant donnée une matrice M, l'inverse de cette matrice, noté M est la matrice qui vérifie cette expression: -1 M . M = I ou I est la matrice identité. Ainsi, multiplier une matrice par son inverse génére la matrice identité. Néanmoins, plusieurs conditions doivent être réuni pour pouvoir calculer l'inverse d'une matrice. Celles ci incluent que la hauteur et que la largeur de la matrice soient identiques, et que le déterminant de la matrice soit non nul. Le calcul de l'inverse d'une matrice est une tâche souvent réalisée pour implémenter la cinématique inverse suivant des courbes splines. Q18. Comment calculer l'inverse d'une matrice quelconque? ---------------------------------------------------------- En fonction de la taille de la matrice, le calul de son inverse peut être trivial ou extrèmement compliqué. Par exemple, l'inverse d'une matrice 1x1 est juste la réciproque de l'élément: M = | x | -1 | 1 | M = | - | | x | La résolution pour les matrices 2x2 ou plus peut être réalisé à l'aide de Kramer ou via un ensemble d'équations. Néanmoins, dans certains cas comme les matrices identités ou de rotations, l'inverse est déjà connu ou peut être déterminé à l'aide de la transposée de la matrice. Q19. Comment calculer l'inverse d'une matrice identité? ---------------------------------------------------------- L'inverse d'une matrice identité est la matrice identité : -1 I . I = I La matrice identité a pour déterminant la valeur 1. Q20. Comment calculer l'inverse d'une matrice de rotation? --------------------------------------------------------- Une telle matrice a toujours un déterminant égale à 1, calculer son iverse est équivalent à calculer sa transposée. Une autre façon de faire, si l'angle (NdT : Et l'axe !) de rotation est connu, alors il suffit de prendre l'opposé de l'angle ( -20 pour 20 par exemple) et de calculer une nouvelle matrice de rotation. Q21. Comment calculer l'inverse d'une matrice à l'aide de Kramer? -------------------------------------------------------------------- Soit une matrice 3x3: | A B C | | | M = | D E F | | | | G H I | Alors, le déterminant se calcul comme suit: n --- \ i det M = / M * submat M * -1 --- 0,i 0,i i=1 où submat M ij défini la matrice composé de toutes les lignes et de toutes les colonnes de M à l'exception de la ligne i et de la colonne j. submat M peut être appellé de manière récursive. ij Si le déterminant est non nul, l'inverse de la matrice existe. Dans ce cas, la valeurs de chaque élément de l'inverse est: -1 1 i+j M = ----- * det submat M * -1 j,i det M i,j Q22. Comment calculer l'inverse d'une matrice 2x2? ---------------------------------------------------- Pour une matrice 2x2, les calculs sont moins complexe. Soit: | A B | M = | | | C D | Le déterminant est: det = AD - BC Et l'inverse se défini par: -1 1 | D -B | M = --- | | det | -C A | Ceci peut être démontré par les rêgles de Kramer. Soit: | A B | M = | | | C D | Alors, le déterminant est: 0 1 det = M * submat M * -1 + M * submat M * -1 0,0 0,0 0,1 0,1 <=> M * M * 1 + M * M * -1 0,0 1,1 0,1 1,0 <=> A * D + B * C * -1 <=> AD + BC . -1 <=> AD - BC ============== Et l'inverse s'obtient par: -1 0+0 -1 M = det submat * -1 <=> M = M * 1 <=> D 0,0 0,0 0,0 1,1 -1 1+0 -1 M = det submat * -1 <=> M = M * -1 <=> C * -1 0,1 1,0 0,1 1,0 -1 0+1 -1 M = det submat * -1 <=> M = M * -1 <=> B * -1 1,0 0,1 1,0 0,1 -1 1+1 -1 M = det submat * -1 <=> M = M * 1 <=> A 1,1 1,1 1,1 0,0 Donc l'inverse de la matrice est: -1 1 | D -C | M = --- | | det | -B A | si le déterminant est non nul. Q23. Comment calculer l'inverse d'une matrice 3x3? ---------------------------------------------------- Pour les matrices 3x3 ou plus, l'inverse peut être calculer soit à l'aide de Kramer, soit par la résolution d'un ensemble d'équations linéaires. Si ont applique les règles de Kramer à la matrice M: | A B C | M = | D E F | | G H I | Alors, le déterminant se calcul comme suit: det M = A * (EI - HF) - B * (DI - GF) + C * (DH - GE) En supposant que ce déterminant est non nul, alors, l'inverse de la matrice est donnée par: -1 1 | EI-FH -(BI-HC) BF-EC | M = ----- . | -(DI-FG) AI-GC -(AF-DC) | det M | DH-GE -(AH-GB) AE-BD | Ceci peut s'implémenter à l'aide d'une pair de fonctions 'C': --------------------------------- VFLOAT m3_det( MATRIX3 mat ) { VFLOAT det; det = mat[0] * ( mat[4]*mat[8] - mat[7]*mat[5] ) - mat[1] * ( mat[3]*mat[8] - mat[6]*mat[5] ) + mat[2] * ( mat[3]*mat[7] - mat[6]*mat[4] ); return( det ); } ---------------------------------- void m3_inverse( MATRIX3 mr, MATRIX3 ma ) { VFLOAT det = m3_det( ma ); if ( fabs( det ) < 0.0005 ) { m3_identity( ma ); return; } mr[0] = ma[4]*ma[8] - ma[5]*ma[7] / det; mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det; mr[2] = ma[1]*ma[5] - ma[4]*ma[2] / det; mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det; mr[4] = ma[0]*ma[8] - ma[6]*ma[2] / det; mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det; mr[6] = ma[3]*ma[7] - ma[6]*ma[4] / det; mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det; mr[8] = ma[0]*ma[4] - ma[1]*ma[3] / det; } --------------------------------- Q24. Comment calculer l'inverse d'une matrice 4x4? ---------------------------------------------------- Les mêmes méthodes peuvent être appliquées aux matrices 3x3 et aux matrices 4x4. Un moyen efficace est de réutiliser les fonctions 'C' utilisées pour calculer le déterminant et l'inverse d'une matrice 3x3. Pour pouvoir utiliser les rêgles de Kramer, il est nécéssaire de déterminer les sous-matrices: -------------------------- void m4_submat( MATRIX4 mr, MATRIX3 mb, int i, int j ) { int ti, tj, idst, jdst; for ( ti = 0; ti < 4; ti++ ) { if ( ti < i ) idst = ti; else if ( ti > i ) idst = ti-1; for ( tj = 0; tj < 4; tj++ ) { if ( tj < j ) jdst = tj; else if ( tj > j ) jdst = tj-1; if ( ti != i && tj != j ) mb[idst*3 + jdst] = mr[ti*4 + tj ]; } } } -------------------------- Le déterminant d'une matrice 4x4 peut être calculée comme suit: -------------------------- VFLOAT m4_det( MATRIX4 mr ) { VFLOAT det, result = 0, i = 1; MATRIX3 msub3; int n; for ( n = 0; n < 4; n++, i *= -1 ) { m4_submat( mr, msub3, 0, n ); det = m3_det( msub3 ); result += mr[n] * det * i; } return( result ); } -------------------------- Et l'inverse: -------------------------- int m4_inverse( MATRIX4 mr, MATRIX4 ma ) { VFLOAT mdet = m4_det( ma ); MATRIX3 mtemp; int i, j, sign; if ( fabs( mdet ) < 0.0005 ) return( 0 ); for ( i = 0; i < 4; i++ ) for ( j = 0; j < 4; j++ ) { sign = 1 - ( (i +j) % 2 ) * 2; m4_submat( ma, mtemp, i, j ); mr[i+j*4] = ( m3_det( mtemp ) * sign ) / mdet; } return( 1 ); } -------------------------- Ces fonctions sont d'une utilité incroyable. Elles permettent le calcul de la matrice de base pour les splines, les rotations inverses et la résolution d'équations matricielles. Q25. Comment calculer l'inverse d'une matrice à l'aide d'équations linéaires? ----------------------------------------------------------------------- Soit M: | A B C | M = | D E F | | G H I | telle que l'inverse existe: | P Q R | M' = | S T U | | V W X | alors, on a: -1 M . M = I | A B C | | P Q R | | 1 0 0 | | D E F | . | S T U | = | 0 1 0 | | G H I | | V W X | | 0 0 1 | Donc, la matrice inverse peut être calculée par la résolution d'un ensemble d'équations linéaires: | AP + BS + CV | | 1 | Column 0 (X) | DP + ES + FV | = | 0 | | GP + HS + IV | | 0 | | AQ + BT + CW | | 0 | Column 1 (Y) | DQ + ET + FW | = | 1 | | GQ + HT + IW | | 0 | | AR + BU + CX | | 0 | Column 2 (Z) | DR + EU + FX | = | 0 | | GR + HU + IX | | 1 | TRANSFORMATIONS =============== Q26. Qu'est ce qu'une matrice de rotation? ------------------------------- Une matrice de rotation est utilisé pour tourner un ensemble de point dans un système de coordonnées. Chaque point a de nouvelles coordonnées, mais leurs distances relatives 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 a deux dimensions, la matrice de rotation est la suivante: | cos(A) -sin(A) | | | | sin(A) cos(A) | Quand l'angle A est nul, on génére la matrice identité: | 1 0 | I = | | | 0 1 | Si A vaut +90 degrées, on a la matrice: | 0 -1 | M = | | | 1 0 | Si l'angle vaut -90 degrées: | 0 1 | M = | | | -1 0 | Prendre l'opposée de l'angle revient à transposer la matrice. Si la matrice de rotation est multipliée par sa transposé, le résultat est la matrice identitée. Q27. Comment les matrices de rotations interagissent avec le système de coordonnées? ------------------------------------------------------ Les conventions mathématiques veulent qu'une rotation positive génére une rotation dans le sens opposé des aiguilles d'une montre. On considére 3 matrices de rotations cartésiennes. Soit un système de coordonnées main droite. Pour chaque axe de rotation, regardons le long de chaque axe vers les valeurs positives: +----------------------------------------+ | | | axe X axe Y axe Z | | | | | | ^ Y ^ Z Y ^ | | | | | | | | | | | | | | | | | | | | | | O----> Z O----> X X <----O | | | +----------------------------------------+ Puisque que l'on connait le sens de rotation, il est possible de générer un ensemble de coordonnées mappées pour chaque rotation. Considérons une rotation de +90°: Considérons l'axe X, on obtient: ( 0, 1, 0 ) --> ( 0, 0, 1 ) ( 0, 0, 1 ) --> ( 0,-1, 0 ) ( 0,-1, 0 ) --> ( 0, 0,-1 ) ( 0, 0,-1 ) --> ( 0, 1, 0 ) Ce qui peut peut se simplifier par: X' = X Y' = -Z Z' = Y On peut donc écrire la matrice suivante: | 1 0 0 | Rx = | 0 cos A -sin A | | 0 sin A cos A | De même avec l'axe Y: ( 0, 0, 1) --> ( 1,0, 0) ( 1, 0, 0) --> ( 0,0,-1) ( 0, 0,-1) --> (-1,0, 0) (-1, 0, 0) --> ( 0,0, 1) Plus simplement, on a: X' = Z Y' = Y Z' = -X D'où la matrice: ( 0, 1, 0 ) --> ( -1, 0, 0 ) (-1, 0, 0 ) --> ( 0, -1, 0 ) ( 0,-1, 0 ) --> ( 1, 0, 0 ) ( 1, 0, 0 ) --> ( 0, 1, 0 ) Donc: X' = -Y Y' = X Z' = Z Ce qui donne: | cos A -sin A 0 | Rz = | sin A cos A 0 | | 0 0 1 | Voici les trois matrices de rotation de base en OpenGL :) Q28. Comment générer une matrice de rotation d'axe X? ------------------------------------------------------- Utilisez la matrice 4x4 suivante: | 1 0 0 0 | M = | 0 cos(A) -sin(A) 0 | | 0 sin(A) cos(A) 0 | | 0 0 0 1 | Q29. Comment générer une matrice de rotation d'axe Y? ------------------------------------------------------- Utilisez la matrice 4x4 suivante: | cos(A) 0 -sin(A) 0 | M = | 0 1 0 0 | | sin(A) 0 cos(A) 0 | | 0 0 0 1 | Q30. Comment générer une matrice de rotation d'axe Z? ------------------------------------------------------- Utilisez la matrice 4x4 suivante: | cos(A) -sin(A) 0 0 | M = | sin(A) cos(A) 0 0 | | 0 0 1 0 | | 0 0 0 1 | Q31. Qu'est ce que les angles d'Euler? --------------------------- Les angles d'Euler sont le nom donnée à un ensemble d'angles de rotation qui spécifie chacune une rotation autour des axes X, Y et Z. Ils sont spécifié sous la forme d'un vecteur |x y z| et peuvent être stocké comme une structure de donnée VECTOR. Exemple: | 0 0 0 | générera la matrice identité. | 90 0 0 | est une rotation de 90° autour de l'axe X. | 0 90 0 | est une rotation de 90° autour de l'axe Y et | 0 0 90 | est une rotation de 90° autour de l'axe Z. Q32. Qu'est ce que le tanguage (yaw), le roulis (roll) et l'orientation (pointer vers le bas/haut, pich)? ---------------------------------- Ces termes (NdT : Please, help, comment bien les traduire ?) sont d'origine aéronautique et correspondent aux rotations à l'aide des angles d'Euler (Système de Coordonnée 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. Le piqué devient la rotation sur l'axe X, le tanguage devient Y et le roulis la rotation autour de l'axe Z. Q33. Comment combiner les matrices de rotations? ---------------------------------------- Les matrices de rotations se combinent en les multipliant entre elles. Attention à l'ordre dans lequel vous les multiplier ! Sinon... Q34. Qu'est ce que la perte d'un degré de liberté? ------------------------- Le problème de la perte d'un degré de liberté, le "Gimbal 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 confondu 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, toutes rotation autour de l'axe X tourne l'objet suivant Z! Pire encore, il est devenue impossible de tourner l'objet autour de l'axe X. La seule solution a ce problème est d'utiliser les quaternions. Q35. Quel est la manière correcte de combiner les matrices de rotations? ---------------------------------------------------------- En réalité, il n'y a pas de façon correcte de combiner les matrices de rotations. Néanmoins, afin de prédire les résultats de la combinaison des matrices, un peu d'organisation est nécéssaire. Le moyen le plus simple de tourner un objet est de multiplier les matrices dans cette ordre: M = X.Y.Z 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 est inversé. Par exemple, si vous êtes debout, et que vous vous tourner vers la droite, tout ce que vous voyez dans votre champs 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: M = -Z.-Y.-X Ceci est l'inverse (ou la transposé) de la matrice de rotation de l'objet. Q36. Comment générer une matrice de rotation à partir d'angles d'Euler? ----------------------------------------------------------- A 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 ensembles: 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'appel peut être placé dans une routine séparé : m3_fromeuler( MATRIX *mat_final, VECTOR3 *euler ) Néanmoins, la réalision de cette séquence d'appels est vraiment très inéfficace en terme de temps de calculs. Etant donnée 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 arbitraire, 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: M = X.Y.Z où M est la matrice final, 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: | 1 0 0 | X = | 0 A -B | | 0 B A | | C 0 -D | Y = | 0 1 0 | | D 0 C | | E -F 0 | Z = | F E 0 | | 0 0 1 | 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: M = X.Y.Z peut se partager en 2 multiplication de matrices: M' = X.Y M = M'.Z Evaluont M': M' = X.Y | 1 0 0 | | C 0 -D | M' = | 0 A -B | . | 0 1 0 | | 0 B A | | D 0 C | | 1.C + 0.0 + 0.D 1.0 + 0.1 + 0.0 1.-D + 0.0 + 0.C | M' = | 0.C + A.0 + -B.D 0.0 + A.1 + -B.0 0.-D + A.0 + -B.C | | 0.C + B.0 + A.D 0.0 + B.1 + A.0 0.-D + B.0 + A.C | En simplifiant M', on a: | C 0 -D | M' = | -B.D A -B.C | | A.D B A.C | D'où M devient: M = M'.Z | C 0 -D | | E -F 0 | M = | -BD A -BC | . | F E 0 | | AD B AC | | 0 0 1 | | C.E + 0.F + -D.0 C.-F + 0.E + -D.0 C.0 + 0.0 + -D.1 | M = | -BD.E + A.F + -BC.0 -BD.-F + A.E + -BC.0 -BD.0 + A.0 + -BC.1 | | AD.E + B.F + AC.0 AD.-F + B.E + AC.0 AD.0 + 0.0 + AC.1 | En simplifiant M: | CE -CF -D | M = | -BDE+AF -BDF+AE -BC | | ADE+BF -ADF+BE AC | C'est la matrice de rotations finale. En tant que matrice 4x4: | CE -CF -D 0 | M = | -BDE+AF BDF+AE -BC 0 | | ADE+BF -ADF+BE AC 0 | | 0 0 0 1 | Les valeurs individuelles de A,B,C,D,E et F sont évalué en premier. Ensuite, on évalue BD et AD puisqu'ils sont fréquent.. Donc, voici l'algorithme final: ----------------------- 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; ----------------------- A l'aide des multiplications de matrices, on aurait du faire 128 multiplications, 96 additions et 80 assignements. Avec cet algorithme, on a fait seulement 12 multiplications, 6 soustractions et 18 assignements! . Donc, par l'usage de l'algorithme optimisé, on réalise un gain de 1000%! Q37. Comment générer des angles d'Euler à partir d'une matrice de rotation? -------------------------------------------------------- Cette opération est exactement l'opposé de celle vu plus haut. Soit une matrice de rotation: | CE -CF -D 0 | M = | -BDE+AF BDF+AE -BC 0 | | ADE+BF -ADF+BE AC 0 | | 0 0 0 1 | 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ées C pour une matrice 4x4, les valeurs d'index sont les suivants: | 0 1 2 3 | M = | 4 5 6 7 | | 8 9 10 11 | | 12 13 14 15 | 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é à 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: axe X: M[6] = -BC M[10] = AC axe Z: M[0] = CE M[1] = -CF Les angles de rotation peuvent être obtenue en prenant chaque pair de valeurs divisée par C et en pasant le résultats aux fonctions inverses correspondante. 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 axes. Lors du calcul de la matrice, on a: | 0.E -0.F 1 0 | M = | -B.1.E+AF B.1.F+AE -B.0 0 | | A.1.E+BF -A.1.F+BE A.0 0 | | 0 0 0 1 | D'où: | 0 0 1 0 | M = | -BE+AF BF+AE 0 0 | | AE+BF -AF+BE 0 0 | | 0 0 0 1 | En arrangant: | 0 0 1 0 | M = | -BE+AF AE+BF 0 0 | | AE+BF BE-AF 0 0 | | 0 0 0 1 | On peut voir la matrice sous cette forme: | 0 0 -1 0 | M = | -V W 0 0 | | W V 0 0 | | 0 0 0 1 | où V vaut BE-AF et W AE+BF Ces deux valeurs peuvent être vu comme le sinus et le cosinus d'une seule rotation. L'alogorithme final est donc: ----------------------------------- angle_y = D = -asin( mat[2]); /* Calcul de l'Angle Y */ C = cos( angle_y ); angle_y *= RADIANS; if ( fabs( C ) > 0.005 ) /* Gimball 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 /* Gimball 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 ); ----------------------------------- Q38. Comment générer une matrice de rotation pour un axe et un angle donné? ----------------------------------------------------------------------- La seule façon de générer ce type de matrices de rotation est à l'aide des quaternions. Q39. Comment générer une matrice de rotation pour rendre deux vecteurs colinéaires? ------------------------------------------------------------------------ Quand on développe une application d'animation, un requête commune est de troyver la matrice de rotation qui "map" un vecteur direction sur un autre. Ce problème peut être visualisé en considérant deux vecteurs directions attaché à leurs base. Donc, l'entière totalité de l'espace de rotation forme une sphère unité. En théorie, il existe un nombre infinie de rotations possible 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 chamin qui couvre la plus petite distance angulaire entre les deux vecteurs. L'axe de rotation de ce chemin se calcul à l'aide du produit vectoriel entre les deux vecteurs: Vaxis = Vs x Vf L'angle de rotation est calculé à l'aide du produit scalaire entre les deux vecteurs: -1 Vangle = cos ( Vs . Vf ) Q40. Comment utiliser les matrices pour convertir entre deux systèmes de coordonnées? ----------------------------------------------------------------------- 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 3 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: Mfinal = Mrot . Morig où Mfinal 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: -1 Mfinal . Morig = Mrot -1 Mrot = Mfinal . Morig Ainsi, la matrice de rotation peut être calculer via la multiplication de la matrice finale avec l'inverse de la matrice de départ. Une fois calculé, cette matrice de rotation peut être conservé dans un quaternion. Q41. Qu'est ce qu'une matrice de translation? ---------------------------------- Une matrice de translation sert a positionner un objet dans l'espace sans le tourner. Les translations sous forme matricielle ne peuvent être réalisé qu'avec des matrices 4x4 (NdT : en système de coordonnées homogène). Si la translation se définit par un vecteur [X Y Z], alors on a la matrice 4x4 suivante: | 1 0 0 X | | | | 0 1 0 Y | M = | | | 0 0 1 Z | | | | 0 0 0 1 | Si le vecteur est [0 0 0] alors l'objet n'est pas modifié. Q42. Qu'est ce qu'une matrice de mise à l'échelle? ------------------------------ 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: | X 0 0 0 | | | | 0 Y 0 0 | M = | | | 0 0 Z 0 | | | | 0 0 0 1 | Si le vecteur de mise à l'échelle est [1 1 1], alors, on obtient la matrice identité et l'objet ne change pas. Q43. Qu'est ce que qu'une matrice de déformation? ------------------------------- 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éformations existent: o étirer X selon Y o étirer X selon Z o étirer Y selon X o étirer Y selon Z o étirer Z selon X o étirer Z selon Y Ces 6 transformations peuvent se combiner dans une seule matrice: | 1 Syx Szx 0 | | | | Sxy 1 Szy 0 | M = | | | Sxz Syz 1 0 | | | | 0 0 0 1 | | | Où Sij représente une déformation de I selon J Q44. Comment réaliser une interpolation linéaire entre deux matrices? ---------------------------------------------------------------- Etant donnée deux matrices de transformation, le problème est de trouver le moyen de déterminer les positions intermédiares 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érique(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 (NdT : Cf Mathématiques : Interpolation & approximation): Vr = Va + t .(Vb - Va ) où Vr est le vecteur résultant Va est le vecteur position de départ Vb est le vecteur position final Cette équation s'applique aussi bien aux vecteurs de la translation qu'a celui de la rotation. Une fois déterminé, la translation et la rotation résultante sont convertie dans la matrice intermédiare voulue. Q45. Comment réaliser une interpolation cubique entre quatre matrices? ---------------------------------------------------------------- Etant donnée quatres matrices, le problème consiste a trouver un moyen pour déterminer les positions intermédiaires spécifié 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 quatres matrices sont converties dans leurs vecteurs rotations et translations correspondant (Euler ou Sphérique). Chaque ensemble de 4 vecteurs est alors convertie en un unique vecteur géométrique G. A l'aide des mathématiques des splines, ce vecteur est converti en une matrice d'interpolation M. Si G est défini comme telle: | x1 x2 x3 x4 | G = | y1 y2 y3 y4 | | z1 z2 z3 z4 | Alors, la multiplication par la matrice de base : | -4.5 9.0 -5.5 1.0 | Mb = | 13.5 -22.5 9.0 0.0 | | -13.5 18.0 -4.5 0.0 | | 4.5 -4.5 1.0 0.0 | va générer une matrice d'interpolation 3x4 Mi: Mi = G .Mb Ceci peut être implémenter à l'aide d'une multiplication standard matrice-vecteur. L'interpolation peut être faite par l'usage de la variable paramétrique t: R = Mi . t |t^3| | xr | | A B C D | |t^2| | yr | = | E F G H | . |t | | zr | | I J K L | |1 | Le vecteur résultant peut être convertie en une matrice de rotation ou de translation. Il doit être noté que les chemins de rotation généré peuvent sembler quelque peu acrobatique. C'est normal dans le sens que l'algorithme essaie de trouver le chemin avec le minimum de rotation entre les 4 vecteurs. Des angles d'Euler ou Sphériques, ces derniers semblent en général être plus "propre" pour cette interpolation. Q46. Comment afficher une matrice? ------------------------------- Quand on utilise une fenetre graphique, il peut être utile de pouvoir visualiser la matrice en même temps que l'animation. Néanmoins, afficher une matrice de rotation comme un tableau de valeurs numériques n'est pas d'une très grande utilité. Une des alternatives est d'utiliser des méthodes graphiques comme le graphe à bar. Un peu comme un equalizer graphique sur une chaine, une matrice de rotation peut être affiché sous un format de barres dans une échelle de -1 à +1. Une matrice 3x3 resemblera à la suivante: +--+ +--+ +--+ |##| | | | | +--+ +--+ +--+ | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ | | |##| | | +--+ +--+ +--+ | | | | | | +--+ +--+ +--+ +--+ +--+ +--+ | | | | |##| +--+ +--+ +--+ | | | | | | +--+ +--+ +--+ Dans ce cas, la matrice de rotation est la matrice identité. Pour plus de clarté, les paramêtres qui sont négatifs peuvent être afficher dans une couleur différente. QUATERNIONS =========== Q47. Qu'est ce que les quaternions? -------------------------- Les quaternions permettre d'étendre la notion de rotation en 3 dimensions à celles en 4 dimensions. Ils permettent ainsi d'éviter le "gimbal-lock" et l'implémentation de rotation plus continu et plus précise. Un quaternion est défini via l'usage de 4 valeurs réels |x y z w|. Elles sont calculé par une combinaison des 3 coordonnées de l'axe de rotation et de l'angle correspondant. Q48. Quel est le rapport entre les quaternions et l'animation 3D? ----------------------------------------------- Comme mentionner plus haut, les angles d'Euler ont quelque défaut du à l'ordre dans lequel sont réalisées les rotations. Les quaternions solucionnent ce problème. Au lieu de tourner un objet via une série de rotations successive, les quaternions permettent au programmeur de tourner un objet autour d'un axe arbitraire et d'un angle quelconque. La rotation est néanmoins toujours réaliser par des calculs matricielles. Néanmoins, au lieu de multiplier les matrices ensemble, les quaternions les représentant sont multipliés. Le résultat final est reconverti en la matrice désirée. Les quaternions offre aussi l'avantage de permettre l'interpolation. Ceci permet des rotations plus souple et plus réaliste. Q49. Comment calculer le conjugué d'un quaternion? ------------------------------------------------------ Ceci peut être fait en inversant la polarité de la partie vectorielle du quaternion : Qr = ( Qr.scalaire, -Qr.vecteur ) -- Qr = ( Qr.scalaire, -Qr.vecteur ) ---------------------------------------------------------------- quaternion_conjugate( QUAT *qr, QUAT *qa ) { qr -> qw = qa -> qw; qr -> qx = -qa -> qx; qr -> qy = -qa -> qy; qr -> qz = -qa -> qz; } -------------------------------------- Q50. Comment calculer l'inverse d'un quaternion? ---------------------------------------------------- Idem que plus haut. Q51. Comment calculer la norme d'un quaternion? ------------------------------------------------------ La norme se calcul en multipliant le quaternion par son conjugué. ------------ / -- |Qr| = \/ Qr.Qr Ce qui peut s'implémenter comme suit: ------------------------------------------------------------------- QFLOAT quaternion_magnitude( QUAT *qa ) { return( sqrt(qa->qw*qa->qw+ qa->qx*qa->qx+ qa->qy*qa->qy+qa->qz*qa->qz) ) } ------------------------------------------------------------------- Q52. Comment normaliser un quaternion? ------------------------------------- Un quaternion peut se normaliser de la même manière qu'un vecteur. On le divise par sa norme. Un quaternion unitaire a toujours une norme de 1. Q53. Comment multiplier deux quaternions? ------------------------------------------------ Soit deux quaternion Q1 et Q2, l'objectif est de calculer la rotation combiné Qr: Qr = Q1.Q2 Ceci peut se faire via cette expression: Qr = Q1.Q2 = ( w1.w2 - v1.v2, w1.v2 + w2.v1 + v1 x v2 ) où v1 = (x,y,z) de Q1 w1 = (w) de Q1 v2 = (x,y,z) de Q2 w2 = (w) de Q2 et . et x représente respectivement le produit scalaire et vectoriel. Ceci peut s'implémenter comme suit: --------------------------------------------------- quaternion_multiply( QUAT *qr, QUAT *qa, QUAT *qb ) { qr.scalar = v3_dot( &qa->vector, &qb->vector ); v3_cross( &va, &qa->vector, &qb->vector ); v3_scalef( &vb, &qa->vector, &qb->scalar ); v3_scalef( &vc, &qb->vector, &qa->scaler ); v3_add( &va, &va, &vb ); v3_add( &qr->vector, &va, &vc ); quaternion_normalise( qr ); } --------------------------------------------------- Q54. Comment convertir un quaternion en matrice de rotation? -------------------------------------------------------- Soit un quaternion Q: Q = |X Y Z W| Alors, ce quaternion peut se convertir en une matrice 3x3 comme suit: | 2 2 | | 1 - 2Y - 2Z 2XY - 2ZW 2XZ + 2YW | | | | 2 2 | M = | 2XY + 2ZW 1 - 2X - 2Z 2YZ - 2XW | | | | 2 2 | | 2XZ - 2YW 2YZ + 2XW 1 - 2X - 2Y | | | Si une matrice 4x4 est requise, alors la dernière ligne et la dernière colonne peuvent être dupliquées. La matrice peut se générer via ces expression: ---------------- xx = X * X; xy = X * Y; xz = X * Z; xw = X * W; yy = Y * Y; yz = Y * Z; yw = Y * W; zz = Z * Z; zw = Z * W; mat[0] = 1 - 2 * ( yy + zz ); mat[1] = 2 * ( xy - zw ); mat[2] = 2 * ( xz + yw ); mat[4] = 2 * ( xy + zw ); mat[5] = 1 - 2 * ( xx + zz ); mat[6] = 2 * ( yz - xw ); mat[8] = 2 * ( xz - yw ); mat[9] = 2 * ( yz + xw ); mat[10] = 1 - 2 * ( xx + yy ); mat[3] = mat[7] = mat[11 = mat[12] = mat[13] = mat[14] = 0; mat[15] = 1; ---------------- Q55. Comment convertir une matrice de rotation en un quaternion? -------------------------------------------------------- Une matrice de rotation peut se convertir à l'aide de cet algorihme. Calcul de la trace de la matrice: 2 2 2 T = 4 - 4x - 4y - 4z 2 2 2 = 4( 1 -x - y - z ) = mat[0] + mat[5] + mat[10] + 1 Si la trace est > 0, le calcul est instantané: S = 0.5 / sqrt(T) W = 0.25 / S X = ( mat[9] - mat[6] ) * S Y = ( mat[2] - mat[8] ) * S Z = ( mat[4] - mat[1] ) * S Si la trace de la matrice est < ou = à 0, il faut identifier l'élément le plus grand dans la diagonale principale de la matrice. En fonction de la position de cette valeur: Colonne 0: S = sqrt( 1.0 + mr[0] - mr[5] - mr[10] ) * 2; Qx = 0.5 / S; Qy = (mr[1] + mr[4] ) / S; Qz = (mr[2] + mr[8] ) / S; Qw = (mr[6] + mr[9] ) / S; Colonne 1: S = sqrt( 1.0 + mr[5] - mr[0] - mr[10] ) * 2; Qx = (mr[1] + mr[4] ) / S; Qy = 0.5 / S; Qz = (mr[6] + mr[9] ) / S; Qw = (mr[2] + mr[8] ) / S; Colonne 2: S = sqrt( 1.0 + mr[10] - mr[0] - mr[5] ) * 2; Qx = (mr[2] + mr[8] ) / S; Qy = (mr[6] + mr[9] ) / S; Qz = 0.5 / S; Qw = (mr[1] + mr[4] ) / S; Le quaternion est défini comme: Q = | Qx Qy Qz Qw | Q56. Comment convertir un axe de rotation et un angle en un quaternion? ---------------------------------------------------------------- Etant donnée l'axe de rotation et l'angle, cet algorithme peut être utilisé pour générer un quaternion: ------------------------------------------------ sin_a = sin( angle / 2 ) cos_a = cos( angle / 2 ) q -> x = axis -> x * sin_a q -> y = axis -> y * sin_a q -> z = axis -> z * sin_a q -> w = cos_a quaternion_normalise( q ); ------------------------------------------------ Il est nécéssaire de normaliser le quaternion par la suite. Q57. Comment convertir un quaternion en un axe de rotation et un angle? ---------------------------------------------------------------- Un quaternion peut se re convertir en un angle et un axe de rotation via l'algorithme suivant: --------------------------------------------------- quaternion_normalise( qr ); cos_angle = qr -> qw; angle = acos( cos_angle ) * 2 * RADIANS; sin_angle = sqrt( 1.0 - cos_angle * cos_angle ); if ( fabs( sin_angle ) < 0.0005 ) sa = 1; axis -> vx = qr -> qx / sa; axis -> vy = qr -> qy / sa; axis -> vz = qr -> qz / sa; --------------------------------------------------- Q58. Comment convertir des angles de rotations sphériques en un quaternion? ---------------------------------------------------------------- Un axe de rotation peut être défini par des coordonnées sphériques (latitude et longitude) et un angle de rotation. Dans ce cas, le quaternion peut être calculé comme suit: ----------------------- sin_a = sin( angle / 2 ) cos_a = cos( angle / 2 ) sin_lat = sin( latitude ) cos_lat = cos( latitude ) sin_long = sin( longitude ) cos_long = cos( longitude ) qx = sin_a * cos_lat * sin_long qy = sin_a * sin_lat qz = sin_a * sin_lat * cos_long qw = cos_a ----------------------- Q59. Comment convertir un quaternion en des angles de rotations sphériques? ---------------------------------------------------------------- Un quaternion peut se convertir en coordonnée sphérique via: ----------------------- cos_angle = q -> qw; sin_angle = sqrt( 1.0 - cos_angle * cos_angle ); angle = acos( cos_angle ) * 2 * RADIANS; if ( fabs( sin_angle ) < 0.0005 ) sa = 1; tx = q -> qx / sa; ty = q -> qy / sa; tz = q -> qz / sa; latitude = -asin( ty ); if ( tx * tx + tz * tz < 0.0005 ) longitude = 0; else longitude = atan2( tx, tz ) * RADIANS; if ( longitude < 0 ) longitude += 360.0; ----------------------- A name=Q60>Q60. Comment convertir des angles d'Euler en un quaternion? ------------------------------------------------------------------- La conversion d'angles d'Euler en quaternions peut se faire à l'aide de multiplication de quaternions. Chaque angle de rotation est converti en une pair angle-axe, chaque axe correspondant à un axe Euclidien. Ces paires sont converties en quaternions qui sont multipliés ensemble. Implémentation: --------------------------------------------- quaternion_from_euler( QUATERNION *q, VFLOAT ax, VFLOAT ay, VFLOAT az ) { VECTOR3 vx = { 1, 0, 0 }, vy = { 0, 1, 0 }, vz = { 0, 0, 1 }; QUATERNION qx, qy, qz, qt; quaternion_from_axisangle( qx, &vx, rx ); quaternion_from_axisangle( qy, &vy, ry ); quaternion_from_axisangle( qz, &vz, rz ); quaternion_multiply( &qt, &qx, &qy ); quaternion_multiply( &q, &qt, &qz ); } --------------------------------------------- Q61. Comment utiliser des quaternions pour réaliser une interpolation linéaire entre matrices? ------------------------------------------------------------------------------- Dans beaucoup d'apllications, il peut être nécessaire d'interpoler entre 2 positions de rotation d'un objet donnée. Ces positions peuvent être spécifié à l'aide de l'animation par keyframe ou cinématique inverse. Il est nécéssaire d'avoir au moins deux matrices, la matrice de départ et la matrice finale ( MS et MF). En interpolation linéaire, la matrice de rotation interpolée est générée en utilisant une équation paramétrique où T varie de 0.0 à 1.0. A T=0, la matrice interpolée est égale à la matrice de départ. A T=1, la matrice interpolée est égale à la matrice de fin. Donc, la matrice de rotation interpolée (MI) est spécifiée par: MI = F( MS, MI, T ) où F est une fonction d'interpolation. LA première étape est de calculer la matrice de rotation qui va convertir MS vers MF: -1 T = Ms . Mf où Ms est la matrice de départ, Mf est la matrice finale, et T la matrice intermédiaire. Ensuite, il convient de convertir cette matrice en un axe et un angle de rotation à l'aide des quaternions. Afin de générer la matrice de rotation désirée, il suffit de modifier l'angle de rotation en fonction de t et de reconstruire la matrice de rotation voulue. Exemple: m4_transpose( mt, ms ); /* Inversion */ m4_mult( ms, mt, mb ); /* Matrice de Rotation */ m4_to_axisangle( ms, axis, angle ); /* Rotation axe/angle */ for ( t = 0; t < 1.0; t += 0.05 ) { m4_from_axisangle( mi, axis, angle * t ); /* Interpolation Finale */ ... ce que vous voulez ... } où t est le facteur d'interpolation allant de 0.0 à 1.0 Q62. Comment utiliser les quaternions pour réaliser une interpolation cubique entre matrices? ------------------------------------------------------------------------------ Parfois, il est nécessaire de réaliser une interpolation cubique. Pour ce faire, il faut au moins 4 matrices. Chacune est alors convertie en un ensemble de rotation sphériques via les quaternions (ie. longitude, latitude et angle de rotation). Ces derniers sont multiplier avec la matrice de base d'une courbe spline cardinal. La matrice obtenue permet de déterminer les angles de rotations sphériques intermédiares. Une fois ces coordonnées connues, il est aisé de générer la matrice interpolée via les quaternions. Algorithme: ---------------------------------------------------------------------- for ( n = 0; n < 4; n++ ) m4_to_spherical( mat[n], &v_sph[n] ); /* Coordonnées Sphériques */ m4_multspline( m_cardinal, v_sph, v_interp ); /* Vecteur Interpolation */ ... v3_cubic( v_pos, v_interp, t ); /* Interpolation */ m4_from_spherical( m_rot, v_pos ); /* Matrice Interpolée */ ----------------------------------------------------------------------