DirectX11 学习笔记7 - 支持自由移动的摄像机
阅读原文时间:2023年07月13日阅读:2

如今将又一次制定一个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
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);

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

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3EzNjExMDYzMDY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器