jika saya melihat matriks yang terisi dalam program saya, saya melihat komponen terjemahan menempati elemen ke-4, ke-8 dan ke-12.
Sebelum saya mulai, penting untuk dipahami: ini berarti matriks Anda adalah baris utama . Karena itu, Anda menjawab pertanyaan ini:
matriks WVP utama kolom saya berhasil digunakan untuk mengubah simpul dengan panggilan HLSL: mul (vektor, matriks) yang seharusnya menghasilkan vektor yang diperlakukan sebagai baris-utama, jadi bagaimana matriks utama kolom yang disediakan oleh pustaka matematika saya berfungsi?
cukup sederhana: matriks Anda adalah baris-utama.
Begitu banyak orang menggunakan matriks baris-besar atau transposed, sehingga mereka lupa bahwa matriks tidak berorientasi seperti itu secara alami. Jadi mereka melihat matriks terjemahan sebagai berikut:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Ini adalah matriks terjemahan yang dialihkan . Bukan itu yang tampak seperti matriks terjemahan normal. Terjemahan berada di kolom 4 , bukan baris keempat. Kadang-kadang, Anda bahkan melihat ini di buku teks, yang merupakan sampah.
Sangat mudah untuk mengetahui apakah sebuah matriks dalam array adalah baris atau kolom-utama. Jika baris-utama, maka terjemahan disimpan dalam indeks 3, 7, dan 11. Jika itu kolom-utama, maka terjemahan disimpan dalam indeks 12, 13, dan 14. Indeks nol-basis tentu saja.
Kebingungan Anda berasal dari keyakinan bahwa Anda menggunakan matriks kolom-utama ketika Anda sebenarnya menggunakan yang utama-baris.
Pernyataan bahwa baris vs kolom utama adalah konvensi notasi saja sepenuhnya benar. Mekanika perkalian matriks dan perkalian matriks / vektor adalah sama tanpa memperhatikan konvensi.
Apa yang berubah adalah arti dari hasil.
Matriks 4x4 setelah semua hanyalah kotak angka 4x4. Itu tidak harus merujuk pada perubahan sistem koordinat. Namun, begitu Anda menetapkan makna ke matriks tertentu, Anda sekarang perlu tahu apa yang disimpan di dalamnya dan bagaimana menggunakannya.
Ambil matriks terjemahan yang saya tunjukkan di atas. Itu matriks yang valid. Anda bisa menyimpan matriks itu di float[16]
dalam salah satu dari dua cara:
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};
Namun, saya mengatakan bahwa matriks terjemahan ini salah, karena terjemahannya ada di tempat yang salah. Saya secara khusus mengatakan bahwa itu dialihkan relatif terhadap konvensi standar untuk bagaimana membangun matriks terjemahan, yang seharusnya terlihat seperti ini:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Mari kita lihat bagaimana ini disimpan:
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};
Perhatikan bahwa column_major
adalah persis sama seperti row_major_t
. Jadi, jika kita mengambil matriks terjemahan yang tepat , dan menyimpannya sebagai kolom-utama, itu sama dengan mentransposasikan matriks itu dan menyimpannya sebagai baris-utama.
Itulah yang dimaksud dengan menjadi hanya konvensi notasi. Sebenarnya ada dua set konvensi: penyimpanan memori dan transposisi. Penyimpanan memori adalah kolom vs baris utama, sedangkan transposisi normal vs ditransformasikan.
Jika Anda memiliki matriks yang dihasilkan dalam urutan baris-utama, Anda bisa mendapatkan efek yang sama dengan mentransposisi setara kolom-utama dari matriks itu. Dan sebaliknya.
Penggandaan matriks hanya dapat dilakukan dengan satu cara: diberikan dua matriks, dalam urutan tertentu, Anda mengalikan nilai-nilai tertentu bersama-sama dan menyimpan hasilnya. Sekarang,, A*B != B*A
tetapi kode sumber sebenarnya A*B
sama dengan kode untuk B*A
. Keduanya menjalankan kode yang sama untuk menghitung output.
Kode perkalian matriks tidak peduli apakah matriks kebetulan disimpan dalam urutan kolom-utama atau baris-utama.
Hal yang sama tidak dapat dikatakan untuk perkalian vektor / matriks. Dan inilah alasannya.
Multiplikasi vektor / matriks adalah kepalsuan; itu tidak bisa dilakukan. Namun, Anda bisa mengalikan matriks dengan matriks lain. Jadi jika Anda berpura-pura vektor adalah matriks, maka Anda dapat secara efektif melakukan perkalian vektor / matriks, cukup dengan melakukan perkalian matriks / matriks.
Vektor 4D dapat dianggap sebagai vektor kolom atau vektor baris. Yaitu, vektor 4D dapat dianggap sebagai matriks 4x1 (ingat: dalam notasi matriks, jumlah baris lebih dulu) atau matriks 1x4.
Tapi ada satu hal: Diberikan dua matriks A dan B, A*B
hanya didefinisikan jika jumlah kolom A sama dengan jumlah baris B. Oleh karena itu, jika A adalah matriks 4x4 kami, B harus berupa matriks dengan 4 baris di dalamnya. Oleh karena itu, Anda tidak dapat melakukan A*x
, di mana x adalah vektor baris . Demikian pula, Anda tidak dapat melakukan di x*A
mana x adalah vektor-kolom.
Karena itu, sebagian besar perpustakaan matematika matriks membuat asumsi ini: jika Anda mengalikan vektor kali dengan matriks, Anda benar-benar bermaksud melakukan perkalian yang benar-benar berfungsi , bukan yang tidak masuk akal.
Mari kita tentukan, untuk setiap vektor 4D x, berikut ini. C
akan menjadi bentuk matriks kolom-vektor x
, dan R
harus menjadi bentuk matriks baris-vektor dari x
. Mengingat ini, untuk setiap matriks 4x4 A, A*C
merepresentasikan matriks mengalikan A dengan vektor-kolom x
. Dan R*A
merepresentasikan matriks yang mengalikan vektor baris x
dengan A.
Tetapi jika kita melihat ini menggunakan matematika matriks ketat, kita melihat bahwa ini tidak setara . R*A
tidak boleh sama dengan A*C
. Ini karena vektor baris tidak sama dengan vektor kolom. Mereka bukan matriks yang sama, jadi mereka tidak menghasilkan hasil yang sama.
Namun, mereka terkait dalam satu cara. Memang benar itu R != C
. Namun, juga benar bahwa , di mana T adalah operasi transpos. Dua matriks adalah transpos satu sama lain.R = CT
Ini fakta yang lucu. Karena vektor diperlakukan sebagai matriks, mereka juga memiliki kolom vs pertanyaan penyimpanan baris-utama. Masalahnya adalah mereka berdua terlihat sama . Array float adalah sama, jadi Anda tidak bisa membedakan antara R dan C hanya dengan melihat data. Satu- satunya cara untuk mengetahui perbedaannya adalah dengan bagaimana mereka digunakan.
Jika Anda memiliki dua matriks A dan B, dan A disimpan sebagai baris-mayor dan B sebagai kolom-mayor, mengalikannya sama sekali tidak berarti . Anda mendapatkan omong kosong sebagai hasilnya. Yah, tidak juga. Secara matematis, apa yang Anda dapatkan setara dengan melakukan . Atau ; mereka identik secara matematis.AT*B
A*BT
Oleh karena itu, perkalian matriks hanya masuk akal jika dua matriks (dan ingat: perkalian vektor / matriks hanyalah perkalian matriks) disimpan dalam urutan utama yang sama.
Jadi, apakah kolom vektor-utama atau baris-utama? Keduanya dan tidak sama seperti yang dinyatakan sebelumnya. Ini adalah kolom utama hanya ketika digunakan sebagai matriks kolom, dan itu adalah baris utama ketika digunakan sebagai matriks baris.
Oleh karena itu, jika Anda memiliki matriks A yang merupakan kolom utama, x*A
berarti ... tidak ada. Sekali lagi, artinya , tapi bukan itu yang benar-benar Anda inginkan. Demikian pula, apakah transkripsi multiplikasi jika baris-utama.x*AT
A*x
A
Oleh karena itu, urutan perkalian vektor / matriks tidak berubah, tergantung pada urutan utama data Anda (dan apakah Anda menggunakan matriks transposisi).
Mengapa dalam cuplikan kode berikut tidak r! = R2
Karena kode Anda rusak dan bermasalah. Secara matematis ,. Jika Anda tidak mendapatkan hasil ini, maka tes kesetaraan Anda salah (masalah presisi floating-point) atau kode multiplikasi matriks Anda rusak.A * (B * C) == (CT * BT) * AT
mengapa pos3! = pos untuk
Karena itu tidak masuk akal. Satu-satunya cara untuk menjadi kenyataan adalah jika . Dan itu hanya berlaku untuk matriks simetris.A * t == AT * t
A == AT