refactored camera

This commit is contained in:
2024-12-04 04:58:29 +03:00
parent 9c0285e353
commit 0afa20b4e5
16 changed files with 262 additions and 194 deletions

View File

@@ -0,0 +1,22 @@
//
// Created by Orange on 12/4/2024.
//
#pragma once
#include "Constants.h"
#include "omath/projection/Camera.hpp"
namespace omath::source
{
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
{
public:
Camera(const Vector3& position, const ViewAngles& viewAngles,
const projection::ViewPort& viewPort, const Angle<float, 0, 180, AngleFlags::Clamped>& fov, float near, const float far) :
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
{
}
void LookAt(const Vector3& target) override;
[[nodiscard]] Mat4x4 GetViewMatrix() const override;
[[nodiscard]] Mat4x4 GetProjectionMatrix() const override;
};
}

View File

@@ -0,0 +1,24 @@
//
// Created by Orange on 12/4/2024.
//
#pragma once
#include <omath/Vector3.hpp>
#include <omath/Mat.hpp>
#include <omath/Angle.hpp>
#include <omath/ViewAngles.hpp>
namespace omath::source
{
constexpr Vector3 kAbsUp = {0, 0, 1};
constexpr Vector3 kAbsRight = {0, -1, 0};
constexpr Vector3 kAbsForward = {1, 0, 0};
using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
} // namespace omath::source

View File

@@ -0,0 +1,98 @@
//
// Created by Orange on 12/4/2024.
//
#pragma once
#include "Constants.h"
namespace omath::source
{
[[nodiscard]]
inline Vector3 ForwardVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
return {cosPitch * cosYaw, cosPitch * sinYaw, -sinPitch};
}
[[nodiscard]]
inline Vector3 RightVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
const auto cosRoll = angles.roll.Cos();
const auto sinRoll = angles.roll.Sin();
return
{
-1 * sinRoll * sinPitch * cosYaw + -1 * cosRoll * -sinYaw,
-1 * sinRoll * sinPitch * sinYaw + -1 * cosRoll * cosYaw,
-1 * sinRoll * cosPitch
};
}
[[nodiscard]]
inline Vector3 UpVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
const auto cosRoll = angles.roll.Cos();
const auto sinRoll = angles.roll.Sin();
return
{
cosRoll * sinPitch * cosYaw + - sinRoll * -sinYaw,
cosRoll * sinPitch * sinYaw + - sinRoll * cosYaw,
cosRoll * cosPitch,
};
}
[[nodiscard]]
constexpr Mat4x4 ViewMatrixFromVecs(const Vector3& forward, const Vector3& right, const Vector3& up,
const Vector3& camera_pos)
{
return Mat4x4{
{right.x, right.y, right.z, 0},
{up.x, up.y, up.z, 0},
{forward.x, forward.y, forward.z, 0},
{0, 0, 0, 1},
} *
MatTranslation<float, MatStoreType::ROW_MAJOR>(-camera_pos);
}
[[nodiscard]] inline Mat4x4 ViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
{
return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
[[nodiscard]]
inline Mat4x4 PerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far)
{
constexpr auto kMultiplyFactor = 0.75f;
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f) * kMultiplyFactor;
return {
{-1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, -1.f / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, 1, 0},
};
}
} // namespace omath::source

View File

@@ -2,9 +2,10 @@
// Created by Orange on 11/23/2024.
//
#pragma once
#include "omath/Vector3.hpp"
#include "omath/Mat.hpp"
#include "omath/Angle.hpp"
#include "omath/Mat.hpp"
#include "omath/Vector3.hpp"
namespace omath::opengl
{
@@ -14,34 +15,31 @@ namespace omath::opengl
template<class Type = float>
requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> ViewMatrix(const Vector3& forward,
const Vector3& right,
const Vector3& up,
const Vector3& cam_origin)
requires std::is_arithmetic_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> ViewMatrix(const Vector3& forward, const Vector3& right,
const Vector3& up, const Vector3& cam_origin)
{
return
return Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR>
{
{right.x, up.x, -forward.x, 0},
{right.y, up.y, -forward.y, 0},
{right.z, up.z, -forward.z, 0},
{-cam_origin.x, -cam_origin.y, -cam_origin.z, 1},
};
{right.x, right.y, right.z, 0},
{up.x, up.y, up.z, 0},
{-forward.x, -forward.y, -forward.z, 0},
{0, 0, 0, 1},
} * MatTranslation<Type, MatStoreType::COLUMN_MAJOR>(-cam_origin);
}
template<class Type>
requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> PerspectiveProjectionMatrix(
const float fieldOfView, const Type& aspectRatio, const Type& near, const Type& far)
requires std::is_arithmetic_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR>
PerspectiveProjectionMatrix(const float fieldOfView, const Type& aspectRatio, const Type& near, const Type& far)
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2);
return
{
{static_cast<Type>(1) / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, static_cast<Type>(1) / (fovHalfTan), 0, 0},
{0, 0, -(far + near) / (far - near), -(static_cast<Type>(2) * far * near) / (far - near)},
{0, 0, -1, 0},
return {
{static_cast<Type>(1) / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, static_cast<Type>(1) / (fovHalfTan), 0, 0},
{0, 0, -(far + near) / (far - near), -(static_cast<Type>(2) * far * near) / (far - near)},
{0, 0, -1, 0},
};
}
}
} // namespace omath::opengl

