您的位置:首页 > 运维架构

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

2013-03-01 00:04 489 查看
在做所有的事情之前,我们必须要了解怎么在3D的世界中绘图。这也是为了帮助我们调整视点,不然调来调去都是黑框...
3D世界中的坐标系也是笛卡尔坐标系,y轴就像是现实世界中的“高低”,而x和z像是地面的坐标。



我们写一个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();
}


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

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


(有点小。。)

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

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

我把摄像机的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));
  }


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



笔者的话:

进入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日
转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: