si je regarde une matrice peuplée dans mon programme, je vois les composants de traduction occupant les 4e, 8e et 12e éléments.
Avant de commencer, il est important de comprendre: cela signifie que vos matrices sont des lignes majeures . Par conséquent, vous répondez à cette question:
ma matrice WVP majeure de colonne est utilisée avec succès pour transformer les sommets avec l'appel HLSL: mul (vecteur, matrice), ce qui devrait entraîner le traitement du vecteur comme ligne majeure, alors comment la matrice principale de colonne fournie par ma bibliothèque de mathématiques peut-elle fonctionner?
est assez simple: vos matrices sont des lignes majeures.
Tant de gens utilisent des matrices à lignes majeures ou transposées, qu'ils oublient que les matrices ne sont pas naturellement orientées de cette façon. Ils voient donc une matrice de traduction comme ceci:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Il s'agit d'une matrice de traduction transposée . Ce n'est pas ce à quoi ressemble une matrice de traduction normale. La traduction va dans la 4ème colonne , pas dans la quatrième ligne. Parfois, vous voyez même cela dans les manuels, ce qui est une pure ordure.
Il est facile de savoir si une matrice dans un tableau est une ligne ou une colonne majeure. S'il s'agit d'une ligne majeure, la traduction est stockée dans les index 3, 7 et 11. S'il s'agit d'une colonne majeure, la traduction est stockée dans les index 12, 13 et 14. Indices de base zéro bien sûr.
Votre confusion vient du fait de croire que vous utilisez des matrices à colonnes majeures alors que vous utilisez en fait des matrices à lignes majeures.
L'affirmation selon laquelle la ligne par rapport à la colonne principale n'est qu'une convention de notation est entièrement vraie. La mécanique de la multiplication matricielle et de la multiplication matrice / vecteur est la même quelle que soit la convention.
Ce qui change, c'est la signification des résultats.
Une matrice 4x4, après tout, n'est qu'une grille de nombres 4x4. Il n'a pas a faire référence à un changement de système de coordonnées. Cependant, une fois que vous attribuez un sens à une matrice particulière, vous devez maintenant savoir ce qui y est stocké et comment l'utiliser.
Prenez la matrice de traduction que je vous ai montrée ci-dessus. C'est une matrice valide. Vous pouvez stocker cette matrice de l'une float[16]
des deux manières suivantes:
float row_major_t[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
float column_major_t[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
Cependant, j'ai dit que cette matrice de traduction est erronée, car la traduction est au mauvais endroit. J'ai dit spécifiquement qu'il est transposé par rapport à la convention standard sur la façon de construire des matrices de traduction, qui devrait ressembler à ceci:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Voyons comment ils sont stockés:
float row_major[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
float column_major[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
Notez que column_major
c'est exactement la même chose que row_major_t
. Donc, si nous prenons une matrice de traduction appropriée et la stockons en tant que colonne majeure, cela revient à transposer cette matrice et à la stocker comme ligne majeure.
C'est ce que l'on entend par n'être qu'une convention de notation. Il existe en réalité deux ensembles de conventions: le stockage en mémoire et la transposition. Le stockage en mémoire est une colonne par rapport à une ligne principale, tandis que la transposition est normale ou transposée.
Si vous avez une matrice qui a été générée dans l'ordre des lignes principales, vous pouvez obtenir le même effet en transposant l'équivalent des colonnes majeures de cette matrice. Et vice versa.
La multiplication des matrices ne peut se faire que dans un sens: étant donné deux matrices, dans un ordre spécifique, vous multipliez certaines valeurs ensemble et stockez les résultats. Maintenant, A*B != B*A
mais le code source réel de A*B
est le même que le code de B*A
. Ils exécutent tous les deux le même code pour calculer la sortie.
Le code de multiplication de matrice ne se soucie pas de savoir si les matrices se trouvent être stockées dans l'ordre des colonnes principales ou des lignes principales.
La même chose ne peut pas dire pour la multiplication vecteur / matrice. Et voici pourquoi.
La multiplication vecteur / matrice est un mensonge; cela ne peut pas être fait. Cependant, vous pouvez multiplier une matrice par une autre matrice. Donc, si vous prétendez qu'un vecteur est une matrice, vous pouvez effectivement faire une multiplication vecteur / matrice, simplement en faisant une multiplication matrice / matrice.
Un vecteur 4D peut être considéré comme un vecteur colonne ou un vecteur ligne. Autrement dit, un vecteur 4D peut être considéré comme une matrice 4x1 (rappelez-vous: en notation matricielle, le nombre de lignes vient en premier) ou une matrice 1x4.
Mais voici la chose: étant donné deux matrices A et B, A*B
n'est définie que si le nombre de colonnes de A est le même que le nombre de lignes de B.Par conséquent, si A est notre matrice 4x4, B doit être une matrice à 4 lignes en elle. Par conséquent, vous ne pouvez pas effectuer A*x
, où x est un vecteur ligne . De même, vous ne pouvez pas effectuer x*A
où x est un vecteur de colonne.
Pour cette raison, la plupart des bibliothèques mathématiques matricielles font cette hypothèse: si vous multipliez un vecteur fois une matrice, vous voulez vraiment faire la multiplication qui fonctionne réellement , pas celle qui n'a aucun sens.
Définissons, pour tout vecteur 4D x, ce qui suit. C
doit être la forme matricielle vecteur colonne de x
, et R
doit être la forme matricielle vecteur ligne de x
. Compte tenu de cela, pour toute matrice 4x4 A, A*C
représente la matrice multipliant A par le vecteur colonne x
. Et R*A
représente la matrice multipliant le vecteur ligne x
par A.
Mais si nous regardons cela en utilisant des mathématiques matricielles strictes, nous voyons que ceux-ci ne sont pas équivalents . R*A
ne peut pas être le même que A*C
. En effet, un vecteur ligne n'est pas la même chose qu'un vecteur colonne. Ce ne sont pas la même matrice, donc ils ne produisent pas les mêmes résultats.
Cependant, ils sont liés d'une manière. C'est vrai ça R != C
. Cependant, il est également vrai que , où T est l'opération de transposition. Les deux matrices sont transposées l'une de l'autre.R = CT
Voici un fait amusant. Étant donné que les vecteurs sont traités comme des matrices, ils ont également une question de stockage colonne contre ligne principale. Le problème est qu'ils se ressemblent tous les deux . Le tableau de flottants est le même, vous ne pouvez donc pas faire la différence entre R et C simplement en regardant les données. La seule façon de faire la différence est de savoir comment ils sont utilisés.
Si vous avez deux matrices A et B et que A est stocké en tant que ligne principale et B en tant que colonne principale, leur multiplication n'a aucun sens . Vous obtenez un non-sens en conséquence. Eh bien pas vraiment. Mathématiquement, ce que vous obtenez est l'équivalent de le faire . Ou ; ils sont mathématiquement identiques.AT*B
A*BT
Par conséquent, la multiplication matricielle n'a de sens que si les deux matrices (et rappelez-vous: la multiplication vecteur / matrice n'est qu'une multiplication matricielle) sont stockées dans le même ordre majeur.
Alors, un vecteur colonne-majeur ou ligne-majeur? Ce n'est ni l'un ni l'autre, comme indiqué précédemment. Il n'est majeur de colonne que lorsqu'il est utilisé comme matrice de colonne, et il est majeur de ligne lorsqu'il est utilisé comme matrice de ligne.
Par conséquent, si vous avez une matrice A qui est une colonne majeure, cela x*A
signifie ... rien. Eh bien, encore une fois, cela signifie , mais ce n'est pas ce que vous vouliez vraiment. De même, la multiplication transposée est-elle si la ligne est majeurex*AT
A*x
A
Par conséquent, l'ordre de la multiplication du vecteur / matrice ne change, en fonction de votre commande majeure des données (et si vous utilisez des matrices transposés).
Pourquoi dans l'extrait de code suivant, r! = R2
Parce que votre code est cassé et bogué. Mathématiquement, . Si vous n'obtenez pas ce résultat, votre test d'égalité est incorrect (problèmes de précision en virgule flottante) ou votre code de multiplication de matrice est rompu.A * (B * C) == (CT * BT) * AT
pourquoi pos3! = pos pour
Parce que ça n'a pas de sens. La seule façon d'être vrai serait si . Et cela n'est vrai que des matrices symétriques.A * t == AT * t
A == AT