Last active
October 8, 2019 22:45
-
-
Save gszauer/c12f5fc0faeb5f21062399d965c8ace0 to your computer and use it in GitHub Desktop.
OrbitCamera
This file contains 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
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles | |
float getRoll(const quat& q) { | |
// roll (x-axis rotation) | |
float sinr_cosp = 2.0f * (q.w * q.x + q.y * q.z); | |
float cosr_cosp = 1.0f - 2.0f * (q.x * q.x + q.y * q.y); | |
return atan2(sinr_cosp, cosr_cosp); | |
} | |
float getPitch(const quat& q) { | |
// pitch (y-axis rotation) | |
float sinp =+ 2.0f * (q.w * q.y - q.z * q.x); | |
if (fabs(sinp) >= 1) { | |
return copysign(3.14159265359f / 2.0f, sinp); // use 90 degrees if out of range | |
} | |
return asin(sinp); | |
} | |
float getYaw(const quat& q) { | |
// yaw (z-axis rotation) | |
float siny_cosp = +2.0 * (q.w * q.z + q.x * q.y); | |
float cosy_cosp = +1.0 - 2.0 * (q.y * q.y + q.z * q.z); | |
return atan2(siny_cosp, cosy_cosp); | |
} | |
struct SceneCamera { | |
vec3 position; | |
float yaw; | |
float pitch; | |
float panSpeed; | |
float zoomSpeed; | |
float rotateSpeed; | |
}; | |
SceneCamera SceneCameraInit(const vec3& position, const vec3& target) { | |
SceneCamera result; | |
result.position = position; | |
quat rotation = lookRotation(target - position, vec3(0, 1, 0)); | |
camera.yaw = getYaw(rotation) * QUAT_RAD2DEG; | |
camera.pitch = getPitch(rotation) * QUAT_RAD2DEG; | |
result.panSpeed = 1.0f; | |
result.zoomSpeed = 1.0f; | |
result.rotateSpeed = 1.0f; | |
return result; | |
} | |
void SceneCameraPan(Camera& camera, const vec2& normalizedMouseDelta) { | |
quat yRot = angleAxis(yaw * QUAT_DEG2RAD, vec3(0, 1, 0)); | |
quat xRot = angleAxis(pitch * QUAT_DEG2RAD, vec3(1, 0, 0)); | |
quat rotation = yRot * xRot; | |
vec3 delta = vec3(normalizedMouse.x, -normalizedMouse.y, 0.0f); | |
delta = rotation * delta; | |
camera.position += delta * camera.panSpeed; | |
} | |
void SceneCameraZoom(Camera& camera, float direction) { | |
quat yRot = angleAxis(yaw * QUAT_DEG2RAD, vec3(0, 1, 0)); | |
quat xRot = angleAxis(pitch * QUAT_DEG2RAD, vec3(1, 0, 0)); | |
quat rotation = yRot * xRot; | |
vec3 forward = rotation * vec3(0, 0, 1); | |
camera.position += forward * camera.zoomSpeed * direction; | |
} | |
void SceneCameraRotate(Camera& camera, const vec2& normalizedMouse) { | |
camera.yaw += normalizedMouse.x * rotateSpeed; | |
camera.pitch += normalizedMouse.y * rotateSpeed; | |
while (yaw > 360.0f) { yaw -= 360.0f; } | |
while (yaw < 0.0f) { yaw += 360.0f; } | |
while (pitch > 360.0f) { pitch -= 360.0f; } | |
while (pitch < 0.0f) { pitch += 360.0f } | |
} | |
mat4 SceneCameraGetLookAtMatrix(const Camera& camera) { | |
quat yRot = angleAxis(yaw * QUAT_DEG2RAD, vec3(0, 1, 0)); | |
quat xRot = angleAxis(pitch * QUAT_DEG2RAD, vec3(1, 0, 0)); | |
quat rotation = yRot * xRot; | |
vec3 forward = rotation * vec3(0, 0, 1); | |
vec3 up = rotation * vec3(0, 1, 0); | |
return lookAt(position, position + forward, up); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment