作者在21章结尾的原话是:
“细心的朋友们应该可以发现,这个程序运行起来还是有一点小问题的,当我们对摄像机进行旋转操作时,视图有时候会发生倾斜,如果对于飞行射击游戏,这样的倾斜是完全没问题的,但是如果是做CF,CS,鬼泣这类的第一人称的游戏的话,那就不应该发生这样的视觉倾斜了。
摄像机之所以发生倾斜是因为我们构造的摄像机的几个分量是两两之间互相垂直的。要想解决这样的问题,就需要保证每次进行摄像机的左右旋转时,是绕着垂直于世界坐标系的轴的向量,而这根轴的向量就是世界坐标系的Y轴。这是我们以后待完成的工作了。”
作者随口一说又不放出例子可是害苦我等小白了,弄了一天无果去作者大神的CSDN博客看到热心同学的留言,算是解决这个问题:
看了半小时鼠标晃动地面倾斜的问题,其实正常情况下左右移动应该是所有三个方向向量按世界坐标的Y周旋转,而不是摄像机的局部的Y轴。另外CalculateViewMatrix里面那些单位化长度,几个再相互算正交都是没必要的,只要变形的结果对,就不需要这些。这个函数这样改就可以了。
VOID CameraClass::RotationUpVec(FLOAT fAngle)
{
D3DXMATRIX R;
FLOAT length = D3DXVec3Length(&(m_vTargetPosition - m_vCameraPosition));
D3DXMatrixRotationY(&R, fAngle);
//左右旋转的时候一般情况下只能绕着世界坐标Y轴转而不是本地Y -- m_vRightVector,避免X方向产生Y坐标,导致地面倾斜,这个可以作为地震崩塌之类的特效吧,呵呵
D3DXVec3TransformCoord(&m_vUpVector, &m_vUpVector, &R);
D3DXVec3TransformCoord(&m_vLookVector, &m_vLookVector, &R);
D3DXVec3TransformCoord(&m_vRightVector, &m_vRightVector, &R);
m_vTargetPosition = m_vCameraPosition + m_vLookVector * length;
}
把以上函数替换源码中的同名函数后,晃动鼠标视角再也不会出现水平方向上倾斜的问题了。
数据成员说明:
//成员变量的声明
D3DXVECTOR3m_vRightVector; // 右分量向量
D3DXVECTOR3m_vUpVector; // 上分量向量
D3DXVECTOR3m_vLookVector; // 观察方向向量
D3DXVECTOR3m_vCameraPosition; // 摄像机位置的向量
D3DXVECTOR3m_vTargetPosition; //目标观察位置的向量
D3DXMATRIXm_matView; // 取景变换矩阵
D3DXMATRIXm_matProj; // 投影变换矩阵
LPDIRECT3DDEVICE9m_pd3dDevice; //Direct3D设备对象