openGL+VS2010的例程--空间摄影机注释版(三维)

效果图如上:

步骤:请看注释,这里略。

实现代码,有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/

 

posted @ 2015-01-15 15:06  joyce3800  阅读(288)  评论(0编辑  收藏  举报