Si miro una matriz poblada en mi programa, veo los componentes de traducción que ocupan los elementos 4º, 8º y 12º.
Antes de comenzar, es importante entender: esto significa que sus matrices son de fila mayor . Por lo tanto, responde a esta pregunta:
mi matriz WVP de columna principal se utiliza con éxito para transformar vértices con la llamada HLSL: mul (vector, matriz), lo que debería dar como resultado que el vector sea tratado como fila mayor, entonces, ¿cómo puede funcionar la matriz principal de columna proporcionada por mi biblioteca matemática?
es bastante simple: sus matrices son de fila mayor.
Tantas personas usan matrices de fila mayor o transpuestas, que olvidan que las matrices no están orientadas naturalmente de esa manera. Entonces ven una matriz de traducción como esta:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Esta es una matriz de traducción transpuesta . Así no es como se ve una matriz de traducción normal. La traducción va en la cuarta columna , no en la cuarta fila. A veces, incluso ves esto en los libros de texto, que es basura absoluta.
Es fácil saber si una matriz en una matriz es fila o columna mayor. Si es mayor de fila, entonces la traducción se almacena en los índices 3, 7 y 11. Si se trata de una columna principal, la traducción se almacena en los índices 12, 13 y 14. Índices de base cero, por supuesto.
Su confusión surge de creer que está usando matrices de columnas principales cuando de hecho está usando las de filas principales.
La afirmación de que fila vs. columna mayor es una convención de notación solamente es completamente cierta. La mecánica de la multiplicación matricial y la multiplicación matriz / vector son las mismas independientemente de la convención.
Lo que cambia es el significado de los resultados.
Una matriz 4x4 después de todo es solo una cuadrícula de números 4x4. No tiene que referirse a un cambio de sistema de coordenadas. Sin embargo, una vez que asigna significado a una matriz particular, ahora necesita saber qué está almacenado en ella y cómo usarla.
Tome la matriz de traducción que le mostré arriba. Esa es una matriz válida. Puede almacenar esa matriz en una float[16]
de dos maneras:
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};
Sin embargo, dije que esta matriz de traducción está mal, porque la traducción está en el lugar equivocado. Dije específicamente que se transpone en relación con la convención estándar sobre cómo construir matrices de traducción, que debería verse así:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Veamos cómo se almacenan estos:
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};
Tenga en cuenta que column_major
es exactamente lo mismo que row_major_t
. Entonces, si tomamos una matriz de traducción adecuada y la almacenamos como columna mayor, es lo mismo que transponer esa matriz y almacenarla como fila mayor.
Eso es lo que significa ser solo una convención de notación. Realmente hay dos conjuntos de convenciones: almacenamiento de memoria y transposición. El almacenamiento de memoria es la columna frente a la fila principal, mientras que la transposición es normal frente a la transpuesta.
Si tiene una matriz que se generó en orden de fila mayor, puede obtener el mismo efecto transponiendo el equivalente de columna mayor de esa matriz. Y viceversa.
La multiplicación de matrices solo se puede hacer de una manera: dadas dos matrices, en un orden específico, se multiplican ciertos valores y se almacenan los resultados. Ahora, A*B != B*A
pero el código fuente real para A*B
es el mismo que el código para B*A
. Ambos ejecutan el mismo código para calcular la salida.
Al código de multiplicación de matrices no le importa si las matrices están almacenadas en orden de columna mayor o de fila mayor.
El mismo no puede decirse de vector / matriz de la multiplicación. Y he aquí por qué.
La multiplicación de vectores / matrices es una falsedad; No se puede hacer. Sin embargo, puede multiplicar una matriz por otra matriz. Entonces, si finges que un vector es una matriz, entonces puedes hacer efectivamente la multiplicación de vector / matriz, simplemente haciendo la multiplicación de matriz / matriz.
Un vector 4D puede considerarse un vector de columna o un vector de fila. Es decir, un vector 4D puede considerarse como una matriz 4x1 (recuerde: en notación matricial, el recuento de filas es lo primero) o una matriz 1x4.
Pero aquí está la cosa: dadas dos matrices A y B, A*B
solo se define si el número de columnas de A es el mismo que el número de filas de B. Por lo tanto, si A es nuestra matriz 4x4, B debe ser una matriz con 4 filas en eso. Por lo tanto, no puede realizar A*x
, donde x es un vector de fila . Del mismo modo, no puede realizar x*A
donde x es una columna-vector.
Debido a esto, la mayoría de las bibliotecas de matemáticas de matriz hacen esta suposición: si multiplica un vector por una matriz, realmente quiere hacer la multiplicación que realmente funciona , no la que no tiene sentido.
Definamos, para cualquier vector 4D x, lo siguiente. C
será el vector columna de matriz forma de x
, y R
será la fila-vector matriz de forma de x
. Dado esto, para cualquier matriz 4x4 A, A*C
representa la matriz que multiplica A por el vector columna x
. Y R*A
representa la matriz multiplicando el vector fila x
por A.
Pero si miramos esto usando matemática matricial estricta, vemos que no son equivalentes . R*A
no puede ser lo mismo que A*C
. Esto se debe a que un vector fila no es lo mismo que un vector columna. No son la misma matriz, por lo que no producen los mismos resultados.
Sin embargo, están relacionados de una manera. Es verdad eso R != C
. Sin embargo, también es cierto que , donde T es la operación de transposición. Las dos matrices son transposiciones una de la otra.R = CT
Aquí hay un hecho curioso. Como los vectores se tratan como matrices, también tienen una pregunta de almacenamiento columna vs. fila principal. El problema es que ambos se ven iguales . La matriz de flotadores es la misma, por lo que no puede distinguir la diferencia entre R y C simplemente mirando los datos. La única forma de notar la diferencia es por cómo se usan.
Si tiene dos matrices A y B, y A está almacenada como mayor de fila y B como mayor de columna, multiplicarlas no tiene sentido . Obtienes tonterías como resultado. Bueno en realidad no. Matemáticamente, lo que obtienes es el equivalente a hacer . o ; Son matemáticamente idénticos.AT*B
A*BT
Por lo tanto, la multiplicación de matrices solo tiene sentido si las dos matrices (y recuerde: la multiplicación de vectores / matrices es solo una multiplicación de matrices) se almacenan en el mismo orden principal.
Entonces, ¿es un vector columna mayor o mayor fila? Es ambos y ninguno, como se dijo antes. Es mayor de columna solo cuando se usa como matriz de columna, y es mayor de fila cuando se usa como matriz de fila.
Por lo tanto, si tiene una matriz A que es la columna mayor, x*A
significa ... nada. Bueno, de nuevo, significa , pero eso no es lo que realmente querías. Del mismo modo, se transpone la multiplicación si es mayor de fila.x*AT
A*x
A
Por lo tanto, el orden de los vectores / multiplicación de matrices hace el cambio, dependiendo de su gran orden de los datos (y si está utilizando matrices transpuestas).
¿Por qué en el siguiente fragmento de código r! = R2
Porque tu código está roto y tiene errores. Matemáticamente, . Si no obtiene este resultado, entonces su prueba de igualdad está mal (problemas de precisión de punto flotante) o su código de multiplicación de matriz está roto.A * (B * C) == (CT * BT) * AT
¿Por qué pos3! = pos para
Porque eso no tiene sentido. La única forma de ser verdad sería si . Y eso solo es cierto para las matrices simétricas.A * t == AT * t
A == AT