Comment le GLKMasortingx «Column Major» de GLKit?

Prémisse A

Lorsque vous parlez de masortingces “Column Major” en mémoire linéaire, les colonnes sont spécifiées les unes après les autres, de sorte que les 4 premières entrées en mémoire correspondent à la première colonne de la masortingce. Les masortingces “Row Major”, quant à elles, sont censées spécifier les lignes les unes après les autres, de sorte que les 4 premières entrées en mémoire spécifient la première ligne de la masortingce.


Un GLKMasortingx4 ressemble à ceci:

 union _GLKMasortingx4 { struct { float m00, m01, m02, m03; float m10, m11, m12, m13; float m20, m21, m22, m23; float m30, m31, m32, m33; }; float m[16]; } typedef union _GLKMasortingx4 GLKMasortingx4; 

La documentation sur le membre m dit:

Un tableau unidimensionnel des éléments de la masortingce dans l’ordre des colonnes.

Prémisse B

Une “ligne” dans un GLKMasortingx4 est un ensemble de 4 flotteurs déclarés horizontalement ( [m00, m01, m02, m03] serait la première “ligne”). Ainsi, ces entrées peuvent être interprétées comme mRowCol ( m12 serait l’entrée de la rangée 1, colonne 2).


Si nous regardons comment ces membres de structure GLKMasortingx sont disposés en fonction de l’ordre des déclarations, nous voyons:

[m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, ...]

Les 4 premières entrées représentent clairement la première ligne de la masortingce, pas la première colonne.

Conclusion

m n’est pas réellement Column Major, et les documents sont faux.


Maintenant, je dois noter que je ne crois pas réellement la conclusion, mais les deux prémisses semblent assez raisonnables. Vraiment, je me méfie le plus de la prémisse B, mais il semble étrange de définir une “ligne” verticale et une “colonne” horizontale. Quelqu’un peut-il expliquer cela?

La déclaration est un peu déroutante, mais la masortingce est en ordre majeur de colonne. Les quatre lignes de la structure représentent les colonnes de la masortingce, m0 * étant la colonne 0 et m3 * étant la colonne 3. Il est facile à vérifier. Créez simplement une masortingce de traduction et vérifiez les valeurs m30, m31 et m32 pour les composants de traduction.

Je suppose que votre confusion provient du fait que la structure place les flottants en rangées, alors qu’ils représentent en fait des colonnes.

Cela vient de la spécification OpenGL –

colonne majeure

Le sharepoint confusion est exactement ceci: comme d’autres l’ont déjà noté, nous indexons une masortingce majeure de colonne avec le premier index indiquant la colonne, pas la ligne :

  • m00 fait référence à colonne = 0, rangée = 0 ,
  • m01 fait référence à colonne = 0, rangée = 1 ,
  • m02 fait référence à colonne = 0, rangée = 2 ,

MATLAB a probablement beaucoup consortingbué à consortingbuer indirectement à cette confusion. Tandis que MATLAB utilise la colonne major pour sa représentation interne des données , il utilise toujours une convention d’indexation de ligne majeure de x(row,col) . Je ne sais pas pourquoi ils ont fait ça.

Notez également qu’OpenGL utilise par défaut les vecteurs de colonne. En d’autres termes , vous êtes censé publier la masortingce par le vecteur à transformer, tel que (MATRIX*VECTOR) dans un shader. Contrastez avec (VECTOR*MATRIX) ce que vous feriez pour une masortingce de rangées majeures.

Il serait peut-être utile de regarder mon article sur les masortingces majeures de rangée vs majeure de colonne en C.

Column major est contre-intuitif lors de la mise en place de masortingces dans le code

Plus je regarde cela, plus je pense que c’est une erreur de travailler dans la colonne majeure du code C, à cause de la nécessité de transposer mentalement ce que vous faites. Lorsque vous présentez une masortingce dans du code, la nature de notre langage, de gauche à droite, vous empêche d’écrire une masortingce, ligne par ligne:

 float a[4] = { 1, 2, 3, 4 }; 

Alors, on dirait très naturellement que vous spécifiez par rangée, la masortingce

 1 2 3 4 

Mais si vous utilisez une spécification majeure de colonne, vous avez en fait spécifié la masortingce

 1 3 2 4 

Ce qui est vraiment contre-intuitif. Si nous avions un langage vertical (ou “colonne majeure”), il serait plus facile de spécifier des masortingces de colonnes majeures dans le code.

Est-ce que tout cela est un autre argument de contournement pour Direct3D? Je ne sais pas, vous me dites.

Vraiment, pourquoi OpenGL utilise-t-il alors les masortingces majeures de colonnes?

En creusant plus profondément , il semble que cela ait été fait pour pouvoir “poster” des masortingces multipliées par des vecteurs tels que (MATRIX*VECTOR) , c’est-à-dire pour pouvoir utiliser des vecteurs colonnes (majeurs) tels que :

Multiplication de masortingces majeures de colonnes

 ┌ 2 8 1 1 ┐ ┌ 2 ┐ │ 2 1 7 2 │ │ 2 │ │ 2 6 5 1 │ │ 2 │ └ 1 9 0 0 ┘ └ 1 ┘ 

Comparez cela à devoir utiliser des vecteurs de lignes:

Multiplication masortingcielle majeure

 [ 2 2 2 1 ] ┌ 2 8 1 1 ┐ │ 2 1 7 2 │ │ 2 6 5 1 │ └ 1 9 0 0 ┘ 

Le problème est que, si les masortingces sont spécifiées en tant que rangée principale, vous devez “utiliser” les vecteurs de rangée et les masortingces de multiplication préalable par le vecteur qu’elles transforment .

La raison pour laquelle vous “devriez” utiliser des vecteurs de lignes lorsque vous utilisez des masortingces de lignes majeures est une représentation cohérente des données : après tout, un vecteur de lignes est juste une masortingce de 1 ligne, 4 colonnes.

Le problème de la prémisse B est que vous supposez qu’une “ligne” dans un GLKMasortingx4 est un ensemble de 4 flotteurs déclarés horizontalement ([m00, m01, m02, m03] serait la première “ligne”).

Nous pouvons vérifier cela simplement en vérifiant la valeur de column dans le code suivant:

 GLKMasortingx3 masortingx = {1, 2, 3, 4, 5, 6, 7, 8, 9}; GLKVector3 column = GLKMasortingx3GetColumn(m, 0); 

Remarque: J’ai utilisé GLKMasortingx3 pour des raisons de simplicité, mais il en va de même pour GLKMasortingx4 .