⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cpp

📁 AABB碰撞检测,目前主流3D游戏必需,希望对大家有帮助
💻 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 + -