Skip to content

Instantly share code, notes, and snippets.

@catid
Created November 17, 2019 06:49
Show Gist options
  • Save catid/634b8eb244044d8279082f6ef5b8da33 to your computer and use it in GitHub Desktop.
Save catid/634b8eb244044d8279082f6ef5b8da33 to your computer and use it in GitHub Desktop.
Snippet to rotate around a globe in two axes
/*
RotationFromEulerAngles()
This solves the issue where rotating on one axis and then by another causes
the second rotation to get distorted. Instead the rotation on both axes are
performed at once.
+yaw (radians) rotates the camera clockwise.
+pitch (radians) rotates the camera so it is looking slant-downward.
Coordinate system used by mesh:
(+x, +y, +z) = (+right, +down, +forward)
*/
static Quat RotationFromEulerAngles(float yaw, float pitch)
{
/*
Math review:
Quaternion from axis-angle:
qx = ax * sin(angle / 2)
qy = ay * sin(angle / 2)
qz = az * sin(angle / 2)
qw = cos(angle / 2)
cross(a, b) = |a|*|b|*sin(angle)*(normal vector to a, b)
dot(a, b) = |a|*|b|*cos(angle)
*/
// Signs and offsets are tuning to fix up the coordinate system
yaw += M_PI_FLOAT;
// Half angle for quaternion formula
yaw *= 0.5f;
pitch *= 0.5f;
// Points on sphere chosen by yaw, pitch
Vector3 p_f(cosf(yaw), 0.f, -sinf(yaw));
Vector3 p_t(0.f, -cosf(pitch), -sinf(pitch));
// Calculate cross- and dot-products for quaternion formula
Vector3 c = cross(p_f, p_t);
const float cos_angle = dot(p_f, p_t);
return Quat(c.getX(), c.getY(), c.getZ(), cos_angle);
}
@catid
Copy link
Author

catid commented Nov 17, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment