设计一个灵活的Camera类(2)

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;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值