因为浅墨的摄像机有镜头倾斜的问题,根据评论对其做了一些改变,最终可以让镜头不倾斜了。
具体改动的函数是绕上向量旋转的函数。将绕上向量旋转改为绕Y轴旋转即可。因为根据人的视觉习惯是绕Y轴旋转的。
//-----------------------------------------------------------------------------
//沿上分量旋转fAngle个弧度单位的角度
//-----------------------------------------------------------------------------
void CameraClass::RotationUpVec(float fAngle)
{
D3DXMATRIX R;
D3DXMatrixRotationY(&R, fAngle); //创建出绕Y轴旋转fAngle个单位的R矩阵
D3DXVec3TransformCoord(&m_vUpVector, &m_vUpVector, &R); //让m_vUpVector向量绕Y轴旋转fAngle个角度
D3DXVec3TransformCoord(&m_vRightVector, &m_vRightVector, &R); //让m_vRightVector向量绕Y轴旋转fAngle个角度
D3DXVec3TransformCoord(&m_vLookVector, &m_vLookVector, &R); //让m_vLookVector向量绕Y轴旋转fAngle个角度
float length = D3DXVec3Length(&(m_vTargetPosition - m_vCameraPosition));
m_vTargetPosition = m_vCameraPosition + m_vLookVector * length; //更新一下观察点的新位置
}
运行结果:
源代码Camera.h:
//*****************************************************************************************
//封装了虚拟摄像机类的头文件
//*****************************************************************************************
#pragma once
#include <d3d9.h>
#include <d3dx9.h>
#include "D3DUtil.h"
class CameraClass
{
private:
//成员变量的声明
D3DXVECTOR3 m_vRightVector; //右分量向量
D3DXVECTOR3 m_vUpVector; //上分量向量
D3DXVECTOR3 m_vLookVector; //观察方向分量
D3DXVECTOR3 m_vCameraPosition; //摄像机位置的向量
D3DXVECTOR3 m_vTargetPosition; //目标观察位置的向量
D3DXMATRIX matView; //取景变换矩阵
D3DXMATRIX matProj; //投影变换矩阵
LPDIRECT3DDEVICE9 m_pd3dDevice; //Direct3D设备对象
private:
void CalculateViewMatrix(D3DMATRIX *pMatrix); //计算取景变换矩阵
void VectorNormalize(); //先把3个向量都规范化并使其相互垂直,成为一组正交矩阵
public:
//构造函数和析构函数
CameraClass(LPDIRECT3DDEVICE9 pd3dDevice); //构造函数
~CameraClass(void); //析构函数
//三个Get系列函数
void GetProjMatrix(D3DMATRIX *pMatrix) {*pMatrix = 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(D3DMATRIX *pMatrix = NULL); //设置投影变换矩阵
void SetProjMatrix(D3DMATRIX *pMatrix = NULL); //设置投影变换矩阵
//沿各分量平移的三个函数
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向量旋转
};
Camera.cpp:
//=============================================================================
//封装了实现虚拟摄像机类的源文件
//=============================================================================
#include "CameraClass.h"
//-----------------------------------------------------------------------------
//构造函数
//-----------------------------------------------------------------------------
CameraClass::CameraClass(LPDIRECT3DDEVICE9 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)
}
//根据给定的矩阵计算出取景变换矩阵
void CameraClass::CalculateViewMatrix(D3DMATRIX *pMatrix)
{
//创建出取景变换矩阵
//依次写出取景变换矩阵的第一行
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;
}
//-----------------------------------------------------------------------------
//先把3个向量都规范化并使其相互垂直,成为一组正交矩阵
//-----------------------------------------------------------------------------
void CameraClass::VectorNormalize()
{
D3DXVec3Cross(&m_vUpVector, &m_vLookVector, &m_vRightVector); //上向量与观察向量垂直
D3DXVec3Normalize(&m_vUpVector, &m_vUpVector); //规范化上向量
}
//-----------------------------------------------------------------------------
//设置摄像机的观察位置
//-----------------------------------------------------------------------------
void CameraClass::SetTargetPosition(D3DXVECTOR3 *pLookAt)
{
//先看看pLookat是否为默认值NULL
if(pLookAt)
m_vTargetPosition = *pLookAt;
m_vLookVector = m_vTargetPosition - m_vCameraPosition; //观察点位置减摄像机目标位置,得到观察方向向量
D3DXVec3Normalize(&m_vLookVector, &m_vLookVector); //规范化m_vLookVector向量
VectorNormalize(); //正交并规范化三个向量
}
//-----------------------------------------------------------------------------
//设置摄像机的位置
//-----------------------------------------------------------------------------
void CameraClass::SetCameraPosition(