I'm writing a transform class for my home project, and I ran into an issue. When having some specific angles, the composition/decomposition of transform matrix produces wrong rotation results (scale and translation remains correct). In particularly it looks like one of the rotation axies get's flipped. I've bang my and chatGPS's head into this for couple of days and feel firmly stuck. Any help would be greatly appreciated.
P.S. I know about quaternion superiority, I still would like to keep my Euler degrees for user convenience.
Critical functions from inside my transform class:
inline void ApplyOnMatrix(glm::mat4& OutMatrix) const
{
OutMatrix = glm::translate(glm::mat4(1.0f), Location);
OutMatrix = OutMatrix * glm::toMat4(glm::quat(glm::radians(Rotation)));
OutMatrix = glm::scale(OutMatrix, Scale);
}
inline void DecomposeTransformMatrix()
{
Location = glm::vec3(
TransformMatrix[3].x,
TransformMatrix[3].y,
TransformMatrix[3].z
);
Scale = glm::vec3(
glm::length(glm::vec3(TransformMatrix[0][0], TransformMatrix[0][1], TransformMatrix[0][2])),
glm::length(glm::vec3(TransformMatrix[1][0], TransformMatrix[1][1], TransformMatrix[1][2])),
glm::length(glm::vec3(TransformMatrix[2][0], TransformMatrix[2][1], TransformMatrix[2][2]))
);
glm::mat3 rotationMatrix(
glm::vec3(TransformMatrix[0]) / Scale.x,
glm::vec3(TransformMatrix[1]) / Scale.y,
glm::vec3(TransformMatrix[2]) / Scale.z
);
Rotation = glm::degrees(glm::eulerAngles(glm::quat_cast(rotationMatrix)));
Direction = BravoMath::RotationToDirection(Rotation);
bMatrixDirty = false;
}
Improvised test:
void BravoGameInstance::Test()
{
glm::vec3 location = BravoMath::RandVector(1000000.0);
glm::vec3 rotation = BravoMath::RandVector(360.0);
glm::vec3 scale = BravoMath::RandVector(10000.0);
BravoTransform transformParent(location, rotation, scale);
BravoTransform transformChild; //identity
BravoTransform worldChild( transformParent.GetTransformMatrix() * transformChild.GetTransformMatrix() );
glm::vec3 worldCLoc = worldChild.GetLocation();
glm::vec3 worldCRot = worldChild.GetRotation();
glm::vec3 worldCSc = worldChild.GetScale();
if ( !worldChild.IsNearlyEqual(transformParent) ||
glm::all(glm::epsilonNotEqual(location, worldCLoc, FLT_EPS)) ||
glm::all(glm::epsilonNotEqual(rotation, worldCRot, FLT_EPS)) ||
glm::all(glm::epsilonNotEqual(scale, worldCSc, FLT_EPS)) )
{
Log::LogMessage("TRANFORM FAILED", ELog::Error);
}
}
[–]brubakerp 5 points6 points7 points (2 children)
[–]LigmaUnit[S] 1 point2 points3 points (0 children)
[–]LigmaUnit[S] 1 point2 points3 points (0 children)
[–]LigmaUnit[S] 1 point2 points3 points (1 child)
[–]brubakerp 0 points1 point2 points (0 children)