3. BOYUT
Herkese selam. Üçüncü boyuttaki ilerleyişimize kaldığımız yerden devam ediyoruz. Geçen yazımızda, C64'te 3D efektleri yapmakla ilgili bazı felsefi soruları yanıtlamaya çalışmış, ardından vektörlerin ne olduğu ve üzerlerinde toplama ve çıkarma işlemlerinin nasıl yapıldığını konuşmuştuk. Bu sayıda ise şu konulara değineceğiz:
.Vektör İşlemleri
..Vektörlerin boyu ..Vektör ile skaler çarpımı ..Vektörlerin nokta çarpımı (dot product)
.Vektörlerin 3D efektleri ile ne ilgisi var
..Objelerin vektör kullanılarak ifade edilmesi ..Doğrusal kenarlar ve yüzeyler ..Eğrisel kenarlar ve yüzeyler
.Vektör Dönüşümleri
..Dönüşüm kavramına giriş ..Yer değiştirme (translation) ..Dönme (rotation) ..Ölçekleme (scaling)
Dönüşümlerin birleştirilmesi. Bu yazıya başlamadan hemen önce geçen yazıyı bir kez daha okumanızı tavsiye ederim.
Vektör İşlemleri
Vektörlerde toplama ve çıkarma işlemlerinden bahsettikten sonra sıra çarpma işlemine geldi. Fakat vektörler söz konusu olduğunda çarpma işleminin üç değişik versiyonundan bahsedebiliriz.
Bir skaler ile bir vektörün çarpımı, İki vektörün nokta çarpımı (dot product), İki vektörün çapraz çarpımı (cross product)
Çapraz çarpım konusuna bu yazıda değinmeyeceğiz. Vektörlerde çarpma işlemlerinden bahsederken ihtiyacımız olacak olan bir kavram daha var: Vektörlerin boyu. Bu konuyu kısaca açıkladıktan sonra skaler çarpıma geçebiliriz.
Vektörün Boyu
Vektörleri ilk başta tanımlarken bir büyüklük ve bir yön ifade ettiklerini söylemiştik. İşte bu büyüklüğü vektör koordinatlarından elde etmenin yolundan bahsetmenin zamanı geldi. Aslında bir vektörün boyunu bulmak için Pisagor teoremini kullanmamız yeterlidir. P vektörünün boyunu |P| diye gösterirsek:
P(x1,y1) olsun
|P| = √(x1² + y1²)

Vektör ile skaler çarpımı
Hatırlarsanız vektörler için çok boyutlu büyüklükler, skalerler için ise tek boyutlu büyüklükler demiştik. Bir skaler ile bir vektörün çarpımı tanımlı bir işlemdir ve sonucu da bir vektördür. Bütün yapmamız gereken skaler ile vektörün tüm bileşenlerini teker teker çarpıp sonuçlardan yeni bir vektör oluşturmaktır:
n skaler bir sayı olsun. P(x1,y1) vektörünü n ile çarparsak:
n * P(x1,y1) = (n*x1, n*y1) n pozitif bir sayı ise bu yaptığımız çarpım, vektörün yönünü değiştirmeden boyunu n oranında uzatır. n negatif ise yönü tam olarak tersine çevirip n'nin mutlak değeri oranında boy uzatılır. Uzatılır diyorsak da unutmayın n eğer 0 ile 1 arasında bir değere sahipse o zaman vektörün boyu kısalmış olur.

Vektörlerin nokta çarpımı
İki vektörün nokta çarpımı şöyle tanımlanmıştır:
P(x1,y1) . Q(x2,y2) = (x1*x2) + (y1*y2)
Yani x koordinatları birbiri ile çarpılır. Aynı şekilde y koordinatları birbiri ile çarpılır. Bu iki çarpım toplanır. Yani nokta çarpımın sonucu bir skalerdir.
Bazı trigonometrik çıkarımlardan sonra bu işlemin aslında aşağıdaki gibi de ifade edilebildiğini görürüz.
P(x1,y1) . Q(x2,y2) = [P][Q]cos(a)
Burada a açısı P ve Q vektörlerinin arasındaki açıdır. [P] P'nin uzunluğudur (boyudur). Bu işlem geometrik olarak şöyle yorumlanabilir. [P]cos(a) aslında P vektörünün Q üzerine olan izdüşümünün boyudur. Bu boy ile Q'nun boyunun çarpımı, nokta çarpımını verir.

