#include"D3DCamera.h"
#pragma comment(lib, "d3dx9.lib")
CCamera::CCamera()
:m_Eye(D3DXVECTOR3(0.0f, 0.0f, 0.0f)),
m_At(D3DXVECTOR3(0.0f, 0.0f, 0.0f)),
m_Up(D3DXVECTOR3(0.0f, 0.0f, 0.0f)),
m_vDelta(D3DXVECTOR3(0.0f, 0.0f, 0.0f)),
m_fFOV(0.0f),
m_fAspect(0.0f),
m_fNear(0.0f),
m_fFar(0.0f),
m_fCameraYawAngle(0.0f),
m_fCameraPitchAngle(0.0f),
m_fRotationYVelocity(0.0f),
m_fRotationXVelocity(0.0f),
m_fTranslationVelocity(0.0f),
m_fMaxXPitch(D3DX_PI * 0.1f),
m_fMinXPitch(-(D3DX_PI * 0.1f)),
m_bIsRot(false)
{
m_LastPoint.x = 0;
m_LastPoint.y = 0;
}
CCamera::~CCamera(){}
void CCamera::InitCamera(
D3DXVECTOR3 &Eye,
D3DXVECTOR3 &At,
D3DXVECTOR3 &Up,
float FOV,
float Aspect,
float Near,
float Far,
float RotationYVelocity,
float RotationXVelocity,
float TranslationVelocity,
float MaxXPitch,
float MinXPitch)
{
//得到相关参数
m_Eye = Eye;
m_At = At;
m_Up = Up;
m_fFOV = FOV;
m_fAspect = Aspect;
m_fNear = Near;
m_fFar = Far;
m_fRotationYVelocity = RotationYVelocity;
m_fRotationXVelocity = RotationXVelocity;
m_fTranslationVelocity = TranslationVelocity;
m_fMaxXPitch = MaxXPitch;
m_fMinXPitch = MinXPitch;
//得到视图变换矩阵
D3DXMatrixLookAtLH(&m_ViewTransMatrix, &m_Eye, &m_At, &m_Up);
//得到投影变换矩阵
D3DXMatrixPerspectiveFovLH(&m_ProjTransMatrix, m_fFOV, m_fAspect, m_fNear, m_fFar);
//根据矩阵到欧拉角转换公式, 其中h、p、b分别是绕Y轴、X轴、Z轴旋转的角位移
// | cos(h)cos(b)+sin(h)sin(p)sin(b) sin(b)cos(p) -sin(h)cos(b)+cos(h)sin(p)sin(b)|
//M(世界坐标系->视图坐标系) = |-cos(h)sin(b)+sin(h)sin(p)cos(b) cos(b)cos(p) sin(b)sin(h)+cos(h)sin(p)cos(b)|
// | sin(h)cos(p) -sin(p) cos(h)cos(p) |
//根据矩阵到欧拉角转换公式得到摄像机绕Y轴旋转的欧拉角
m_fCameraYawAngle = atan2f(((D3DXVECTOR3*)(&m_ProjTransMatrix._31))->x, ((D3DXVECTOR3*)(&m_ProjTransMatrix._31))->z);
//根据矩阵到欧拉角转换公式得到摄像机绕X轴旋转的欧拉角
m_fCameraPitchAngle = asinf(-(((D3DXVECTOR3*)(&m_ProjTransMatrix._31))->y));
}
const D3DXMATRIX* CCamera::GetViewTransMatrix() const
{
//返回当前的视图变换矩阵
return &m_ViewTransMatrix;
}
const D3DXMATRIX* CCamera::GetProjTransMatrix() const
{
//返回当前的投影变换矩阵
return &m_ProjTransMatrix;
}
const D3DXVECTOR3* CCamera::GetEye() const
{
//返回当前的摄像机位置
return &m_Eye;
}
void CCamera::GetKeyboardInput(float transVelocity)
{
//设置当前摄象机三个方向上的平移量都为0
m_vDelta = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
if(GetKeyState('W') & 0x8000)
m_vDelta.z += m_fTranslationVelocity*transVelocity;
else if(GetKeyState('S') & 0x8000)
m_vDelta.z -= m_fTranslationVelocity*transVelocity;
if(GetKeyState('A') & 0x8000)
m_vDelta.x -= m_fTranslationVelocity*transVelocity;
else if(GetKeyState('D') & 0x8000)
m_vDelta.x += m_fTranslationVelocity*transVelocity;
}
void CCamera::Update(/*D3DXMATRIX& m_ViewTransMatrix*/)
{
POINT ptCurrentPos = {0, 0}; ///上次移动的位置
POINT ptDeltaPos = {0, 0}; ///偏移量
//得到当前光标位置
GetCursorPos(&ptCurrentPos);
//得到当前光标位置相对于上次光标位置的X轴偏移量
ptDeltaPos.x = ptCurrentPos.x - m_LastPoint.x;
//得到当前光标位置相对于上次光标位置的Y轴偏移量
ptDeltaPos.y = ptCurrentPos.y - m_LastPoint.y;
//设置上次光标位置为当前光标位置
m_LastPoint = ptCurrentPos;
//根据X轴偏移量得到摄像机绕Y轴旋转的欧拉角偏移量, 用结果递增欧拉角
m_fCameraYawAngle += ptDeltaPos.x * m_fRotationYVelocity;
//根据Y轴偏移量得到摄像机绕X轴旋转的欧拉角偏移量, 用结果递增欧拉角, 有最大角和最小角限定
if(m_fCameraPitchAngle + ptDeltaPos.y * m_fRotationXVelocity > m_fMinXPitch &&
m_fCameraPitchAngle + ptDeltaPos.y * m_fRotationXVelocity < m_fMaxXPitch)
m_fCameraPitchAngle += ptDeltaPos.y * m_fRotationXVelocity;
//根据摄像机的欧拉角Yaw、欧拉角Pitch计算旋转矩阵, 此旋转矩阵是视图变换矩阵中旋转部分的逆矩阵
D3DXMATRIX matCameraRot;
ZeroMemory(&matCameraRot, sizeof(D3DXMATRIX));
D3DXMatrixRotationYawPitchRoll(&matCameraRot, m_fCameraYawAngle, m_fCameraPitchAngle, 0.0f);
//得到摄像机的本地坐标轴方向向量经过旋转后在世界坐标系中的方向
D3DXVECTOR3 vWorldY, vWorldZ;
D3DXVECTOR3 vLocalY = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
D3DXVECTOR3 vLocalZ = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
D3DXVec3TransformCoord(&vWorldY, &vLocalY, &matCameraRot);
D3DXVec3TransformCoord(&vWorldZ, &vLocalZ, &matCameraRot);
//得到摄像机的本地坐标轴偏移量经过旋转后在世界坐标系中的偏移量
D3DXVECTOR3 vWorldDelta;
D3DXVec3TransformCoord(&vWorldDelta, &m_vDelta, &matCameraRot);
//得到摄象机位置
m_Eye += vWorldDelta;
//得到摄象机观察点
m_At = m_Eye + vWorldZ;
//更新视矩阵
D3DXMatrixLookAtLH(&m_ViewTransMatrix, &m_Eye, &m_At, &vWorldY);
}
//设置摄象机距阵应用
void CCamera::SetMatrix(LPDIRECT3DDEVICE9 pDevice)
{
//为有效的设备对象
if(pDevice)
{
//设置摄象机视图转化
pDevice->SetTransform(D3DTS_VIEW, &m_ViewTransMatrix);
//设置摄象机投影转化
pDevice->SetTransform(D3DTS_PROJECTION, &m_ProjTransMatrix);
}
}