Quaternions
Je vous préviens tout de suite, je n'ai pas tout compris et je vais surtout appliquer bêtement, mais de ce que j'en ais compris:
Les quaternions font partis de l'ensemble des hyper-complexes
H=a+b.i+c.j+d.k
avec a qui est la composante réelle ou scalaire de H, et b, c et d qui sont les composantes complexes de H.
Nous avons toujours i2 = j2 = k2 = -1
Vous aurez plus de précisions sur les quaternions sur le site de wikipédia si celà vous intéresses (voir d'autres sites).
Multiplication de Hamilton
Mais ce qui nous intéresses surtout c'est ce qui suit et qui est simple à mettre en oeuvre:
Soit Q = a+b.i+c.j+d.k
Q' = a'+b'.i+c'.j+d'.k
Q * Q' = aa' - bb' - cc' - dd' + (ab' + ba' + cd' + dc')i + (ac' + ca' + db' + bd')j + (ad' + da' + bc' + cb')k
Or, la multiplication de quaternions unitaires est similaire à faire des rotations:
Si on considère que i, j et k représentent les axes d'un monde 3D, il faut savoir que la multiplication de deux quaternions représente dans ce monde 3D un rotation sur ces axes.
L'algèbre
des quaternions n'est pas commutatif. Cela se démontre, mais cela peut
aussi facilement se concevoir. Imaginez un cube (ou prenez votre vieux rubik's
cube) et faite lui faire une rotation suivant x puis suivant y. Notez la position
des faces de votre cube. Refaites la manip mais d'abord suivant y puis x. Les
faces ne sont pas du tout positionnées de la même manière
que précédemment.
Quaternions unitaires
Ils forment une sphère, et il y a une sorte de correspondance entre un quaternion unitaire et une rotation vectorielle dans l'espace euclidien de dimension 3, Cette particularité permet une représentation simple du produit de deux rotations vectorielles.
La norme d'un
quaternion se calcule de la manière suivante : racine ( a2
+ b2 + c2 + d2 ). Il est
donc facile de calculer à partir d'un quaternion quelconque le quaternion
unitaire (quaternion de norme 1).
Convertir un axe avec un angle de rotation en quaternion
la conversion en quaternion se fera de la manière suivante:
a = cos(angle/2)
b = x * sin(angle/2)
c = y * sin(angle/2)
d = z * sin(angle/2)
Attention
à travailler en radian ou de convertir les degrés en radian
Convertir un quaternion unitaire en matrice
Si le quaternion unitaire représente une rotation depuis l'origine, on peut le représenter à l'aide d'une matrice 3x3
Matrix = [ 1 - 2y2 - 2z2 2xy - 2wz 2xz + 2wy 2xy + 2wz 1 - 2x2 - 2z2 2yz - 2wx 2xz - 2wy 2yz + 2wx 1 - 2x2 - 2y2 ]
Il existe l'équivalent pour les quaternions non unitaires. En fait, cette matrice présentée ici est une matrice simplifiée de celle correspondant aux quaternions quelconque. Elle ne fonctionne donc qu'avec des quaternions unitaires...
C'est bien beau tout ça, mais à quoi cela peut servir ?
En fait cela va servir à modifier la matrice Modelview. Car maintenant
que nous avons calculé les rotations sur les différents axes,
il faudrait peut-être les appliquer. Il existe une fonction OpenGL qui
va permettre de modifier la matrice courante (pour nous Model View) en lui appliquant
une nouvelle matrice. Sauf que celle-ci est en 4x4
Donc pour convertir en 4x4 notre quaternion, nous ferons:
Matrix = [ 1 - 2y2 - 2z2 2xy - 2wz 2xz + 2wy 0 2xy + 2wz 1 - 2x2 - 2z2 2yz - 2wx 0 2xz - 2wy 2yz + 2wx 1 - 2x2 - 2y2 0 0 0 0 1 ]
Et voilà pour les quaternions, en tout cas appliqués à la 3D...
J'insiste,
il s'agit de la matrice simplifiée, elle n'est utilisable que si vous
travaillez avec un quaternion unitaire ! Donc après avoir converti un
axe avec un angle de rotation en quaternion, il peut être nécessaire
(ou non...) de transformer votre quaternion en quaternion unitaire.
Nous aurions
pu aussi reconvertir le quaternion en coordonnées x,y,z et angle puis
utiliser glrotation pour effectuer la rotation de la caméra. Mais le
traitement serait plus lourd. J'ai quand même mis une méthode permettant
de faire cette conversion dans le code.
Voici enfin une classe quaternion permettant d'utiliser les quaternions
D'autres
méthodes peuvent être ajoutées dans cette classe. Mais je
n'en ai pas besoin dans l'immédiat...
Cf. chapitre sur le C++ pour les méthodes un peu particulières comme operator, ... (si vous ne faites pas ce genre de programmation tout les jours...)