uygulama kodumuz aşağıda verilmiştir.
/// 3D ALANDA HEDEF BULMA
// Daha önce 2d alan üzerindeki yapmıs olduğum yön bulma algoritmasını
// bu 3d alana uyarladık. Daha da sadelestirilebilir.
// Farklı çözümlemeler muhakkak vardır.
// kullanmadığımız değişkenler kalmış olabilir
// 3d bir pencerede uzayda kaybolmama ve doğru konumlanma icin Nesneler her
// zaman bu 2 matrix arasına alınır.
//glPushMatrix(); nesne glPopMatrix(); nesnelerin zemine (istediğimiz yere) doğru
//konumlanmasını sağlayan matrixlerdir
// Nesnelerin istediğimiz yere doğru konumlanması icin nesne bu ikisi arasında olmalıdır.
#include <iomanip>
#include<stdlib.h>
#include<stdio.h>
#include <gl/glaux.h>
#include <time.h>
#include <math.h>
#include <iostream>
#include <gl/freeglut.h>
#include <gl/gl.h>
#include <iostream>
#define ESC 27
bool karakterAl= false;
float GAZ= 0.0;
float lazer=0.0;
short dur,yon;
float iox,ioz,arax,araz;
int ay=0,ay1=0;
GLdouble ox=0.0,oy=0.0,oz=0.0;
float tcap,icap,xcap,fcap;
float scb,ascb=1;;/// solid cube ve anahtar
float d=0;
int anapen;
int altpen;
float der=0;
float rad=0,rado1;
float uz1,uz2;
static char bas[10];
float tx;
float my=30;
float tz;
float mx;
float mz=0;
float ty=0.1;
float x = 0.0, y = 9.0,z=-10; //
float deltaMove = 0.0; //
// Camera direction kamera yönü
float lx = 0.0, ly=-15,lz=0.1; // camera points initially along y-axis
float angle = 0.0; // angle of rotation for the camera direction
float deltaAngle = 0.0; // additional angle change when dragging
// Mouse drag control
int isDragging = 0; // true when dragging sürüklemek
int xDragStart = 0; // records the x-coordinate when dragging starts
///-----------------------------------------------------------------------
using namespace std;
///-------------------------------------------------------------------------------
void harfYaz(char *s)
{
unsigned int i;
for (i = 0; i < strlen (s); i++)
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, s[i]);
}
void harfYazak(char *s)
{
unsigned int i;
for (i = 0; i < strlen (s); i++)
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_12, s[i]);
}
void kamera(int w, int h)
{
float ratio = ((float) w) / ((float) h); // window aspect ratio
glMatrixMode(GL_PROJECTION); // projection matrix is active
glLoadIdentity(); // reset the projection
gluPerspective(60.0, ratio, 0.1, 150.0); // perspective transformation
glMatrixMode(GL_MODELVIEW); // return to modelview mode
glViewport(0, 0, w, h); // set viewport (drawing area) to entire window
}
void zeminTop()// zeminde belirli aralıklarla çoğaltacağımız topların prototipi
{
glColor3f(1.0, 1.0, 1.0);/// bazen farkında olmadan renkler karışabilir. Bu şekilde
/// beyaz bir filtre yaparak istediğimiz rengi elde ederiz.
//glPushMatrix(); bir sonraki foksiyonda çoğaltma esnasında matrixleri kullandığımz için burada
// kullanmasakda olur.
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(0.16, 6, 6);
//glPopMatrix();
}
void alan()
{ int i, j;
// zeminimiz
glColor3f(0.0, 0.7, 0.0);
glTranslatef(0,0,0);
glBegin(GL_QUADS);
glVertex4f(-60.0,0, -60.0, 1);
glVertex4f(-60.0,0, 60.0, 1);
glVertex4f(60.0,0, 60.0, 1);
glVertex4f( 60.0,0, -60.0, 1);
glEnd();
// 11*11 121 adet zemine 2 birim arayla top yerlestiriyoruz.
for(i = -5; i < 6; i++)
for(j = -5; j < 6; j++) {
glPushMatrix();// nesnelerin zemine (istediğimiz yere) doğru konumlanmasını sağlayan matrix
glTranslatef(i*2.0,0 , j*2.0);
zeminTop();
glPopMatrix();// nesnelerin istediğimiz yere doğru konumlanmasını sağlayan 2. matrix
// 3d uzayda kaybolmama ve doğru konumlama icin Nesneler her zaman bu 2 matrix arasına alınır.
}
}
//**********************************************************************************
void update(void)// yon tusları ile kamera hareket hızı
{
if (deltaMove) { // update camera position
mx += deltaMove * lx * 0.1;
mz += deltaMove * lz * 0.1;
}
glutPostRedisplay(); // redisplay everything
}
void koordinat()
{
glPushMatrix();
glTranslatef(0,0.1,0);
glColor3f(0.0,0.0,1.0);
glLineWidth(1);
glBegin(GL_LINES);
glVertex3f(0.0,0,-20.0);
glVertex3f(0.0,0,20.0);
glColor3f(1.0,0.0,0.0);
glVertex3f(-20.0,0,0.0);
glVertex3f(20.0,0,0.0);
glEnd(); glPopMatrix();
}
void koorcapsd()
{
glPushMatrix();
glTranslatef(0,0.2,0);
glColor3f(0.0,0.0,1.0);
glLineWidth(3);
glBegin(GL_LINES);
glVertex3f(ox,0,oz);
glVertex3f(0,0,0);
glEnd(); glPopMatrix();
}//********************************************************
void karakter1()//******************************
{
{
glColor4f(0.9,0.2,0.0,1.0);
glTranslatef (tx,-0.23 ,tz );
glPushMatrix();
glScalef(3,1,1);
glRotatef(d,0,1,0); //önünü hedef yönüne döndürmek
glutSolidSphere(0.50, 20, 20);
glPopMatrix(); }
if(yon==1||yon==3)d=-rad*180/3.14;/// kendi içinde zıt
if(yon==2||yon==4)d=-1*rad*180/3.14;///bunlarda kendi içinde zıt
}
void karakter2()
{
glColor3f(1.0,0.0,0.0);
glTranslatef (tx,0.02 ,tz );
glPushMatrix();
glRotatef(d,0,1,0);//önünü hedef yönüne döndürmek
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,0,0.5);///glColor3f(0.0,1.0,0.0);
glVertex3f(-0.5,0,-0.5); ///glColor3f(1.0,0.0,0.0);
glVertex3f(1.0,0,0.0);
glEnd();
if(yon==1||yon==3)d=-rad*180/3.14;/// kendi içinde zıt
if(yon==2||yon==4)d=-1*rad*180/3.14;///bunlarda kendi içinde zıt
glPopMatrix();
}///-------------------------------------
void adem()// konum isaretleme tel kafesimiz
{
glColor3f(0.0, 0.0, 1.0);// mavi renk
if(ascb==1){
if(tx==ox)scb=0;else scb=1.0;
{glPushMatrix();
glTranslatef (iox,0 , ioz );
glutWireCube(scb);
glPopMatrix();}
}
}//------------------------------
void klavye (unsigned char key, int x, int y)// klavyeden veri alma
{
if(key==49){mz=0;my=30;ly=-15; }// kamera bakış açısı üst
if(key=='z'||key=='Z'){GAZ=0;}// durdur
if(key=='x'||key=='X'){GAZ=0.1;}// hızı değiştir
if(key=='a'||key=='A'){if(karakterAl==1)karakterAl=0;else karakterAl=1;}// karakter değistir
if(key==32){tx=0;tz=0;mx=0;mz=0; ox=0;oz=0;ay=0;ay1=0;icap=0;fcap=0;rad=0;}// konum sıfırlama
if(key==27){exit(0);}// kapat çık
if(key==48){my=10;mz=-25;tx=0; ly=-0.2;}// kamera bakış açısı perspektif
}///-------------------------------------
void yonler()
{ // Daha önce 2d alan üzerindeki yapmıs olduğum yön bulma algoritmasını
// bu 3d alana uyarladık. Daha da sadelestirilebilir.
// Farklı çözümlemeler muhakkak vardır.
switch(yon){
case 1:
if(tx>=ox+iox&&tz>=oz+ioz){GAZ=0;ox=tx;oz=tz;}
if(ay==1 )
{ lazer=GAZ;if(ox!=0 )ay1=1;
if(ay1==1){
tx+=cos( rad )*GAZ;
tz+=sin( rad )*GAZ;
}
}else {GAZ=0;tx=tx;tz=tz;}
break;
case 2:
if(tx>=ox+iox&&tz<=oz+ioz){GAZ=0;ox=tx;oz=tz;}
if(ay==1 )
{ lazer=GAZ;if(ox!=0 )ay1=1;
if(ay1==1){
tx+=cos( rad )*GAZ;
tz+=sin( rad )*GAZ;
}
}else {GAZ=0;tx=tx;tz=tz;}
break;
case 3:
if(tx<=ox+iox&&tz<=oz+ioz){GAZ=0;ox=tx;oz=tz;}
if(ay==1 )
{ lazer=GAZ;if(ox!=0 )ay1=1;
if(ay1==1){
tx+=cos( rad )*GAZ;
tz+=sin( rad )*GAZ;
}
} else {GAZ=0;tx=tx;tz=tz;}
break;
case 4:
if(tx<=ox+iox&&tz>=oz+ioz){GAZ=0;ox=tx;oz=tz;}
if(ay==1 )
{ lazer=GAZ;if(ox!=0 )ay1=1;
if(ay1==1){
tx+=cos( rad )*GAZ;
tz+=sin( rad )*GAZ;
}
} else {GAZ=0;tx=tx;tz=tz;}
break;
glutPostRedisplay();
}}//----------------------------------------------------------------------------------------------------
void renderScene()// 3d sahne dünyamız
{
xcap=(ox*ox)+(oz*oz);// karakterimizin değişen
xcap=sqrt(xcap) ;// hedefleri doğru bulması icin (uzaklık, çap alma işlemi)
// Clear color and depth buffers
glClearColor(0.0, 0.7, 1.0, 1.0); // sky color is light blue
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();// uzay matrixini almak
gluLookAt(mx, my, mz,
mx + lx,my + ly,mz + lz,
0.0f,1.0f,0.0f);/// kamera yönetimi
yonler();
update();
alan();
koordinat();
glPushMatrix();
glDepthMask(GL_FALSE);
glTranslated(ox,oy,oz);// tel kafesin konumunu alma
adem();/// telkafes (hedef isaretleme)
glutSolidSphere(0.0,15,15);
glDepthMask(GL_TRUE);
glPopMatrix();
if(karakterAl==true)karakter1();// top hedefe giden
if(karakterAl==false)karakter2();// ücgen hedefe giden
glutSwapBuffers();// görüntü alma
glutPostRedisplay();// run time çalışma
}
void altkare(){//alt pencereyi çizgilerle ayırma
glColor3f(0.0,0.5,1.0);
glBegin(GL_LINES);
glVertex2f(0.0,-1.0);
glVertex2f(0.0,1.0);
glVertex2f(1.0,0.0);
glVertex2f(-1.0,0.0);
glVertex2f(-0.8,1.0);
glVertex2f(-0.8,-1.0);
glVertex2f(0.8,1.0);
glVertex2f(0.8,-1.0);
glEnd();;
}
void altRender()// alt pencerenin dünyası
{
glClearColor(0.9, 0.8, 0.2, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTexCoord4f(1, 0,0,1);
glColor3f(0.7, 0.7, 0.7);
glRectd(-0.25,-1.0,0.45,1);
altkare();// alt pencereyi bölümlere ayırma
glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"a: karakter al " );
glRasterPos2f (-0.25, -0.8);
harfYazak (bas);
sprintf (bas,"yon tuslari-sag maus");
glRasterPos2f (-0.25, 0.1);
harfYazak (bas);
sprintf (bas,"ox oz : %1.1f : %1.1f ",ox,oz );
glRasterPos2f (0.05, 0.1);
harfYaz (bas);
sprintf (bas," tx tz : %1.1f : %1.1f ",tx,tz );
glRasterPos2f (0.05, -0.9);
harfYaz (bas);
if(yon==1) {glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"1 Dogu");
glRasterPos2f (-0.99, 0.1);
harfYaz (bas);}
if(yon==2) {glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"2 kuzey");
glRasterPos2f (-0.99, -0.8);
harfYaz (bas);}
if(yon==4) {glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"4 Guney");
glRasterPos2f (0.80, 0.1);
harfYaz (bas);}
if(yon==3) {glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"3 Bati");
glRasterPos2f (0.66, -0.9);
harfYaz (bas);}
{glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"x: Gaz=0.1");
glRasterPos2f (0.46, -0.8);
harfYazak (bas);}
glColor3f(0.0, 0.0, 0.0);
sprintf (bas," gaz %1.2f ",GAZ );
glRasterPos2f (0.8, -0.8);
harfYaz (bas);
/// ************************
glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"z: Gaz=0.0");
glRasterPos2f (0.45, 0.18);
harfYazak (bas);
glColor3f(0.0, 0.0, 0.0);
sprintf (bas,"drc:%1.0f ",d);
glRasterPos2f (-0.5, -0.8);
harfYaz (bas);
sprintf (bas," rad:%1.1f ",rad);///= 0,0174
glRasterPos2f (-0.5, 0.1);
harfYaz (bas);
sprintf (bas,"0 ve 1 kamera acisi ");
glRasterPos2f (-0.79, 0.1);
harfYazak (bas);
sprintf (bas," xcap: %1.0f ",xcap);
glRasterPos2f (-0.78, -0.8);
harfYaz (bas);
/// **************************
glutSwapBuffers();/// sürekli görüntü alma
glutPostRedisplay();///sürekli döngü run time anlık veri alma
}
void pressSpecialKey(int key, int xx, int yy)
{
switch (key) {
case GLUT_KEY_UP : deltaMove = 0.30; break;// kamera tuş yönetimi
case GLUT_KEY_DOWN : deltaMove = -0.30; break;// kamera tuş yönetimi
}
}
void releaseSpecialKey(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP : deltaMove = 0.0; break;// tus yukarda kamerayı durdur
case GLUT_KEY_DOWN : deltaMove = 0.0; break;// tus yukarda kamerayı durdur
}
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
void mouseMove(int x, int y) // sürekli maus konumunu almak (basarak yada basmadan sürüklerken)
// sürükleme esnasındaki sürekliliği bu anlık
//konum yakalama fonksiyunuyla yapıyoruz. glutMotionFunc(mouseMove);
{ ascb=0;
if (isDragging) { // only when dragging
// update the change in angle
deltaAngle = (x - xDragStart) * 0.005;
// camera's direction is set to angle + deltaAngle
lx = -sin(angle + deltaAngle);
lz = cos(angle + deltaAngle);
}
///*************************************************************
GLint viewport[4];// burdan
GLdouble modelview[16],projection[16];
GLfloat wx=x,wy,wz;
glGetIntegerv(GL_VIEWPORT,viewport);
y=viewport[3]-y;
wy=y;
glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
glGetDoublev(GL_PROJECTION_MATRIX,projection);
glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&wz);
gluUnProject(wx,wy,wz,modelview,projection,viewport,&ox,&oy,&oz);// bu arada ki kod bloku 3d uzayda mausun tıkladığı xyz konumunu bize verir
// bunu internette ki bir uygulamadan aldım. O uygulamayıda blogda vereceğim inşallah.
// burada fonksiyon sonuna kadar olan bölümü bir alttaki
//tıklanan maus fonksiyonunda da kullanacağız.
if(xcap!=tcap) {arax=tx;araz=tz;iox=arax;ioz=araz;
rad=atan2(araz,arax); }// hedefe varmadan hedef değiştiğinde yeni hedef konumunu almak
uz1=ox; uz2=oz; ///x z kordinatlarinin atanmasi
rad=atan2(uz2,uz1);///2 nokta arasindaki aciyi alma
///------------------------------------
if(ox>0&&oz>0) {yon=1;ay=1;} /// dogu
if(ox>0&&oz<0) {yon=2;ay=1; } /// kuzey
if(ox<0&&oz<0) {yon=3; ay=1;} /// bati
if(ox<0&&oz>0) {yon=4; ay=1;} /// guney
}//<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
void murat(int button, int state, int x, int y) // ** tıklanan maus **
// sağ kulak ile kamera bakış açısı sol kulak konum alma)
{
if (button == GLUT_RIGHT_BUTTON) { // sağ maus basılı iken ekran yönetimi
ascb=0;ay=0;
if (state == GLUT_DOWN) { // left mouse button pressed
isDragging = 1; // start dragging
xDragStart = x; // save x where button first pressed
}
else { /* (state = GLUT_UP) */
angle += deltaAngle; // update camera turning angle
isDragging = 0; // no longer dragging
}
}
/// ----------------------------------------------------------
switch(button) {
case GLUT_LEFT_BUTTON : // sol buton kullan
{
ascb=1;
if(state == GLUT_DOWN) { iox=ox;ioz=oz;///sol buton basıldığında koordinat ataması ***
GAZ=0.03;// ilk hız atama
GLint viewport[4];// buradan (3d uzayda xyz konumunu verir)
GLdouble modelview[16],projection[16];
GLfloat wx=x,wy,wz;
glGetIntegerv(GL_VIEWPORT,viewport);
y=viewport[3]-y;
wy=y;
glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
glGetDoublev(GL_PROJECTION_MATRIX,projection);
glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&wz);
gluUnProject(wx,wy,wz,modelview,projection,viewport,&ox,&oy,&oz);// buraya 3d
//uzayda xyz konumunu verir
if(xcap!=tcap) {arax=tx;araz=tz;iox=arax;ioz=araz;
rad=atan2(araz,arax);// hedefe varmadan hedef değiştiğinde
//yeni hedef konumunu almak
}
uz1=ox; uz2=oz; // x z kordinatlarinin atanmasi (y sürekli 0 karakterlerimiz için)
rad=atan2(uz2,uz1);// 2 nokta (x,z) arasindaki aciyi alma
///---------yön bulma------------------
if(ox>0&&oz>0) {yon=1;ay=1;} /// dogu
if(ox>0&&oz<0) {yon=2;ay=1; } /// kuzey
if(ox<0&&oz<0) {yon=3; ay=1;} /// bati
if(ox<0&&oz>0) {yon=4; ay=1;} /// guney
break;
}
}
}
}//-------------------------------------------------------
//----------------------------------------------------------------------
// Main program - standard GLUT initializations and callbacks
//----------------------------------------------------------------------
int main(int argc, char **argv)
{
// general initializations
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(5, 5);
glutInitWindowSize(800,600);
anapen=glutCreateWindow("OpenGL/Mekke Program");
// register callbacks
glutReshapeFunc(kamera); // window reshape callback
glutDisplayFunc(renderScene); // (re)display callback
glutIgnoreKeyRepeat(1); // ignore key repeat when holding key down
glutMouseFunc(murat); // process mouse button push/release
glutMotionFunc(mouseMove); // process mouse dragging motion
glutKeyboardFunc(klavye);
glutSpecialFunc(pressSpecialKey); // process special key pressed
glutSpecialUpFunc(releaseSpecialKey); // process special key release
glEnable(GL_DEPTH_TEST);// subwin den once olmalı
altpen=glutCreateSubWindow(anapen,5,565,790,34);//pen,x-y,weight-high
glutDisplayFunc(altRender);
glutMainLoop();
return 0; // this is just to keep the compiler happy
}