GLUT Dersleri - 4 (Klavye Kullanarak Kamera Hareketi)
(781 kelime) (461 okuma) ![Yazdırılabilir Sayfa](images/print.gif)
Klavye Kullanarak Kamera Hareketi:
Bu dersimizde geçen ders öğrendiğimiz klavye yordamlarını kullanarak bir örnek
üzerinde deneme yapacağız. Örneğimizde sahnemize kardanadamlar çizdirip daha sonra
kamera hareketini klavye tuşlarına göre sağlayarak yarattığımız bu sahne içinde
gezineceğiz. Sağ ve Sol ok tuşları ile kameramızı y ekseni etrafında çevireceğiz,
yani sağa ve sola bakma hareketi uygulayacağız. İleri ve Geri ok tuşları sahne
üzerinde ileri ve geri hareket etmemizi sağlayacaklar. Bu küçük uygulamayı
oluşturma aşamaları için gerekli olan kodları adım adım açıklama satırları ile
birlikte vereceğiz. Aşağıdaki kod parçalarını birleştirdiğiniz zaman işler
durumda olan örnek uygulamayı elde edebilirsiniz. İlk önce gerekli olan bazı global
parametre tanımlarını yapalım:
#include <math.h>
#include <gl\glut.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <stdlib.h>
static float angle=0.0,ratio;
static float x=0.0f,y=1.75f,z=5.0f;
static float lx=0.0f,ly=0.0f,lz=-1.0f;
static GLint snowman_display_list;
Yukarıdaki tanımların ne işe yarayacakları kod aşamalarını adım adım
incelediğimiz zaman açıklığa kavuşacaklar. Şimdilik kısaca işlevlerini verelim.
- angle :: kameranın y ekseni etrafındaki dönüş açısı
- x,y,z :: kamera pozisyonu
- lx,ly,lz :: Görüş doğrultumuzu belirten vektör.
- ratio :: pencere yükseklik / genişlik oranı
- snowman_display_list :: tek bir kardam için display list indisi
Şimdi ise pencere büyüklüğü değiştirilmesi sırsında çağırılacak olan
yordamımızı inceleyelim. Bu yordam geçen derslerimizde oluşturduğumuz yordama
benziyor. Tek farkı ise içinde global parametrelere göre kamera konumlandırması yapan
bir yordamın bulunması. "gluLookAt" yordamı ile OpenGL sahnemiz içerisinde
kameramızı konumlandırmayı kolay bir biçimde gerçekleştiriyoruz. Bu yordamın ilk
üç parametresi sırası ile kameranın konumunu x, y, z olarak alıyor, sonraki üç
parametre ise kameranın baktığı noktanın koordinatlarını x, y, ve z olarak istiyor.
Son üç parametre ise kamera 'nın üst kısmının hangi doğrultuya baktığını
belirten vektörün x, y ve z değerlerini istiyor. Bu son vektör genellikle (0,1,0)
şeklinde olmaktadır. Kameramızı yatırmak ister isek bu değerler ile oynayabiliriz.
Fakat bu uygulamamızda bu özelliği kullanmıyoruz.
void changeSize(int w, int h) {
// Sıfıra bölme hatası oluşmaması için standart bir kontrol
if(h == 0)
h = 1;
ratio = 1.0f * w / h;
// pencere içinde görüntü oluşturma sistemini modifiye etmeden
önce resetliyelim.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// viewport u tüm pencereyi içine alacak şekilde ayarlayalım.
glViewport(0, 0, w, h);
// bakış açısı ile ilgili ayarlamaları yapalım
gluPerspective(45,ratio,1,1000);
// koordinat sistemin modifiye etmeden önce resetleyelim.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Kameramızı konumlandırıyoruz. Bakacağımız noktayı belirten
konumu hesaplarken:
// (kamera pozisyonu + bakış doğrultusu) formülüne uygun olarak
hesaplama yaptığımıza dikkat edin.
gluLookAt(x, y, z, x + lx,y + ly,z + lz,0,1,0);
}
Şimdi ise kardan adamı çizen display list 'i oluşturan yordamlar ve tüm sahneyi
çizen yordamı veriyoruz. Bu kısımlar kamera kontrolünden bağımsızdırlar.
Displaylist 'ler hakkında yeterli bilgiye sahip değil iseniz bu kısmı
anlayamayabilirsiniz. Sitemizde yer alan "DisplayList Kulanımı" isimli
dökümanı inceleyerek diplaylist 'ler hakkında bilgi sahibi olabilirsiniz.
void drawSnowMan() {
glColor3f(1.0f, 1.0f, 1.0f);
// vücudu çiz
glTranslatef(0.0f ,0.75f, 0.0f);
glutSolidSphere(0.75f,20,20);
// kafayı çiz
glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f,20,20);
// gözleri çiz
glPushMatrix();
glColor3f(0.0f,0.0f,0.0f);
glTranslatef(0.05f, 0.10f, 0.18f);
glutSolidSphere(0.05f,10,10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f,10,10);
glPopMatrix();
// burnu çiz
glColor3f(1.0f, 0.5f , 0.5f);
glRotatef(0.0f,1.0f, 0.0f, 0.0f);
glutSolidCone(0.08f,0.5f,10,2);
}
GLuint createDL() {
GLuint snowManDL;
// display list için yeni bir tanımlayıcı numara (id) yarat
snowManDL = glGenLists(1);
// listeyi başlat
glNewList(snowManDL,GL_COMPILE);
// kardanadamı çizme işini gerçekleştiren komutların bulunduğu
yordamı çağır.
drawSnowMan();
// displaylist 'i bitir (artık bu displaylist her çağrıldığında
hızlı bir biçimde kardanadam çizilecektir.)
glEndList();
return(snowManDL);
}
void initScene() {
glEnable(GL_DEPTH_TEST);
// displaylist 'i oluştur.
snowman_display_list = createDL();
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// tabanı çiz
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, -100.0f);
glEnd();
// 36 adet kardam adamı bir matriz görünümünde çiz
for(int i = -3; i < 3; i++)
for(int j=-3; j < 3; j++) {
glPushMatrix();
glTranslatef(i*10.0,0,j
* 10.0);
glCallList(snowman_display_list);;
glPopMatrix();
}
glutSwapBuffers();
}
Şimdide özel tuşlara basılmaları kontrol etmekle yükümlü olan yordamı veriyoruz.
Sağ ve Sol ok tuşları ile y ekseni ile yapılan açıyı değiştiriyor, daha sonra
çağırılan yordamın içerisinden değişen açı değerine göre bakış doğrultusu
vektörünü değiştirip kamera doğrultumuzu günlüyoruz. İleri ve Geri ok tuşlarına
basıldığında ise çağrılan yordam içerisinden bakış doğrultumuz boyunca
ilerlemeyi, yani pozisyonumuzu günlemeyi gerçekleştiriyoruz. Bu bahsedilen yordamlar
içerisinde çeşitli fonksiyonlar çağırılarak basit trigonometrik işlemler
yapılmakta, bu işlemler ile vektörler üzerinde uygun hesaplamalr
gerçekleştirilmekte. Bu hesaplamaları anlamakta zorluk çekiyorsanız lineer cebir ve
vektör aritmetiği ile ilgili temel kaynaklardan faydalanabilirsiniz.
void inputKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT :
angle -= 0.01f;
orientMe(angle);break;
case GLUT_KEY_RIGHT :
angle +=0.01f;
orientMe(angle);break;
case GLUT_KEY_UP :
moveMeFlat(1);break;
case GLUT_KEY_DOWN :
moveMeFlat(-1);break;
}
}
void orientMe(float ang) {
lx = sin(ang);
lz = -cos(ang);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void moveMeFlat(int direction) {
x = x + direction*(lx)*0.1;
z = z + direction*(lz)*0.1;
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
Son olarak ise geçen derslerimizden aşina olduğunuz, artık standart hale gelen
main() yordamızı veriyoruz.
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,360);
glutCreateWindow("KardanAdamlar :: www.oyunyapimi.org");
initScene();
glutSpecialFunc(inputKey);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutMainLoop();
return(0);
}
Deniz Aydınoğlu tarafından www.lighthouse3d.com
sitesindeki belgeden çevrilmiştir :: 2002 ::
|