|
3D Grafik Programlama - 1 |
|
Gönderiliyor lütfen bekleyin... |
|
|
Eminim herkes şu oyunlar nasıl yapılıyor yada şu film
efektleri nasıl yapılıyor diye sormuştur. Bu yazıdan sonra 3D grafiklerin ne olduğunu
kabaca öğrenmiş olacaksınız. Yazılarımızın diğer serilerinde ise 3D grafik
çizimleri ile ilgili
değişik uygulamalar yapacağız. 3D uygulamaları için Donanım olarak
yeterli bir makineye sahip olmamız gerekir. Eskiden bu büyük bir sorundu
ama artık standart ev makinelerinin
ekran kartları yeterince güçlü ve temel 3D uygulamalarını zorlanmadan
çalıştırabilmekteler. Yazılım
olarak ise her 3D uygulaması ya işletim sistemi tabanlı ( DirectX gibi ) ya da software
tabanlı kaynaklara ihtiyaç duymaktadır. Herhangi bir 3D oyununuz Directx kullanarak
da çalışabilirken bazen DirectX tek başına yeterli olmayabilir.
3D uygulamarı için OpenGL standardı gelmiştir. Burada
Open free, açık anlamında GL ise Graphics Library anlamındadır.OpenGL
kütüphaneleri
SGI tarafından C/C++ dili kullanılarak yapılmıştır. Ancak OpenGL düşük seviyeli fonksiyonları
içermektedir. SGI OpenGL kütüphanelerinin üzerine ayrıca Open Inventor adını verdiğimiz
kütüphaneleri geliştirmiştir. Open Inventor ile C++ Object Oriented gücü ile yazılımlarımızı
çok daha hızlı ve güzel geliştirebiliriz. Yazılarımızda Open Inventor toolkit' ini kullanacağız. Oyun
ya da ileri grafik uygulamaları ya Open Inventor ya da Open Inventor tarzında daha
gelişmiş grafik kütüphaneleri kullanmaktadır. Bu standart artık neredeyse heryerde
kabul edilmiştir. Başka dilde geliştirilen kütüphaneler bile OpenGL veya Inventor kütüphanelerini
temel almaktadır.
Size şaşırtıcı gelebilir ama 3D graphics işinde matematik
neredeyse geliştirdiğiniz projenin %50 sinden fazla zamanını alır. Bundan dolayı sağlam
matematik temeli olmayan insanların 3D graphics de başarılı olmaları pek mümkün değildir. İleri
yazılarımızda size simülasyonların temelini oluşturan matematiği ve bunların koda
nasıl aktarılacağını göstereceğim. Başlamadan önce indirmeniz gerekenler :
http://www.coin3d.org/download/ (linkinden
SoQt 1 , Coin 1 ,Simage-1 indirin )
ftp://ftp.trolltech.com/qt/non-commercial/QtWin230-NonCommercial.exe
Bunları kurduktan sonra makineniz OpenGL ile neredeyse
her türlü hayalinizi yapabileceğiniz duruma gelecektir. Ayrıca uygulamalarınızda yanınızdan
ayıramayacağınız help dosyasını da buradan indirebilirsiniz tıklayın.
ÇİZİM DEĞİL NESNE
Görüntüleme sınıfları : QT ve XT
QT ve XT Sınıfları görüntüleme için gerekli kütüphaneleri
ve fonksiyonları barındıran en önemli sınıflardandır. Inventorun burada bize sağladığı
en büyük yararlardan birisi de low level sınıflar ile herhangi bir şekilde bizi muhatap
kılmamasıdır. Herşey kullanıcıya kolaylık sağlayan arayüzler ile halledilmektedir. Şimdi
XT veya QT kütüphanelerinin fonksiyonlarını nasıl kullanabiliriz onları bir tanıtalım.Aşağıda
gördüğünüz kod SGI grafik uygulamalarında yer alan en temel örnektir! Ekran açmaktan başka
hiçbirşey yapmaz. Dilerseniz header' ları ve içeride kullandığımız fonksiyonları inceleyelim.
Inventor/SoQt.h headerimiz 3D uygulamaları için gerekebilecek
temel sınıfları ve fonksiyonları barındıran en önemli class' tır.Aklınıza gelebilecek
her türlü işlem için SoQt header' ı içindeki fonksiyonlara ve tanımlara başvurulacaktır. Detaylarında
kaybolmayın, 3D uygulamaları için C++ gurusu olmanız gerekmiyor!
Window ve Viewer :
// Herhangi bir yerde bulabileceginiz en basit SGI
uygulaması
// Ana kütüpaneler için SoQt headerini ekliyoruz
#include <Inventor/Qt/SoQt.h>
// Viewer için Qt nun Viewerini kullanıyoruz
// Plane viewer,full viewer,fly viewer gibi birçok değişik viewer daha vardır.
// Biz görüntüleri
#include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
main(int , char **argv)
{
// SoQt kütüphanelerini çağırıyoruz aşağıda ki 2 satır window açabilmek
için gerekli fonksiyonları harekete geçirmektedir
Widget myWindow = SoQt::init(argv[0]);
if (myWindow == NULL) exit(1);
// SoQt kütüphanelerinin
altında görüntüleme için gerekli fonksiyonu çağırıyoruz
// Aşağıda ki satır ile nesnelerimizi görebilecegimiz
myViewer nesnesi oluşturuluyor
SoQtExaminerViewer *myViewer = new SoQtExaminerViewer(myWindow);
// Aşağıda ki satırda penceremize ad veriyoruz
// myViewer nesnesinin setTitle özelliğini değiştirerek
myViewer->setTitle("Pencereme ad verelim");
// myViewer nesnesini show fonksiyonunu çalıştırıyoruz.
// Ancak bu fonksiyonun çağırılması ekranda görüntülüme
başladığı anlamında değildir
// SoQt kütüphaneleri aracılığı ile "window" oluşturulması
gerekmektedir
myViewer->show();
// Aşağıda ki SoQt (yukarıda ki show fonksiyonu ile karıştırmayın) show
fonksiyonunu kullanarak
// ExaminerViewerin gösterilebileceği bir window oluşturuyor
SoQt::show(myWindow);
// Görüntünün devamlı bir şekilde yenilenmesi için mainloop fonksiyonunu
da çağırdıktan sonra
// Penceremizi elde ederiz
SoQt::mainLoop();
}
|
Nesneleri oluşturuyoruz !!
Buraya kadar herşey kolaydı sadece bir window açtık
ve examinerviewer dediğimiz görüntüleme aracını oluşturduk. Şimdi dünyamızı oluşturmak
için neler yapmamız gerekiyor onlardan bahsedeceğim. Yukarı da bahsettiğim gibi grafik
programlama da çizim diye bir şey yoktur herşey nesnedir. (ne demek istediğimi ileriki
yazılarda daha iyi anlayacaksınız.)
3D dünyamızda herşeyi nesnelerle tanımlamaktayız. Nesnelerimizin
renk, pozisyon, malzeme,... gibi aklınıza gelebilecek çeşitli özellikleri vardır. İşleri daha
basitleştirmek için ve aynı dili konuşmak için ise OpenGL notasyonu geliştirilmiştir
bu sayede hem kod geliştirici hem de işin teorik kısmını geliştirenler birbirleri
ile daha iyi anlaşabilirler. İçi boş veya sadece düz çizgi olan bir daire üst nesneleri
tanımlarken birbirine dönük oklu daireler ise pozisyonları tanımlamaktadır.
Bundan sonraki yazılarımızda
bunlara daha da aşina olacaksınız. Bu bir standart olarak kabul edilmiş ve böyle uygulanmaktadır. Aşağıda
ki uygulamamızda su molekülünü modelliyoruz. Inventor su moleküllerine low-level bir
uygulama olarak değil (şu noktayı çiz renk matrisini şöyle doldur...) bir kimyacı gibi
bakmaktadır (elimde 2 küçük 1 tane büyük küre var renkleri şu, uzayda pozisyonları
...).Elbette işin detayında low-level olarak yapılmaktadır bütün işlemler.
Nesneleri örnek kodumuzu yazarken daha detaylı inceleyeceğiz.
Inventor notasyonuna uygun bir şekilde bir
su molekülü görmektesiniz. En üst kısımda bir su molekülü var. Daha aşağılara indiğimiz
zaman ise atomlar ve atomların pozisyon, şekil, renk
gibi aklınıza gelebilecek özellikleri tutan nesneler vardır. Peki en can alıcı
soruyu sorma vakti geldi su molekülü ve atomlar nasıl bir nesne Inventor
dilinde ? Nasıl oluşturulmaktadır ?
SoSeparator (Süper Nesne):
Inventor da herşey SoSeparator nesnesinin altındadır. Yukarıda
gördüğünüz örnekte molekül ve atomların hepsi birer SoSeparator nesnesidir. SoSeparator
nesnesi alt seviyede özellikleri olan nesneleri barındıran büyük bir nesnedir. Elimizde
100 lerce separator nesnesi olabilir. Örnek olarak yukarıda 3 atom, 1 molekül var yani
toplamda 4 tane separator nesnemiz var.Separator nesnesine nesne eklemek için addChild
adını verdiğimiz bir fonksiyonu kullanacağız.
Bu fonksiyonun kullanımı şöyledir :
void addChild (SoNode * child)
|
addChild dışında, removeChild, replaceChild gibi değişik
fonksiyonlar da vardır. Örneğimizde bu metodlar daha da pekişecektir.
SoTransform :
Haklı olarak moleküllerimizin pozisyonları da olacak.
Bunlar pozisyonlar SoTransform nesnelerinin sorumluluğundadır. Örneğinz trans1
isimli SoTransform tipinden bir nesnemiz olduğunu varsayalım. Eğer trans1 nesnesinin sadece
x doğrultusunda olmasını istersek :
trans1->translation.setValue(1.0,0.0,0.0) |
yazarak işlemimizi gerçekleştirebiliriz. Help dosyasından bakarak diğer fonksiyonlara
erişebilirsiniz.
SoCube, SoSphere, SoCone,... :
Inventor SoCube SoSphere gibi şekil özelliklerini barındıran
nesneler ile zorlanmadan küre, küp, koni,... çizmemizi sağlamaktadır. Ayrıca bu nesnelerin
fonksiyonları bunların yarıçaplarını, uzunluklarını,... değiştirmemize izin vermektedir.
SoMaterial :
SoMaterial nesnesi ile cismimizin rengini, transparan
görünüşünü, parlaklığını ayarlayabiliriz. Bunun dışında SoMaterial
nesnesinin kullanabileceği değişik fonksiyonlar daha vardır.
ONEMLI NOT !!! Kullandığınız her nesne için yukarıya
headerini eklemeyi unutmayın! Header path i help file da bulabilirsiniz.
Kod Yazma Zamanı !
// görüntüleme aracı için gerekli kütüphaneler
#include <Inventor/Qt/SoQt.h>
#include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
// kullandığımız nesneler için gerekli kütüphaneler
// kullandığımız her So ile başlayan nesne için gerekli
headerleri help file ile bulup ekleriz
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoSphere.h>
#include <Inventor/nodes/SoTransform.h>
// standart c kütüphaneleri
#include <stdlib.h>
#include <stdio.h>
void main(int argc, char **argv)
{
QWidget *myWindow = SoQt::init(argv[0]);
if (myWindow == NULL) exit(1);
// herşeyimizi su molekülü adını verdiğimiz SoSeparator nesnesinini altına
koyacağız
SoSeparator *waterMolecule = new SoSeparator;
// oxygen nesnesi oluşturuyoruz
SoSeparator *oxygen = new SoSeparator;
// SoMaterial ile Material nesnesi oluşturuyoruz aşağıda rengini kırmızı yapacağız
SoMaterial *kirmizirenk = new SoMaterial;
// Sırayla pozisyon ve şekil nesnelerini oluşturuyoruz
SoSphere *sphere1 = new SoSphere;
SoSeparator *hydrogen1 = new SoSeparator;
SoSeparator *hydrogen2 = new SoSeparator;
SoTransform *hydrogentransform1 = new SoTransform;
SoTransform *hydrogentransform2 = new SoTransform;
SoSphere *sphere2 = new SoSphere;
SoSphere *sphere3 = new SoSphere;
// kirmizirenk adını verdiğimiz Material nesnesinin diffuseColor özelliğini
kırmızı yapıyoruz
kirmizirenk->diffuseColor.setValue(1.0, 0.0, 0.0);
// pozisyon nesnelerini x-y-z düzleminde kabaca oturtuyoruz transform nesnesinin
translation fonksiyonunu kullanarak
hydrogentransform1->translation.setValue(0.0, -1.2, 0.0);
hydrogentransform2->translation.setValue(1.1852, 1.3877, 0.0);
// oxygen separatorune material nesnesini ekliyoruz
oxygen->addChild(kirmizirenk);
// oxygen separatorune sphere nesnesini ekliyoruz
oxygen->addChild(sphere1);
// hydrogen separatorune pozisyon nesnesini ekliyoruz
hydrogen1->addChild(hydrogentransform1);
// nesneleri eklemeye devam ediyoruz
hydrogen1->addChild(sphere2);
hydrogen2->addChild(hydrogentransform2);
hydrogen2->addChild(sphere3);
// su molekülü adını verdiğimiz separatore bütün separatorleri ekliyoruz
waterMolecule->addChild(oxygen);
waterMolecule->addChild(hydrogen1);
waterMolecule->addChild(hydrogen2);
// bundan sonra görüntüleme işlemi kalıyor bunun için myViewer e waterMolecule
// ekliyoruz
// aşağıda gördüğünüz kodlar hemen hemen her zaman standart olacaktır
SoQtExaminerViewer *myViewer = new SoQtExaminerViewer(myWindow);
myViewer->setSceneGraph(waterMolecule);
myViewer->setTitle("Examiner Viewer");
myViewer->show();
SoQt::show(myWindow);
SoQt::mainLoop();
}
|
İşimiz bittikten sonra görüntümüz böyle olacaktır. Yukarıda
bilmenin ve dikkat etmeniz gereken tek şey, nesnelerin fonksiyonlarına nasıl ulaşabiliriz
ve ulaştıktan sonra o nesnenin özelliklerini nasıl değiştirebiliriz. Ayrıca
nesneleri eklerken yazımın başında verdiğim yönteme göre sıraya dikkat edilmesi gerekmektedir.
Yani
Separator nesnelerinin altına özellikleri eklemeliyiz.
Sonuç ve Sonraki Yazılarımızda
SGI Inventor ile 3D uygulamalarını çok kolay bir şekilde
halledebiliriz. Sonraki yazılarımızda action, event, multiple fields, numerical methods, FEM
modelling, Stochastic Simulation, collusion detection, particle systems gibi ileri tekniklerle
ilgileneceğiz. Bu konularla ilgili internette bol miktarda referans var aşağıda verdiğim
gibi buralardan güzel bir başlangıç yapabilirsiniz.Örnek kodları indirmek için tıklayın
Özkan Eren
[email protected]
Makale:
3D Grafik Programlama - 1 C++ ve C++.NET dili Özkan Eren
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|