View File

@@ -1,135 +0,0 @@
//
// Created by Orange on 11/24/2024.
//
#pragma once
#include "omath/Mat.hpp"
#include "omath/Vector3.hpp"
#include <omath/Angle.hpp>
#include <omath/ViewAngles.hpp>
#include <omath/projection/Camera.hpp>
namespace omath::source
{
constexpr Vector3 kAbsUp = {0, 0, 1};
constexpr Vector3 kAbsRight = {0, -1, 0};
constexpr Vector3 kAbsForward = {1, 0, 0};
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
inline Vector3 ForwardVector(const ViewAngles& angles);
inline Vector3 RightVector(const ViewAngles& angles);
inline Vector3 UpVector(const ViewAngles& angles);
template<class Type = float>
requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
[[nodiscard]] constexpr Mat<4, 4, Type, MatStoreType::ROW_MAJOR> ViewMatrixFromVecs(const Vector3& forward, const Vector3& right,
const Vector3& up, const Vector3& camera_pos)
{
return Mat<4, 4, Type, MatStoreType::ROW_MAJOR>{
{right.x, right.y, right.z, 0},
{up.x, up.y, up.z, 0},
{forward.x, forward.y, forward.z, 0},
{0, 0, 0, 1},
} * MatTranslation<float, MatStoreType::ROW_MAJOR>(-camera_pos) ;
}
template<class Type = float>
requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::ROW_MAJOR> ViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
{
return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
template<class Type>
requires std::is_arithmetic_v<Type> && std::is_signed_v<Type>
[[nodiscard]] Mat<4, 4, Type, MatStoreType::ROW_MAJOR>
PerspectiveProjectionMatrix(const Type& fieldOfView, const Type& aspectRatio, const Type& near, const Type& far)
{
constexpr auto kMultiplyFactor = Type(0.75);
const Type fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2) * kMultiplyFactor;
return {
{-static_cast<Type>(1) / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, -static_cast<Type>(1) / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(static_cast<Type>(2) * far * near) / (far - near)},
{0, 0, 1, 0},
};
}
// Copied from
// https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/mathlib/mathlib_base.cpp#L919
[[nodiscard]]
inline Vector3 ForwardVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
return {cosPitch * cosYaw, cosPitch * sinYaw, -sinPitch};
}
[[nodiscard]]
inline Vector3 RightVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
const auto cosRoll = angles.roll.Cos();
const auto sinRoll = angles.roll.Sin();
return
{
-1 * sinRoll * sinPitch * cosYaw + -1 * cosRoll * -sinYaw,
-1 * sinRoll * sinPitch * sinYaw + -1 * cosRoll * cosYaw,
-1 * sinRoll * cosPitch
};
}
[[nodiscard]]
inline Vector3 UpVector(const ViewAngles& angles)
{
const auto cosPitch = angles.pitch.Cos();
const auto sinPitch = angles.pitch.Sin();
const auto cosYaw = angles.yaw.Cos();
const auto sinYaw = angles.yaw.Sin();
const auto cosRoll = angles.roll.Cos();
const auto sinRoll = angles.roll.Sin();
return
{
cosRoll * sinPitch * cosYaw + - sinRoll * -sinYaw,
cosRoll * sinPitch * sinYaw + - sinRoll * cosYaw,
cosRoll * cosPitch,
};
}
using Camera = omath::projection::Camera<ViewAngles, decltype(ViewMatrix<float>), decltype(PerspectiveProjectionMatrix<float>)>;
// Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
// const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far,
// const std::function<ViewMatFunc>& viewMatFunc, const std::function<ProjectionFunc>& projFunc)
inline Camera CreateCamera(const Vector3& position, const auto& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far)
{
return Camera(position, viewAngles, viewPort, fov, near, far, ViewMatrix<float>, PerspectiveProjectionMatrix<float>);
}
} // namespace omath::source