📄 camera.cpp
字号:
//--------------------------------------------------
// Desc: 摄像机
// Author: artsylee/2006.12.27
//--------------------------------------------------
#include "Common.h"
#include "Camera.h"
#include "Heightmap.h"
extern CHeightmap g_Hmap;
CCamera::CCamera()
{
m_Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_Right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
m_Up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
m_Look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
}
CCamera::~CCamera()
{
}
void CCamera::GetViewMatrix(D3DXMATRIX* V)
{
D3DXVec3Normalize(&m_Look, &m_Look);
D3DXVec3Cross(&m_Up, &m_Look, &m_Right);
D3DXVec3Normalize(&m_Up, &m_Up);
D3DXVec3Cross(&m_Right, &m_Up, &m_Look);
D3DXVec3Normalize(&m_Right, &m_Right);
float x = -D3DXVec3Dot(&m_Right, &m_Position);
float y = -D3DXVec3Dot(&m_Up, &m_Position);
float z = -D3DXVec3Dot(&m_Look, &m_Position);
(*V)(0,0) = m_Right.x; (*V)(0, 1) = m_Up.x; (*V)(0, 2) = m_Look.x; (*V)(0, 3) = 0.0f;
(*V)(1,0) = m_Right.y; (*V)(1, 1) = m_Up.y; (*V)(1, 2) = m_Look.y; (*V)(1, 3) = 0.0f;
(*V)(2,0) = m_Right.z; (*V)(2, 1) = m_Up.z; (*V)(2, 2) = m_Look.z; (*V)(2, 3) = 0.0f;
(*V)(3,0) = x; (*V)(3, 1) = y; (*V)(3, 2) = z; (*V)(3, 3) = 1.0f;
}
void CCamera::MoveLR(float units)
{
m_Position += D3DXVECTOR3(m_Right.x, 0.0f, m_Right.z) * units;
}
void CCamera::MoveUD(float units)
{
m_Position.y += units;
}
void CCamera::MoveFB(float units)
{
m_Position += D3DXVECTOR3(m_Look.x, 0.0f, m_Look.z) * units;
}
void CCamera::RotateRight(float angle)
{
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &m_Right, angle);
D3DXVec3TransformCoord(&m_Up, &m_Up, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
void CCamera::RotateUp(float angle)
{
D3DXMATRIX T;
D3DXMatrixRotationY(&T, angle);
D3DXVec3TransformCoord(&m_Right, &m_Right, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
void CCamera::RotateLook(float angle)
{
// FPS not need
}
//----------------------------------------------------
// 视线在Y=0平面上的投影与+Z轴的角度(0-360)
// 正X轴方向为90度
//----------------------------------------------------
float CCamera::GetRotateYAngle(void)
{
D3DXVECTOR3 pane(m_Look.x, 0.0f, m_Look.z);
D3DXVECTOR3 zxis(0.0f, 0.0f, 1.0f);
float panelen = D3DXVec3Length(&pane);
float zxislen = D3DXVec3Length(&zxis);
float dotValue = D3DXVec3Dot(&pane, &zxis)/panelen/zxislen;
float angle = acos(dotValue)*(float)M_180_PI;
if(m_Look.x<0.0f)
{
angle = 360.0f-angle;
}
return angle;
}
//----------------------------------------------------
// 视线在X=0平面上的投影与+Z轴的角度(0-360)
// 负Y轴方向为90度
//----------------------------------------------------
float CCamera::GetRotateXAngle(void)
{
D3DXVECTOR3 pane(0.0f, m_Look.y, m_Look.z);
D3DXVECTOR3 zxis(0.0f, 0.0f, 1.0f);
float panelen = D3DXVec3Length(&pane);
float zxislen = D3DXVec3Length(&zxis);
float dotValue = D3DXVec3Dot(&pane, &zxis)/panelen/zxislen;
float angle = acos(dotValue)*(float)M_180_PI;
if(m_Look.y>0.0f)
{
angle = 360.0f-angle;
}
return angle;
}
//---------------------------------------------------
// Save position
//---------------------------------------------------
void CCamera::SaveCamera(const char *pFile) const
{
CIniFile posini(pFile);
posini.WriteVec3D("FreeCamera", "Position", D3DToVec3D(m_Position));
posini.WriteVec3D("FreeCamera", "Up", D3DToVec3D(m_Up));
posini.WriteVec3D("FreeCamera", "Right", D3DToVec3D(m_Right));
posini.WriteVec3D("FreeCamera", "Look", D3DToVec3D(m_Look));
posini.Save();
}
//---------------------------------------------------
// Load position
//---------------------------------------------------
void CCamera::LoadCamera(const char *pFile)
{
CIniFile posini(pFile);
m_Position = Vec3DToD3D(posini.ReadVec3D("FreeCamera", "Position"));
m_Up = Vec3DToD3D(posini.ReadVec3D("FreeCamera", "Up"));
m_Right = Vec3DToD3D(posini.ReadVec3D("FreeCamera", "Right"));
m_Look = Vec3DToD3D(posini.ReadVec3D("FreeCamera", "Look"));
}
//---------------------------------------------------
// 第三人称摄像机
//---------------------------------------------------
ModelViewCamera::ModelViewCamera()
{
m_bRotateFromParent = false;
m_bScaleFromParent = false;
SetNodeType(NT_CAMERA);
m_fCameraYawAngle = 0.0f;
m_fCameraPitchAngle = 0.0f;
m_fRadius = 30.0f;
m_vDestination = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_vOffsetParentPos = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
m_Right = D3DXVECTOR3(-1.0f, 0.0f, 0.0f);
m_bCollision = true;
}
ModelViewCamera::~ModelViewCamera()
{
}
void ModelViewCamera::SetCameraRadius(float fRadius)
{
m_fRadius = fRadius;
}
float ModelViewCamera::GetCameraRadius(void)
{
return m_fRadius;
}
void ModelViewCamera::ScaleCameraRadius(float fScale)
{
m_fRadius *= fScale;
}
void ModelViewCamera::SetOffsetParentPos(D3DXVECTOR3 vOffsetPos)
{
m_vOffsetParentPos = vOffsetPos;
}
void ModelViewCamera::GetOffsetParentPos(D3DXVECTOR3 *pOffsetPos)
{
*pOffsetPos = m_vOffsetParentPos;
}
//---------------------------------------------------
// 摄像机绕观察点的Y轴旋转
// (0.0度为指向-Z轴方向)
// (PI/2度为-X轴方向)
//---------------------------------------------------
void ModelViewCamera::RotateUp(float angle)
{
m_fCameraYawAngle += angle;
D3DXMATRIX T;
D3DXMatrixRotationY(&T, angle);
D3DXVec3TransformCoord(&m_Right, &m_Right, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
//---------------------------------------------------
// 摄像机绕观察点的Y轴旋转到指定角度
//---------------------------------------------------
void ModelViewCamera::RotateUpTo(float fDestAngle)
{
float angle = fDestAngle - m_fCameraYawAngle;
m_fCameraYawAngle = fDestAngle;
D3DXMATRIX T;
D3DXMatrixRotationY(&T, angle);
D3DXVec3TransformCoord(&m_Right, &m_Right, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
//---------------------------------------------------
// 摄像机绕观察点上下移动(180度范围内)
// (0.0度为指向-Z轴方向)
// (PI/2度为-Y轴方向)
//---------------------------------------------------
void ModelViewCamera::RotateRight(float angle)
{
if(m_fCameraPitchAngle+angle <= M_PI/2.0f && m_fCameraPitchAngle+angle >= -M_PI/2.0f)
{
m_fCameraPitchAngle += angle;
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &m_Right, angle);
D3DXVec3TransformCoord(&m_Up, &m_Up, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
}
//---------------------------------------------------
// 摄像机绕观察点上下移动到指定角度(180度范围内)
//---------------------------------------------------
void ModelViewCamera::RotateRightTo(float fDestAngle)
{
if(fDestAngle<=M_PI/2.0f && fDestAngle>=-M_PI/2.0f)
{
float angle = fDestAngle - m_fCameraPitchAngle;
m_fCameraPitchAngle = fDestAngle;
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &m_Right, angle);
D3DXVec3TransformCoord(&m_Up, &m_Up, &T);
D3DXVec3TransformCoord(&m_Look, &m_Look, &T);
}
}
//---------------------------------------------------
// TODO here: 暂时不用实现
//---------------------------------------------------
void ModelViewCamera::RotateLook(float angle)
{
}
//---------------------------------------------------
// TODO here: 暂时不用实现
//---------------------------------------------------
void ModelViewCamera::RotateLookTo(float fDestAngle)
{
}
//---------------------------------------------------
// 摄像机的视矩阵
//---------------------------------------------------
void ModelViewCamera::GetViewMatrix(D3DXMATRIX* V)
{
//---------------------------------------------------
while(m_fCameraYawAngle>=AS_PI*2.0f)
{
m_fCameraYawAngle -= AS_PI*2.0f;
}
while(m_fCameraYawAngle<0.0f)
{
m_fCameraYawAngle += AS_PI*2.0f;
}
//---------------------------------------------------
D3DXMATRIX matTan, matRot;
D3DXMatrixTranslation(&matTan, 0.0f, 0.0f, m_fRadius);
D3DXMatrixRotationYawPitchRoll(&matRot, m_fCameraYawAngle, -m_fCameraPitchAngle, 0.0f);
matTan *= matRot;
//D3DXVec3TransformCoord(&m_Position, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &matTan);
// 优化后的代码
m_Position.x = matTan._41;
m_Position.y = matTan._42;
m_Position.z = matTan._43;
if(m_pParent)
{
m_Position = m_pParent->GetDerivedPos() + m_Position;
m_vDestination = m_pParent->GetDerivedPos();
m_vDestination += m_vOffsetParentPos;
}
else
{
m_Position = GetDerivedPos();
}
if(m_bCollision)
{
//---------------------------------------------------
// 限制摄像机的最低高度
float height = g_Hmap.GetHeight(&m_Position);
if(m_Position.y < height + 2.0f)
{
m_Position.y = height + 2.0f;
}
//---------------------------------------------------
}
// 摄像机操作时必须保持m_Right正确
m_Look = m_vDestination - m_Position;
D3DXVec3Normalize(&m_Look, &m_Look);
D3DXVec3Normalize(&m_Right, &m_Right);
D3DXVec3Cross(&m_Up, &m_Look, &m_Right);
D3DXVec3Normalize(&m_Up, &m_Up);
// Update the view matrix
D3DXMatrixLookAtLH(V, &m_Position, &m_vDestination, &m_Up);
}
//---------------------------------------------------
// Save position
//---------------------------------------------------
void ModelViewCamera::SaveCamera(const char *pFile) const
{
CIniFile posini(pFile);
posini.WriteVec3D("ModelViewCamera", "Offset", D3DToVec3D(m_vOffsetParentPos));
posini.WriteVec3D("ModelViewCamera", "Right", D3DToVec3D(m_Right));
posini.WriteFloat("ModelViewCamera", "Yaw_Angle", m_fCameraYawAngle);
posini.WriteFloat("ModelViewCamera", "Pitch_Angle", m_fCameraPitchAngle);
posini.WriteFloat("ModelViewCamera", "Radius", m_fRadius);
posini.Save();
}
//---------------------------------------------------
// Load position
//---------------------------------------------------
void ModelViewCamera::LoadCamera(const char *pFile)
{
CIniFile posini(pFile);
m_vOffsetParentPos = Vec3DToD3D(posini.ReadVec3D("ModelViewCamera", "Offset"));
m_Right = Vec3DToD3D(posini.ReadVec3D("ModelViewCamera", "Right"));
m_fCameraYawAngle = posini.ReadFloat("ModelViewCamera", "Yaw_Angle");
m_fCameraPitchAngle = posini.ReadFloat("ModelViewCamera", "Pitch_Angle");
m_fRadius = posini.ReadFloat("ModelViewCamera", "Radius");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -