DirectX11 学习笔记7 - 支持自由移动的摄像机

来源:互联网 发布:ubuntu 修改用户目录 编辑:程序博客网 时间:2024/04/30 03:04

现在将重新制定一个camera摄像机。可以自由移动。

比如前进 后退,上游 下潜。 各个方向渲染之类的。

首先设置按键。

这个时候需要在

XWindow.h 里面

bool XWindow::frame(){//判断是否按下ESC键if(x_input->isKeyDown(VK_ESCAPE))return false;//如果A,S,D,W,Q,E,Z,X,C键按下,移动摄像机 if(GetAsyncKeyState('W') & 0x8000)    //前后 x_graphics->x_camera->walk(-0.1f); if(GetAsyncKeyState('S') & 0x8000)    x_graphics->x_camera->walk(0.1f); if(GetAsyncKeyState('A') & 0x8000)    //左右 x_graphics->x_camera->strafe(-0.1f); if(GetAsyncKeyState('D') & 0x8000)    x_graphics->x_camera->strafe(0.1f); //if(GetAsyncKeyState('Q') & 0x8000)    //上下 //x_graphics->x_camera->fly(-0.1f); //if(GetAsyncKeyState('E') & 0x8000)    //x_graphics->x_camera->fly(0.1f); //if(GetAsyncKeyState('Z') & 0x8000)    //x_graphics->x_camera->pitch(PI/180); //if(GetAsyncKeyState('X') & 0x8000)    //x_graphics->x_camera->yaw(PI/180); //if(GetAsyncKeyState('C') & 0x8000)    //x_graphics->x_camera->roll(PI/180);//动画,旋转摄像机 //x_graphics->x_camera->roll(PI/180);//开始渲染return x_graphics->frame();}
添加一些按键。如果报错的话, 可能是x_camera 在XGraphics.h 类里面是私有的,可以设置成公有

private: bool render(); public:XCamera *x_camera;//摄像机private:XD3Device *x_d3d;//3D设备XModel *x_model;//模型XShader *x_shader;//渲染器HWND hwnd;


然后很简单吧

然后就是修改摄像机了

先上代码再讲解吧

#pragma once#include <xnamath.h>class XCamera{public:enum CameraType { LANDOBJECT, AIRCRAFT };XCamera();void strafe(float units); // l左右//void fly(float units);    // 上下void walk(float units);   // 前后//void pitch(float angle); // 旋转view坐标系right向量//void yaw(float angle);   // 旋转up向量//void roll(float angle);  // 旋转look向量void getViewMatrix(XMMATRIX& V); void setCameraType(CameraType cameraType); void getPosition(XMFLOAT3* pos); void setPosition(XMFLOAT3* pos); void getRight(XMFLOAT3* right);void getUp(XMFLOAT3* up);void getLook(XMFLOAT3* look);private:CameraType _cameraType;XMFLOAT3 _right,_up,_look,_pos;};XCamera::XCamera(){_cameraType=AIRCRAFT;_pos=XMFLOAT3(0.0f, 0.0f, -10.0f);_right=XMFLOAT3(1.0f,0.0f,0.0f);_up=XMFLOAT3(0.0f,1.0f,0.0f);_look=XMFLOAT3(0.0f,0.0f,1.0f);}void XCamera::getPosition(XMFLOAT3* pos){*pos = _pos;}void XCamera::setPosition(XMFLOAT3* pos){_pos = *pos;}void XCamera::getRight(XMFLOAT3* right){*right = _right;}void XCamera::getUp(XMFLOAT3* up){*up = _up;}void XCamera::getLook(XMFLOAT3* look){*look = _look;}//行走,沿着摄像机观察方向的移动void XCamera::walk(float units){XMVECTOR vpos,vlook;vpos=XMLoadFloat3(&_pos);vlook=XMLoadFloat3(&_look);// 仅在x,z平面移动if( _cameraType == LANDOBJECT ){vpos += XMVectorSet(_look.x, 0.0f, _look.z,0)*units;}if( _cameraType == AIRCRAFT )vpos += vlook * units;XMStoreFloat3(&_pos,vpos);}//扫视,是指保持观察方向不变,沿向量right方向从一边平移到另一边void XCamera::strafe(float units){XMVECTOR vpos,vright;vpos=XMLoadFloat3(&_pos);vright=XMLoadFloat3(&_right);// 仅在x,z平面移动if( _cameraType == LANDOBJECT )vpos += XMVectorSet(_right.x, 0.0f, _right.z,0.0f) * units;if( _cameraType == AIRCRAFT )vpos += vright * units;XMStoreFloat3(&_pos,vpos);}/*//飞行模式,升降,指沿着向量up方向的移动void XCamera::fly(float units){// 仅在y轴移动if( _cameraType == LANDOBJECT )_pos.y += units;if( _cameraType == AIRCRAFT )_pos += _up * units;}void XCamera::pitch(float angle){XMMATRIX T;T=XMMatrixRotationAxis( _right, angle);// 绕着right向量,旋转up和look_up=XMVector3TransformCoord(_up,_up, T);_look=XMVector3TransformCoord(_look, T);}void XCamera::yaw(float angle){D3DXMATRIX T;//对LANDOBJECT,总是绕着(0,1,0)旋转。if( _cameraType == LANDOBJECT )T=XMMatrixRotationY(angle);//对于aircraft,绕着up向量旋转if( _cameraType == AIRCRAFT )T=XMMatrixRotationAxis(_up, angle);// 绕着up或者y轴,旋转right和look_right=XMVector3TransformCoord(_right, T);_look=XMVector3TransformCoord(_look, T);}void XCamera::roll(float angle){//只对aircraft模式才左roll旋转if( _cameraType == AIRCRAFT ){D3DXMATRIX T;T=XMMatrixRotationAxis(_look, angle);// 绕着look向量,旋转up和right_right=XMVector3TransformCoord(_right, T);_up=XMVector3TransformCoord(_up, T);}}*/void XCamera::getViewMatrix(XMMATRIX &V){XMVECTOR vlook,vup,vright,vpos;vpos=XMLoadFloat3(&_pos);vlook=XMLoadFloat3(&_look);vup=XMLoadFloat3(&_up);vright=XMLoadFloat3(&_right);// 保持view局部坐标系,各轴的彼此正交vlook=XMVector3Normalize(vlook);// look X rightvup=XMVector3Cross(vlook, vright);vup=XMVector3Normalize(vup);vright=XMVector3Cross(vup, vlook);vright=XMVector3Normalize(vright);V=XMMatrixLookAtLH( vpos,vlook, vup);// 生成view矩阵://float x = -D3DXVec3Dot(&_right, &_pos);//float y = -D3DXVec3Dot(&_up, &_pos);//float z = -D3DXVec3Dot(&_look, &_pos);//(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;//(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;//(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;//(*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;}void XCamera::setCameraType(CameraType cameraType){_cameraType = cameraType;}

注释掉的地方是一个坑。为什么呢。

下面就要讲XMVECTOR 和XMFloat3的区别

前者是向量。后者就是一个点结构

前者支持各种运算。差 点  乘 加减

后者 只能赋值啊什么的。是不是特别奇怪。因为XMVECTOR

看源码

// Vector intrinsic: Four 32 bit floating point components aligned on a 16 byte // boundary and mapped to hardware vector registers#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)typedef __m128 XMVECTOR;#else

128位懂了吧。不能随便玩, 不然会报错 涉及到对齐问题

上节说了,全局变量和局部变量可以用XMVECTOR 但是类变量不建议用

偏偏这个摄像机是类变量。作死啊。只有设成XMFloat3了

看源码

// 3D Vector; 32 bit floating point componentstypedef struct _XMFLOAT3{    FLOAT x;    FLOAT y;    FLOAT z;#ifdef __cplusplus    _XMFLOAT3() {};    _XMFLOAT3(FLOAT _x, FLOAT _y, FLOAT _z) : x(_x), y(_y), z(_z) {};    _XMFLOAT3(CONST FLOAT *pArray);    _XMFLOAT3& operator= (CONST _XMFLOAT3& Float3);#endif // __cplusplus

32位的 只能赋值 怎么玩 怎么玩 

上面摄像机类加注释了的函数是之前悲剧了的,我以为Float可以做运算。结果悲剧了。

后来查了一下。 可以用一个转换

XMVECTOR vpos,vright;vpos=XMLoadFloat3(&_pos);vright=XMLoadFloat3(&_right);// 仅在x,z平面移动if( _cameraType == LANDOBJECT )vpos += XMVectorSet(_right.x, 0.0f, _right.z,0.0f) * units;if( _cameraType == AIRCRAFT )vpos += vright * units;XMStoreFloat3(&_pos,vpos);

看懂了吗 看懂了吗。 先load 把float装到vector局部变量  然后进行运算

运算完成后  再store 

是不是很烦

是不是

没办法。目前我只会这样弄。你嫌烦 直接全局变量吧。或者回归dx10math.h 

废话不说 效果图。

只改了walk函数。 其他自己改改吧,锻炼下自己

//(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;//(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;//(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;//(*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;

对了还有上面这个。原教程是直接这样算的一个矩阵,麻烦吧。麻烦吧。 懂不起含义了吧 快看龙书就懂了。懂了之后怎么办。还敲这么多??

V=XMMatrixLookAtLH( vpos,vlook, vup);

一句话搞定,就不要造轮子了

2 0
原创粉丝点击