📄 game_camera.cpp
字号:
#include "Game_User.h"
CCamera::CCamera(LPDIRECT3DDEVICE9 pDevice, LPD3DXVECTOR3 pos)
{
m_bTrackMode = FALSE;
m_pDevice = pDevice;
m_Yaw = 0;
m_Pitch = 0;
m_vPos = *pos;
m_Distance = 200;
m_pCursor = NULL;
//计算屏幕宽度,高度
D3DSURFACE_DESC m_d3dsdBackBuffer;
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
//从设备交换链中取得后台缓冲
m_pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
//取得表面的信息
pBackBuffer->GetDesc( &m_d3dsdBackBuffer );
m_scrWidth = (float)m_d3dsdBackBuffer.Width;
m_scrHeight = (float)m_d3dsdBackBuffer.Height;
}
CCamera::~CCamera()
{
// SAFE_RELEASE(m_pKeyFrameInterpolator);
m_pDevice = NULL;
}
//更新3D变换矩阵
void CCamera::Update3DMatrix(float timeNow)
{
if(m_bTrackMode) UpdateFromTracked(timeNow);
D3DXMATRIX matView;
D3DXVECTOR3 vLookAt;
GetLookAt(&vLookAt);//获得观察点坐标
D3DXMatrixLookAtLH(&matView,&m_vPos,&vLookAt,&D3DXVECTOR3(0,1,0));
m_pDevice->SetTransform(D3DTS_VIEW,&matView);
m_matView = matView;
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,D3DX_PI/4,1.0,1.0f,12000.0f);
m_pDevice->SetTransform(D3DTS_PROJECTION,&matProjection);
m_matProjection = matProjection;
m_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
}
//更新2D变换矩阵
//使用屏幕坐标系(0,0)~(1,1);
void CCamera::Update2DMatrix()
{
// RECT rect;
// m_pDevice->GetScissorRect(&rect);
D3DXMATRIX matOrtho;
D3DXMATRIX matIdentity;
// D3DVIEWPORT9 viewPort;
//Retrieves the viewport parameters currently set for the device.
// m_pDevice->GetViewport(&viewPort);
//设置正交投影矩阵
//m_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
D3DXMatrixOrthoLH(&matOrtho,m_scrWidth ,m_scrHeight, 0.0f, 1000.0f);
D3DXMatrixIdentity(&matIdentity);
m_pDevice->SetTransform(D3DTS_PROJECTION, &matOrtho);
m_pDevice->SetTransform(D3DTS_WORLD, &matIdentity); //WORDTRANS留给各个渲染对象使用
m_pDevice->SetTransform(D3DTS_VIEW, &matIdentity);
}
void CCamera::SetYawPitch(float yaw,float pitch)
{
m_Yaw = yaw;
m_Pitch = pitch;
}
//摄像机绕着观察点旋转,上下偏转
void CCamera::YawPitchAt(float yaw,float pitch)
{
//沿着观察点变化
D3DXVECTOR3 vLookAt;
GetLookAt(&vLookAt); //先保存变换前的焦点坐标
m_Yaw+=yaw; //改变偏位角度
if(m_Pitch-pitch<D3DX_PI/3.0f&& m_Pitch-pitch>-D3DX_PI/2.0f)
//改变仰角
m_Pitch-=pitch;
//跟SetLookAt()做的一样操作
m_vPos.x=vLookAt.x-m_Distance*cosf(m_Pitch)*sinf(m_Yaw); //更新摄像机坐标
m_vPos.y=vLookAt.y-m_Distance*sinf(m_Pitch); //更新摄像机坐标
m_vPos.z=vLookAt.z-m_Distance*cosf(m_Pitch)*cosf(m_Yaw);
} //水平方向角度,仰角
//沿着观察点变换方位
void CCamera::YawPitchPos(float yaw,float pitch)
{
m_Yaw += yaw;
if(m_Pitch+pitch > D3DX_PI*0.49f)
{
m_Pitch = D3DX_PI*0.49f;
return;
}
if(m_Pitch+pitch < -D3DX_PI*0.49f)
{
m_Pitch = -D3DX_PI*0.49f;
return;
}
m_Pitch += pitch;
};
//移动,向前/侧向移动,主要用于自由摄像机
void CCamera::MoveRelative(float dSide,float dForward)
{
D3DXVECTOR3 vDir;//方向向量(单位向量)
D3DXVECTOR3 vSide;//right向量
vDir.x=cosf(m_Pitch)*sinf(m_Yaw);
vDir.y=sinf(m_Pitch);
vDir.z=cosf(m_Pitch)*cosf(m_Yaw);
D3DXVec3Cross(&vSide,&D3DXVECTOR3(0,1,0),&vDir);
if(m_Distance-dForward >0)
{
m_Distance += dForward;
m_vPos += vDir*dForward + vSide*dSide;
}
}
void CCamera::AimTo(D3DVECTOR *pLookAt)
{
D3DVECTOR vDir;
vDir.x=pLookAt->x-m_vPos.x;
vDir.y=pLookAt->y-m_vPos.y;
vDir.z=pLookAt->z-m_vPos.z;
D3DXVec3Normalize((D3DXVECTOR3*)&vDir,(D3DXVECTOR3*)&vDir);
m_Pitch=acos(vDir.y);
if(vDir.z!=0 )
m_Yaw=atan(vDir.z/vDir.x);
else
m_Yaw=D3DX_PI/2;
}
void CCamera::AddRotationKey(float time,float yaw,float pitch)
{
D3DXQUATERNION qX(-sin(pitch/2), 0, 0,cos(pitch/2));
D3DXQUATERNION qY(0,sin(yaw/2), 0, cos(yaw/2));
D3DXKEY_QUATERNION qKey={time,qX*qY};
}
void CCamera::AddRotationKey(float time,const D3DXQUATERNION &vRotation)
{
D3DXKEY_QUATERNION keyV;
keyV.Time=time;
keyV.Value=vRotation;
}
HRESULT CCamera::UpdateFromTracked(float Time)
{ //从轨迹更新摄象机坐标和方向
D3DXQUATERNION R;
D3DXVECTOR3 T;
R.x=-R.x; //GetSRT Bug? 这里可能有问题
R.y=-R.y;
R.z=-R.z;
m_vPos=T;
D3DVECTOR zAixes={ 2*R.x*R.z+2*R.y*R.w,
2*R.y*R.z-2*R.x*R.w,
1-(2*R.x*R.x+2*R.y*R.y)};
m_Yaw=atan2(zAixes.x,zAixes.z);
m_Pitch=asinf(zAixes.y);
return S_OK;
}
void CCamera::GetRayOrigDir(D3DXVECTOR3* vPickRayOrig, D3DXVECTOR3* vPickRayDir, CTerrain* m_pMesh)
{
/*方向矢量
DIRview.x = (2*screenPt.x/screenWidth-1)/projMatrix._m11;
DIRview.y = (2*screenPt.y/screenHeight-1)/projMatrix._m22;
DIRview.z = 1;*/
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
POINT p= m_pCursor->GetPosition();
v.x = ( (2* p.x / m_scrWidth ) - 1) / m_matProjection._11;
v.y = -( (2* p.y / m_scrHeight ) - 1) / m_matProjection._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DXMATRIXA16 matView, m, matWorld;
matWorld = (m_pMesh->m_matWorld);
matView = matWorld * m_matView;
D3DXMatrixInverse( &m, NULL, &matView);
//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig->x = m._41;
vPickRayOrig->y = m._42;
vPickRayOrig->z = m._43;
}
void CCamera::GetRayOrigDirFormTerrain(D3DXVECTOR3* vPickRayOrig, D3DXVECTOR3* vPickRayDir, CTerrain* pTerrain)
{
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
POINT p= m_pCursor->GetPosition();
v.x = ( (2* p.x / m_scrWidth ) - 1) / m_matProjection._11;
v.y = -( (2* p.y / m_scrHeight ) - 1) / m_matProjection._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DXMATRIXA16 matView, m, matWorld;
matWorld = (pTerrain->m_matWorld);
matView = matWorld * m_matView;
D3DXMatrixInverse( &m, NULL, &matView);
//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig->x = m._41;
vPickRayOrig->y = m._42;
vPickRayOrig->z = m._43;
};
void CCamera::GetRayOrigDirFormMesh(D3DXVECTOR3* vPickRayOrig, D3DXVECTOR3* vPickRayDir, CMesh* pMesh)
{
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
POINT p= m_pCursor->GetPosition();
v.x = ( (2* p.x / m_scrWidth ) - 1) / m_matProjection._11;
v.y = -( (2* p.y / m_scrHeight ) - 1) / m_matProjection._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DXMATRIXA16 matView, m, matWorld;
matWorld = (pMesh->m_p1MatMesh);
matView = matWorld * m_matView;
D3DXMatrixInverse( &m, NULL, &matView);
//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig->x = m._41;
vPickRayOrig->y = m._42;
vPickRayOrig->z = m._43;
};
void CCamera::GetRayOrigDirFormSkinMesh(D3DXVECTOR3* vPickRayOrig, D3DXVECTOR3* vPickRayDir, CSkinMesh* pSkinMesh)
{
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
POINT p= m_pCursor->GetPosition();
v.x = ( (2* p.x / m_scrWidth ) - 1) / m_matProjection._11;
v.y = -( (2* p.y / m_scrHeight ) - 1) / m_matProjection._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DXMATRIXA16 matView, m, matWorld;
matWorld = (pSkinMesh->m_matWorld);
matView = matWorld * m_matView;
D3DXMatrixInverse( &m, NULL, &matView);
//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
vPickRayOrig->x = m._41;
vPickRayOrig->y = m._42;
vPickRayOrig->z = m._43;
};
void CCamera::GetRayOrigDir(D3DXVECTOR3* vPickRayOrig, D3DXVECTOR3* vPickRayDir)
{
*vPickRayOrig = m_vPos;
D3DXVECTOR3 v;
POINT p= m_pCursor->GetPosition();
v.x = ( (2* p.x / m_scrWidth ) - 1) / m_matProjection._11;
v.y = -( (2* p.y / m_scrHeight ) - 1) / m_matProjection._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DXMATRIXA16 m;
D3DXMatrixInverse(&m, NULL, &m_matView);
//把上述坐标转换成世界坐标
vPickRayDir->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
vPickRayDir->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
vPickRayDir->z = v.x*m._13 + v.y*m._23 + v.z*m._33;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -