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  */

    ----------------------------------------------------------------------