VEKTÖR MATRıSLERıArtık bu matris hadisesini geometride nasıl kullandığımızı öğrenme zamanı geldi. Vektörlerimizi bir matris haline getireceğiz. 3D vektörlerde bu iş için 1x3'lük bir sütun matris ya da 3x1'lik satır matris yeterli gibi. Bu boy değişimi bize sadece sağdan çarpma ya da soldan çarpma gibi farklılıklar sağlayacak. Teori yine aynı kalacak. Ama biz geleneğe uyup 1x3'lük sütun matrisleri kullanalım. Örneğin [a,b,c] vektörünü şu şekilde matris olarak göstereceğiz:
[a]
[b]
[c]
Tabi her seferinde böyle sütunlar yazmak zor olduğundan vektörleri [a,b,c] olarak göstermeye devam edeceğiz. O yüzden notasyonla ilgili bir uyarı yapalım da sonra işler karışmasın.
[a]
[b] = [a,b,c] != [a b c]
[c]
Yani dikey yazdığım şey her zaman bir sütun matris. Yatay yazdığımda ise, elemanları virgülle ayırıyorsam bir vektör, dolayısıyla bir sütun matristen; boşlukla ayırıyorsam bir satır matristen bahsediyor olacağım.
Bu noktada transpose (Türkçe'si ne bilmiyorum) matris olayından bahsedelim. Bir matrisin satır ve sütunlarının yer değiştirmiş haline o matrisin transpose'u denir. Örneğin
[a] [2 3]T
[b] = [a b c]T [2 0 1] = [0 1]
[c] [3 1 5] [1 5]
Transpose işareti matrisin sol üst köşesinde bir 'T' harfidir. Ama ben bunu zaman zaman matrisin yanına da koyabilirim. ([a,b,c]T = [a b c] gibi.) Matrisi ismiyle kullanırken de, A'nın transpose'u anlamına gelen T(A) kullanacağım.
Transpose her ne kadar matrisin 90 derece sağa yatmışı gibi görünsede aslen değildir. Yukarıdaki örneğe dikkatlice bakarsanız ne demek istediğim anlaşılır sanırım. Ayrıca bir matrisin transpose'unun transpose'u kendisidir.
Transpose olayını bildiğimiz bir konuda kullanalım şimdi.
ıki vektörün skalar çarpımı neydi:
[a,b,c] . [d,e,f] = ad + be + cf
Bunu matris halinde şöyle gösterebiliriz:
[d]
[a b c] [e] = [ad + be + cf]
[f]
Yani u ve v iki vektör olmak üzere; "u.v = T(u)v". ılk vektörün transpose'unu alıp ikinci vektörle çarparsak, içinde iki vektörün skalar çarpımının bulunduğu 1x1'lik bir matris elde ederiz.
Neyse transpose mevzusunu burada bırakıyorum. şimdi konunun özüne dalıyorum.
Matrislerle Yön ve Pozisyon VektörleriTüm tutorial boyunca en kafamızı ağrıtan olay bu yön ve pozisyon vektörlerinin birbirinden ayrılması idi. Tamam bazılarınız diyebilir ya sadece yön ya da sadece pozisyon vektörleri kullanalım diye. Genelde de bir demoda, oyunda, simülasyonda vs. sadece pozisyon vektörlerini kullanacağız (nesnelerin pozisyonları olarak). Ama tanımladığımız uzayların hepsinde 3 adet yön vektörü bulunmak zorunda. Bu vektörleri ne yapalım, çöpe mi atalım? Ayrıca yön vektörlerini de kapsayan bir motor yazacaksak yine işler karışır. O yüzden bu işi bir sistematiğe bağlama zamanı geldi.
Yapacağımız çıkarımlar yine çevrim formüllerine dayanacak. A uzayında tanımlı v=[x,y,z] vektörü olsun. A uzayının B uzayında tanımı ise şöyle:
[px,py,pz]' pozisyon (merkez)
[xx,xy,xz]' yön (i)
[yx,yy,yz]' yön (j)
[zx,zy,zz]' yön (k)
Bu durumda v vektörünün B uzayında karşılığı olan v' şöyle olacaktı:
v yön vektörü ise:v' . i = x*xx + y*yx + z*zx + 0*px
v' . j = x*xy + y*yy + z*zy + 0*py
v' . k = x*xz + y*yz + z*zz + 0*pz
v yön pozisyon vektörü ise:v' . i = x*xx + y*yx + z*zx + 1*px
v' . j = x*xy + y*yy + z*zy + 1*py
v' . k = x*xz + y*yz + z*zz + 1*pz
Merkezin toplanması hadisesini bu sefer daha ilginç bir şekilde yazdım. Yön vektörlerinde katsayılar x,y,z,0 iken, pozisyon vektörlerinde x,y,z,1 oldu.
O zaman burada bir cinlik yapma zamanı geldi. Programda nasıl olsa her vektörün yön vektörü mü pozisyon vektörü mü olduğunu tutacağımıza göre, bu bilgiyi neden vektörün içinde yeni bir eleman olarak tutmayalım? Yani v bir yön vektörü ise onu [x,y,z,0] olarak, v bir pozisyon vektörüyse onu [x,y,z,1] olarak gösterelim.
Bu taktiğin ne gibi avantajları var peki? Bi kere işin teori kısmından epey bir yük gidecek. Hem yön hem de pozisyon vektörlerinde çalışan daha basit bir sistemimiz olacak. Pratik açıdan da yön ve pozisyon vektörlerinin ayrımını sağlayan koşul ifadelerinden kurtulacağız ve programımız daha da hızlanacak. Tabi bu nosyonu kullanmayıp amaca özel sistemler geliştirebilirsiniz. Ama ilk aşamada kusursuz çalışan bu yöntemi kullanmakta fayda var.
Neyse dağıldık yine. Bu durumda vektörleri 1x4'lük matrisler olarak ifade edeceğim. 2D için 1x3 olacaktı mesela ama o durum hiçbir zaman konumuza girmeyecek.
Skalar çarpımda matris notasyonu diye bir şey olmayacak artık ama skalar çarpım kodu yazarken ilk 3 elemanı kullanmak hala elimizde. Zaten birazdan çok fazla şey kaybetmediğimizi göreceğiz. Vektörel çarpımda matris notasyonunun ise pratik bir değeri olacağını sanmıyorum.
Peki vektörlerde dördüncü elemanı olarak 0 ya da 1 dışında bir sayı kullanırsak ne olur? O zaman, açıkça görüleceği üzere, uzay çevrimlerinde kaynak uzayın merkezi değil, merkezinin 0 ya da 1'den farklı bir katı kullanılır. Örneğin bu değeri 0 ve 1 arasında oynatarak vektörleri yön ve pozisyon arası getirip götürebilir ve ilginç bir efekt bulduğumuzu sanabiliriz. Lakin bu, vektörleri iki uzayın merkezi arasında getirip götürmekten başka bir fayda sağlamayacaktır.
Aslında bu son elemanın faydalarını şu ana kadar gördüklerimizi aşmayan bir örnekle anlatayım.
Örneğin elimizdeki bir karenin köşelerinin koordinatları şöyle olsun:
[0,1,0,1]
[0,1,1,1]
[1,1,0,1]
[1,1,1,1]
Kolayca anlaşılacağı gibi bu kare y=1 düzlemi üzerinde. Bu karenin ön yüzeyi yukarı doğru bakıyor olsun. O zaman [0,1,0,0] şeklinde bir normal vektörümüz olur. Bu normal vektörü karenin ön yüzünün nereye baktığını gösteriyor. Bu vektörü kullanarak kare üzerine gelen bir ışığın hangi açıyla geldiğini bulabiliriz (skalar çarpımın verdiği sonuçları hatırlayın) ama konumuz bu değil. Sadece bu vektörün
yönünün önemli olduğunu, uzaydaki konumunun ise hiç bir işe yaramadığını bilmeliyiz. Yani bu normal kare üstünde olsa da, merkezde olsa da, [2,6,0,1] pozisyonunda olsa da karenin baktığı yönü veriyor.
Karenin koordinatları pozisyon vektörleriydi. Normali ise bir yön vektörü. şimdi vektörler arası yaptığımız işlemleri bir de mantıken inceleyelim.
Bir yön vektörünü bir yön vektörüyle topladığımızda, örneğin normali kendisiyle topladığımızda sonuç yine bir yön vektörü olacak ([0,1,0,0]+[0,1,0,0]=[0,2,0,0]). Bunda şaşılacak bir şey yok zira iki yön vektörünün toplamı art arda o yönlerde vektörlerin uzunlukları kadar ilerlemek demek. 4 kere sağa sonra 2 kere sola dediğimizde aslında 2 kere sağa demek istediğimizi herkes anlıyor. Aynı şekilde yön vektöründen yön vektörü çıkarmak da çok abes gelmeyecektir.
Peki bir pozisyon vektörünü bir yön vektörüyle toplayalım, örneğin karenin bir köşesine normalini ekleyelim:
[0,1,0,1]+[0,1,0,0]=[0,2,0,1]
Sonuçta bir noktaya varmamız gerekiyor ve bingo! ışlemimiz de bir pozisyon vektörü verdi. Yani bir pozisyon vektörüne bir yön vektörü eklediğimizde, aslında yaptığımız şey o pozisyondan o yönde ilerlemek (yön derken yön + uzunluk kastettiğimizi taa tutorialın başında demiş olmalıyız.
Demediysek de o anlamda kullanıyoruz.) Bir pozisyon vektöründen bir yön vektörü çıkardığımızda ise aslında ters yönde ilerlemiş olacağız
Ama bir yön vektöründen bir pozisyon vektörü çıkarırsak...
[0,1,0,0]-[0,1,0,1]=[0,0,0,-1]
Oradaki -1 ne anlama geliyor? Tamamen tutarsız bir işlem yaptığımız anlamına geliyor. Yani bir yön vektöründen bir pozisyonun çıkması gayet anlamsız bir olay. Ben şahsen kafamda bu işlemi canlandıracak temeller bulamıyorum. Peki bu bir sorun mu? Hayır değil. -1 ile gösterilen ve her zaman bir pozisyon vektörünün bir yön vektöründen farkı olan başka bir vektör türü tanımlayabilirsiniz. Peki bu bir işe yarar mı? Belki. Peki kullanacak mıyız? Hayır. Bu tutorialda geometrik anlamı olmayan hiçbir şey yapmayacağız. ısteyen kendi başına deneysel takılabilir tabi.
Bir başka saçma işlem ise iki pozisyon vektörünü toplamak. ıki konumun toplamı bana hiç bir şey ifade etmiyor. Ama bu işlemi kullanarak daha ilginç bir şey yapabiliriz, o da iki ya da daha fazla konumun orta noktasını bulmak.
Örneğin karenin merkezini bulmak istiyoruz. Dört noktayı toplayıp dörde bölersek:
([0,1,0,1]+[0,1,1,1]+[1,1,0,1]+[1,1,1,1])/4 = [2,4,2,4]/4 = [0.5,1,0.5,1]
Sonuç kesinlikle tutarlı. Halbuki ara işlemde ortaya çıkan [2,4,2,4] anlamsız bir vektördü. Böyle işlemler yapmayacaksanız son elemanı tek bir bitte tutmak mantıklı olabilir ama. Bu tür işlemler için o elemanı da diğerleri gibi görmemiz gerekiyor.
Son elemanın faidelerinden bir tanesi de bir pozisyon vektöründen bir başka pozisyon vektörünün çıkarılması. Örnek olarak ilk köşeden diğerini çıkaralım:
[0,1,0,1]-[0,1,1,1]=[0,0,-1,0]
Sonucumuz bir yön vektörü. Bu vektör de ilk köşe ile ikinci köşe arasındaki kenarın uzaydaki rotasyonunu veriyor. Ya da bir başka bakış açısıyla, ilk köşeden bu yön kadar ilerlersek ikinci köşeye ulaşırız. Tamamen makul bir işlem.
Son olarak da skalar çarpımdan bahsedelim. Skalar çarpım fark ettiğiniz gibi pozisyon vektörlerine uygulanamıyor. Peki skalar çarpım bize ne veriyordu? ıki vektör arasındaki açının kosinüsünü. Peki bu kavram tamamen yönlerle alakalı değil mi? Yani uzayda iki pozisyon düşünün; bu pozisyonlar arasında bir açı mı var ki kosinüsü olsun? Ancak üç pozisyon olursa bir açı elde ederiz ve bu açıyı da köşelerin birbirinden çıkarılmasıyla bulunan kenar vektörleri sayesinde bulabiliriz. Bu kenar vektörleri de yukarıda gördüğümüz gibi birer yön vektörü olmaktalar.
Büyük ihtimalle pozisyon vektörleri ile çalışacaksınız demiştim. O yüzden özel sistemler geliştirip dördüncü elemanın dertlerinden kurtulabilirsiniz. Ama ısrarlı biri demo yapımında mutlaka normalleri de yönetmek isteyecektir. Bu nedenle 4 elemanlı vektörlere alışmak sizin için elzem olacaktır. Nedenini sonraki bölüm olan 'Uzay Matrisleri'nde çok çok daha belirgin şekilde göreceğiz.