12.2.2围绕任意轴旋转
为了实现我们的摄像机旋转方法,我们需要能够绕着任意轴旋转,D3DX库提供下面的函数来解决这个问题:
Builds a matrix that rotates around an arbitrary axis.
D3DXMATRIX * D3DXMatrixRotationAxis( D3DXMATRIX * pOut, CONST D3DXVECTOR3 * pV, FLOAT Angle);
Parameters
- pOut
- [in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
- pV
- [in] Pointer to the arbitrary axis. See D3DXVECTOR3.
- Angle
- [in] Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.
Return Values
Pointer to a D3DXMATRIX structure rotated around the specified axis.
Remarks
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixRotationAxis function can be used as a parameter for another function.
例如,假如我们想绕向量(0.707, 0.707, 0)轴旋转π/2角度。我们可以这样写:
D3DXMATRIX R;
D3DXVECTOR3 axis(0.707f, 0.707f, 0.0f);
D3DXMatrixRotationAxis(&R, &axis, D3DX_PI / 2.0f);
|
12.2.3Pitch、Yaw和Roll
因为方向向量描述了摄像机相对于世界坐标系的方向,我们必须考虑在使用倾斜(pitch)、偏航(yaw)和滚转(roll)时及时更新方向向量。这其实也是非常简单的。图12.4,12.5,12.6分别显示了摄像机的倾斜、偏航和滚转操作。
当倾斜(pitch)时,我们需要将up和look向量绕着right向量旋转一定角度。同样的,当偏航(yaw)时,我们需要将look和right向量绕着up向量旋转一定角度。最后,当滚转(roll)时,我们需要将up和right向量绕着look向量旋转一定角度。
我们现在明白了为什么D3DXMatrixRotationAxis函数是非常必要的,因为这三个向量中的任何一个都可能围绕世界坐标系中的任意轴旋转。
对于倾斜(pitch)、偏航(yaw)和滚转(roll)的执行我们已经讨论了。然而,对于LAND_OBJECT模式就有一些限制。我们在偏航(yaw)方法中只围绕y轴旋转,我们完全屏蔽滚转(roll)。当然你可以根据你的程序需要来改变Camera类。我们这里只是一个示例而已。
倾斜(pitch)、偏航(yaw)和滚转(roll)方法代码的具体实现如下:
void cCamera::pitch(float angle)
{
D3DXMATRIX transform_matrix;
D3DXMatrixRotationAxis(&transform_matrix, &m_right, angle);
// rotate m_up and m_look around m_right vector
D3DXVec3TransformCoord(&m_up, &m_up, &transform_matrix);
D3DXVec3TransformCoord(&m_look, &m_look, &transform_matrix);
}
void cCamera::yaw(float angle)
{
D3DXMATRIX transform_matrix;
// rotate around world y-axis (0, 1, 0) always for land object
if(m_camera_type == LAND_OBJECT)
D3DXMatrixRotationY(&transform_matrix, angle);
else // rotate around own up vector for aircraft
D3DXMatrixRotationAxis(&transform_matrix, &m_up, angle);
// rotate m_right and m_look around m_up or y-axis
D3DXVec3TransformCoord(&m_right, &m_right, &transform_matrix);
D3DXVec3TransformCoord(&m_look, &m_look, &transform_matrix);
}
void cCamera::roll(float angle)
{
// only roll for aircraft type
if(m_camera_type == AIR_CRAFT)
{
D3DXMATRIX transform_matrix;
D3DXMatrixRotationAxis(&transform_matrix, &m_look, angle);
// rotate m_up and m_right around m_look vector
D3DXVec3TransformCoord(&m_up, &m_up, &transform_matrix);
D3DXVec3TransformCoord(&m_right, &m_right, &transform_matrix);
}
}
12.2.4Walking、Strafing和Flying
当提到walking时,我们的意思是在我们观察的方向上移动位置(也就是说,沿着look向量)。Strafing是说在我们观察方向的左右移动,也就是沿着right向量移动。最后,我们说flying就是沿着up向量移动。为了沿着这些轴移动,我们只需要简单地加一个向量就可以了(如图12.7)。
就象旋转一样,我们需要对移动作一些限制。例如,LAND_OBJECT不允许飞起来。因此我们把移动限制在xz平面。然而,因为LAND_OBJECT能够允许爬楼梯和登山,所以,我们设置cCamera::set_position方法,它允许你手动设置你的摄像机位置来达到你的高度和位置。
移动(walk)、平移(strafe)和飞行(fly)方法代码的具体实现如下:
void cCamera::walk(float units)
{
// move only on xz plane for land object
if(m_camera_type == LAND_OBJECT)
m_pos += D3DXVECTOR3(m_look.x, 0.0f, m_look.z) * units;
else // AIR_CRAFT
m_pos += m_look * units;
}
void cCamera::strafe(float units)
{
// move only on xz plane for land object
if(m_camera_type == LAND_OBJECT)
m_pos += D3DXVECTOR3(m_right.x, 0.0f, m_right.z) * units;
else // AIR_CRAFT
m_pos += m_right * units;
}
void cCamera::fly(float units)
{
// move only on y_axis for land object
if(m_camera_type == LAND_OBJECT)
m_pos.y += units;
else
m_pos += m_up * units;
}