www.pudn.com > notWow.rar > Camera.cpp


#include "Camera.h" 
 
#include "Math.h" 
#include "Input.h" 
extern Mouse			g_Mouse; 
extern Keyboard			g_Keyboard; 
 
bool Frustum::Construct(D3DXMATRIX matProj,D3DXMATRIX matView,float Far,float Near) 
{ 
	D3DXMATRIX Matrix; 
	float      ZMin, Q; 
 
	if(Near != 0.0f ) 
		ZMin = Near; 
	else 
		ZMin = -matProj._43 / matProj._33; 
 
	if(Far != 0.0f)  
	{ 
		// Calculate new projection matrix based on distance provided 
		Q = Far / (Far - ZMin); 
		matProj._33 = Q; 
		matProj._43 = -Q * ZMin; 
	} 
 
	D3DXMatrixMultiply(&Matrix, &matView, &matProj); 
 
	// Calculate the planes 
	m_Planes[0].a = Matrix._14 + Matrix._11; // Left 
	m_Planes[0].b = Matrix._24 + Matrix._21; 
	m_Planes[0].c = Matrix._34 + Matrix._31; 
	m_Planes[0].d = Matrix._44 + Matrix._41; 
	D3DXPlaneNormalize(&m_Planes[0], &m_Planes[0]); 
 
	m_Planes[1].a = Matrix._14 - Matrix._11; // Right 
	m_Planes[1].b = Matrix._24 - Matrix._21; 
	m_Planes[1].c = Matrix._34 - Matrix._31; 
	m_Planes[1].d = Matrix._44 - Matrix._41; 
	D3DXPlaneNormalize(&m_Planes[1], &m_Planes[1]); 
	 
	m_Planes[2].a = Matrix._14 - Matrix._12; // Top 
	m_Planes[2].b = Matrix._24 - Matrix._22; 
	m_Planes[2].c = Matrix._34 - Matrix._32; 
	m_Planes[2].d = Matrix._44 - Matrix._42; 
	D3DXPlaneNormalize(&m_Planes[2], &m_Planes[2]); 
 
	m_Planes[3].a = Matrix._14 + Matrix._12; // Bottom 
	m_Planes[3].b = Matrix._24 + Matrix._22; 
	m_Planes[3].c = Matrix._34 + Matrix._32; 
	m_Planes[3].d = Matrix._44 + Matrix._42; 
	D3DXPlaneNormalize(&m_Planes[3], &m_Planes[3]); 
 
	m_Planes[4].a = Matrix._14 + Matrix._13; // Near 
	m_Planes[4].b = Matrix._24 + Matrix._23; 
	m_Planes[4].c = Matrix._34 + Matrix._33; 
	m_Planes[4].d = Matrix._44 + Matrix._43; 
	D3DXPlaneNormalize(&m_Planes[4], &m_Planes[4]); 
 
	m_Planes[5].a = Matrix._14 - Matrix._13; // Far 
	m_Planes[5].b = Matrix._24 - Matrix._23; 
	m_Planes[5].c = Matrix._34 - Matrix._33; 
	m_Planes[5].d = Matrix._44 - Matrix._43; 
	D3DXPlaneNormalize(&m_Planes[5], &m_Planes[5]); 
 
	return true; 
} 
 
bool Frustum::ConstructForSky(D3DXMATRIX matProj,D3DXMATRIX matView,float Far,float Near,float BottomParam) 
{ 
	D3DXMATRIX Matrix; 
	float      ZMin, Q; 
 
	ZMin = Near; 
	Q = Far / (Far - ZMin); 
	matProj._33 = Q; 
	matProj._43 = -Q * ZMin; 
 
	D3DXMatrixMultiply(&Matrix, &matView, &matProj); 
 
	// Calculate the planes 
	m_Planes[0].a = Matrix._14 + Matrix._11; // Left 
	m_Planes[0].b = Matrix._24 + Matrix._21; 
	m_Planes[0].c = Matrix._34 + Matrix._31; 
	m_Planes[0].d = Matrix._44 + Matrix._41; 
	D3DXPlaneNormalize(&m_Planes[0], &m_Planes[0]); 
 
	m_Planes[1].a = Matrix._14 - Matrix._11; // Right 
	m_Planes[1].b = Matrix._24 - Matrix._21; 
	m_Planes[1].c = Matrix._34 - Matrix._31; 
	m_Planes[1].d = Matrix._44 - Matrix._41; 
	D3DXPlaneNormalize(&m_Planes[1], &m_Planes[1]); 
	 
	m_Planes[2].a = Matrix._14 - Matrix._12; // Top 
	m_Planes[2].b = Matrix._24 - Matrix._22; 
	m_Planes[2].c = Matrix._34 - Matrix._32; 
	m_Planes[2].d = Matrix._44 - Matrix._42; 
	D3DXPlaneNormalize(&m_Planes[2], &m_Planes[2]); 
 
	//						d						b 
	m_Planes[3].a = -Matrix._14 * BottomParam + Matrix._12 ; // Bottom 
	m_Planes[3].b = -Matrix._24 * BottomParam + Matrix._22 ; 
	m_Planes[3].c = -Matrix._34 * BottomParam + Matrix._32 ; 
	m_Planes[3].d = -Matrix._44 * BottomParam + Matrix._42 ; 
	D3DXPlaneNormalize(&m_Planes[3], &m_Planes[3]); 
 
	m_Planes[4].a = Matrix._14 + Matrix._13; // Near 
	m_Planes[4].b = Matrix._24 + Matrix._23; 
	m_Planes[4].c = Matrix._34 + Matrix._33; 
	m_Planes[4].d = Matrix._44 + Matrix._43; 
	D3DXPlaneNormalize(&m_Planes[4], &m_Planes[4]); 
 
	m_Planes[5].a = Matrix._14 - Matrix._13; // Far 
	m_Planes[5].b = Matrix._24 - Matrix._23; 
	m_Planes[5].c = Matrix._34 - Matrix._33; 
	m_Planes[5].d = Matrix._44 - Matrix._43; 
	D3DXPlaneNormalize(&m_Planes[5], &m_Planes[5]); 
 
	return true; 
} 
 
