Yazılarımı Daha Kolay Takip Etmek İçin Tıklayın!

XNA’de 3 BOYUT TEMELLERİ ve NESNELERİN HAREKET MANTIĞI

yazan: 12/5/2008 7:19:00 AM

Herkese merhabalar, uzun bir aradan sonra XNA hakkındaki yazılarıma devam ediyorum. Malum vizelerdi, Türkiye’ye dönüş heyecanıydı ödevlerdi … bir sürü bahaneden sonra, tekrar bir seri başlatmayı düşünüyorum. XNA’ de 2 boyut ve XNA’de multiplayer yazı dizilerim oldukça iyi tepkiler aldı. Desteğiniz için hepinize teşekkür ediyorum.

Bu yazımın konusu 3 boyuta girişten ziyade XNA’de 3 boyutun mantığını anlatmak olacak, önce mantığını kavrayalım, sonra zaten bizi kimse tutamaz. Öncelikle bazı konuları maddeler halinde inceleyelim, gerektiği yerde açıklayalım.

. XNA sağ el koordinat sistemini kullanır. Yani sağ elinizin parmak uçları X eksenini gösterirken avucunuz Y eksenini ve baş parmağınız da Z eksenini gösterir.

. XNA’de 2 tip iz düşüm (projeksiyon) vardır. İz düşüm bir nesnenin görüntüsünün mesafesine göre nasıl ölçeklendiğidir gibi bilgisayar oyunlarına özel bir tanım yapalım şimdilik. Bu iki tip sırasıyla;

-          Perspektif: Cisim uzaklaştıkça daha ufak gözükür, görülebilir genişlik artar.

-          Ortogonal: Bu tipte ise uzaklaşsa bile cismin boyutu değişmez, 2 boyut gibi düşünelim.

. Köşeler: Diğer bir deyişle “açısal oluşum noktaları” evrende bir nokta düşünün. Bu noktadan çıkan doğrular aralarında açıları oluşturacaktır. Örneğin hemen bulunduğunuz odanın tavanının köşesine bakın, sırasıyla biri X, biri Y, biri de Z ekseninde 3 doğru çıkıyor değil mi? Ve aralarında 90 derecelik dik açı var. Ve her şekil köşelerin birleştirilmsiyle oluşur, çocukken bulmacalarda noktaları birleştirdiğimizi hatırlayalım. Ve eğer bu noktaların her birinden 3 boyuta doğru çizgilir çıksaydı ne olurdu? Yanıt basit 3 boyutlu modeller. Az önceki örnekten devam edelim odadaki her köşeyi birbirine bağlayın ne oldu? Bir oda yani dikdörgenler prizması, değil mi.

Eh artık 3 boyutun unsurlarını biliyoruz peki bunları nasıl kullanacağız da bir oyun ortaya çıkacak?

XNA’de köşeler:

XNA’de köşeler, yerlerini ve diğer özelliklerini renk vb. içeren yapılar (struct) yardımı ile tanımlanırlar.

VertexPositionColor -> bu yapı ile bir köşe (vertex); yeri (position) ve rengi (color) ile tanımlanır.

VertexPositionTexture -> bu yapı ile bir köşe; yeri ve dokusu (texture) ile tanımlanır, desenin kendi içinde (0,0) desenin sol üst; (1,1) desenin sağ alt köşe limitidir.

VertexPositionColorTexture -> yukarıdaki iki yapının bileşimi gibi düşünelim.

VertexPositionNormalTexture -> bir normal vektörü ve bunun yanında yer ve desen tanımlanır.

XNA’de köşeleri birleştirmek için; GraphicsDevice.DrawPrimitives metodu kullanılır, bu metodun ilkel tipler (Primitive Types) için tanımlanmış enumaration değerlerine göre köşeler bir düzen içinde birleştirilir. Buradaki ilkel tipler programlama dillerindeki int, float vb. ilkel tiplerle karıştırılmamalıdır. Bahsettiğimiz Enum değerleri, 1. Parametre olarak kullanılacaktır; hepsi PrimitiveType. xxxx  şeklinde kullanılabilirler. Bu metodu kullanmadan önce Vertex buffer dediğimiz bir köşe listesini oluşturmamız gerekir. Bunu da Enum değerlerini gösterdikten sonra anlatacağım.

.PointList -> Köşe listesinde (Vertex Buffer) bulunan her vertex birbirinden bağımsız birer nokta şeklinde çizilir.

.LineList -> Köşe listesindeki köşeler sırayla ikişerli olarak gruplandırılır ve her ikilinin arası bir çizgi ile doğrusal olarak birleştirilir.

.LineStrip -> Köşe listesindeki köşeler sıra ile art arda birleştirilir.

