Open GeTechG opened 2 years ago
I'm not the dev but What you have right there is called a "singularity". It's not the fault of imguizmo but an inherent flaw in Euler angles. They occur when one of the rotation axes (specifically the second one that's applied) is at or close to 90/-90 degrees. The solution is to store the models rotation as something other than Euler angles. You can use a rotation matrix, axis-angle, or quaternions.
Yes, but that's the result of the DecomposeMatrixToComponents
method, I have trouble understanding how I can turn an imguizmo matrix into what you listed, I would be fine with quaternions.
Yes, the only way out is to switch to matrices or quaternions. But the question of how to defeat singularity is open, because in such editors as unity, unreal, godot, etc. have the ability to change angles via sliders and there is somehow this problem solved.
I found this one - https://euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm, but it doesn't help much, or I did something wrong.
Apologies for not responding before. I dont know unity at all but in unreal engine, all actors use the FTransform struct. It is composed of 2 vectors for Translation and Scale as well ad a quaternion for orientation. So no actor in unreal uses Euler angles. In order to make them actually useful for humans, they have an FRotator struct that represents orientation as Euler angles. Then they have functions that convert back and forth between them. Now I don't know how it works exactly in unreal, but I imagine it works like this:
If you have your GitHub tied to your epic account, you can find the headers in
Engine/Source/Runtime/Core/Public/Math
They're Rotator.h and Quat.h.
The implementations of the functions are in
Engine/Source/Runtime/Core/Private/Math/UnrealMath.cpp
Also here is an article on converting between the two. It's actually not a trivial thing.
That should be enough to get you started. Depending on the math library you're using, it might already have functions for those conversions. Good luck!
@GeTechG Have you find a way to fix this issue on your side? I have the same problem with ImGuizmo.
When I change rotation from my ImGui interface, no problem. Only with the ImGuizmo ROTATE. And I already have quaternion for the renderer. The question is for RecomposeMatrixFromComponents
and DecomposeMatrixToComponents
.
https://user-images.githubusercontent.com/1573282/204129900-972091e4-e4df-458d-8ac6-46d1408451b8.mp4
Okay, I found a solution. Here an example, maybe it can help someone in the futur.
XMFLOAT4X4 tempViewMatrix;
XMStoreFloat4x4(&tempViewMatrix, viewMatrix);
XMFLOAT4X4 tempProjMatrix;
XMStoreFloat4x4(&tempProjMatrix, camComponent.Camera.GetProjMatrix());
XMFLOAT4X4 tempTransformMatrix;
XMStoreFloat4x4(&tempTransformMatrix, transform.GetTransform());
ImGuizmo::SetDrawlist(ImGui::GetBackgroundDrawList());
ImGuizmo::Manipulate(*tempViewMatrix.m, *tempProjMatrix.m, mCurrentGizmoOperation, mCurrentGizmoMode, *tempTransformMatrix.m);
if (ImGuizmo::IsUsing())
{
float Ftranslation[3] = { 0.0f, 0.0f, 0.0f }, Frotation[3] = { 0.0f, 0.0f, 0.0f }, Fscale[3] = { 0.0f, 0.0f, 0.0f };
ImGuizmo::DecomposeMatrixToComponents(*tempTransformMatrix.m, Ftranslation, Frotation, Fscale);
switch (mCurrentGizmoOperation)
{
case ImGuizmo::TRANSLATE:
transform.Translation = DirectX::XMFLOAT3(Ftranslation);
break;
case ImGuizmo::ROTATE:
{
XMMATRIX tempMatrix = XMLoadFloat4x4(&tempTransformMatrix);
XMVECTOR tempVectorMatrix = XMQuaternionRotationMatrix(tempMatrix);
transform.SetRotationQuaternion(tempVectorMatrix);
break;
}
case ImGuizmo::SCALE:
transform.Scale = DirectX::XMFLOAT3(Fscale);
break;
}
}
In case it helps anyone, I encountered the exact same issue but solved it differently: instead of using the DecomposeMatrixToComponents/RecomposeMatrixFromComponents idiom, I only used DecomposeMatrixToComponents and applied the transformations directly to the matrix as my engine is using float4x4 internally.
All axes are fine, but when you rotate the Y axis on the -90 and 90 edges the angle is inverted and does not behave correctly. (In the video Y axis is Z, as I have a different stored rotation)
https://user-images.githubusercontent.com/20752579/169524827-671b3085-a3b5-4ab8-90a3-af6a5088e27d.mp4