openGL+VS2010的例程--空间摄影机注释版(三维)
2015-01-15 15:06
585 查看
![](http://images.cnitblog.com/blog/444792/201501/151500297454533.jpg)
效果图如上:
步骤:请看注释,这里略。
实现代码,有3个文件,如下:
1、main.cpp
/********************************************************************** Camera with OpenGL June, 11th, 2000 This tutorial was written by Philipp Crocoll Contact: philipp.crocoll@web.de www.codecolony.de Every comment would be appreciated. If you want to use parts of any code of mine: let me know and use it! ********************************************************************** ESC: exit CAMERA movement: w : forwards s : backwards a : turn left d : turn right x : turn up y : turn down v : strafe right c : strafe left r : move up f : move down ***********************************************************************/ #include <GL\glut.h> #include <windows.h> #include "camera.h" CCamera Camera; // 绘制网格-第1个参数网格的总边长,第2、3个是横纵线条的总个数。 void DrawNet(GLfloat size, GLint LinesX, GLint LinesZ) { glBegin(GL_LINES); for (int xc = 0; xc < LinesX; xc++) { glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / 2.0); // 当LinesX=30时, (-1,0,1) (-1+2/29, 0, 1)(-1+4/29, 0, 1).....(-1+2*29/29, 0, 1) glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 0.0, size / -2.0);// (-1,0,-1) } for (int zc = 0; zc < LinesX; zc++) { glVertex3f( size / 2.0, 0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); glVertex3f( size / -2.0, 0.0, -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); } glEnd(); } void reshape(int x, int y) { if (y == 0 || x == 0) return; //Nothing is visible then, so return //Set a new projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); //Angle of view:40 degrees //Near clipping plane distance: 0.5 //Far clipping plane distance: 20.0 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); glMatrixMode(GL_MODELVIEW); glViewport(0,0,x,y); //Use the whole window for rendering } void Display(void) { glClear(GL_COLOR_BUFFER_BIT); glLoadIdentity(); Camera.Render(); // 设置摄影机的空间坐标(0,0,4),相当于屏幕前的观察者往后退4个单位 glTranslatef(0.0,0.8,0.0); // 0.8 是该模型的Y轴上实际构造位置 glScalef(4.0,1.0,4.0); // 模型的放大比例 GLfloat size = 2.0; GLint LinesX =41; // 网格面X轴边的线条个数 GLint LinesZ = 41; GLfloat halfsize = size / 2.0; glColor3f(1.0,1.0,1.0); // 白色 glPushMatrix(); // 压栈1 glTranslatef(0.0,-halfsize ,0.0); // 下沉半个单位绘制底面网格 DrawNet(size,LinesX,LinesZ); // 绘制网格 glTranslatef(0.0,size,0.0);// 上升一个完整的单位绘制底面网格 DrawNet(size,LinesX,LinesZ); // 绘制网格 glPopMatrix(); // 出栈1 glColor3f(0.0,0.0,1.0); // 蓝色 glPushMatrix(); glTranslatef(-halfsize,0.0,0.0); // 左移半个单位绘制底面网格 glRotatef(90.0,0.0,0.0,halfsize); // 沿着Z轴顺时针旋转90°。 DrawNet(size,LinesX,LinesZ); glTranslatef(0.0,-size,0.0); // 沿着Y轴负方向移动,即世界坐标的右移。 DrawNet(size,LinesX,LinesZ); glPopMatrix(); glColor3f(1.0,0.0,0.0); // 红色 glPushMatrix(); glTranslatef(0.0,0.0,-halfsize); // 沿着Z轴负方向移动 glRotatef(90.0,halfsize,0.0,0.0); // 沿着X轴顺时针旋转90°。 DrawNet(size,LinesX,LinesZ); glTranslatef(0.0,size,0.0); // 沿着Y轴正方向移动,即世界坐标的往前靠。 DrawNet(size,LinesX,LinesZ); glPopMatrix(); glFlush(); glutSwapBuffers(); } void KeyDown(unsigned char key, int x, int y) { switch (key) { case 27: //ESC PostQuitMessage(0); // 关闭应用程序 break; case 'a': // 视角面向左 Camera.RotateY(5.0); Display(); break; case 'd': // 视角面向右 Camera.RotateY(-5.0); Display(); break; case 'w': // 视角点前移 Camera.MoveForwards( -0.1 ) ; Display(); break; case 's': // 视角点后退 Camera.MoveForwards( 0.1 ) ; Display(); break; case 'x': // 视角面向上 Camera.RotateX(5.0); Display(); break; case 'y': // 视角面向下 Camera.RotateX(-5.0); Display(); break; case 'c': // 视角点左移 Camera.StrafeRight(-0.1); Display(); break; case 'v': // 视角点右移 Camera.StrafeRight(0.1); Display(); break; case 'f': // 视角点下移 Camera.Move(F3dVector(0.0,-0.3,0.0)); Display(); break; case 'r': // 视角点上移 Camera.Move(F3dVector(0.0,0.3,0.0)); Display(); break; } } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(600,600); glutCreateWindow("Camera"); Camera.Move( F3dVector(0.0, 0.0, 3.0 )); // 摄影机的空间坐标 Camera.MoveForwards( 1.0 ); // 略 glutDisplayFunc(Display); // 在以下几种情况下会被调用,在窗口从被遮挡中恢复时调用,动画刷新调用等。 glutReshapeFunc(reshape); // 调整窗口大小时被调用,创建窗口相当于调整了一次窗口大小。 glutKeyboardFunc(KeyDown); // 按键触发时执行 glutMainLoop(); return 0; }
2、Camera.cpp
#include "camera.h" #include "math.h" #include <iostream> #include "windows.h" SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ) { SF3dVector tmp; tmp.x = x; tmp.y = y; tmp.z = z; return tmp; } SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v) { SF3dVector result; result.x = u->x + v->x; result.y = u->y + v->y; result.z = u->z + v->z; return result; } void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2) { Dst->x += V2->x; Dst->y += V2->y; Dst->z += V2->z; } /***************************************************************************************/ CCamera::CCamera() { //Init with standard OGL values: Position = F3dVector ( 0.0, 0.0, 0.0); // 观察点的初始值 ViewDir = F3dVector( 0.0, 0.0, -1.0); // 观察面的初始值 ViewDirChanged = false; //Only to be sure: RotatedX = RotatedY = RotatedZ = 0.0; // 旋转角度的初始值 } // 获取观察面 void CCamera::GetViewDir( void ) { // 假设视角面的向量是1个单位,根据各轴面的旋转角度,计算X、Y、Z的比值。 // 那么step1是处理无俯仰视角的过程;step2是处理存在俯仰的过程。 SF3dVector Step1, Step2; //Rotate around Y-axis: Step1.x = cos( (RotatedY + 90.0) * PIdiv180);// 视角点在世界坐标系的偏移位置 Step1.z = -sin( (RotatedY + 90.0) * PIdiv180); //Rotate around X-axis: double cosX = cos (RotatedX * PIdiv180); Step2.x = Step1.x * cosX; Step2.z = Step1.z * cosX; Step2.y = sin(RotatedX * PIdiv180); //Rotation around Z-axis not yet implemented, so: ViewDir = Step2; } void CCamera::Move (SF3dVector Direction) { AddF3dVectorToVector(&Position, &Direction ); // 观察点的最终值,分多次操作值累加而成 } // 以Y轴(0,1,0)为旋转轴 void CCamera::RotateY (GLfloat Angle) { RotatedY += Angle; ViewDirChanged = true; } // 以X轴(1,0,0)为旋转轴 void CCamera::RotateX (GLfloat Angle) { RotatedX += Angle; ViewDirChanged = true; } // 渲染 void CCamera::Render( void ) { // 旋转模型(观察面调整) glRotatef(-RotatedX , 1.0, 0.0, 0.0); glRotatef(-RotatedY , 0.0, 1.0, 0.0); glRotatef(-RotatedZ , 0.0, 0.0, 1.0); glTranslatef( -Position.x, -Position.y, -Position.z ); // 移动(观察点调整) } // 视角点前后移 void CCamera::MoveForwards( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.x = ViewDir.x * -Distance; MoveVector.y = ViewDir.y * -Distance; // 视角点 前后移动时,有“上浮”和“下潜”的感觉。 MoveVector.z = ViewDir.z * -Distance; AddF3dVectorToVector(&Position, &MoveVector ); } // 视角点左右移 void CCamera::StrafeRight ( GLfloat Distance ) { if (ViewDirChanged) GetViewDir(); SF3dVector MoveVector; MoveVector.z = -ViewDir.x * -Distance; MoveVector.y = 0.0; // 视角点 水平移动时,Y轴保持不变。 MoveVector.x = ViewDir.z * -Distance; AddF3dVectorToVector(&Position, &MoveVector ); }
3、camera.h
#include <gl\glut.h> // Need to include it here because the GL* types are required #define PI 3.1415265359 #define PIdiv180 3.1415265359/180.0 ///////////////////////////////// //Note: All angles in degrees // ///////////////////////////////// struct SF3dVector //Float 3d-vect, normally used { GLfloat x,y,z; }; struct SF2dVector { GLfloat x,y; }; class CCamera { private: SF3dVector Position; SF3dVector ViewDir; /*Not used for rendering the camera, but for "moveforwards" So it is not necessary to "actualize" it always. It is only actualized when ViewDirChanged is true and moveforwards is called*/ bool ViewDirChanged; GLfloat RotatedX, RotatedY, RotatedZ; void GetViewDir ( void ); public: CCamera(); //inits the values (Position: (0|0|0) Target: (0|0|-1) ) void Render ( void ); //executes some glRotates and a glTranslate command //Note: You should call glLoadIdentity before using Render void Move ( SF3dVector Direction ); void RotateX ( GLfloat Angle ); void RotateY ( GLfloat Angle ); void RotateZ ( GLfloat Angle ); void RotateXYZ ( SF3dVector Angles ); void MoveForwards ( GLfloat Distance ); void StrafeRight ( GLfloat Distance ); }; SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ); SF3dVector AddF3dVectors ( SF3dVector * u, SF3dVector * v); void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2);
文章原始出处:http://www.codecolony.de/
相关文章推荐
- openGL+VS2010的例程--空间摄影机(三维)
- openGL+VS2010的例程--空间摄影机+灯光渲染成型(三维)
- openGL+VS2010的例程--城堡模型注释版(三维)
- openGL+VS2010的例程--太阳地球月球运动模型增强版(三维)
- openGL+VS2010的例程--太阳地球月球运动模型(三维)
- openGL+VS2010的例程--旋转贴图灯笼(三维)
- openGL+VS2010的例程--旋转彩球(三维)
- openGL+VS2010的例程--旋转变色立方体(三维)
- openGL+VS2010的例程--静态平滑变色三角形(二维)
- Captain Dialog 2009-09-18 VC+OpenGL实现空间三维Delaunay三角剖分
- 用OpenGL实现三维点到屏幕空间的投影
- VC+OpenGL实现空间三维Delaunay三角剖分
- OpenGL入门学习 教程 (五)三维的空间变换
- VC+OpenGL实现空间三维Delaunay三角剖分
- VC+OpenGL实现空间三维Delaunay三角剖分
- OpenGL入门学习之五——三维的空间变换
- OpenGL入门学习——第五课 三维的空间变换
- OpenGL 三维的空间变换
- VS2010-MFC:用OpenGL在对话框中的PictureControl(图片控件)中绘制三维模型,可旋转、平移、缩放,可用于三维模型的预览
- vs2010配置OpenGL