.TriangleList -> Köşe listesindeki köşeler üçer üçer gruplandırılır, her üçlü bağımsız bir üçgen oluşturur.

.TriangleStrip -> Her yeni üçgen kendinden önceki üçgenin son iki noktası kullanılarak oluşturulur, dolayısı ile üçgenler bağlıdır, ilk üçgen dışındaki üçgenler için tek nokta gerek ve yeterlidir.

.TriangleFan -> İlk köşemiz tüm üçgenlerin tepe noktası olur ve üçgenler birfan şeklinde oluşur. Buna örnek olarak ikiye kesilmiş portakalı verebilirim, orta noktasını ilk noktamız kabul edersek, her dilim bir üçgen oluşturacaktır, tepe noktaları ortak olacaktır.

GraphicsDevice ekranKartı;

Şeklinde tanımlanmış bir aygıtımız olduğunu varsayarak; Bir  Vertex buffer ‘ı(Köşe Listemizi) nasıl oluşturacağız; buna bakalım;

VertexBuffer köşeListesi;

           // Diyerek bir VertexBuffer tanımlamış olalım. 

VertexPositionColor[]  köşeler= new  VertexPorsitionColor[10];             

//10 köşe barındıran bir dizi oluşturduk;

köşeler[0] = new VertexPositionColor(new Vector3(0.0f, 0.0f, 0.0f),Color.White);

            // gibi bir kodla tüm köşelerimizi atayacağınızı varsayıyorum; 

köşelListesi = new VertexBuffer (ekranKartı, 10* VertexPositionColor.SizeInBytes,

                 BufferUsage.WriteOnly);

// diyerek Vertex Bufferımızı oluşturduk. Buradaki 10 listemizdeki eleman sayısı.

 

Yukarıda fark etmişsinizdir; Köşemizin yerini belirlerken Vector3 diye bir yapı kullandık; peki bu yapı nedir?

Adından da anlaşılacağı üzere Vector3 yapısı 3 boyutlu bir vektör tutar, yani X, Y ve Z koordinatlarından oluşan bir vektörü tutar. Vektör denince kafası karışanlar için, buna noktanın tanımlandığı hacim (dünya, oda … vb 3 boyutlu bir mekan) içerisindeki yerini belirtir diyelim. Yani odanın duvarında duran X ve Y koodinatlarına sahip bir sinek değil de odada uçan, oda hacmi içinde herhangi bir yerde olan sineğin konumu Smile.

Madem Vector3 yapısına (struct) giriş yaptık kısaca metotlarının bazılarından bahsedivereyim;

Vector3.Distance() -> verilen iki nokta arasındaki uzaklığı hesaplar.

Vector3.Add()

Vector3.Subtract() -> bu metotlar, vektörel toplama ve çıkartma yapar. Yani X değerleri  X Değerlerinden, Y değerleri Y değerlerinden … çıkartılır.

Vector3.Multiply()

Vector3.Divide() -> Bu iki metor  iki vektör arası çarpma bölme işlemi veya verilen bir sayı ile bir vektörü çarpıp bölme işini yapar.

Vector3.Clamp() -> Vektörü verilen sınırların içinde tutar, sınırın dışarısında bir değer almasını engeller; yani yukarıdaki örnekteki sinek bu metot yardımı ile odanın dışına çıkamaz.

Vector3.Lerp() -> İki vektör arası doğrusal interpolasyonu hesaplar.

Vector3.SmoothStep() -> Verilen bir değeri ağılık kabul ederek, iki vektör arası interpolasyonu hesaplar.

 

Bunlardan ayrı olarak yine Vector3 yapısına dahil özelliklerden bazıları da;

Vector3.Zero -> Geriye tüm değerleri 0 olarak atanmış bir vektör döndürür. (0,0,0)

Vector3.Up -> Yukarıya bakan bir vektör döndürür (0,1,0)

Vector3.Right -> Sağa bakan bir vektör döndürür (1,0,0)

Vector3.Forward -> Sağ el koordinat sistemine göre ileri giden bir vektör döndürür (0,0,-1)

Vector3.Left , Vector3.Down, Vector3.Backward

Vector3.UnitX -> bir birim X vektörü döndürür (1,0,0)

Vector3.UnitY, Vector3.UnitZ

 

Peki bir nesne (model) köşelerin birleştirilmesinden oluşuyorsa ve her köşe bir vektör olarak temsil ediliyorsa, Oyunun geçeceği dünya nasıl temsil edilmeli?

Yanıt matrisler, eğer içinde bulunduğumuz oda bir 3 boyutlu matrisle temsil ediliyor olsaydı, kağıt üzerinde sineğimizin nerede uçuyor olduğunu işaretleyebilecektik.