Örnek: (2,5) . (1,-2) = (2*1) + (5*(-2)) = 2 + (-10) = -8
Nokta çarpımın 3D efektlerdeki en önemli faydalarından biri iki vektör arasındaki açıyı bulmaya yaramasıdır. Bu açı da ışıklandırma efektlerinde işe yarar.
(x1*x2) + (y1*y2) = [P][Q]cos(a)
cos(a) = ( (x1*x2) + (y1*y2) ) / ( [P][Q] )
cos(a)'yı bildiğimiz için a'yı da bulabiliriz. Ama çoğu zaman zaten bize lazım olan a'nın kendisi değil kosinüsüdür. Bunu ileride göreceksiniz.
Son olarak ufak bir gözlem yapmanızı isteyeceğim. İki vektörün aralarındaki açı 90 derece ise nokta çarpımları ne olur? cos(90)'ın değeri 0'dır. Yani vektörlerin boyları ne olursa olsun 0 ile çarpılacakları için aralarındaki açı dik olan iki vektörün nokta çarpımı her zaman 0 olacaktır.
Vektörler ile 3D efektlerin ne ilgisi var?
Bu kadar çok vektörlerden bahsetmemize rağmen henüz sadece vektörler üzerinde bazı işlemlerin matematiksel olarak nasıl yapılacağını gördük. Bu işlemlerin ve vektörel ifadelerin ne işimize yarayacağını anlayabilirsek onları gereken yerlerde kullanabilecek durumdayız.
Objelerin vektörlerle ifade edilmesi
İşte kilit konu bu. Uzayda duran herhangi bir obje (kalem, kitap, ev, Hüsnü, Ayşe vs...) nasıl matematiksel olarak ifade edilebilir. Bir objenin şeklini matematiksel olarak ifade etmenin bir yolunu bulmalıyız ki o obje hakkındaki bilgileri bilgisayarda saklayabilelim ve üzerinde işlemler yapabilelim.
Her objeyi sonsuz sayıda noktalardan oluşuyor gibi düşünebiliriz. Yani sonsuz miktarda belleğimiz, sonsuz güçte bir CPU'muz olsa bir objeyi oluşturan bütün noktaları bir vektör olarak alıp her nokta için x ve y koordinatlarını belleğe saklayabilir ve üzerlerinde işlem yapabilirdik. Bu pratikte mümkün olmadığına göre bütün noktaları seçmeyeceğiz.
Eğer objenin sınırlarındaki noktaları seçip içini göz ardı edersek bayağı bir noktadan kurtulmuş oluruz. Yani artık objenin sadece dış yüzeylerindeki noktaları düşünelim. Maalesef hala sonsuz sayıda nokta demektir bu. İşte bu noktada bu sonsuz sayıdaki dış noktadan sonlu sayıda nokta seçip objeyi yaklaşık bir şekilde modelleyeceğiz.
Modellemek
Modellemek bütün mühendislik dallarında kullanılan bir terimdir. Genel olarak gerçek dünyada var olan bir objeyi, olayı veya problemi matematiksel olarak ifade etmeye verilen addır. Çoğunlukla bu matematiksel ifadeye çevrim esnasında bazı bilgiler kaybedilir ve sisteme bir 'hata payı' dahil olur. Bu hata payının miktarı bilindiği müddetçe modelden verimli sonuçlar elde edilebilir. Mesela bir kalemin boyunu ölçseniz ve 20 cm deseniz bir modelleme yapmış olursunuz. Bu modelleme ile gerçek dünyada var olan 'kalemin boyu' kavramını matematiksel bir büyüklük olan '20 cm' ile modellemiş olursunuz. Cetvelinizdeki en dar çentik 1 mm ise siz kalemin boyunu 20.0 cm ile 20.1 cm arasında gördüğünüz için 20 cm dersiniz ama kalemin gerçek boyu belki de 20.024 cm. Ama sizin elinizdeki imkanlarla bunu bilme şansınız yok. Peki modeliniz bu durumda hiç işe yaramaz mı? Mesela birisi dese ki “ben bu kalemden 4 tanesini uç uca koyacağım acaba şuradaki 1 metrelik masaya sığar mı?” Siz bu modeli kullanarak bu probleme cevap verebilirsiniz. Elinizdeki model kalemin 20 cm olduğunu ve 1 mm'lik hata payınız olduğunu söyler. Öyleyse 4 kalemin boylarında 4 kere maksimum hatayı göze alırsanız 4 kalemin uç uca 80 cm olacağını ve 4 mm'lik hata payınız olduğunu söyleyebilirsiniz. Bu da 1 m'nin altında olduğu için bu kalem manyağı arkadaşınıza içinin rahat olmasını söyleyebilirsiniz.
Obje Modellemek
Böylece objenin dış yüzeylerinden seçeceğiniz sınırlı sayıdaki nokta ile o objeyi modelleyebilirsiniz. Bu noktada objenin özelliklerine bakılarak nasıl bir modelleme yapılacağına ve ne tip noktaların seçileceğine karar verilir. Örneğin elinizde tam düzgün küp şeklinde bir obje varsa bunun 8 köşe noktasını seçerek modelleyebilirsiniz. Bu noktaların aralarında doğrusal kenarlar olduğunu, kenarların oluşturduğu karelerin de doğrusal yüzeyler olduğunu söylersiniz. Aralardan daha fazla nokta da seçebilirsiniz. Ama doğrusal olduğunu bir kere söylediğiniz bir kenarın iki dış köşesini vermişseniz ortasından üçüncü bir noktayı daha vermeye gerek yoktur. Çünkü zaten o iki kenarın doğrusal olduğunu bir kere söylediniz. Bu sayede o aradaki her noktayı tanımlamış oldunuz. Bunun dışında seçilecek her ekstra nokta sisteme getirilen gereksiz bir yük olacaktır.

