GLUT Dersleri - 2 (Pencere Boyut Kontrolü ve Basit Animasyon)

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 ::




Bu yazının bulunduğu site: OyunYapimi.org
http://www.oyunyapimi.org

Bu yazı için adres:
http://www.oyunyapimi.org/modules.php?name=Sections&op=viewarticle&artid=8