XNA’de matrisler, bir nesnenin rotasyonunda (bir eksen etrafında dönme hareketleri), ölçeklendirilmesinde (uzağa giden nesne küçülür) ve translasyonunda (sabit yönlü hareket) kullanılır.

Eğer matris kullanmıyor olsaydık, bir nesnenin tüm hareketleri için vektörün her bir değerine tek tek ulaşıp o değeri değiştirecektik. Ama bu işi iki matrisin arasındaki matematiksel işlemler aracılığı ile yaparsak hem X, Y ve Z değerlerine ayrı ayrı ulaşmak zorunda kalmayacağız hem de her bir işlemi tek tek uygulamak yerine aynı anda hem haraket ettirebilecek hem de nesnenin boyutunu değiştirebileceğiz.

Matrislerin kullanılmasının bir diğer sebebi ise çağdaş ekran kartlarının tümünde GPU üzerinde matris algoritmaları olması, böylece CPU üzerine binecek yükten de kurtulmuş oluyoruz.

Bir nesneye Matris işlemleri ile haraket nasıl verilir?

Bir noktamız var koordinatları (20,10,30) olsun. Bunu 30 birim yukarı hareket ettirmek istiyoruz. Bunu nasıl yapacağız?

Sonunda Lineer Cebir dersleri bir işe yarıyor ve matrislerde çarpma yapıyoruz.

         [1, 0, 0, 0]

[20,10,30,1] x|0, 1, 0, 0|  = [20, 40, 30, 1]

                     |0, 0, 1, 0|

                     [ 0,30,0, 1]

Gördüğünüz gibi y değeri 30 arttı.

Eğer bu işlemde, ilk matrisimizde en sondaki 1’i arttırsaydık 60 birim ilerlemiş olacaktık, yani bu ilerleme katsayısıdır.

Eğer, İkinci matristeki köşegende bulunan 1’leri  arttırsaydık, nesnemizin boyu büyüyecekti, yani bu köşegen de nesnemizin ölçeklendirilmesinden sorumlu.

Ve aynı zamanda eğer ikinci matrisimizde sin ve cos değerleri kullanıyor olsaydık, nesnemiz dönme hareketi yapacaktı. Gördüğünüz gibi neredeyse hiç uğraşmadan tek matris işleminde nesnemizi hareket ettirdik.

Yazımı bitirmeden önce son bir şey söylemek istiyorum, matrisler sizi korkutmasın çünkü bu işlemleri XNA sizin için Matrix sınıfı aracılığı ile yapıyor, buradaki amacım size işin işleyiş mantığını göstermekti. Bir sonraki yazımda size Matris sınıfından bazı işlevlerinden bahsedeceğim, Eğer zaman bulursam Efektlere de tanıtma niyetinde bir giriş yapmak istiyorum. Hepinize kolay gelsin.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Etiketler: , , ,

XNA

Related posts

Comments

3/3/2010 12:37:38 PM

ucvhost

Thanks for the great post,i love to read articles that are informative and beneficial in nature.

ucvhost us

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

3/11/2010 3:17:25 PM

 

Yazar Hakkında

Erçin YONTAR
Erçin Yontar
1986 yılında Çorlu'da doğdu.İlk öğrenimini Ankara'da, ortaöğrenimini Eskişehir'de gördü.
Çanakkale 18 Mart Üniversitesi Bilgisayar Mühendisliği Bölümü mezunu.
Yazılım ile çok ilgili; Visual Studiosu daima açık :) bunun sayesinde Imagine Cup 2008 Türkiye 3.sü ve bir çok proje geliştiriyor.
Yazılım dışında : Frp hastası, rock/metal dinliyor, organizasyon işlerine merak sardı. Bunların yanında o bir; 
MCTS (Microsoft Certified Technology Specialist)



MSP (Microsoft Student Partner)

Bana posta atın Send mail

Favorilerine Ekle


Add to Technorati Favorites

 

Twitter - Ne Yapıyorum?

    Pages

      Recent comments

      Feragatname

      Burada yazan yazılar ve içerdikleri fikirler yazarına aittir. Başkasını ilgilendirmez. Yazıları kaynağını kopyaladığınız yazının içinde tıklanabilir link halinde belirtmek şartı ile olduğu gibi kullanabilirsiniz. Bu kuralları değiştirme hakkım saklıdır. Yarın bir gün benim yazım benim blogumdan başka bir yerde olamaz dersem Kopyaladığınız yazıyı da silmek zorundasınız. Bu işe girşen kişi bu koşulları ve doğan yasal yükümlülükleri kabul etmiş sayılır. Eyvallah diyen devam etsin.

      © Tüm hakları saklıdır.

      Giriş