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

📄 camera.cpp

📁 3D游戏展示程序
💻 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 + -