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

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

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

OpenGL织梦之旅【第四章】第1节.设置视点函数gluLookAt_第1张图片

       我们写一个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_第2张图片 (有点小。。)

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

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

       我把摄像机的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日

转载请注明出处

你可能感兴趣的:(OpenGL织梦之旅【第四章】第1节.设置视点函数gluLookAt)