效果图如上:
步骤:请看注释,这里略。
实现代码,有3个文件,如下:
1、main.cpp
1 /********************************************************************** 2 3 Camera with OpenGL 4 5 June, 11th, 2000 6 7 This tutorial was written by Philipp Crocoll 8 Contact: 9 philipp.crocoll@web.de 10 www.codecolony.de 11 12 Every comment would be appreciated. 13 14 If you want to use parts of any code of mine: 15 let me know and 16 use it! 17 18 ********************************************************************** 19 ESC: exit 20 21 CAMERA movement: 22 w : forwards 23 s : backwards 24 a : turn left 25 d : turn right 26 x : turn up 27 y : turn down 28 v : strafe right 29 c : strafe left 30 r : move up 31 f : move down 32 33 ***********************************************************************/ 34 35 #include <GL\glut.h> 36 #include <windows.h> 37 #include "camera.h" 38 39 40 CCamera Camera; 41 42 // 绘制网格-第1个参数网格的总边长,第2、3个是横纵线条的总个数。 43 void DrawNet(GLfloat size, GLint LinesX, GLint LinesZ) 44 { 45 glBegin(GL_LINES); 46 for (int xc = 0; xc < LinesX; xc++) 47 { 48 glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 49 0.0, 50 size / 2.0); // 当LinesX=30时, (-1,0,1) (-1+2/29, 0, 1)(-1+4/29, 0, 1).....(-1+2*29/29, 0, 1) 51 glVertex3f( -size / 2.0 + xc / (GLfloat)(LinesX-1)*size, 52 0.0, 53 size / -2.0);// (-1,0,-1) 54 } 55 for (int zc = 0; zc < LinesX; zc++) 56 { 57 glVertex3f( size / 2.0, 58 0.0, 59 -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); 60 glVertex3f( size / -2.0, 61 0.0, 62 -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size); 63 } 64 glEnd(); 65 } 66 67 void reshape(int x, int y) 68 { 69 if (y == 0 || x == 0) return; //Nothing is visible then, so return 70 71 //Set a new projection matrix 72 glMatrixMode(GL_PROJECTION); 73 glLoadIdentity(); 74 //Angle of view:40 degrees 75 //Near clipping plane distance: 0.5 76 //Far clipping plane distance: 20.0 77 gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0); 78 79 glMatrixMode(GL_MODELVIEW); 80 glViewport(0,0,x,y); //Use the whole window for rendering 81 } 82 83 void Display(void) 84 { 85 glClear(GL_COLOR_BUFFER_BIT); 86 glLoadIdentity(); 87 Camera.Render(); // 设置摄影机的空间坐标(0,0,4),相当于屏幕前的观察者往后退4个单位 88 glTranslatef(0.0,0.8,0.0); // 0.8 是该模型的Y轴上实际构造位置 89 90 glScalef(4.0,1.0,4.0); // 模型的放大比例 91 92 GLfloat size = 2.0; 93 GLint LinesX =41; // 网格面X轴边的线条个数 94 GLint LinesZ = 41; 95 96 GLfloat halfsize = size / 2.0; 97 glColor3f(1.0,1.0,1.0); // 白色 98 99 glPushMatrix(); // 压栈1 100 glTranslatef(0.0,-halfsize ,0.0); // 下沉半个单位绘制底面网格 101 DrawNet(size,LinesX,LinesZ); // 绘制网格 102 glTranslatef(0.0,size,0.0);// 上升一个完整的单位绘制底面网格 103 DrawNet(size,LinesX,LinesZ); // 绘制网格 104 glPopMatrix(); // 出栈1 105 106 glColor3f(0.0,0.0,1.0); // 蓝色 107 glPushMatrix(); 108 glTranslatef(-halfsize,0.0,0.0); // 左移半个单位绘制底面网格 109 glRotatef(90.0,0.0,0.0,halfsize); // 沿着Z轴顺时针旋转90°。 110 DrawNet(size,LinesX,LinesZ); 111 glTranslatef(0.0,-size,0.0); // 沿着Y轴负方向移动,即世界坐标的右移。 112 DrawNet(size,LinesX,LinesZ); 113 glPopMatrix(); 114 115 glColor3f(1.0,0.0,0.0); // 红色 116 glPushMatrix(); 117 glTranslatef(0.0,0.0,-halfsize); // 沿着Z轴负方向移动 118 glRotatef(90.0,halfsize,0.0,0.0); // 沿着X轴顺时针旋转90°。 119 DrawNet(size,LinesX,LinesZ); 120 glTranslatef(0.0,size,0.0); // 沿着Y轴正方向移动,即世界坐标的往前靠。 121 DrawNet(size,LinesX,LinesZ); 122 glPopMatrix(); 123 124 glFlush(); 125 glutSwapBuffers(); 126 127 } 128 129 void KeyDown(unsigned char key, int x, int y) 130 { 131 switch (key) 132 { 133 case 27: //ESC 134 PostQuitMessage(0); // 关闭应用程序 135 break; 136 case 'a': // 视角面向左 137 Camera.RotateY(5.0); 138 Display(); 139 break; 140 case 'd': // 视角面向右 141 Camera.RotateY(-5.0); 142 Display(); 143 break; 144 case 'w': // 视角点前移 145 Camera.MoveForwards( -0.1 ) ; 146 Display(); 147 break; 148 case 's': // 视角点后退 149 Camera.MoveForwards( 0.1 ) ; 150 Display(); 151 break; 152 case 'x': // 视角面向上 153 Camera.RotateX(5.0); 154 Display(); 155 break; 156 case 'y': // 视角面向下 157 Camera.RotateX(-5.0); 158 Display(); 159 break; 160 case 'c': // 视角点左移 161 Camera.StrafeRight(-0.1); 162 Display(); 163 break; 164 case 'v': // 视角点右移 165 Camera.StrafeRight(0.1); 166 Display(); 167 break; 168 case 'f': // 视角点下移 169 Camera.Move(F3dVector(0.0,-0.3,0.0)); 170 Display(); 171 break; 172 case 'r': // 视角点上移 173 Camera.Move(F3dVector(0.0,0.3,0.0)); 174 Display(); 175 break; 176 177 } 178 } 179 180 int main(int argc, char **argv) 181 { 182 glutInit(&argc, argv); 183 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 184 glutInitWindowSize(600,600); 185 glutCreateWindow("Camera"); 186 Camera.Move( F3dVector(0.0, 0.0, 3.0 )); // 摄影机的空间坐标 187 Camera.MoveForwards( 1.0 ); // 略 188 glutDisplayFunc(Display); // 在以下几种情况下会被调用,在窗口从被遮挡中恢复时调用,动画刷新调用等。 189 glutReshapeFunc(reshape); // 调整窗口大小时被调用,创建窗口相当于调整了一次窗口大小。 190 glutKeyboardFunc(KeyDown); // 按键触发时执行 191 glutMainLoop(); 192 return 0; 193 }
2、Camera.cpp
1 #include "camera.h" 2 #include "math.h" 3 #include <iostream> 4 #include "windows.h" 5 6 SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ) 7 { 8 SF3dVector tmp; 9 tmp.x = x; 10 tmp.y = y; 11 tmp.z = z; 12 return tmp; 13 } 14 15 SF3dVector AddF3dVectors (SF3dVector* u, SF3dVector* v) 16 { 17 SF3dVector result; 18 result.x = u->x + v->x; 19 result.y = u->y + v->y; 20 result.z = u->z + v->z; 21 return result; 22 } 23 24 void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2) 25 { 26 Dst->x += V2->x; 27 Dst->y += V2->y; 28 Dst->z += V2->z; 29 } 30 31 32 /***************************************************************************************/ 33 34 CCamera::CCamera() 35 { 36 //Init with standard OGL values: 37 Position = F3dVector ( 0.0, 38 0.0, 39 0.0); // 观察点的初始值 40 ViewDir = F3dVector( 0.0, 41 0.0, 42 -1.0); // 观察面的初始值 43 ViewDirChanged = false; 44 //Only to be sure: 45 RotatedX = RotatedY = RotatedZ = 0.0; // 旋转角度的初始值 46 } 47 48 // 获取观察面 49 void CCamera::GetViewDir( void ) 50 { 51 // 假设视角面的向量是1个单位,根据各轴面的旋转角度,计算X、Y、Z的比值。 52 // 那么step1是处理无俯仰视角的过程;step2是处理存在俯仰的过程。 53 SF3dVector Step1, Step2; 54 //Rotate around Y-axis: 55 Step1.x = cos( (RotatedY + 90.0) * PIdiv180);// 视角点在世界坐标系的偏移位置 56 Step1.z = -sin( (RotatedY + 90.0) * PIdiv180); 57 //Rotate around X-axis: 58 double cosX = cos (RotatedX * PIdiv180); 59 Step2.x = Step1.x * cosX; 60 Step2.z = Step1.z * cosX; 61 Step2.y = sin(RotatedX * PIdiv180); 62 //Rotation around Z-axis not yet implemented, so: 63 ViewDir = Step2; 64 } 65 void CCamera::Move (SF3dVector Direction) 66 { 67 AddF3dVectorToVector(&Position, &Direction ); // 观察点的最终值,分多次操作值累加而成 68 } 69 70 // 以Y轴(0,1,0)为旋转轴 71 void CCamera::RotateY (GLfloat Angle) 72 { 73 RotatedY += Angle; 74 ViewDirChanged = true; 75 } 76 // 以X轴(1,0,0)为旋转轴 77 void CCamera::RotateX (GLfloat Angle) 78 { 79 RotatedX += Angle; 80 ViewDirChanged = true; 81 } 82 83 // 渲染 84 void CCamera::Render( void ) 85 { 86 // 旋转模型(观察面调整) 87 glRotatef(-RotatedX , 1.0, 0.0, 0.0); 88 glRotatef(-RotatedY , 0.0, 1.0, 0.0); 89 glRotatef(-RotatedZ , 0.0, 0.0, 1.0); 90 91 glTranslatef( -Position.x, -Position.y, -Position.z ); // 移动(观察点调整) 92 } 93 94 // 视角点前后移 95 void CCamera::MoveForwards( GLfloat Distance ) 96 { 97 if (ViewDirChanged) GetViewDir(); 98 SF3dVector MoveVector; 99 MoveVector.x = ViewDir.x * -Distance; 100 MoveVector.y = ViewDir.y * -Distance; // 视角点 前后移动时,有“上浮”和“下潜”的感觉。 101 MoveVector.z = ViewDir.z * -Distance; 102 AddF3dVectorToVector(&Position, &MoveVector ); 103 } 104 // 视角点左右移 105 void CCamera::StrafeRight ( GLfloat Distance ) 106 { 107 if (ViewDirChanged) GetViewDir(); 108 SF3dVector MoveVector; 109 MoveVector.z = -ViewDir.x * -Distance; 110 MoveVector.y = 0.0; // 视角点 水平移动时,Y轴保持不变。 111 MoveVector.x = ViewDir.z * -Distance; 112 AddF3dVectorToVector(&Position, &MoveVector ); 113 }
3、camera.h
1 #include <gl\glut.h> // Need to include it here because the GL* types are required 2 #define PI 3.1415265359 3 #define PIdiv180 3.1415265359/180.0 4 5 ///////////////////////////////// 6 //Note: All angles in degrees // 7 ///////////////////////////////// 8 9 struct SF3dVector //Float 3d-vect, normally used 10 { 11 GLfloat x,y,z; 12 }; 13 struct SF2dVector 14 { 15 GLfloat x,y; 16 }; 17 18 class CCamera 19 { 20 private: 21 SF3dVector Position; 22 SF3dVector ViewDir; /*Not used for rendering the camera, but for "moveforwards" 23 So it is not necessary to "actualize" it always. It is only 24 actualized when ViewDirChanged is true and moveforwards is called*/ 25 bool ViewDirChanged; 26 GLfloat RotatedX, RotatedY, RotatedZ; 27 void GetViewDir ( void ); 28 public: 29 CCamera(); //inits the values (Position: (0|0|0) Target: (0|0|-1) ) 30 void Render ( void ); //executes some glRotates and a glTranslate command 31 //Note: You should call glLoadIdentity before using Render 32 void Move ( SF3dVector Direction ); 33 void RotateX ( GLfloat Angle ); 34 void RotateY ( GLfloat Angle ); 35 void RotateZ ( GLfloat Angle ); 36 void RotateXYZ ( SF3dVector Angles ); 37 void MoveForwards ( GLfloat Distance ); 38 void StrafeRight ( GLfloat Distance ); 39 }; 40 41 42 SF3dVector F3dVector ( GLfloat x, GLfloat y, GLfloat z ); 43 SF3dVector AddF3dVectors ( SF3dVector * u, SF3dVector * v); 44 void AddF3dVectorToVector ( SF3dVector * Dst, SF3dVector * V2);
文章原始出处:http://www.codecolony.de/