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

openGL+VS2010的例程--空间摄影机+灯光渲染成型(三维)

2015-01-16 10:02 423 查看


效果图如上:

步骤:略

实现代码如下:

1、main.cpp

/**********************************************************************

Lighting and depth testing

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>        //includes gl.h and glu.h
#include <windows.h>
#include "camera.h"

CCamera Camera;
bool LightEnabled = true;
float TorusRotated = 0.0;

static GLfloat MatSpec[] = {1.0,1.0,1.0,1.0};
static GLfloat MatShininess[] = {50.0};  // 设置材料反射指数
//其中,LightPosition也是一个四维数组,四维数组的前3项依次为光源位置的X,Y,Z分量,第四个值很特殊,一般为1或-1。当
//LightPosition[4]=-1的时候,表示光源位于距离场景无限远的地方,无论前面设置的X,Y,Z是什么值。当LightPosition[4]=1
//时,光源的位置就是前三项所指定的位置。
static GLfloat LightPos[] = {-2.0,2.0,3.0,0.0};

void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //Don't forget the depth buffer!
glLoadIdentity();    //Load a new modelview matrix -> we can apply new transformations
Camera.Render();  // 移动新视点的矩阵
glLightfv(GL_LIGHT0, GL_POSITION, LightPos); // 设置光源在场景中的位置
glutSolidSphere(1.0,40,40); //  设置球体1

glTranslatef(2.0,0.0,0.0);
glutSolidSphere(0.8,40,40); //  设置球体2

glPushMatrix(); // 压栈1
glTranslatef(0.0,2.0,0.0);
glutSolidSphere(1.2,40,40); //  设置球体3
glPopMatrix(); // 出栈1

glTranslatef(0.0,0.0,2.0);
glutSolidSphere(0.5,40,40);  //  设置球体4

glTranslatef(-4.0,0.0,0.0);
glRotatef(TorusRotated, 0.0,1.0,0.0);
glutSolidTorus(0.3,1.0,16,32);  // glutWireTorus  绘制线框圆环 glutSolidTorus 绘制实心圆环

glFlush();            //Finish rendering
glutSwapBuffers();    //Swap the buffers ->make the result of rendering visible
}

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
//Adjust point size to window size
glPointSize(GLfloat(x)/200.0);
}
void KeyDown(unsigned char key, int x, int y)
//Note: because there is an Idle-func, we don't have to call Display here
{
switch(key)
{
case 27:    //ESC
exit(0);
break;
case 97:        //a
Camera.RotateY(5.0);
break;
case 100:        //d
Camera.RotateY(-5.0);
break;
case 119:        //w
Camera.MoveForwards( -0.1 ) ;
break;
case 115:        //s
Camera.MoveForwards( 0.1 ) ;
break;
case 120:        //x
Camera.RotateX(5.0);
break;
case 121:        //y
Camera.RotateX(-5.0);
break;
case 99:        //c
Camera.StrafeRight(-0.1);
break;
case 118:        //v
Camera.StrafeRight(0.1);
break;
case 'l':
LightEnabled = !LightEnabled;
if (LightEnabled) glEnable(GL_LIGHTING);
else glDisable(GL_LIGHTING);
break;
}
}
static long long times = 0;
void Idle(void)
{
times++; // 延迟
if(times>500000)
times =0;
if(times% 500000== 0)
{
TorusRotated += 2.0;
Display();
}
}

int main(int argc, char **argv)
{
//Initialize GLUT
glutInit(&argc, argv);
//Lets use doublebuffering, RGB(A)-mode and a depth buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // 新增“深度缓冲”
glutInitWindowSize(600,600);
//Create a window with rendering context and everything else we need
glutCreateWindow("Lighting and depth testing");
//Assign the event-handling routines
glutDisplayFunc(Display);
glutReshapeFunc(Reshape);
glutKeyboardFunc(KeyDown);
glutIdleFunc(Idle); // 新增“空闲任务”
Camera.Move(F3dVector(0.0,0.0,15.0)); // 摄影机的位置
//Lighting stuff:
glShadeModel(GL_SMOOTH);    //GL_FLAT would look much worse GL_SMOOTH // 平滑过渡颜色
glEnable(GL_DEPTH_TEST); // 开启深度测试,比较在z轴上的点是否最靠前。
// GL_DIFFUSE 漫射光   GL_SPECULAR  镜面光
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, MatSpec);   // 镜面光的颜色 -- 缺省值
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, MatShininess);  // 称为 镜面指数 ,取值范围是0到128。

glEnable(GL_LIGHTING); // 打开光照效果
glEnable(GL_LIGHT0); // 使用默认的0号灯

//Let GLUT get the msgs and tell us the ones we need
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 )
{
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 );
}

void CCamera::RotateY (GLfloat Angle)
{
RotatedY += Angle;
ViewDirChanged = true;
}

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