旋转后向右、向上和向前不正确
Incorrect right, up and forward after rotation
我正在使用 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) 的前方。
- 我怎么可能只是滚动而不是倾斜?
- 为什么矩阵乘以点得到正确的结果?
在您的代码中,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
};
我正在使用 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) 的前方。
- 我怎么可能只是滚动而不是倾斜?
- 为什么矩阵乘以点得到正确的结果?
在您的代码中,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
};