標籤:c++ directx directx11 圖形
現在將重新制定一個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);
一句話搞定,就不要造輪子了
DirectX11 學習筆記7 - 支援自由移動的攝像機