📄 camera.cpp
字号:
// Camera.cpp: implementation of the CCamera class.
//
//////////////////////////////////////////////////////////////////////
#include "d3dx9mesh.h"
#include "d3dx9anim.h"
#include "d3dx9.h"
#include "Camera.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCamera::CCamera(LPDIRECT3DDEVICE9 pDevice,
LPD3DXVECTOR3 pos)
{
m_bTrackMode=TRUE;
m_pDevice=pDevice;
m_Yaw=0;
m_Pitch=0;
m_vPos=*pos;
m_Distance=300;
m_pKeyFrameInterpolator=NULL;
TranslateKeys.clear();
RotationKeys.clear();
//计算屏幕宽度,高度
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);
}
//更新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);
D3DXMATRIX matProjection;
D3DXMatrixPerspectiveFovLH(&matProjection,D3DX_PI/4,m_scrWidth/m_scrHeight,1.0f,8000.0f);
m_pDevice->SetTransform(D3DTS_PROJECTION,&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;
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留给各个渲染对象使用
#if SCREENCOORD_MODE==SCREENCOORD_LOWERLEFT
matIdentity._41=-m_scrWidth/2;
matIdentity._42=-m_scrHeight/2;
#else //if SCREENCOORD_MODE==SCREENCOORD_UPPERLEFT
matIdentity._41=-m_scrWidth/2;
matIdentity._42= m_scrHeight/2;
matIdentity._22=-1;
#endif
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<0 && m_Pitch-pitch>-D3DX_PI/3.0f) //改变仰角
m_Pitch-=pitch;
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;
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);
//D3DXVec3Normalize(&vSide,&vSide);
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};
RotationKeys.push_back(qKey);
/*
//This also works!
D3DXQUATERNION q;
D3DXQuaternionRotationYawPitchRoll(&q,yaw,pitch,0);
D3DXKEY_QUATERNION qKey={time,q};
RotationKeys.push_back(qKey);
*/
}
void CCamera::AddRotationKey(float time,const D3DXQUATERNION &vRotation)
{
D3DXKEY_QUATERNION keyV;
keyV.Time=time;
keyV.Value=vRotation;
RotationKeys.push_back(keyV);
}
HRESULT CCamera::UpdateFromTracked(float Time)
{ //从轨迹更新摄象机坐标和方向
D3DXQUATERNION R;
D3DXVECTOR3 T;
//第一次调用时会创建
if(!m_pKeyFrameInterpolator)
{
#if (D3D_SDK_VERSION & 32)
if(D3D_OK!=D3DXCreateKeyframedAnimationSet("InterPolator",
1.0, D3DXPLAY_LOOP,1,0,NULL,&m_pKeyFrameInterpolator))
return E_FAIL;
m_pKeyFrameInterpolator->RegisterAnimationSRTKeys("Camera",0,RotationKeys.size(),
TranslateKeys.size(),NULL,&RotationKeys[0],&TranslateKeys[0],NULL);
#else
if(D3D_OK!=D3DXCreateKeyFrameInterpolator ("InterPolator",0,0,
&RotationKeys[0],RotationKeys.size(),
&TranslateKeys[0],TranslateKeys.size(),1.0f, &m_pKeyFrameInterpolator))
return E_FAIL;
#endif
}
//Time/=1000; //Debug on break point use only
float period=(float)m_pKeyFrameInterpolator->GetPeriod();
float mTime=Time-period*floor(Time/period); //mTime=time%period
#if (D3D_SDK_VERSION & 32)
LRESULT ret=m_pKeyFrameInterpolator->GetSRT(mTime,0,NULL,&R,&T);
#else
LRESULT ret=m_pKeyFrameInterpolator->GetSRT(mTime,NULL,&R,&T);
#endif
R.x=-R.x; //GetSRT Bug? 这里可能有问题
R.y=-R.y;
R.z=-R.z;
m_vPos=T;
//Below is xAixes,yAixes, zAixes of the Rotated coordinate system
//1 - (2Y2 + 2Z2 ) 2XY + 2ZW 2XZ - 2YW
//2XY - 2ZW 1 - (2X2 + 2Z2 ) 2YZ + 2XW
//2XZ + 2YW 2YZ - 2XW 1 - (2X2 + 2Y2 )
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::GetCursorRayDir(POINT ptCursor,D3DVECTOR *vPickRayDir)
{
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,4/3.0f,1.0f,6000.0f);
//计算屏幕空间的坐标(-1,-1)~(1,1)
D3DXVECTOR3 v;
// v.x = ( (-1+2* ptCursor.x / m_scrWidth ) /*- 1*/ ) / matProj._11;
// v.y = ( (-1+2* ptCursor.y / m_scrHeight ) /*- 1*/ ) / matProj._22;
v.x = ( (2* ptCursor.x / m_scrWidth ) /*- 1*/ ) / matProj._11;
v.y = ( (2* ptCursor.y / m_scrHeight ) /*- 1*/ ) / matProj._22;
v.z = 1.0f;
//获得视图变换矩阵的逆矩阵
D3DVECTOR vLookAt;
GetLookAt(&vLookAt);
D3DXMATRIXA16 matView, m;
D3DXMatrixLookAtLH(&matView,(D3DXVECTOR3*)&m_vPos,
(D3DXVECTOR3*)&vLookAt,&D3DXVECTOR3(0,1,0));
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;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -