//=============================================================================
// Name: CameraClass.h
// Des: 一个封装了实现虚拟摄像机的类的头文件
// 2013年 3月10日 Create by 浅墨
//=============================================================================
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
class CameraClass
{
private:
//成员变量的声明
D3DXVECTOR3 m_vRightVector; // 右分量向量
D3DXVECTOR3 m_vUpVector; // 上分量向量
D3DXVECTOR3 m_vLookVector; // 观察方向向量
D3DXVECTOR3 m_vCameraPosition; // 摄像机位置的向量
D3DXVECTOR3 m_vTargetPosition; //目标观察位置的向量
D3DXMATRIX m_matView; // 取景变换矩阵
D3DXMATRIX m_matProj; // 投影变换矩阵
LPDIRECT3DDEVICE9 m_pd3dDevice; //Direct3D设备对象
public:
//一个计算取景变换的函数
VOID CalculateViewMatrix(D3DXMATRIX *pMatrix); //计算取景变换矩阵
//三个Get系列函数
VOID GetProjMatrix(D3DXMATRIX *pMatrix) { *pMatrix = m_matProj; } //返回当前投影矩阵
VOID GetCameraPosition(D3DXVECTOR3 *pVector) { *pVector = m_vCameraPosition; } //返回当前摄像机位置矩阵
VOID GetLookVector(D3DXVECTOR3 *pVector) { *pVector = m_vLookVector; } //返回当前的观察矩阵
//四个Set系列函数,注意他们参数都有默认值NULL的,调用时不写参数也可以
VOID SetTargetPosition(D3DXVECTOR3 *pLookat = NULL); //设置摄像机的目标观察位置向量
VOID SetCameraPosition(D3DXVECTOR3 *pVector = NULL); //设置摄像机所在的位置向量
VOID SetViewMatrix(D3DXMATRIX *pMatrix = NULL); //设置取景变换矩阵
VOID SetProjMatrix(D3DXMATRIX *pMatrix = NULL); //设置投影变换矩阵
public:
// 沿各分量平移的三个函数
VOID MoveAlongRightVec(FLOAT fUnits); // 沿right向量移动
VOID MoveAlongUpVec(FLOAT fUnits); // 沿up向量移动
VOID MoveAlongLookVec(FLOAT fUnits); // 沿look向量移动
// 绕各分量旋转的三个函数
VOID RotationRightVec(FLOAT fAngle); // 绕right向量选择
VOID RotationUpVec(FLOAT fAngle); // 绕up向量旋转
VOID RotationLookVec(FLOAT fAngle); // 绕look向量旋转
public:
//构造函数和析构函数
CameraClass(IDirect3DDevice9 *pd3dDevice); //构造函数
virtual ~CameraClass(void); //析构函数
};
//=============================================================================
// Name: CameraClass.cpp
// Des: 一个封装了实现虚拟摄像机的类的源文件
// 2013年 3月10日 Create by 浅墨
//=============================================================================
#include "CameraClass.h"
#ifndef WINDOW_WIDTH
#define WINDOW_WIDTH 800 //为窗口宽度定义的宏,以方便在此处修改窗口宽度
#define WINDOW_HEIGHT 600 //为窗口高度定义的宏,以方便在此处修改窗口高度
#endif
//-----------------------------------------------------------------------------
// Desc: 构造函数
//-----------------------------------------------------------------------------
CameraClass::CameraClass(IDirect3DDevice9 *pd3dDevice)
{
m_pd3dDevice = pd3dDevice;
m_vRightVector = D3DXVECTOR3(1.0f, 0.0f, 0.0f); // 默认右向量与X正半轴重合
m_vUpVector = D3DXVECTOR3(0.0f, 1.0f, 0.0f); // 默认上向量与Y正半轴重合
m_vLookVector = D3DXVECTOR3(0.0f, 0.0f, 1.0f); // 默认观察向量与Z正半轴重合
m_vCameraPosition = D3DXVECTOR3(0.0f, 0.0f, -250.0f); // 默认摄像机坐标为(0.0f, 0.0f, -250.0f)
m_vTargetPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f); //默认观察目标位置为(0.0f, 0.0f, 0.0f);
}
//-----------------------------------------------------------------------------
// Name:CameraClass::CalculateViewMatrix( )
// Desc: 根据给定的矩阵计算出取景变换矩阵
//-----------------------------------------------------------------------------
VOID CameraClass::CalculateViewMatrix(D3DXMATRIX *pMatrix)
{
//1.先把3个向量都规范化并使其相互垂直,成为一组正交矩阵
//第一个参数为输出结果,第二个参数为要被规范化的向量
D3DXVec3Normalize(&m_vLookVector, &m_vLookVector); // 规范化观察分量
//计算两个向量的叉乘,第一个参数为输出结果,第二、三个参数为参加叉乘运算的两个向量
D3DXVec3Cross(&m_vUpVector, &m_vLookVector, &m_vRightVector); // 上向量与观察向量垂直
D3DXVec3Normalize(&m_vUpVector, &m_vUpVector); // 规范化上向量
D3DXVec3Cross(&m_vRightVector, &m_vUpVector, &m_vLookVector); // 右向量与上向量垂直
D3DXVec3Normalize(&m_vRightVector, &m_vRightVector); // 规范化右向量
// 2.创建出取景变换矩阵
//依次写出取景变换矩阵的第一行
pMatrix->_11 = m_vRightVector.x; // Rx
pMatrix->_12 = m_vUpVector.x; // Ux
pMatrix->_13 = m_vLookVector.x; // Lx
pMatrix->_14 = 0.0f;
//依次写出取景变换矩阵的第二行
pMatrix->_21 = m_vRightVector.y; // Ry
pMatrix->_22 = m_vUpVector.y; // Uy
pMatrix->_23 = m_vLookVector.y; // Ly
pMatrix->_24 = 0.0f;
//依次写出取景变换矩阵的第三行
pMatrix->_31 = m_vRightVector.z; // Rz
pMatrix->_32 = m_vUpVector.z; // Uz
pMatrix->_33 = m_vLookVector.z; // Lz
pMatrix->_34 = 0.0f;
//依次写出取景变换矩阵的第四行
pMatrix->_41 = -D3DXVec3Dot(&m_vRightVector, &m_vCameraPosition); // -P*R
pMatrix->_42 = -D3DXVec3Dot(&m_vUpVector, &m_vCameraPosition); // -P*U
pMatrix->_43 = -D3DXVec3Dot(&m_vLookVector, &m_vCameraPosition); // -P*L
pMatrix->_44 = 1.0f;
}
//-----------------------------------------------------------------------------
// Name:CameraClass::SetTargetPosition( )
// Desc: 设置摄像机的观察位置
//-----------------------------------------------------------------------------
VOID CameraClass::SetTargetPosition(D3DXVECTOR3 *pLookat)
{
//先看看pLookat是否为默认值NULL
if (pLookat != NULL) m_vTargetPosition = (*pLookat);
else m_vTargetPosition = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
m_vLookVector = m_vTargetPosition - m_vCameraPosition; //观察点位置减摄像机位置,得到观察方向向量
D3DXVec3Normalize(&m_vLookVector, &m_vLookVector); //规范化m_vLookVector向量
//正交并规范化m_vUpVector和m_vRightVector
D3DXVec3Cross(&m_vUpVector, &m_vLookVector, &m_vRightVector);
D3DXVec3Normalize(&m_vUpVector, &m_vUpVector);
D3DXVec3Cross(&m_vRightVector, &m_vUpVector, &m_vLookVector);
D3DXVec3Normalize(&m_vRightVector, &m_vRightVector);
}
//-----------------------------------------------------------------------------
// Name:CameraClass::SetCameraPosition( )
// Desc: 设置摄像机所在的位置
//-----------------------------------------------------------------------------
VOID CameraClass::SetCameraPosition(D3DXVECTOR3 *pVector)
{
D3DXVECTOR3 V = D3DXVECTOR3(0.0f, 0.0f, -250.0f);
m_vCameraPosition = pVector ? (*pVector) : V;//三目运算符,如果pVector为真的话,
//返回*pVector的值(即m_vCameraPosition=*pVector),
//否则返回V的值(即m_vCameraPosition=V)
}
//-----------------------------------------------------------------------------
// Name:CameraClass::SetViewMatrix( )
// Desc: 设置取景变换矩阵
//-----------------------------------------------------------------------------
VOID CameraClass::SetViewMatrix(D3DXMATRIX *pMatrix)
{
//根据pMatrix的值先做一下判断
if (pMatrix) m_matView = *pMatrix;
else CalculateViewMatrix(&m_matView);
m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView);
//把取景变换矩阵的值分下来分别给右分量,上分量,和观察分量
m_vRightVector = D3DXVECTOR3(m_matView._11, m_matView._12, m_matView._13);
m_vUpVector = D3DXVECTOR3(m_matView._21, m_matView._22, m_matView._23);
m_vLookVector = D3DXVECTOR3(m_matView._31, m_matView._32, m_matView._33);
}
//-----------------------------------------------------------------------------
// Name:CameraClass::SetProjMatrix( )
// Desc: 设置投影变换矩阵
//-----------------------------------------------------------------------------
VOID CameraClass::SetProjMatrix(D3DXMATRIX *pMatrix)
{
//判断值有没有,没有的话就计算一下
if (pMatrix != NULL)
m_matProj = *pMatrix;
else
//视截体远景设为30000.0f,这样就不怕看不到远处的物体了
D3DXMatrixPerspectiveFovLH(&m_matProj, D3DX_PI / 4.0f, (float)((double)WINDOW_WIDTH/WINDOW_HEIGHT), 1.0f, 30000.0f);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProj);//设置投影变换矩阵
}
//-----------------------------------------------------------------------------
// Name:CameraClass::MoveAlongRightVec( )
// Desc: 沿右向量平移fUnits个单位
//-----------------------------------------------------------------------------
VOID CameraClass::MoveAlongRightVec(FLOAT fUnits)
{
//直接乘以fUnits的量来累加就行了
m_vCameraPosition += m_vRightVector * fUnits;
m_vTargetPosition += m_vRightVector * fUnits;
}
//-----------------------------------------------------------------------------
// Name:CameraClass::MoveAlongUpVec( )
// Desc: 沿上向量平移fUnits个单位
//-----------------------------------------------------------------------------
VOID CameraClass::MoveAlongUpVec(FLOAT fUnits)
{
//直接乘以fUnits的量来累加就行了
m_vCameraPosition += m_vUpVector * fUnits;
m_vTargetPosition += m_vUpVector * fUnits;
}
//-----------------------------------------------------------------------------
// Name:CameraClass::MoveAlongLookVec( )
// Desc: 沿观察向量平移fUnits个单位
//-----------------------------------------------------------------------------
VOID CameraClass::MoveAlongLookVec(FLOAT fUnits)
{
//直接乘以fUnits的量来累加就行了
m_vCameraPosition += m_vLookVector * fUnits;
m_vTargetPosition += m_vLookVector * fUnits;
}
//-----------------------------------------------------------------------------
// Name:CameraClass::RotationRightVec( )
// Desc: 沿右向量旋转fAngle个弧度单位的角度
//-----------------------------------------------------------------------------
VOID CameraClass::RotationRightVec(FLOAT fAngle)
{
D3DXMATRIX R;
D3DXMatrixRotationAxis(&R, &m_vRightVector, fAngle); //创建出绕m_vRightVector旋转fAngle个角度的R矩阵
//根据矩阵变换一个向量,第一个参数为输出结果,第二个参数为要被变换的向量,第三个参数为用于变换的矩阵
D3DXVec3TransformCoord(&m_vUpVector, &m_vUpVector, &R); //让m_vUpVector向量绕m_vRightVector旋转fAngle个角度
D3DXVec3TransformCoord(&m_vLookVector, &m_vLookVector, &R);//让m_vLookVector向量绕m_vRightVector旋转fAngle个角度
m_vTargetPosition = m_vLookVector * D3DXVec3Length(&m_vCameraPosition);//更新一下观察点的新位置(方向乘以模=向量)
}
//-----------------------------------------------------------------------------
// Name:CameraClass::RotationUpVec( )
// Desc: 沿上向量旋转fAngle个弧度单位的角度
//-----------------------------------------------------------------------------
VOID CameraClass::RotationUpVec(FLOAT fAngle)
{
D3DXMATRIX R;
D3DXMatrixRotationAxis(&R, &m_vUpVector, fAngle); //创建出绕m_vUpVector旋转fAngle个角度的R矩阵
D3DXVec3TransformCoord(&m_vRightVector, &m_vRightVector, &R); //让m_vRightVector向量绕m_vUpVector旋转fAngle个角度
D3DXVec3TransformCoord(&m_vLookVector, &m_vLookVector, &R); //让m_vLookVector向量绕m_vUpVector旋转fAngle个角度
m_vTargetPosition = m_vLookVector * D3DXVec3Length(&m_vCameraPosition);//更新一下观察点的新位置(方向乘以模=向量)
}
//-----------------------------------------------------------------------------
// Name:CameraClass::RotationLookVec( )
// Desc: 沿观察向量旋转fAngle个弧度单位的角度
//-----------------------------------------------------------------------------
VOID CameraClass::RotationLookVec(FLOAT fAngle)
{
D3DXMATRIX R;
D3DXMatrixRotationAxis(&R, &m_vLookVector, fAngle); //创建出绕m_vLookVector旋转fAngle个角度的R矩阵
D3DXVec3TransformCoord(&m_vRightVector, &m_vRightVector, &R); //让m_vRightVector向量绕m_vLookVector旋转fAngle个角度
D3DXVec3TransformCoord(&m_vUpVector, &m_vUpVector, &R); //让m_vUpVector向量绕m_vLookVector旋转fAngle个角度
m_vTargetPosition = m_vLookVector * D3DXVec3Length(&m_vCameraPosition);//更新一下观察点的新位置(方向乘以模=向量)
}
//-----------------------------------------------------------------------------
// Desc: 析构函数
//-----------------------------------------------------------------------------
CameraClass::~CameraClass(void)
{
}
调用:
Objects_Init():
描述:渲染资源初始化函数,在此函数中进行要被渲染的物体的资源的初始化
// 创建并初始化虚拟摄像机
g_pCamera = new CameraClass(g_pd3dDevice);
g_pCamera->SetCameraPosition(&D3DXVECTOR3(0.0f, 200.0f, -300.0f)); //设置摄像机所在的位置
g_pCamera->SetTargetPosition(&D3DXVECTOR3(0.0f, 300.0f, 0.0f)); //设置目标观察点所在的位置
g_pCamera->SetViewMatrix(); //设置取景变换矩阵
g_pCamera->SetProjMatrix(); //设置投影变换矩阵
Direct3D_Update():
描述:不是即时渲染代码但是需要即时调用的,如按键后的坐标的更改,都放在这里
// 沿摄像机各分量移动视角
if (g_pDInput->IsKeyDown(DIK_A)) g_pCamera->MoveAlongRightVec(-0.3f);
if (g_pDInput->IsKeyDown(DIK_D)) g_pCamera->MoveAlongRightVec( 0.3f);
if (g_pDInput->IsKeyDown(DIK_W)) g_pCamera->MoveAlongLookVec( 0.3f);
if (g_pDInput->IsKeyDown(DIK_S)) g_pCamera->MoveAlongLookVec(-0.3f);
if (g_pDInput->IsKeyDown(DIK_R)) g_pCamera->MoveAlongUpVec( 0.3f);
if (g_pDInput->IsKeyDown(DIK_F)) g_pCamera->MoveAlongUpVec(-0.3f);
//沿摄像机各分量旋转视角
if (g_pDInput->IsKeyDown(DIK_LEFT)) g_pCamera->RotationUpVec(-0.003f);
if (g_pDInput->IsKeyDown(DIK_RIGHT)) g_pCamera->RotationUpVec( 0.003f);
if (g_pDInput->IsKeyDown(DIK_UP)) g_pCamera->RotationRightVec(-0.003f);
if (g_pDInput->IsKeyDown(DIK_DOWN)) g_pCamera->RotationRightVec( 0.003f);
if (g_pDInput->IsKeyDown(DIK_Q)) g_pCamera->RotationLookVec( 0.001f);
if (g_pDInput->IsKeyDown(DIK_E)) g_pCamera->RotationLookVec(-0.001f);
//鼠标控制右向量和上向量的旋转
g_pCamera->RotationUpVec(g_pDInput->MouseDX()* 0.001f);
g_pCamera->RotationRightVec(g_pDInput->MouseDY() * 0.001f);
//鼠标滚轮控制观察点收缩操作
static FLOAT fPosZ=0.0f;
fPosZ += g_pDInput->MouseDZ()*0.03f;
//计算并设置取景变换矩阵
D3DXMATRIX matView;
g_pCamera->CalculateViewMatrix(&matView);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);