Doğrusal Kenarlar ve Yüzeyler.
Eğer obje böyle doğrusal kenar ve yüzeylere sahipse genelde 3 boyutlu jargonda MESH (meş diye okunur) olarak bilinen modelleme ile modellenir. Bu metotda obje, köşe noktaları ve köşeleri bağlayan kenarlar ve kenarların arasında kalan yüzeyler cinsinden ifade edilir. Unutulmaması gereken şey bu kenarların doğrusal, yüzeylerin düzlemsel olduğudur.
Eğri Kenar ve Yüzeyler
Bu konuya kısaca değineceğiz. Bazen eğri kenarları olan organik canlı, kumaş vs. gibi objeler farklı matematiksel ifadelerle modellenir. Çoğunlukla polinomik yaklaşık modelleme teknikleri kullanan bu sistemlerde (splines, NURBS vs.) işlemler daha güçlü matematik CPU'lara ihtiyaç duyar. Yani kısa vadede C64 üzerinde kalkışmasanız iyi olur. Önce doğrusal sistemlerde kendinizi geliştirmeniz daha mantıklı olur.
Vektörel Dönüşümler
Dönüşüm nedir?
En genel tabiriyle dönüşüm eldeki bir vektöre bir takım işlemler uygulayıp yeni bir vektör elde etmemizi sağlayan bir operasyondur. Yani elimizde P vektörü varken bu vektöre M dönüşümünü uygularsak P' vektörü elde ederiz. Mesela örnek bir dönüşüm şöyle olabilir: P vektörünün bütün koordinatlarına 3 eklemek. Ya da P vektörünün x koordinatını 5 ile çarpıp y koordinatını 2 ile bölmek. Aklınıza gelen her dönüşüm, sonuçta aynı boyutlu başka bir vektör verdiği müddetçe geçerli bir dönüşümdür. (Hatta aynı boyutlu olmak zorunda bile değildir. Mesela perspektif dönüşüm 3 boyutlu bir vektörü iki boyutlu bir vektöre dönüştürür. Buna sonra değineceğiz)
Dönüşümler çoğu zaman tek bir vektöre uygulanmazlar. Birçok vektöre aynı anda uygulanırlar. Uzayda objeler köşe noktaları ile tanımlanabileceği için bir objeyi oluşturan bütün noktalara bir dönüşüm uygulanarak obje üzerinde bir dönüşüm yapılabilir. Bu dönüşüm objenin şeklinde bir değişiklik yapmayıp uzaydaki yerini veya duruşunu değiştirebilir. Ya da objenin şeklinde bir deformasyon meydana getirebilir; işte dönüşümlerin 3D efektlerdeki kullanımı budur. Dönen küpler veya 3 boyutlu mekanlarda yapılan gezintiler hep aslında objeleri tanımlayan köşelere, o anda kameranın bulunduğu yer ve açıya göre bir takım dönüşümlerin uygulanması sonucu elde edilen yeni koordinatlara göre ekranda çizim yapılması ile gerçekleştirilir.
Yer Değiştirme
Bir noktanın koordinatlarına bir takım değerler eklediğimizde o noktanın yerini değiştirmiş oluruz. Bir objeyi modellerken kullandığımız bütün köşe noktalarına aynı dönüşümü uygularsak objeyi olduğu gibi uzayda hareket ettirmiş oluruz.
Genel olarak yer değiştirme hareketini de bir U(xh,yh) vektörü ile tanımlarsak, P(x1,y1) noktasını U vektörü kadar yer değiştirdiğimizde varacağımız noktaya Q(x2,y2) dersek, x2 = x1 + xh, y2 = y1 + yh olur.

Dönme
Dönme işleminin nasıl olduğunu anlayabilmek için tek bir noktanın a açısı kadar origin etrafında döndürülmesini inceleyeceğiz.

