打造3D游戏中第一人称视觉效果 - 带可测试源代码下载

来源:互联网 发布:网络电视直播在线 编辑:程序博客网 时间:2024/05/21 16:58

首先解决的一个问题:什么是镜头?

我们可以想象拍戏那种镜头,对着什么东西,就能拍出什么东西,然后我们就可以在电视屏幕或者电影屏幕上看到这些东西。3D世界里面也是这样定义一个镜头,在这个镜头范围之内的东西就可以显示在电脑屏幕中。

如下图在一个方各地上行走:

  

下面是把镜头抽象起来:

拍戏的时候,这个镜头是个实体,那么在我们的3D世界里面我们也是这样把镜头当做一个实体,在代码中体现出来就是一个类。

在游戏中控制镜头前进,后退,左移,右移,其实就是在代码中操作这个类。

所以问题就归结为如何构建这个类,和如何操作这个类了。

首先构建这个类的对象成员有如下数据:

class Camera{protected:D3DXMATRIX mView;//操作镜头的主要矩阵D3DXMATRIX mProj;//投影到屏幕上的矩阵D3DXMATRIX mViewProj;//从镜头空间到投影到屏幕上的矩阵 D3DXVECTOR3 mPosW;//镜头位置 D3DXVECTOR3 mRightW;//镜头的由向量 D3DXVECTOR3 mUpW;//镜头的上向量 D3DXVECTOR3 mLookW;//镜头的前向量 float mSpeed;//镜头的速度 

 

镜头的坐标如下:

右上角的代表镜头,指向前的叫前向量,指向上的叫上向量,指向右的叫右向量。这样就构成了镜头坐标空间。就是构建了这样的空间,才可以让镜头前面的物体相对于镜头的位置得以确定!是在看不懂的朋友先熟记一下这个概念,然后建议补一补几何学。


mProj和mViewProj矩阵基本上在所有3D世界都要用到的。这是图形学的构造原理,有空再专门解析一下吧。简单解析一下就是说:利用这些矩阵才能把定位在世界坐标空间的物体投影到屏幕上。

跟本章相关的就是mView矩阵了,就是利用了这个矩阵才能操作镜头的。这个矩阵的计算方法如下:

定义在类中:

class Camera{public:Camera();protected:void buildView();


实现函数:

void Camera::buildView(){// 这里是前向量单位化.D3DXVec3Normalize(&mLookW, &mLookW);     D3DXVec3Cross(&mUpW, &mLookW, &mRightW);//作叉乘可以确保这2个向量是正交的,也就是都互相垂直。D3DXVec3Normalize(&mUpW, &mUpW);D3DXVec3Cross(&mRightW, &mUpW, &mLookW);//再次叉乘保证正交 D3DXVec3Normalize(&mRightW, &mRightW);//这里是根据几何公式来填写这个需要的变换矩阵的,至于是什么公式,我也不记得了,因为公式很复杂,死背不是好办法,但是原理要知道,就是利用这样的矩阵来转换镜头。float x = -D3DXVec3Dot(&mPosW, &mRightW);float y = -D3DXVec3Dot(&mPosW, &mUpW);float z = -D3DXVec3Dot(&mPosW, &mLookW);mView(0,0) = mRightW.x; mView(1,0) = mRightW.y; mView(2,0) = mRightW.z; mView(3,0) = x;   mView(0,1) = mUpW.x;mView(1,1) = mUpW.y;mView(2,1) = mUpW.z;mView(3,1) = y;  mView(0,2) = mLookW.x; mView(1,2) = mLookW.y; mView(2,2) = mLookW.z; mView(3,2) = z;   mView(0,3) = 0.0f;mView(1,3) = 0.0f;mView(2,3) = 0.0f;mView(3,3) = 1.0f;}


下面就是以鼠标和键盘为参数不断更新上面这些参数,得到不断移动镜头的感觉:

void Camera::update(float dt){// 这里是控制方法wsda为前后左右。D3DXVECTOR3 dir(0.0f, 0.0f, 0.0f);if( gDInput->keyDown(DIK_W) )dir += mLookW;if( gDInput->keyDown(DIK_S) )dir -= mLookW;if( gDInput->keyDown(DIK_D) )dir += mRightW;if( gDInput->keyDown(DIK_A) )dir -= mRightW;// Move at mSpeed along net direction.D3DXVec3Normalize(&dir, &dir);mPosW += dir*mSpeed*dt;//这里是控制其速度,可以改变mSpeed的大小以改变其速度,记得mSpeed为类的私有成员。 mPosW.y = 2.0f;//这里是限制其高度,相当于人的高度。如果把这里去掉的话,就可以飞起来了。 if(mPosW.x >= 49.0f)//这下面的代码是控制不要超出了方格地的范围了。mPosW.x = 49.0f;if(mPosW.x <=-49.0f)mPosW.x = -49.0f;if(mPosW.z >= 49.0f)mPosW.z = 49.0f;if(mPosW.z <= -49.0f)mPosW.z = -49.0f;// 下面是鼠标控制代码,控制其向左和向右,向上和向下看.float pitch  = gDInput->mouseDY() / 150.0f;float yAngle = gDInput->mouseDX() / 150.0f;// 向上下方向看时的变换算法.D3DXMATRIX R;D3DXMatrixRotationAxis(&R, &mRightW, pitch);D3DXVec3TransformCoord(&mLookW, &mLookW, &R);D3DXVec3TransformCoord(&mUpW, &mUpW, &R);// 向左向右看时的算法.D3DXMatrixRotationY(&R, yAngle);D3DXVec3TransformCoord(&mRightW, &mRightW, &R);D3DXVec3TransformCoord(&mUpW, &mUpW, &R);D3DXVec3TransformCoord(&mLookW, &mLookW, &R);// 然后需要重新调用前面的函数根据上面的新参数更新计算,这样达到移动镜头的目的.buildView();mViewProj = mView * mProj;}


下面是调用函数,我写了个namespace包起来,方便修改:

#include "CameraRun.h"#include "Camera.h"namespace CameraRun{Camera camera;void initData(){gCamera = &camera;gCamera->pos() = D3DXVECTOR3(-20.0f, 2.0f, 0.0f);}void updateAll(float dt){gCamera->update(dt);}}


玩这个程序只需要修改上面说明的地方就可以自己测试了。

可以修改的地方:

1 修改成为可以飞起来的

2 修改其速度

3 改成不受方格地限制

4 更难的就是修改限制其俯视的角度

 

这里是镜头类下载:

http://download.csdn.net/detail/kenden23/6491871

这里是框架下载:

http://download.csdn.net/detail/kenden23/6491875

都是源代码。

原创粉丝点击