13 Ocak 2009 Salı

XNA’ de 3 Boyutlu Model Ekleme

XNA kütüphanesini kullanarak oluşturduğunuz bir projeye 2 boyutlu bir nesne eklemek için gerekli olan tanımlamalar; öncelikle iki boyutlu resmimizi çizmemizi sağlayacak olan bir SpriteBatch nesnesi, bu resmimizin oyuna yüklenmesini sağlayacak olan bir Texture2D verisi ve resmin konumunu belirteceğimiz Vector2 yapısında tanımlanmış olan bir veriydi.

3 Boyutlu model eklemede işler biraz değişiyor. Herşeyden önce artık model kavramı işin içine giriyor. Artık mesh olarak da bahsedilen doku kavramı işin içine giriyor. Modele farklı açılardan baktığımızda önceki açıda göremediğimiz kısımlarını görürüz. Bu kısımlar aslında o modeli oluştuturken farklı çizilen resimlerin bir araya getirilmesinde kaynaklanıyor. Bu kısımları modelimizin dokuları olarak düşünebiliriz.

Bu yazımda size 3 boyutlu bir modeli eklemek için nelerin gerekli olduğundan ve projemizde yapmamız gerekenlerden bahsedeceğim.

1.) Gerekli Tanımlamalar

Öncelikle modelimiz ile ilgili tutacak bir Model nesnesi tanımlamalıyız.

Bu tanımlamayı Game1.cs sınıfımız içinde sınıf tanımlamamızın hemen içine yazalım. Ardından ekran oranı bilgilerini tutacak olan float türünde “aspectRatio” adlı bir değişken tanımlayalım. Şimdi bu modelimizi farklı açılardan da görmemizi sağlayan kameramız için modeli hangi açıdan görmek istiyorsak bu bilgileri bverebileceğimiz Vector3 tipinde bir değişken tanımlayalım. Bu değişkenimizin adı da “cameraPosition” olsun. “projectionValue” değişkeni modeli ne kadarlık bir açıdan görmek istediğimizi belirler. Bu değeri arttırdığımızda model daha uzaktan gelir, azalttığımızda model sanki daha yakınmış gibi görünür.

public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
Model myModel;
//projection icin gorus acini belirleyecek degisken.
float aspectRatio;
//kamera için
Vector3 cameraPosition;
float projection_value=30.0f;
2.) Modeli Yüklemek

Modeli Yüklemek için LoadContent metodu içine eklememiz gereken bazı komut satırları var. Bunlardan

myModel = Content.Load("Models/model1 ");

Var olan modeli dokularıyla birlikte eklememizi sağlar. Dokularıyla ilgili bir kod yazmadığımız halde nasıl oluyorda model dokularını bulabiliyor?

“fbx” uzantılı modellerimizin dosyaları mevcut. Bu modelleri projemize eklediğimizde modele tıkladığınızda .NET ortamında bu dosya açılır. Dosyanın içerisine baktığınızda her dokuyu aradığı “RelativeFilename” tanımlıdır. Burda dokunun bulunduğu dizinin adresi yer almaktadır.
aspectRatio değeri aşağıdaki komut satırında görüldüğü gibi hesaplanır.

Kameranın yerini belirlemekte kullanacağımız “cameraPozition” değişkeninin ilklemesini de aşağıdaki satırdaki gibi yapıyoruz. Burdaki ilk parametre “right” ı belirten x eksenini ikinci parametre “up” ı belirten y eksenini ve üçüncü parametre “look” ı belirten eksenini ifade etmektedir. Eğer ikinci argümanı 10.f yerine 5000.f oalrak değiştirirseniz cisminizin görünüşünde değişiklik olur. Üst kısmını daha iyi görebilirsiniz.

cameraPosition = new Vector3(0.0f, 10.0f, 5000.0f);

protected override void LoadContent()
{
//modeli yukle
myModel = Content.Load("Models/model1");
//bakis acini belirle,cismin ne kadar darlık ya da genislikte gorulecegidir
aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
(float)graphics.GraphicsDevice.Viewport.Height;
// view matrisin icin kameranin yerini belirliyorsun
cameraPosition = new Vector3(0.0f, 10.0f, 5000.0f);

}

3.) Modeli Çizdirmek


İki boyutşu bir resim çizdirirken yapmamız gerekn 3 satır kod yazmaktı. Ancak 3 boyutlu modelde bu iş biraz daha karışık. Çünklü bu kez çizmemiz gerekende dokular ve her bir doku üzerindeki efektler var. Yani bizim ihtiyacımız olan iki adet içi içe döngü. Dıştaki dökğ modelin içerdiği dokuları çizdirecek içteki döngü ise çizilecek olan doku üzerine tanımlanan efektleri ekleyecek.


Öncelikle modelimizin aslında hareketini de sağlayacan “modelRotation” değişkenini tanımlıyoruz. Bu değişkenin değerinde oynamalar yaptığınızda modelimizin biraz daha sağa dönük durduğunu görebilrsiniz.


effect.EnableDefaultLighting();


Yukarıdaki satır dokular üzerindeki ışıklandırmayı sağlar.


Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);

ile modelimize kameranın bakacağı açıyı belirliyoruz.

mesh.Draw();

Bu satır ile bir dokuyu çizmiş oluyoruz.

float modelRotation = 0.0f;


protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);

// TODO: Add your drawing code here

//world matrisi icin gerekli olan tanimlamalar
Matrix[] transforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(transforms);

//bu asamada modeli cizmeye baslioruz
//model icin birden fazla doku olabilir bu yuzden bir dongu kullanioruz

foreach (ModelMesh mesh in myModel.Meshes)
{

//her doku icinde belirli efektler olabilir bunlar icinde bir dongu kullan
//bu dongu icinde gerekli olan yerlere kamerayi tut.
foreach (BasicEffect effect in mesh.Effects)
{
//dokular üzerindeki isiklandirmayi sagla
effect.EnableDefaultLighting();

effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationY(modelRotation) *
Matrix.CreateTranslation(modelPosition);
effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, Vector3.Up);

//projectiondaki bu 45 derecelik aciyi modeli ne kadar yakindan gorecegini belirler
//bu aci ne kadar büyürse model sana o kadar uzak olur
effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(projection_value),
aspectRatio, 1.0f, 10000.0f);
}//end of inner foreach loop

//simdi bu dokuyu cizdir

mesh.Draw();
}//end of outer foreach loop


base.Draw(gameTime);

}

Şimdi yapmanız gereken internetten bir modeli ve dokularını bulup bunları projenize ekleyip bu satırlarla birlikte bu modelin ekranda görünmesini sağlamak. Kolay gelsin :)

NOT: Modelinize göre "projection_value" değeriyle oynarsanız daha iyi sonuçlar elde edebilrsiniz. Bazı modeller 30.0f değerinde görülebiliyorken bazı modelleri algılayamayabiliyorusunuz. Bu durumda bu değeri küçültmeniz gerekmektedir, eğer model bu değerde çok büyük görünüyorsa bu kez bu değeri azaltmanızı öneririm.



1 yorum:

sulhadin dedi ki...

Çok teşşekkürler bende lise3 öğrencisiyim visualstudio.gen.tr de bu şekilde dersler veriyorum.Bize bir yardımınız bu şekilde oldu şu staj ve iş imkanlarımızada öncü olsanız:)
Başarılarınızın devamını dilerim