#pragma once #include #include namespace orange { enum class ProjectionType { Perspective, InfinitePerspective, Orthographic, }; struct Camera { void lookAt(const vec3& position, const vec3& up = {0.0f, 1.0f, 0.0f}) { transform.orientation = conjugate(Math::lookAt(transform.position, position, up)); } void offsetOrientation(const Radian& yaw, const Radian& pitch) { const quat yawRot = angleAxis(yaw, vec3{0.0f, 1.0f, 0.0f}); const quat pitchRot = angleAxis(pitch, right()); transform.orientation = yawRot * pitchRot * transform.orientation; } vec3 forward() const { return transform.orientation * vec3{0.0f, 0.0f, -1.0f}; } vec3 backward() const { return transform.orientation * vec3{0.0f, 0.0f, +1.0f}; } vec3 right() const { return transform.orientation * vec3{+1.0f, 0.0f, 0.0f}; } vec3 left() const { return transform.orientation * vec3{-1.0f, 0.0f, 0.0f}; } vec3 up() const { return transform.orientation * vec3{0.0f, +1.0f, 0.0f}; } vec3 down() const { return transform.orientation * vec3{0.0f, -1.0f, 0.0f}; } mat4 matrix() const { return projection() * view(); } mat4 projection() const { if (projectionType == ProjectionType::Perspective) { return Math::perspective( fieldOfView, viewportAspectRatio, nearPlane, farPlane); } else if (projectionType == ProjectionType::InfinitePerspective) { return Math::infinitePerspective( fieldOfView, viewportAspectRatio, nearPlane); } else if (projectionType == ProjectionType::Orthographic) { const float distance = 0.5f * (farPlane - nearPlane); return Math::ortho( -orthoScale * viewportAspectRatio, orthoScale * viewportAspectRatio, -orthoScale, orthoScale, -distance, distance); } return mat4{}; } mat4 view() const { return Math::scale(vec3{1.0f} / transform.scale) * quaternionToMatrix4(conjugate(transform.orientation)) * Math::translate(-transform.position); } Transform transform = {}; Radian fieldOfView = Degree(90.0f); float orthoScale = 1.0f; float nearPlane = 0.1f; float farPlane = 1024.0f; float viewportAspectRatio = 1.0f; ProjectionType projectionType = ProjectionType::Perspective; }; }