I am working on adding a matrix handler in my game using OpenGL, and so far most of it works, but I seem to not understand how to properly extract the right, up and forward vectors out of the rotation matrix. I've got the following code:
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( ) );
}
Output:
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
As far as I know the first, second and third row in the matrix are the right, up and forward, so:
Right: 0.0, -1.0, 0.0
Up: 1.0, 0.0, 0.0
Forward: 0.0, 0.0, 1.0
Also, a -90 pitch should point the forward in (0.0, 1.0, 0.0) now.
In your code a_rX
calculates a rotation around the z-axis, and a_rZ
a rotation around the x-axis.
To solve your issue, pitch has to be:
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
};
and roll has to be:
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
};