DirectX11 学习笔记7 - 支持自由移动的摄像机
Posted jhcelue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DirectX11 学习笔记7 - 支持自由移动的摄像机相关的知识,希望对你有一定的参考价值。
如今将又一次制定一个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;
然后非常easy吧
然后就是改动摄像机了
先上代码再解说吧
#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 right vup=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 components typedef 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);
一句话搞定。就不要造轮子了
以上是关于DirectX11 学习笔记7 - 支持自由移动的摄像机的主要内容,如果未能解决你的问题,请参考以下文章