bool Frustum::CheckPoint(float XPos, float YPos, float ZPos) 
{ 
	short i; 
 
	// Make sure point is in frustum 
	for(i=0;i<6;i++)  
	{ 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XPos, YPos, ZPos)) < 0.0f) 
			return false; 
	} 
 
	return true; 
} 
 
bool Frustum::CheckCube(float XCenter, float YCenter, float ZCenter, float Size, bool *CompletelyContained) 
{ 
	short i; 
	DWORD TotalIn = 0; 
 
	// Count the number of points inside the frustum 
	for(i=0;i<6;i++)  
	{ 
 
		DWORD Count = 8; 
		bool  PointIn = true; 
     
		// Test all eight points against plane 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-Size, YCenter-Size, ZCenter-Size)) < 0.0f) 
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter-Size, ZCenter-Size)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-Size, YCenter+Size, ZCenter-Size)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter+Size, ZCenter-Size)) < 0.0f) 
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-Size, YCenter-Size, ZCenter+Size)) < 0.0f)  
		{ 
		PointIn = false; 
		Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter-Size, ZCenter+Size)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-Size, YCenter+Size, ZCenter+Size)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+Size, YCenter+Size, ZCenter+Size)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		// If none contained, return false 
		if(Count == 0) 
		return false; 
 
		// Update counter if they were all in front of plane 
		TotalIn += (PointIn == true) ? 1:0; 
	} 
 
	// Store bool flag if completely contained 
	if(CompletelyContained != NULL) 
		*CompletelyContained = (TotalIn == 6) ? true:false; 
 
	return true; 
} 
 
bool Frustum::CheckRectangle(float XCenter, float YCenter, float ZCenter, float XSize, float YSize, float ZSize, bool *CompletelyContained) 
{ 
	short i; 
 
	DWORD TotalIn = 0; 
 
	// Count the number of points inside the frustum 
	for(i=0;i<6;i++)  
	{ 
		DWORD Count = 8; 
		bool  PointIn = true; 
	     
		// Test all eight points against plane 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, YCenter-YSize, ZCenter-ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize, YCenter-YSize, ZCenter-ZSize)) < 0.0f) 
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, YCenter+YSize, ZCenter-ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize, YCenter+YSize, ZCenter-ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, YCenter-YSize, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize, YCenter-YSize, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, YCenter+YSize, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize, YCenter+YSize, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		// If none contained, return false 
		if(Count == 0) 
			return false; 
 
		// Update counter if they were all in front of plane 
		TotalIn += (PointIn == true) ? 1:0; 
	} 
 
	// Store bool flag if completely contained 
	if(CompletelyContained != NULL) 
		*CompletelyContained = (TotalIn == 6) ? true:false; 
 
	return true; 
} 
 
bool Frustum::CheckPlaneXZ(float XCenter,float ZCenter, float XSize,float ZSize, bool *CompletelyContained) 
{ 
	short i; 
 
	DWORD TotalIn = 0; 
 
	// Count the number of points inside the frustum 
	for(i=0;i<6;i++)  
	{ 
		DWORD Count = 4; 
		bool  PointIn = true; 
	     
		// Test all eight points against plane 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, 0, ZCenter-ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize, 0, ZCenter-ZSize)) < 0.0f) 
		{ 
			PointIn = false; 
			Count--; 
		} 
 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter-XSize, 0, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter+XSize,0, ZCenter+ZSize)) < 0.0f)  
		{ 
			PointIn = false; 
			Count--; 
		} 
 
		// If none contained, return false 
		if(Count == 0) 
			return false; 
 
		// Update counter if they were all in front of plane 
		TotalIn += (PointIn == true) ? 1:0; 
	} 
 
	// Store bool flag if completely contained 
	if(CompletelyContained != NULL) 
		*CompletelyContained = (TotalIn == 6) ? true:false; 
 
	return true; 
 
} 
 
bool Frustum::CheckSphere(float XCenter, float YCenter, float ZCenter, float Radius) 
{ 
	short i; 
 
	// Make sure radius is in frustum 
	for(i=0;i<6;i++)  
	{ 
		if(D3DXPlaneDotCoord(&m_Planes[i], &D3DXVECTOR3(XCenter, YCenter, ZCenter)) < -Radius) 
		return false; 
	} 
	return true; 
} 
 
void Camera::Update(float fTime,float X,float Y,float Z,int Dir) 
{ 
	if(g_Keyboard.GetKeyState(KEY_V)) 
	{ 
		g_Keyboard.SetLock(KEY_V); 
		m_bFPView = !m_bFPView; 
		if(!m_bFPView) 
		{ 
			m_Height = m_Distance = 10.0f; 
		} 
	} 
 
	if(m_bFPView) 
	{ 
		m_Height = 2.0f; 
		m_Distance = 2.0f; 
		m_ZPos = -Math::Sin(Dir); 
		m_XPos = Math::Cos(Dir); 
		m_SkyX = X + m_Sky * m_XPos; 
		m_SkyZ = Z + m_Sky * m_ZPos; 
		m_BGX  = X + m_Background * m_XPos; 
		m_BGZ  = Z + m_Background * m_ZPos; 
		m_XPos = X - m_Distance * m_XPos; 
		m_ZPos = Z - m_Distance * m_ZPos; 
		m_YPos = Y + m_Height; 
		m_BGDir = ( Dir + 180 ) % 360; 
		D3DXVECTOR3 vecEye   = D3DXVECTOR3( m_XPos, m_YPos, m_ZPos); 
		D3DXVECTOR3 vecAt	 = D3DXVECTOR3( X , Y + m_Height , Z ); 
		D3DXVECTOR3 vecUp    = D3DXVECTOR3( 0, 1.0,0); 
		D3DXMatrixLookAtLH( &m_matView, &vecEye, &vecAt, &vecUp ); 
	} 
	else 
	{	 
		float d = (float)g_Mouse.GetDeltaWheel() / 1000; 
		if( !(m_Height < 4.0f && d < 0) && ! (m_Height > 18.0f && d > 0)) 
		{ 
			m_Height += d; 
			m_Distance += d; 
		} 
		m_XPos = Math::Cos(Dir); 
		m_ZPos = -Math::Sin(Dir); 
		m_XPos = X - m_Distance * m_XPos; 
		m_ZPos = Z - m_Distance * m_ZPos; 
		m_YPos = Y + m_Height; 
		D3DXVECTOR3 vecEye   = D3DXVECTOR3( m_XPos, m_YPos, m_ZPos); 
 		D3DXVECTOR3 vecAt	 = D3DXVECTOR3( X , Y+1.0 , Z ); 
 		D3DXVECTOR3 vecUp    = D3DXVECTOR3( X - m_XPos, 1.0, Z - m_ZPos);  
		D3DXMatrixLookAtLH( &m_matView, &vecEye, &vecAt, &vecUp ); 
	}	 
 
	m_matViewProj = m_matView * m_matProj; 
 
	if(m_bFPView) 
	{ 
		m_VisibityFrustum.Construct(m_matProj,m_matView,m_Background); 
		m_BackgroundFrustum.ConstructForSky(m_matProj,m_matView,m_Sky,m_Background,m_SkyPlaneParam); 
	} 
	else 
	{ 
		m_VisibityFrustum.Construct(m_matProj,m_matView); 
	} 
} 
 
 
void Camera::Reset(float Aspect) 
{ 
	float Fov = D3DX_PI/4; 
	D3DXMatrixPerspectiveFovLH(&m_matProj,D3DX_PI/4,Aspect,1.0f,200.0f ); 
	float Tan = Math::Tan(Fov / 2); 
	m_BGHeight = m_Background * Tan * m_SkyPlaneParam; 
	m_SkyY = m_Sky * Tan * m_SkyPlaneParam; 
	m_SkyHeight = m_Sky * Tan; 
	m_SkyHalfWidth = m_Sky * Tan * Aspect + 1.0; 
	m_BGHalfWidth = m_Background * Tan * Aspect + 1.0; 
}