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

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

2015-01-15 15:06 585 查看


效果图如上:

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

实现代码,有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/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: