旋转后右,上,右错误

时间:2018-08-02 19:33:52

标签: opengl coordinate-transformation rotational-matrices

我正在使用OpenGL在我的游戏中添加一个矩阵处理程序,到目前为止,大多数功能都可以使用,但是我似乎不明白如何正确地从旋转矩阵中提取正确,向上和向前的向量。我有以下代码:

glm::mat4 clsMatrixHandler::SetRotation( float a_Pitch, float a_Yaw, float a_Roll )
{
    glm::mat4 l_Rotx;
    glm::mat4 l_Roty;
    glm::mat4 l_Rotz;
    PitchYawRollToXYZMatrices( a_Pitch, a_Yaw, a_Roll, l_Rotx, l_Roty, l_Rotz );
    m_PitchYawRolls.clear( );
    m_PitchYawRolls.push_back( glm::vec3( a_Pitch, a_Yaw, a_Roll ) );
    m_RotationMatrix = l_Rotx * l_Roty * l_Rotz;
    m_Right = glm::vec3( m_RotationMatrix[ 0 ][ 0 ], m_RotationMatrix[ 1 ][ 0 ], m_RotationMatrix[ 2 ][ 0 ] );
    m_Up = glm::vec3( m_RotationMatrix[ 0 ][ 1 ], m_RotationMatrix[ 1 ][ 1 ], m_RotationMatrix[ 2 ][ 1 ] );
    m_Forward = glm::vec3( m_RotationMatrix[ 0 ][ 2 ], m_RotationMatrix[ 1 ][ 2 ], m_RotationMatrix[ 2 ][ 2 ] );
    return m_RotationMatrix;
}

void clsMatrixHandler::PitchYawRollToXYZMatrices( float a_Pitch, float a_Yaw, float a_Roll, glm::mat4& a_rX, glm::mat4& a_rY, glm::mat4& a_rZ )
{
    float l_cPitch = glm::cos( glm::radians( a_Pitch ) );
    float l_sPitch = glm::sin( glm::radians( a_Pitch ) );
    float l_cYaw = glm::cos( glm::radians( a_Yaw ) );
    float l_sYaw = glm::sin( glm::radians( a_Yaw ) );
    float l_cRoll = glm::cos( glm::radians( a_Roll ) );
    float l_sRoll = glm::sin( glm::radians( a_Roll ) );
    a_rX = {
        l_cPitch, -l_sPitch, 0.0f, 0.0f,
        l_sPitch,  l_cPitch, 0.0f, 0.0f,
        0.0f,      0.0f,     1.0f, 0.0f,
        0.0f,      0.0f,     0.0f, 1.0f
    };
    a_rY = {
        l_cYaw, 0.0f, -l_sYaw, 0.0f,
        0.0f,   1.0f,  0.0f,   0.0f,
        l_sYaw, 0.0f,  l_cYaw, 0.0f,
        0.0f,   0.0f,  0.0f,   1.0f
    };
    a_rZ = {
        1.0f, 0.0f,     0.0f,    0.0f,
        0.0f, l_cRoll, -l_sRoll, 0.0f,
        0.0f, l_sRoll,  l_cRoll, 0.0f,
        0.0f, 0.0f,     0.0f,    1.0f
    };
}

void clsMatrixHandler::Test()
{
    float l_Pitch = -90.0f;
    float l_Yaw = 0.0f;
    float l_Roll = 0.0f;
    glm::mat4 l_RotationMatrix = m_MatrixHandler.SetRotation( l_Pitch, l_Yaw, l_Roll );

    std::vector<glm::vec3> l_PYRs = m_MatrixHandler.GetPitchYawRolls( );
    OutputDebugStringA( ( "Pitch: " + std::to_string( l_PYRs[ l_PYRs.size( ) - 1 ].x ) + "\n" +
                          "Yaw: " + std::to_string( l_PYRs[ l_PYRs.size( ) - 1 ].y ) + "\n" +
                          "Roll: " + std::to_string( l_PYRs[ l_PYRs.size( ) - 1 ].z ) + "\n" ).c_str( ) );

    glm::vec4 l_Point = glm::vec4( 10, 0, 0, 0 );
    glm::vec4 l_PointInLocalSpace = l_RotationMatrix * glm::vec4( l_Point.x, l_Point.y, l_Point.z, 0 );

    OutputDebugStringA( ( "New Transformation Matrix: \n" +
                          std::to_string( l_RotationMatrix[ 0 ][ 0 ] ) + ", " + std::to_string( l_RotationMatrix[ 1 ][ 0 ] ) + ", " + std::to_string( l_RotationMatrix[ 2 ][ 0 ] ) + "\n" +
                          std::to_string( l_RotationMatrix[ 0 ][ 1 ] ) + ", " + std::to_string( l_RotationMatrix[ 1 ][ 1 ] ) + ", " + std::to_string( l_RotationMatrix[ 2 ][ 1 ] ) + "\n" +
                          std::to_string( l_RotationMatrix[ 0 ][ 2 ] ) + ", " + std::to_string( l_RotationMatrix[ 1 ][ 2 ] ) + ", " + std::to_string( l_RotationMatrix[ 2 ][ 2 ] ) + "\n"
                          ).c_str( ) );

    OutputDebugStringA( ( "New Point Position: \n" + std::to_string( l_PointInLocalSpace.x ) + ", " + std::to_string( l_PointInLocalSpace.y ) + ", " + std::to_string( l_PointInLocalSpace.z ) + "\n" ).c_str( ) );
}

输出:

Pitch: -90.000000
Yaw: 0.000000
Roll: 0.000000
New Transformation Matrix: 
-0.000000, -1.000000, 0.000000
1.000000, -0.000000, 0.000000
0.000000, 0.000000, 1.000000
New Point Position: 
-0.000000, 10.000000, 0.000000

据我所知,矩阵中的第一行,第二行和第三行是右上,右上的,所以:

Right: 0.0, -1.0, 0.0
Up: 1.0, 0.0, 0.0
Forward: 0.0, 0.0, 1.0

另外,现在-90音高应该指向(0.0,1.0,0.0)的前向。

  1. 我怎么可能只是滚动而不投球?
  2. 为什么将矩阵与点相乘会得到正确的结果?

1 个答案:

答案 0 :(得分:1)

在您的代码中,a_rX计算绕z轴的旋转,a_rZ计算绕x轴的旋转。

要解决您的问题,音高必须为:

a_rX = {
    1.0f, 0.0f,      0.0f,     0.0f,
    0.0f, l_cPitch, -l_sPitch, 0.0f,
    0.0f, l_sPitch,  l_cPitch, 0.0f,      
    0.0f, 0.0f,      0.0f,     1.0f
};

滚动必须是:

a_rZ = {
    l_cRoll, -l_sRoll, 0.0f, 0.0f,
    l_sRoll,  l_cRoll, 0.0f, 0.0f,
    0.0f,     0.0f,    1.0f, 0.0f,
    0.0f,     0.0f,    0.0f, 1.0f
};