Last active
March 5, 2024 14:23
-
-
Save davidfoster/6d01f61d7476ed077e8225672340591c to your computer and use it in GitHub Desktop.
Understanding Quaternions Programmatically
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// deconstruct our rotation into angle/axis formation. | |
float rotationAngle; | |
Vector3 rotationAxis; | |
transform.rotation.ToAngleAxis(out rotationAngle, out rotationAxis); | |
// construct a new rotation from axis and angle. | |
// Qv,θ = |v * sin(θ/2), cos(θ/2)|, where v = axis, θ = angle in radians. | |
float sinThetaOver2 = Mathf.Sin((rotationAngle * Mathf.Deg2Rad) / 2f); | |
float cosThetaOver2 = Mathf.Cos((rotationAngle * Mathf.Deg2Rad) / 2f); | |
Quaternion newRotation = new Quaternion( | |
rotationAxis.x * sinThetaOver2, | |
rotationAxis.y * sinThetaOver2, | |
rotationAxis.z * sinThetaOver2, | |
cosThetaOver2 | |
); | |
// these quaternions are now the same. | |
Debug.Log(transform.rotation == newRotation); | |
// we can now deconstruct our new rotation to find our axis and angle. | |
// Q.w = cos(θ/2) => θ = arcos(Q.w * 2). | |
float theta = (Mathf.Acos(newRotation.w) * 2f) * Mathf.Rad2Deg; | |
// these angles are now the same. | |
Debug.Log(rotationAngle == theta); | |
// and now work out the axis using the known angle. | |
// Qx = vx * sin(θ/2) => vx = Qx / sin(θ/2). | |
Vector3 axis = new Vector3( | |
newRotation.x / (Mathf.Sin((theta * Mathf.Deg2Rad) / 2f)), | |
newRotation.y / (Mathf.Sin((theta * Mathf.Deg2Rad) / 2f)), | |
newRotation.z / (Mathf.Sin((theta * Mathf.Deg2Rad) / 2f)) | |
); | |
// note that there is a special case where the axis should point right if the rotation is identity, in which case the above | |
// calculations resolve NaN. | |
if (newRotation == Quaternion.identity) { | |
axis = Vector3.right; | |
} | |
// these axes are now the same. | |
Debug.Log(rotationAxis == axis); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment