天行健 君子当自强而不息

设计一个灵活的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.3PitchYawRoll

因为方向向量描述了摄像机相对于世界坐标系的方向,我们必须考虑在使用倾斜(pitch)、偏航(yaw)和滚转(roll)时及时更新方向向量。这其实也是非常简单的。图12.412.512.6分别显示了摄像机的倾斜、偏航和滚转操作。

倾斜(pitch)时,我们需要将uplook向量绕着right向量旋转一定角度。同样的,偏航(yaw)时,我们需要将lookright向量绕着up向量旋转一定角度。最后,滚转(roll)时,我们需要将upright向量绕着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.4WalkingStrafingFlying

当提到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;
    }

posted on 2008-03-30 15:07 lovedday 阅读(1955) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论