首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

OpenGL织梦之旅【第四章】第1节.设立视点函数gluLookAt

2013-03-04 
OpenGL织梦之旅【第四章】第1节.设置视点函数gluLookAt在做所有的事情之前,我们必须要了解怎么在3D的世界中

OpenGL织梦之旅【第四章】第1节.设置视点函数gluLookAt

       在做所有的事情之前,我们必须要了解怎么在3D的世界中绘图。这也是为了帮助我们调整视点,不然调来调去都是黑框...

       3D世界中的坐标系也是笛卡尔坐标系,y轴就像是现实世界中的“高低”,而x和z像是地面的坐标。

OpenGL织梦之旅【第四章】第1节.设立视点函数gluLookAt

       我们写一个DrawBox函数,这函数负责绘制一个正方体。

void DrawBox(){glBegin(GL_POLYGON);glColor3f(1.0,0.0,0.0);    glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 0.0f);glEnd();glBegin(GL_POLYGON);    glColor3f(0.0,1.0,0.0);glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f);glVertex3f(1.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(0.0,0.0,1.0);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 1.0f);glVertex3f(0.0f, 0.0f, 1.0f);glEnd();glBegin(GL_POLYGON);glColor3f(1.0,0.0,1.0);glVertex3f(1.0f, 0.0f, 0.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(1.0,1.0,0.0);glVertex3f(0.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(0.0,1.0,1.0);glVertex3f(0.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(0.0f, 1.0f, 1.0f);glEnd();}

        为了让整体的效果更具有3D的效果,我准备在地面上在画上一些蓝色的格子。

像这样:

void DrawGrid(){glLineWidth(2);glColor3f(0.0,0.0,1.0);for (int i=-100; i<=100; i+=10){glBegin(GL_LINES);glVertex3f(i,0.0f,-100.0f);glVertex3f(i,0.0f,100.0f);glEnd();glBegin(GL_LINES);glVertex3f(-100.0f,0.0f,i);glVertex3f(100.0f,0.0f,i);glEnd();}}



 

        在Draw函数中,调用这个函数。这时是没有画面的,因为我们还没有调整视角和视景体。就好比,你放了个东西在0,0,0这个地方,但是视线却没有移到这里来一样,看不到任何东西。

        gluLookAt有九个参数,前三个是视点的坐标(眼睛),中间三个是事物的坐标,最后三个是向上向量,一般把最后三个定为(0,1,0)就行了,因为我们现在暂时不会用到。

       在介绍了gluLookAt后,我们可以发现这个函数有很多个参数,管理起来比较麻烦,所以我直接把这9个参数设为全局变量,写了三个函数来方便使用。

double posX,posY,posZ,viewX,viewY,viewZ,upX,upY,upZ;void setAll(double px,double py,double pz,double vx,double vy,double vz,double ux,double uy,double uz){posX=px;posY=py;posZ=pz;viewX=vx;viewY=vy;viewZ=vz;upX=ux;upY=uy;upZ=uz;}void setLookAt(){gluLookAt(posX,posY,posZ,  viewX,viewY,viewZ,  upX,upY,upZ);}void setPos(double x,double y,double z){posX=x;posY=y;posZ=z;}



 

注:最好是把这个封装到一个类里面,这样管理起来就更方便了!

       在调用gluLookAt之前一定要记得调用glLoadIdentity来重置当前指定的矩阵为单位矩阵.不然就会出问题。

所有的工作的弄完了,下面就剩下一些细节。

       在init函数中启动深度缓冲,在Reshape函数中指定视景体,

void Reshape(int w,int h){WinWidth=w;WinHeight=h;glMatrixMode(GL_PROJECTION);glLoadIdentity();   glViewport(0,0,w,h);gluPerspective(45,1.0*w/h,1,1000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}


 

       这个函数比较复杂,想了解详细就这里。

       再次编译应该就能够看到效果。

OpenGL织梦之旅【第四章】第1节.设立视点函数gluLookAt (有点小。。)

       这个时候当然是要调整一下,视角来看看这个到底是不是我们所画的箱子。

       所以我们注册一个键盘事件函数。

       我把摄像机的y轴坐标固定,然后使其在一个圆形的轨道上移动。摁下‘a’键就向轨道左边移动,摁下‘d’键就向右边移动。这样就像是在一个圆形的小剧场,而中间的那个箱子就是演出的内容(额。。暂时是这个)。

  void ProcessKeyboard(unsigned char key,int x,int y)  {  static double delta;  if (key == 'a')  {  delta+=0.03;  }  if (key == 'd')  {  delta-=0.03;  }  setPos(20*cos(delta),posY,20*sin(delta));  }


 

       再次编译运行就可以看到效果了。

OpenGL织梦之旅【第四章】第1节.设立视点函数gluLookAt

笔者的话:

       进入3D世界最让人感到麻烦的是三维坐标,我刚刚开始学这个的时候也是被各种坐标搞崩溃,用了大量的时间来调坐标,一旦有某个地方坐标错了,就会导致出现黑屏。。。OpenGL 3D编程要求一定的空间想象力和数学能力。克服困难的捷径当时是多多练习,熟练了速度就会快很多。

附本节全部代码:

#define GLUT_DISABLE_ATEXIT_HACK#include <GL/glut.h>   #include <stdio.h>   #include <math.h>   #include <time.h>   #include <iostream>#define PI 3.1415926   int WinWidth,WinHeight;double posX,posY,posZ,viewX,viewY,viewZ,upX,upY,upZ;void setAll(double px,double py,double pz,double vx,double vy,double vz,double ux,double uy,double uz){posX=px;posY=py;posZ=pz;viewX=vx;viewY=vy;viewZ=vz;upX=ux;upY=uy;upZ=uz;}void setLookAt(){gluLookAt(posX,posY,posZ,  viewX,viewY,viewZ,  upX,upY,upZ);}void setPos(double x,double y,double z){posX=x;posY=y;posZ=z;}void DrawBox(){glBegin(GL_POLYGON);glColor3f(1.0,0.0,0.0);    glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(0.0,1.0,0.0);glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f);glVertex3f(1.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(0.0,0.0,1.0);glVertex3f(0.0f, 0.0f, 0.0f);glVertex3f(0.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 1.0f);glVertex3f(0.0f, 0.0f, 1.0f);glEnd();glBegin(GL_POLYGON);glColor3f(1.0,0.0,1.0);glVertex3f(1.0f, 0.0f, 0.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(1.0,1.0,0.0);glVertex3f(0.0f, 1.0f, 0.0f);glVertex3f(0.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 0.0f);glEnd();glBegin(GL_POLYGON);glColor3f(0.0,1.0,1.0);glVertex3f(0.0f, 0.0f, 1.0f);glVertex3f(1.0f, 0.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f);glVertex3f(0.0f, 1.0f, 1.0f);glEnd();}void DrawGrid(){glLineWidth(2);glColor3f(0.0,0.0,1.0);for (int i=-100; i<=100; i+=10){glBegin(GL_LINES);glVertex3f(i,0.0f,-100.0f);glVertex3f(i,0.0f,100.0f);glEnd();glBegin(GL_LINES);glVertex3f(-100.0f,0.0f,i);glVertex3f(100.0f,0.0f,i);glEnd();}}void Draw(){    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);DrawGrid();DrawBox();glutSwapBuffers();}void Update(){glLoadIdentity();setLookAt();    glutPostRedisplay();}void Reshape(int w,int h){WinWidth=w;WinHeight=h;glMatrixMode(GL_PROJECTION);glLoadIdentity();    glViewport(0,0,w,h);gluPerspective(45,1.0*w/h,1,1000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();}void init(){glClearColor(0.0,0.0,0.0,0.0);glEnable(GL_DEPTH_TEST);setAll(20,1.75,0,0,1.75,0,0,1,0);}void ProcessKeyboard(unsigned char key,int x,int y){static double delta;if (key == 'a'){delta+=0.03;}if (key == 'd'){delta-=0.03;}setPos(20*cos(delta),posY,20*sin(delta));}int main(int argc, char *argv[]){WinWidth=400;WinHeight=400;    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);    glutInitWindowPosition(100, 100);    glutInitWindowSize(WinWidth, WinHeight);    glutCreateWindow("HelloOpenGL");    glutReshapeFunc(&Reshape);    glutIdleFunc(&Update);    glutDisplayFunc(&Draw);glutKeyboardFunc(&ProcessKeyboard);init();    glutMainLoop();    return 0;  }



作者:plusplus7

日期:2013年3月1日

转载请注明出处

热点排行