GLUT Dersleri - 2 (Pencere Boyut Kontrolü ve Basit Animasyon)
(589 kelime) (524 okuma) ![Yazdırılabilir Sayfa](images/print.gif)
1. Pencere Boyutu Değişimleri:
Geçen dersimizde oluşturduğumuz örnek pencerenin boyutu ile oynadıysanız,
içindeki görüntünün boyut değişimleri sonucu bozulduğunu farketmişsinizdir.
Genişlik/Yükseklik oranı 1 olan pencerelerde düzgün görünen görüntü bu oran
değişince bozulmaktadır. Bunun sebebi değişen pencere oranlarına uygun olarak OpenGL
sisteminin uyarılması gerekliliğidir. Yani her pencere boyutu değişiminde OpenGL
sistemi uyarılarak çeşitli yordamlar vasıtasıyla yeni oranlar doğrultusunda
persfektif ayarları tazelenmelidir. glutReshapeFunc() yordamı ile istediğimiz bir
fonksiyonun her pencere büyüklüğü değişiminde otomatik olarak çağırılmasını
sağlayabiliriz.
void glutReshapeFunc(void (*func)(int width, int height));
Parametreler:
- func :: pencere büyüklüğü değişiminde çağrılacak
olan ve yeni persfektif oranlarını ayarlamakla yükümlü yordamın adı..
Şimdi yapmamız gereken ana yordamımız içinde glutReshapeFunc ile persfektif ayarı
yapan fonksiyonu GLUT sistemine kaydettirmek. Belirttiğimiz fonksiyonun adı changeSize()
olsun. Aşağıda yeni main yordamı verilmiştir.
void main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("GLUT Dersleri - 2");
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutMainLoop();
}
Şimdide changeSize isimli yordamımızın gerçekleştirimini görelim.Dikkat ederseniz
bu yordamın 2 parametre alması gerekiyor.
void changeSize(int w, int h) {
if(h == 0) h = 1;
float ratio = (float) w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0, 0.0,0.0,-1.0, 0.0f,1.0f,0.0f);
}
İlk satırda daha sonra sıfıra bölme hatası ile karşılaşmamak için pencere
yüksekliği 0'a eşit ise bu sayı 1'e eşitleniyor. 2. satırda pencere için
genişlik/yükseklik oranı hesaplanıyor. Daha sonra projeksiyon matrisi aktif hale
getirilerek sıfırlanıyor ve glViewport yordamı ile görüntünün tüm pencere boyunca
oluşturulması sağlanıyor. gluPerspective yordamı ile persfektif ayarı yapılıyor,
FOV=45 derece ye çekiliyor, ve en son olarak gluLookAt yordamı ile kamera bakış
doğrultusu ve konumu ayarlanıyor.
Tüm bu bahsedilen glu ve gl ön ekli yordamlar GLUT'dan bağımsız ve direk olarak
OpenGL ile ilişkili olduklarından ayrıntılı olarak incelenmemişlerdir. Daha fazla
bilgi edinmek için özellikle OpenGL RedBook 'dan faydalanabilirsiniz.
2. Animasyon Temelleri:
Şu ana kadar elimizde bir GLUT penceresi ve hareketsiz beyaz bir üçgenimiz var.
İsterseniz bu durağan sahnemize biraz hareket kazandıralım.Bunun için işe
üçgenimizi döndürmek ile başlayabiliriz. Peki ama bu işlemi nasıl
gerçekleştireceğiz. Hemen aklımıza bir değişken tutmak, bu değişkeni devamlı
olarak arttırıp değişken vasıtasıyla rotasyon yaparak üçgeni çizmek geliyor.
Fakat bu noktada bir sorunumuz var. Değişkenimizi devamlı olarak nerede
arttıracağız. renderScene() yordamı sadece pencere yeniden çizileceği zaman,
changeSize() yordamı ise her pencere boyutu değişiminde çağırılıyor. Yani bu iki
yordam bizim işimizi görmüyor. Bu tür işlemleri gerçekleştirmek için GLUT sistemi
bize yalın bir yöntem sunmakta. Aynı renderScene ve changeSize yordamlarında
uyguladığımız gibi bir yordam yaratıp bunu GLUT sistemine glutIdleFunc() fonksiyonunu
çağırarak verdiğimiz taktirde, sistem fırsat buldukça sürekli olarak bu fonksiyonu
çağıracaktır. Bizde bu fonksiyon içinde parametremiz üzerinde değişiklikleri
yaparak daha sonra animasyon elde edebileceğiz.
void glutIdleFunc(void (*func)(void));
Parametreler:
- func :: devamlı olarak sistem tarafından çağırılacak
yordamın adı.
İsterseniz şimdilik bu fonksiyona parametre olarak renderScene yordamımızı
verelim, ve animasyon işlemi ile ilgili ayarlamalarımızı çizim işlemleri ile
birlikte bu fonksiyon içinden gerçekleştirelim. İstersek değişik bir yordam
kullanarak animasyon ve çizim işlemlerini farklı yerlerden de yürütebilirdik.
Aşağıda main yordamımızın yeni hali bulunmakta.
void main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("GLUT Dersleri - 2");
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutMainLoop();
}
Şimdi ise renderScene yordamının animasyon öğeleri içeren son halini veriyoruz:
void renderScene() {
// bu değişkeni dönüş açısını tutmakta kullanıyoruz
static float angle = 0.0f;
// Hareket olduğu için önceki örneğin aksine depth buffer 'da da
silem işlemine gidiliyor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// transformasyonların etkisini kaldırmak için matrisin ilk halini
saklıyoruz
glPushMatrix();
// döndürme transformasyonu yapılıyor
glRotatef(angle,0.0,1.0,0.0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.0,0.5,0.0);
glEnd();
// döndürme transformasyonunun etkisi kaldırılıyor. (Eski matris
yükleniyor)
glPopMatrix();
// Double buffering kullanıldığı için çizimin oluşturulduğu
arka buffer ekrana çizdiriliyor
glutSwapBuffers();
// angle her defasında arttırılarak animasyon sağlanıyor.
angle += 0.1f;
}
Açıklama satırlarını da takip ederek yukarıdaki kodu kolaylıkla anlayacağınızı
varsayıyorum. Artık ekranda dönme hareketi yapan bir üçgenimiz var. Gelecek derste
görüşmek üzere, hoşçakalın.
Deniz Aydınoğlu tarafından www.lighthouse3d.com
sitesindeki belgeden çevrilmiştir :: 2002 ::
|