Orange/include/Orange/Graphics/Camera.h

82 lines
2.8 KiB
C++

#pragma once
#include <Orange/Math/Basic.h>
#include <Orange/Math/Transform.h>
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<quat>(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;
};
}