D3DXMatrixLookAtLH函数可计算出观察矩阵(取景变换矩阵),当在某一固定点固定摄像机方位时,该函数十分有用,但其用户接口对于一个能够根据用户输入做出响应移动的摄像机来说,就会力不从心。我们可以实现一个Camera类以使我们能够较D3DXMatrixLookAtLH函数对摄像机更好的控制,该类特别适合于飞行模拟器、第一人称视角游戏。
摄像机的4个向量:右向量、上向量、观察向量、位置向量
通过这些向量来定义摄像机相对于世界坐标系的位置和朝向,前3个向量统称为方向向量,方向向量必须是标准正交的(如果一个向量集中的向量都彼此正交,且模为1,则称该向量是标准正交的)。引入这个约束的原因是后面需要将这些向量插入到一个矩阵的某些行中,以使该矩阵成为标准正交矩阵(如果一个矩阵的行向量是标准正交的),标准正交矩阵的一个重要性质是其逆矩阵与其转置矩阵相等。
摄像机的6中变换运算
- 绕向量right的旋转(俯仰,pitch)
- 绕向量up的旋转(偏航,yaw)
- 绕向量look的旋转(滚动,roll)
- 沿向量right方向的扫视(strafe)
- 沿向量up方向的升降(fly)
- 沿向量look的平动
//灵活camera
class Camera
{
public:
enum CameraType
{
LANDOBJECT, //摄像机沿某些特定轴进行移动
AIRCRAFT //摄像机自由移动
};
Camera();
Camera(CameraType cameraType);
~Camera() {};
void Strafe(float units);
void Fly(float units);
void Walk(float units);
void Pitch(float angle);
void Yaw(float angle);
void Roll(float angle);
void GetViewMatrix(D3DXMATRIX* v);
void SetCameraType(CameraType cameraType);
void GetPosition(D3DXVECTOR3& pos);
void SetPosition(D3DXVECTOR3& pos);
void GetRight(D3DXVECTOR3& right);
void GetUp(D3DXVECTOR3& up);
void GetLook(D3DXVECTOR3& look);
private:
CameraType m_cameraType;
D3DXVECTOR3 m_right;
D3DXVECTOR3 m_up;
D3DXVECTOR3 m_look;
D3DXVECTOR3 m_pos;
};
观察矩阵(取景变换)的计算
position向量:
right向量:
up向量:
look向量:
取景变换所解决的问题其实就是世界坐标系中的物体在以摄像机为中心的坐标系中如果进行描述,等价于将世界坐标系中的物体随摄像机一起进行变换,以使摄像机坐标系与世界坐标系完全重合。所以希望变换矩阵V能够实现:
- pV=(0,0,0) 矩阵V将摄像机移至世界坐标系原点
- rV=(1,0,0) 矩阵V将摄像机的right向量与世界坐标系的x轴重合
- uV=(0,1,0) 矩阵V将摄像机的up向量与世界坐标系的y轴重合
- dV=(0,0,1) 矩阵v将摄像机的look向量与世界坐标系的z轴重合
1.平移
2.旋转,我们需要一个3x3的旋转矩阵A以使3个向量与世界坐标系的x,y,z轴重合,该矩阵需要满足以下方程