programımdaki kalabalık bir matrise bakarsam 4., 8. ve 12. elemanları işgal eden çeviri bileşenlerini görüyorum.
Ben başlamadan önce, anlamak önemlidir: bu matrisler demektir majör satır . Bu nedenle, bu soruya cevap veriyorsunuz:
benim sütun majör WVP matris başarıyla HLSL çağrısı ile köşeleri dönüştürmek için kullanılır: mul (vektör, matris) vektörün satır-majör olarak ele alınması gerekir, bu yüzden matematik kütüphanem tarafından sağlanan sütun majör matrisi nasıl çalışabilir?
oldukça basittir: matrisleriniz satırbaşıdır.
Birçok kişi satır-büyük veya transpozisyonlu matrisler kullanır, matrislerin doğal olarak bu şekilde yönlendirilmediğini unuturlar. Böylece bir çeviri matrisi görüyorlar:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
Bu, aktarılmış bir çeviri matrisidir . Normal bir çeviri matrisi böyle görünmüyor. Çeviri dördüncü satıra değil 4. sütuna gider . Bazen bunu tamamen çöp olan ders kitaplarında bile görürsünüz.
Bir dizideki matrisin satır veya sütun-büyük olup olmadığını bilmek kolaydır. Satır-büyükse, çeviri 3, 7 ve 11. endekslerde saklanır. Sütun-büyükse, çeviri 12, 13 ve 14. endekslerde saklanır. Tabii ki sıfır bazlı endeksler.
Karışıklıklarınız, aslında satır-büyük olanları kullanırken sütun-büyük matrisler kullandığınıza inanmaktan kaynaklanmaktadır.
Satır ve sütun majör ifadelerinin yalnızca gösterimsel bir kural olduğu ifadesi tamamen doğrudur. Matris çarpımı ve matris / vektör çarpımının mekaniği, kural ne olursa olsun aynıdır.
Değişen, sonuçların anlamıdır.
Sonuçta 4x4 matris sadece 4x4 sayı ızgarasıdır. O değil sahip koordinat sistemi değişikliği başvurmak için. Bununla birlikte, belirli bir matrise anlam atadığınızda , şimdi neyin içinde depolandığını ve nasıl kullanılacağını bilmeniz gerekir.
Yukarıda gösterdiğim çeviri matrisini ele alalım. Bu geçerli bir matris. Bu matrisi float[16]
iki yoldan biriyle depolayabilirsiniz :
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};
Ancak, bu çeviri matrisinin yanlış olduğunu söyledim, çünkü çeviri yanlış yerde. Özellikle, bu şekilde görünmesi gereken çeviri matrislerinin nasıl oluşturulacağına ilişkin standart kurallara göre aktarıldığını söyledim:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
Bunların nasıl saklandığına bakalım:
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};
Bildirim column_major
olduğu tam olarak aynı şekilde row_major_t
. Dolayısıyla, eğer uygun bir çeviri matrisi alırsak ve bunu sütun-majör olarak saklarsak, bu matrisi transpoze etmek ve onu satır-majör olarak depolamakla aynıdır.
Yalnızca notasyonel bir sözleşme olmakla kastedilen budur. Gerçekten iki kural dizisi vardır: bellek depolama ve aktarma. Bellek depolama sütun-satır büyük iken, transpozisyon normal veya transpoze edilir.
Satır-büyük sırayla oluşturulmuş bir matrisiniz varsa, o matrisin sütun-büyük eşdeğerini transpoze ederek aynı etkiyi elde edebilirsiniz. Ve tam tersi.
Matris çarpımı yalnızca tek bir yolla yapılabilir: iki matris, belirli bir sırayla, belirli değerleri birlikte çarpar ve sonuçları depolarsınız. Şimdi, A*B != B*A
ancak asıl kaynak kodu A*B
, koduyla aynıdır B*A
. Her ikisi de çıktıyı hesaplamak için aynı kodu çalıştırır.
Matris çarpım kodu, matrislerin sütun-büyük veya satır-büyük sırada depolanıp saklanmadığını umursamaz.
Aynı şey vektör / matris çarpımı için söylenemez. İşte nedeni bu.
Vektör / matris çarpımı yanlıştır; yapılamaz. Ancak, olabilir başka matris ile bir matris çarpın. Bir vektörün bir matris olduğunu varsayarsanız, o zaman etkili bir şekilde matris / matris çarpımı yaparak vektör / matris çarpımını yapabilirsiniz.
Bir 4D vektörü bir kolon-vektörü veya bir satır-vektörü olarak düşünülebilir. Yani, 4D vektörü 4x1 matrisi (hatırlayın: matris notasyonunda önce satır sayısı gelir) veya 1x4 matrisi olarak düşünülebilir.
Ama işte şu: İki A ve B matrisi göz önüne alındığında A*B
, yalnızca A sütunlarının sayısı B'nin satır sayısıyla aynı ise tanımlanır. Bu nedenle, A 4x4 matrisimizse, B 4 sıralı bir matris olmalıdır içinde. Bu nedenle, A*x
x'in bir satır-vektörü olduğu gerçekleştirilemez . Benzer şekilde, x*A
x'in bir sütun-vektör olduğu yerde gerçekleştiremezsiniz .
Bu nedenle, çoğu matris matematik kütüphanesi bu varsayımı yapar: bir vektörü bir matrisle çarpırsanız, gerçekten mantıklı değil, gerçekten çalışan çarpımı yapmak istersiniz .
Herhangi bir 4D vektörü x için aşağıdakileri tanımlayalım. C
'nin sütun-vektör matris formu x
ve' R
nin satır-vektör matris formu olmalıdır x
. Bu göz önüne alındığında, herhangi bir 4x4 matris A için, A*C
A'yı sütun vektörü ile çarparak matrisi temsil eder x
. Ve R*A
satır-vektörünü x
A ile çarparak matrisi temsil eder .
Ancak buna katı matris matematiği kullanarak bakarsak, bunların eşdeğer olmadığını görürüz . R*A
olamaz aynı olacak A*C
. Bunun nedeni, bir satır vektörünün bir sütun vektörü ile aynı şey olmamasıdır. Aynı matris değiller, bu yüzden aynı sonuçları üretmiyorlar.
Ancak, bunlar bir şekilde ilişkilidir. Bu doğru R != C
. Ancak, bu da doğru yerde, T devrik operasyonudur. İki matris birbirinin aktarımlarıdır.R = CT
İşte komik bir gerçek. Vektörler matris olarak değerlendirildiğinden, satır-büyük depolama sorusuna karşı da bir sütunları vardır. Sorun şu ki, ikisi de aynı görünüyor . Şamandıra dizisi aynıdır, bu yüzden sadece verilere bakarak R ve C arasındaki farkı söyleyemezsiniz. Sadece farkı söylemek yolu nasıl kullanıldıkları gereğidir.
İki A ve B matrisiniz varsa ve A satır-ana ve B sütun-ana olarak depolanırsa, bunları çoğaltmak tamamen anlamsızdır . Sonuç olarak saçmalık elde edersiniz. Pek değil. Matematiksel olarak, elde ettiğiniz şey yapmanın eşdeğeridir . Veya ; matematiksel olarak aynıdırlar.AT*B
A*BT
Bu nedenle, matris çarpımı sadece iki matris (ve unutmayın: vektör / matris çarpımı sadece matris çarpımı ise) aynı ana sırada depolanmışsa anlamlıdır.
Peki, bir vektör sütun-büyük veya satır-büyük? Daha önce de belirtildiği gibi, ikisi de değil. Yalnızca bir sütun matrisi olarak kullanıldığında büyük sütun ve bir satır matrisi olarak kullanıldığında büyük satırdır.
Bu nedenle, sütun ana olan bir A matrisiniz varsa x*A
... hiçbir şey ifade etmez. Yine, demek istediğim , ama gerçekten istediğin bu değil. Benzer şekilde, satır- büyükse , aktarılmış çarpma yapar .x*AT
A*x
A
Bu nedenle, vektör / matris çarpma sırası yapar verilerinizin önemli sipariş bağlı olarak değişiklik (ve aktarılmamıştır matrisleri kullanarak ister).
Neden aşağıdaki kod snippet'inde r! = R2
Çünkü kodunuz bozuk ve buggy. Matematiksel olarak ,. Bu sonucu almazsanız, eşitlik testiniz yanlış (kayan nokta hassasiyeti sorunları) veya matris çarpma kodunuz bozulur.A * (B * C) == (CT * BT) * AT
neden pos3! = pos için
Çünkü bu mantıklı değil. Gerçek olmanın tek yolu şuydu . Ve bu sadece simetrik matrisler için geçerlidir.A * t == AT * t
A == AT