La notation matricielle utilisée dans la documentation d'Opengl ne décrit pas la disposition en mémoire des matrices OpenGL.
Je pense que ce sera plus facile si vous laissez tomber/oubliez tout le truc "ligne/colonne-majeur". En effet, en plus de la majeure ligne/colonne, le programmeur peut également décider de la manière dont il souhaite disposer la matrice dans la mémoire (si les éléments adjacents forment des lignes ou des colonnes), en plus de la notation, ce qui ajoute à la confusion.
Les matrices OpenGL ont même disposition de la mémoire que les matrices directx .
x.x x.y x.z 0
y.x y.y y.z 0
z.x z.y z.z 0
p.x p.y p.z 1
ou
{ x.x x.y x.z 0 y.x y.y y.z 0 z.x z.y z.z 0 p.x p.y p.z 1 }
-
x, y, z sont des vecteurs à 3 composantes décrivant le système de coordonnées de la matrice (système de coordonnées local par rapport au système de coordonnées global).
-
p est un vecteur à 3 composantes décrivant l'origine du système de coordonnées de la matrice.
Ce qui signifie que la matrice de traduction doit être disposée en mémoire comme ceci :
{ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, transX, transY, transZ, 1 }.
Restez-en là, et le reste devrait être facile.
---citation de l'ancienne faq d'opengl--
9.005 Les matrices OpenGL sont-elles à dominante colonne ou à dominante ligne ?
Pour des raisons de programmation, les matrices OpenGL sont des tableaux de 16 valeurs avec des vecteurs de base disposés de manière contiguë dans la mémoire. Les composantes de translation occupent les 13e, 14e et 15e éléments de la matrice à 16 éléments, où les indices sont numérotés de 1 à 16 comme décrit dans la section 2.11.2 de la spécification OpenGL 2.1.
La différence entre colonne-major et ligne-major est une pure convention de notation. Notez que la post-multiplication avec des matrices de type colonne-major produit le même résultat que la pré-multiplication avec des matrices de type ligne-major. La spécification OpenGL et le manuel de référence OpenGL utilisent tous deux la notation column-major. Vous pouvez utiliser n'importe quelle notation, tant que c'est clairement indiqué.
Malheureusement, l'utilisation du format column-major dans la spécification et le livre bleu a entraîné une confusion sans fin dans la communauté de programmation OpenGL. La notation colonne-major suggère que les matrices ne sont pas disposées en mémoire comme un programmeur s'y attendrait.
Je vais mettre à jour cette réponse vieille de 9 ans.
Une matrice mathématique est définie comme suit m x n
matrice. Où m
est un nombre de rangées y n
est le nombre de colonnes . Par souci d'exhaustivité, les lignes sont horizontales et les colonnes sont verticales. Lorsque l'on désigne un élément de matrice en notation mathématique Mij
le premier élément ( i
) est un index de ligne, le second ( j
) est un indice de colonne. Lorsque deux matrices sont multipliées, à savoir A(m x n) * B(m1 x n1)
la matrice résultante a le nombre de lignes du premier argument ( A
), et le nombre de colonnes de la seconde( B
), et le nombre de colonnes du premier argument ( A
) doit correspondre au nombre de lignes du second ( B
). donc n == m1
. C'est clair jusqu'ici, oui ?
Maintenant, en ce qui concerne la disposition en mémoire. Vous pouvez stocker la matrice de deux façons. Row-major et column-major. Row-major signifie qu'effectivement vous avez des lignes disposées l'une après l'autre, linéairement. Ainsi, les éléments vont de gauche à droite, ligne après ligne. Un peu comme du texte anglais. Column-major signifie qu'en fait, vous avez colonnes disposés l'un après l'autre, linéairement. Les éléments commencent donc en haut à gauche, et vont de haut en bas.
Exemple :
//matrix
|a11 a12 a13|
|a21 a22 a23|
|a31 a32 a33|
//row-major
[a11 a12 a13 a21 a22 a23 a31 a32 a33]
//column-major
[a11 a21 a31 a12 a22 a32 a13 a23 a33]
Maintenant, voici la partie amusante !
Il existe deux façons de stocker une transformation 3D dans une matrice. Comme je l'ai déjà mentionné, une matrice en 3D stocke essentiellement les vecteurs de base du système de coordonnées et la position. Vous pouvez donc stocker ces vecteurs dans les lignes ou les colonnes d'une matrice. Lorsqu'ils sont stockés en colonnes, vous multipliez une matrice avec un vecteur colonne. Comme ceci.
//convention #1
|vx.x vy.x vz.x pos.x| |p.x| |res.x|
|vx.y vy.y vz.y pos.y| |p.y| |res.y|
|vx.z vy.z vz.z pos.z| x |p.z| = |res.z|
| 0 0 0 1| | 1| |res.w|
Cependant, vous pouvez également stocker ces vecteurs sous forme de lignes, et vous multiplierez alors un vecteur de ligne avec une matrice :
//convention #2 (uncommon)
| vx.x vx.y vx.z 0|
| vy.x vy.y vy.z 0|
|p.x p.y p.z 1| x | vz.x vz.y vz.z 0| = |res.x res.y res.z res.w|
|pos.x pos.y pos.z 1|
Donc. La convention n° 1 apparaît souvent dans les textes mathématiques. La convention n°2 est apparue dans le sdk de DirectX à un moment donné. Les deux sont valables.
Et en ce qui concerne la question, si vous utilisez la convention n°1, alors vos matrices sont en colonne majeure. Et si vous utilisez la convention n°2, alors elles sont en ligne. Cependant, la disposition de la mémoire est la même dans les deux cas.
[vx.x vx.y vx.z 0 vy.x vy.y vy.z 0 vz.x vz.y vz.z 0 pos.x pos.y pos.z 1]
C'est pourquoi j'ai dit qu'il était plus facile de mémoriser quel élément est quel autre, il y a 9 ans.