se osservo una matrice popolata nel mio programma vedo i componenti di traduzione che occupano il 4 °, 8 ° e 12 ° elemento.
Prima di iniziare, è importante capire: questo significa che le tue matrici sono le righe principali . Pertanto, rispondi a questa domanda:
la mia matrice WVP principale di colonna viene utilizzata con successo per trasformare i vertici con la chiamata HLSL: mul (vettore, matrice) che dovrebbe comportare che il vettore venga trattato come maggiore di riga, quindi come può funzionare la matrice di maggiore colonna fornita dalla mia libreria matematica?
è abbastanza semplice: le tue matrici sono in ordine di riga.
Così tante persone usano matrici di riga maggiore o trasposte, che dimenticano che le matrici non sono naturalmente orientate in quel modo. Quindi vedono una matrice di traduzione come questa:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Questa è una matrice di traduzione trasposta . Questo non è l'aspetto di una normale matrice di traduzione. La traduzione va nella quarta colonna , non nella quarta riga. A volte, lo vedi persino nei libri di testo, che è completamente spazzatura.
È facile sapere se una matrice in un array è di tipo riga o colonna. Se è la riga maggiore, la traduzione viene memorizzata negli indici 3, 7 e 11. Se è la colonna maggiore, la traduzione viene memorizzata negli indici 12, 13 e 14. Indici a base zero ovviamente.
La tua confusione deriva dal credere che stai usando le matrici principali di colonna quando in realtà stai usando quelle principali.
L'affermazione che riga vs. colonna maggiore è solo una convenzione notazionale è del tutto vera. La meccanica della moltiplicazione matrice e la moltiplicazione matrice / vettore sono le stesse indipendentemente dalla convenzione.
Ciò che cambia è il significato dei risultati.
Una matrice 4x4 dopo tutto è solo una griglia di numeri 4x4. Non deve fare riferimento a un cambio di sistema di coordinate. Tuttavia, una volta assegnato significato a una matrice particolare, ora è necessario sapere cosa è memorizzato in essa e come usarlo.
Prendi la matrice di traduzione che ti ho mostrato sopra. Questa è una matrice valida. Puoi memorizzare quella matrice float[16]
in uno dei due modi seguenti:
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};
Tuttavia, ho detto che questa matrice di traduzione è sbagliata, perché la traduzione è nel posto sbagliato. Ho detto espressamente che è stato trasposto rispetto alla convenzione standard su come costruire matrici di traduzione, che dovrebbe apparire così:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Diamo un'occhiata a come sono memorizzati:
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};
Si noti che column_major
è esattamente lo stesso di row_major_t
. Quindi, se prendiamo una matrice di traduzione adeguata e la memorizziamo come maggiore di colonna, è lo stesso che trasporre quella matrice e memorizzarla come maggiore di riga.
Questo è ciò che si intende per essere solo una convenzione notazionale. Esistono davvero due serie di convenzioni: memoria e trasposizione. La memoria è la colonna contro la riga maggiore, mentre la trasposizione è normale o trasposta.
Se hai una matrice che è stata generata in ordine di riga maggiore, puoi ottenere lo stesso effetto trasponendo l'equivalente colonna principale di quella matrice. E viceversa.
La moltiplicazione delle matrici può essere fatta in un solo modo: date due matrici, in un ordine specifico, moltiplichi determinati valori insieme e memorizzi i risultati. Ora, A*B != B*A
ma il codice sorgente effettivo per A*B
è lo stesso del codice per B*A
. Entrambi eseguono lo stesso codice per calcolare l'output.
Il codice di moltiplicazione matrice non importa se le matrici si trovano in ordine di colonna maggiore o di riga maggiore.
Lo stesso non si può dire per la moltiplicazione vettoriale / matrice. Ed ecco perché.
La moltiplicazione vettore / matrice è una falsità; non si può fare. Tuttavia, puoi moltiplicare una matrice per un'altra matrice. Quindi, se fai finta che un vettore sia una matrice, puoi effettivamente fare la moltiplicazione vettore / matrice, semplicemente facendo la moltiplicazione matrice / matrice.
Un vettore 4D può essere considerato un vettore colonna o un vettore riga. Cioè, un vettore 4D può essere pensato come una matrice 4x1 (ricorda: nella notazione della matrice, il conteggio delle righe viene prima) o una matrice 1x4.
Ma ecco la cosa: date due matrici A e B, A*B
è definita solo se il numero di colonne di A è uguale al numero di righe di B. Pertanto, se A è la nostra matrice 4x4, B deve essere una matrice con 4 righe dentro. Pertanto, non è possibile eseguire A*x
, dove x è un vettore riga . Allo stesso modo, non è possibile eseguire x*A
dove x è un vettore colonna.
Per questo motivo, la maggior parte delle librerie matematiche di matrice fa questo assunto: se moltiplichi un vettore per una matrice, intendi davvero fare la moltiplicazione che funziona davvero , non quella che non ha senso.
Definiamo, per ogni vettore 4D x, quanto segue. C
deve essere la forma di matrice vettore-colonna di x
e R
deve essere la forma di matrice vettore-riga di x
. Detto questo, per qualsiasi matrice 4x4 A, A*C
rappresenta la matrice che moltiplica A per il vettore colonna x
. E R*A
rappresenta una matrice che moltiplica il vettore riga x
per A.
Ma se guardiamo a questo usando una matrice matematica rigorosa, vediamo che questi non sono equivalenti . R*A
non può essere uguale a A*C
. Questo perché un vettore di riga non è la stessa cosa di un vettore di colonna. Non sono la stessa matrice, quindi non producono gli stessi risultati.
Tuttavia, sono correlati in un modo. È vero quello R != C
. Tuttavia, è anche vero che , dove T è l'operazione di trasposizione. Le due matrici sono trasposte l'una dall'altra.R = CT
Ecco un fatto divertente. Poiché i vettori sono trattati come matrici, anche loro hanno una domanda di archiviazione tra colonna e riga. Il problema è che entrambi sembrano uguali . L'array di float è lo stesso, quindi non si può dire la differenza tra R e C solo guardando i dati. L' unico modo per distinguere è da come vengono utilizzati.
Se hai due matrici A e B e A viene memorizzata come riga maggiore e B come colonna maggiore, moltiplicarle è completamente insignificante . Di conseguenza ottieni sciocchezze. Beh, non proprio. Matematicamente, ciò che ottieni equivale a fare . Oppure ; sono matematicamente identici.AT*B
A*BT
Pertanto, la moltiplicazione di matrici ha senso solo se le due matrici (e ricordate: la moltiplicazione di vettori / matrici è solo una moltiplicazione di matrici) sono memorizzate nello stesso ordinamento principale.
Quindi, è un vettore colonna maggiore o riga maggiore? È entrambi e nessuno dei due, come affermato in precedenza. È maggiore della colonna solo quando viene utilizzato come matrice di colonne ed è maggiore della riga quando viene utilizzato come matrice di righe.
Pertanto, se hai una matrice A che è la colonna maggiore, x*A
significa ... niente. Bene, ancora una volta, significa , ma non è quello che volevi davvero. Allo stesso modo, traspone la moltiplicazione se è maggiore di riga.x*AT
A*x
A
Pertanto, l'ordine del vettore / moltiplicazione di matrici fa il cambiamento, a seconda della maggiore ordinamento dei dati (e se si sta utilizzando matrici trasposte).
Perché nel seguente frammento di codice r! = R2
Perché il tuo codice è rotto e difettoso. Matematicamente, . Se non si ottiene questo risultato, il test di uguaglianza è errato (problemi di precisione in virgola mobile) o il codice di moltiplicazione della matrice è interrotto.A * (B * C) == (CT * BT) * AT
perché pos3! = pos per
Perché non ha senso. L'unico modo per essere veri sarebbe se . E questo è vero solo per le matrici simmetriche.A * t == AT * t
A == AT