Noktamız P(x1,y1) noktası olsun; bu noktayı saatin ters yönünde a açısı kadar döndürdüğümüz zaman noktamız Q(x2,y2) koordinatlarına gelecek. Elimizde x1, x2 ve a varken x2 ve y2'yi nasıl bulacağız?
Bunun için gelin P vektörünü iki bileşene ayıralım: Px(x1,0) ve Py(0,y1). Dikkat ederseniz P'yi, Px'i ve Py'yi ne kadar döndürürsek döndürelim, P her zaman Px ve Py'nin toplamına eşit olacak. Öyleyse biz Px ve Py'nin a açısı kadar döndürüldüğünde nereye geldiklerini bulursak (ki bunu bulmak kolay) sonra bu ikisini toplayıp Q(x2,y2) noktasını bulabiliriz.

Px, a kadar dönünce x ekseni ile a derece açı yapan x1 uzunluğunda bir vektör olur. Trigonometriden hatırlarsak bu durumda Px'in x koordinatı (x1)cos(a) olur. Aynı şekilde y koordinatı ise (x1)sin(a) olur.
Py, a kadar döndüğünde y ekseninin sol tarafına doğru a açısı yapan y1 uzunluğunda bir vektör olur. Onun koordinatları da sırası ile (-y1)sin(a) ve (y1)cos(a) olur.
Son olarak P'nin yeni yerini yani x2 ve y2'yi bulmak için Px ve Py'nin aynı koordinatlarını toplarsak, x2 = (x1)cos(a) – (y1)sin(a) y2 = (x1)sin(a) + (y1)cos(a)
İşte bu bir noktayı tek eksende iki boyutlu döndürmek için gereken işlemdir. Bir objeyi oluşturan bütün noktalar için bu işlem tekrarlanırsa obje origin etrafında (ya da 3 boyutlu düşünürsek z ekseni etrafında) döndürülmüş olur.
Ölçekleme
Ölçekleme işlemi bir objeyi büyütüp küçültmeye yarar. Bir vektörün skaler ile çarpılması konusundan hatırlarsanız, bu işlem sonucu vektörlerin boyları uzayıp kısaltılabiliyordu. Eğer bir objeyi tanımlayan bütün noktaların vektörlerini aynı skaler ile çarparsak o objeyi o skaler oranında ölçeklemiş oluruz.
Genelde bütün noktaların x ve y koordinatları aynı skaler ile çarpılarak ölçeklenir bu durumda obje şeklinde herhangi bir deformasyona uğramadan büyür ve küçülür. Eğer x ve y koordinatları aynı oranda ölçeklenmezse objeler x veya y yönünde yassılaşırlar. Bu da bazen kullanılan bir efekttir. Ben bu efekti Mist demosundaki wobbling vektör partında kullanmıştım.
Hatta objeyi oluşturan noktalar farklı farklı skalerler ile anime bir şekilde ölçeklenirse çok ilginç jelimsi objeler elde edilebilir ki bu tip efektler genelde çok prim yapar. 3 boyut motorunuzu yazdıktan sonra böyle ufak oynamalarla çok ilginç ve orijinal efektler bulabilirsiniz.
Dönüşümlerin birleştirilmesi
Genelde dönüşümler tek tek değil birlikte gerçekleşirler. Yani bir obje uzayda aynı anda yer değiştirip kendi etrafında dönerken büyüyüp küçülüyor olabilir. Bir objeye olan dönüşümler bu durumda birleştirilip hesaplanabilmelidir.
Bu ihtiyacın doğduğu bir diğer popüler durum daha vardır. Kinematik. Örneğin kendi kolunuzu düşünün. Kolunuz omzunuzdan bir açı ile bir eksende dönerken, dirseğiniz başka bir açı ile döndüğünde eliniz ne kadar dönmüş ve yer değiştirmiş olur. Bu soruyu cevaplayabilmek için objelerin birbirlerine bir ebeveyn-çocuk hiyerarşisi ile bağlandığını düşünebiliriz. Yani bu örnekte gövdeniz, üst kolunuzun babası, üst kolunuz ön kolunuzun babası, ön kolunuz ise elinizin babası gibi. Çoğunlukla babalar bir dönüşüm yaptıklarında bütün çocuk ve torunları bu dönüşümü geçirir. Ama çocuk...
What is the matrix
Evet sayın okuyucular. Kısaca matrix matematiğinden de bahsederek gereken bütün temel matematik bilgisini tamamlamış olacağız. Bundan sonra da C64 üzerinde bu efektleri nasıl kodlayacağımıza geçeceğiz. Fakat bu sayı için yeterince şey öğrendiniz. Gelecek yazıda matrix'lerin tanımından devam edeceğim.
Tamamen matematik ağırlıklı olan bu yazıda anlamadığınız pek çok yer olabilir. Vektör işlemleri lise matematik seviyesinde olduğu için daha az problem olabilir ama dönüşümleri anlamak sizi daha çok zorlayabilir. Bu durumlar için forumlar veya mail yoluyla bana sorularınızı ulaştırabilirsiniz.
Gelecek yazıda görüşmek üzere...