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;
}