I'm working on a tool for animating 3D objects, and I've run into an issue that I'm not sure how to solve: There is a rotation gizmo implemented, which works fine. However since it's an animation tool, I need to end up with euler angles after a rotation is performed. And the issue is, since I'm converting to quaternion to perform the rotation along an axis, and then back to euler. At certain angles I end up with flipped signs. (goes up to 180 degrees, and then switches to -180 degrees, and vice versa)
While the rotation looks fine when rendered, the sign flipping causes issues when trying to do the animation interpolation, the object will spin in the opposite direction etc.
The code looks something like this:
local rotation = object:GetQuaternionRotation();
rotation:RotateAroundAxis(direction, mouseDiff);
local newRotation = rotation:ToEuler();
- the direction is a direction vector (x,y,z), when rotating in world space Z direction would be (0, 0, 1) and when rotating in local space the vector is whatever the object's up vector is at that moment in time.
- the mouseDiff is just +- increment based on how much the mouse moved
- and finally RotateAroundAxis looks like this:
function Quaternion:RotateAroundAxis(axis, angle)
-- Calculate half angle
local halfAngle = angle * 0.5
-- Calculate sine and cosine of half angle
local sinHalfAngle = math.sin(halfAngle)
local cosHalfAngle = math.cos(halfAngle)
-- Normalize the axis
axis:Normalize()
local rotationQuat = Quaternion:New(
axis.x * sinHalfAngle,
axis.y * sinHalfAngle,
axis.z * sinHalfAngle,
cosHalfAngle
)
self:Multiply(rotationQuat)
end
I tried just adding the euler values, but that obviously won't work when the direction vector is not axis aligned.
Edit: I understand that quaternions can only represent a spherical rotation, and unlike euler angles can't represent rotation values beyond 360 degrees. Essentially what I'm trying to achieve is continuous rotation past the 360 limit, a sort of cumulative rotation, the same way the gizmos work in Unity/3DS Max etc. I checked some open source libraries, like ImGuizmo, but they don't seem to solve the issue, rather just return a transformation matrix, which again can only store 0-360