se eu olhar para uma matriz preenchida no meu programa, vejo os componentes de tradução ocupando os 4º, 8º e 12º elementos.
Antes de começar, é importante entender: isso significa que suas matrizes são muito importantes . Portanto, você responde a esta pergunta:
a matriz WVP principal da minha coluna é usada com sucesso para transformar vértices com a chamada HLSL: mul (vetor, matriz) que deve resultar no tratamento do vetor como linha principal, então como a matriz principal da coluna fornecida pela minha biblioteca de matemática funciona?
é bem simples: suas matrizes são muito importantes.
Muitas pessoas usam matrizes de linha principal ou transpostas, que esquecem que as matrizes não são naturalmente orientadas dessa maneira. Então eles veem uma matriz de tradução como esta:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Esta é uma matriz de tradução transposta . Não é assim que uma matriz de tradução normal se parece. A tradução está na quarta coluna , não na quarta linha. Às vezes, você até vê isso nos livros didáticos, que são lixo absoluto.
É fácil saber se uma matriz em uma matriz é de linha ou coluna principal. Se for maior da linha, a tradução será armazenada nos índices 3, 7 e 11. Se for maior da coluna, a tradução será armazenada nos índices 12, 13 e 14. Índices de base zero, é claro.
Sua confusão resulta de acreditar que você está usando matrizes principais da coluna quando, na verdade, está usando matrizes principais da linha.
A afirmação de que linha versus coluna principal é apenas uma convenção notacional é inteiramente verdadeira. A mecânica da multiplicação de matrizes e multiplicação de matrizes / vetores é a mesma, independentemente da convenção.
O que muda é o significado dos resultados.
Afinal, uma matriz 4x4 é apenas uma grade de números 4x4. Não precisa se referir a uma mudança no sistema de coordenadas. No entanto, depois de atribuir significado a uma matriz específica, agora você precisa saber o que está armazenado nela e como usá-lo.
Veja a matriz de tradução que mostrei acima. Essa é uma matriz válida. Você pode armazenar essa matriz de float[16]
uma de duas maneiras:
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};
No entanto, eu disse que essa matriz de tradução está errada, porque a tradução está no lugar errado. Eu disse especificamente que ele é transposto em relação à convenção padrão de como criar matrizes de tradução, que deve ser assim:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Vamos ver como eles são armazenados:
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};
Observe que column_major
é exatamente o mesmo que row_major_t
. Portanto, se pegarmos uma matriz de conversão adequada e a armazenamos como principal da coluna, é o mesmo que transpor essa matriz e armazená-la como principal da linha.
É isso que significa ser apenas uma convenção notacional. Na verdade, existem dois conjuntos de convenções: armazenamento e transposição de memória. O armazenamento de memória é principal em relação à coluna, enquanto a transposição é normal em comparação à transposta.
Se você tiver uma matriz que foi gerada na ordem principal da linha, poderá obter o mesmo efeito transpondo o equivalente da coluna principal dessa matriz. E vice versa.
A multiplicação de matrizes só pode ser feita de uma maneira: dadas duas matrizes, em uma ordem específica, você multiplica certos valores e armazena os resultados. Agora,, A*B != B*A
mas o código-fonte real de A*B
é o mesmo que o código de B*A
. Ambos executam o mesmo código para calcular a saída.
O código de multiplicação da matriz não se importa se as matrizes são armazenadas na ordem da coluna principal ou da linha principal.
O mesmo não pode ser dito para a multiplicação de vetores / matrizes. E aqui está o porquê.
A multiplicação de vetores / matrizes é uma falsidade; isso não pode ser feito. No entanto, você pode multiplicar uma matriz por outra matriz. Portanto, se você finge que um vetor é uma matriz, pode efetivamente fazer a multiplicação de vetores / matrizes, simplesmente fazendo a multiplicação de matrizes / matrizes.
Um vetor 4D pode ser considerado um vetor de coluna ou um vetor de linha. Ou seja, um vetor 4D pode ser pensado como uma matriz 4x1 (lembre-se: na notação da matriz, a contagem de linhas vem primeiro) ou uma matriz 1x4.
Mas eis o seguinte: dadas duas matrizes A e B, A*B
apenas é definido se o número de colunas de A for igual ao número de linhas de B. Portanto, se A é nossa matriz 4x4, B deve ser uma matriz com 4 linhas iniciar. Portanto, você não pode executar A*x
, onde x é um vetor de linha . Da mesma forma, você não pode executar x*A
onde x é um vetor de coluna.
Por esse motivo, a maioria das bibliotecas matemáticas de matrizes faz essa suposição: se você multiplicar um vetor por matriz, realmente pretende fazer a multiplicação que realmente funciona , e não a que não faz sentido.
Vamos definir, para qualquer vetor 4D x, o seguinte. C
deve ser a forma da matriz vetor-coluna de x
e R
deve ser a forma da matriz vetor-linha de x
. Dado isso, para qualquer matriz 4x4 A, A*C
representa a multiplicação da matriz A pelo vetor da coluna x
. E R*A
representa a matriz multiplicando o vetor de linha x
por A.
Mas se olharmos para isso usando matemática matricial estrita, veremos que elas não são equivalentes . R*A
não pode ser o mesmo que A*C
. Isso ocorre porque um vetor de linha não é a mesma coisa que um vetor de coluna. Eles não são da mesma matriz e, portanto, não produzem os mesmos resultados.
No entanto, eles estão relacionados de uma maneira. É verdade isso R != C
. No entanto, também é verdade que , onde T é a operação de transposição. As duas matrizes são transpostas uma da outra.R = CT
Aqui está um fato engraçado. Como os vetores são tratados como matrizes, eles também têm uma questão de armazenamento de coluna versus linha principal. O problema é que ambos parecem iguais . A matriz de flutuadores é a mesma, então você não pode dizer a diferença entre R e C apenas olhando os dados. A única maneira de dizer a diferença é como eles são usados.
Se você tiver duas matrizes A e B, e A for armazenada como maior de linha e B como maior de coluna, multiplicá-las não fará sentido . Você fica sem sentido como resultado. Bem, na verdade não. Matematicamente, o que você recebe é o equivalente a fazer . Ou ; eles são matematicamente idênticos.AT*B
A*BT
Portanto, a multiplicação de matrizes só faz sentido se as duas matrizes (e lembre-se: multiplicação de vetores / matrizes é apenas multiplicação de matrizes) são armazenadas na mesma ordem principal.
Então, um vetor é uma coluna principal ou uma linha principal? É ambos e nenhum, como afirmado anteriormente. Ele é importante na coluna somente quando é usado como uma matriz de colunas e é importante na linha quando usado como uma matriz de linhas.
Portanto, se você tiver uma matriz A que é a coluna maior, x*A
significa ... nada. Bem, novamente, isso significa , mas não é isso que você realmente queria. Da mesma forma, a multiplicação transposta se é maior da linha.x*AT
A*x
A
Portanto, a ordem de vector multiplicação / matriz faz mudança, dependendo da sua grande ordem dos dados (e se você estiver usando matrizes transpostas).
Por que, no seguinte trecho de código, r! = R2
Porque seu código está quebrado e com erros. Matematicamente . Se você não obtiver esse resultado, seu teste de igualdade está errado (problemas de precisão de ponto flutuante) ou o código de multiplicação da matriz está quebrado.A * (B * C) == (CT * BT) * AT
por que pos3! = pos para
Porque isso não faz sentido. A única maneira de ser verdade seria se . E isso é verdade apenas para matrizes simétricas.A * t == AT * t
A == AT