mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
huge improvement
This commit is contained in:
@@ -8,8 +8,8 @@
|
||||
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
|
||||
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang.exe",
|
||||
"CMAKE_CXX_COMPILER": "clang++.exe"
|
||||
"CMAKE_C_COMPILER": "cl.exe",
|
||||
"CMAKE_CXX_COMPILER": "cl.exe"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
add_subdirectory(googletest)
|
||||
add_subdirectory(glm)
|
||||
@@ -5,6 +5,8 @@
|
||||
#pragma once
|
||||
#include "omath/Angles.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace omath
|
||||
{
|
||||
@@ -14,14 +16,12 @@ namespace omath
|
||||
Clamped = 1,
|
||||
};
|
||||
|
||||
template<class Type, Type min = 0, Type max = 360, AngleFlags flags = AngleFlags::Normalized>
|
||||
template<class Type, Type min = Type(0), Type max = Type(360), AngleFlags flags = AngleFlags::Normalized>
|
||||
requires std::is_arithmetic_v<Type>
|
||||
class Angle
|
||||
{
|
||||
Type m_angle;
|
||||
public:
|
||||
|
||||
constexpr explicit Angle(const Type& degrees)
|
||||
constexpr Angle(const Type& degrees)
|
||||
{
|
||||
if constexpr (flags == AngleFlags::Normalized)
|
||||
m_angle = angles::WrapAngle(degrees, min, max);
|
||||
@@ -34,17 +34,20 @@ namespace omath
|
||||
std::unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
[[nodiscard]]
|
||||
constexpr static Angle FromDegrees(const Type& degrees)
|
||||
{
|
||||
return {degrees};
|
||||
}
|
||||
constexpr Angle() : m_angle(0)
|
||||
{
|
||||
|
||||
}
|
||||
[[nodiscard]]
|
||||
constexpr static Angle FromRadians(const Type& degrees)
|
||||
{
|
||||
return {angles::RadiansToDegrees(degrees)};
|
||||
return {angles::RadiansToDegrees<Type>(degrees)};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -54,23 +57,11 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Type& operator*()
|
||||
constexpr Type AsDegrees() const
|
||||
{
|
||||
return m_angle;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const Type& Value() const
|
||||
{
|
||||
return **std::as_const(this);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Type& Value()
|
||||
{
|
||||
return **this;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Type AsRadians() const
|
||||
{
|
||||
@@ -86,7 +77,7 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
Type Cos() const
|
||||
{
|
||||
return std::sin(AsRadians());
|
||||
return std::cos(AsRadians());
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -108,13 +99,13 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle& operator+=(const Type& other)
|
||||
constexpr Angle& operator+=(const Angle& other)
|
||||
{
|
||||
if constexpr (flags == AngleFlags::Normalized)
|
||||
m_angle = angles::WrapAngle(m_angle + other, min, max);
|
||||
m_angle = angles::WrapAngle(m_angle + other.m_angle, min, max);
|
||||
|
||||
else if constexpr (flags == AngleFlags::Clamped)
|
||||
m_angle = std::clamp(m_angle + other, min, max);
|
||||
m_angle = std::clamp(m_angle + other.m_angle, min, max);
|
||||
else
|
||||
{
|
||||
static_assert(false);
|
||||
@@ -125,19 +116,22 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle& operator-=(const Type& other)
|
||||
constexpr std::partial_ordering operator<=>(const Angle& other) const = default;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle& operator-=(const Angle& other)
|
||||
{
|
||||
return operator+=(-other);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle& operator+(const Type& other)
|
||||
constexpr Angle& operator+(const Angle& other)
|
||||
{
|
||||
if constexpr (flags == AngleFlags::Normalized)
|
||||
return {angles::WrapAngle(m_angle + other, min, max)};
|
||||
return {angles::WrapAngle(m_angle + other.m_angle, min, max)};
|
||||
|
||||
else if constexpr (flags == AngleFlags::Clamped)
|
||||
return {std::clamp(m_angle + other, min, max)};
|
||||
return {std::clamp(m_angle + other.m_angle, min, max)};
|
||||
|
||||
else
|
||||
static_assert(false);
|
||||
@@ -146,11 +140,9 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Angle& operator-(const Type& other)
|
||||
constexpr Angle& operator-(const Angle& other)
|
||||
{
|
||||
return operator+(-other);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace omath::angles
|
||||
{
|
||||
template<class Type>
|
||||
requires std::is_floating_point_v<Type>
|
||||
[[nodiscard]] constexpr float RadiansToDegrees(const Type& radians)
|
||||
[[nodiscard]] constexpr Type RadiansToDegrees(const Type& radians)
|
||||
{
|
||||
return radians * (Type(180) / std::numbers::pi_v<Type>);
|
||||
}
|
||||
|
||||
template<class Type>
|
||||
requires std::is_floating_point_v<Type>
|
||||
[[nodiscard]] constexpr float DegreesToRadians(const Type& degrees)
|
||||
[[nodiscard]] constexpr Type DegreesToRadians(const Type& degrees)
|
||||
{
|
||||
return degrees * (std::numbers::pi_v<Type> / Type(180));
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include "Vector3.hpp"
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include "Angles.hpp"
|
||||
#include "Vector3.hpp"
|
||||
|
||||
|
||||
namespace omath
|
||||
@@ -33,7 +33,10 @@ namespace omath
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
constexpr static MatStoreType GetStoreOrdering()
|
||||
{
|
||||
return StoreType;
|
||||
}
|
||||
constexpr Mat(const std::initializer_list<std::initializer_list<Type>>& rows)
|
||||
{
|
||||
if (rows.size() != Rows)
|
||||
@@ -133,8 +136,8 @@ namespace omath
|
||||
|
||||
// Operator overloading for multiplication with another Mat
|
||||
template<size_t OtherColumns>
|
||||
constexpr Mat<Rows, OtherColumns, Type, StoreType> operator*(
|
||||
const Mat<Columns, OtherColumns, Type, StoreType>& other) const
|
||||
constexpr Mat<Rows, OtherColumns, Type, StoreType>
|
||||
operator*(const Mat<Columns, OtherColumns, Type, StoreType>& other) const
|
||||
{
|
||||
Mat<Rows, OtherColumns, Type, StoreType> result;
|
||||
|
||||
@@ -158,8 +161,8 @@ namespace omath
|
||||
}
|
||||
|
||||
template<size_t OtherColumns>
|
||||
constexpr Mat<Rows, OtherColumns, Type, StoreType> operator*=(
|
||||
const Mat<Columns, OtherColumns, Type, StoreType>& other)
|
||||
constexpr Mat<Rows, OtherColumns, Type, StoreType>
|
||||
operator*=(const Mat<Columns, OtherColumns, Type, StoreType>& other)
|
||||
{
|
||||
return *this = *this * other;
|
||||
}
|
||||
@@ -306,8 +309,7 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 4> ToScreenMat(const Type& screenWidth, const Type& screenHeight) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
return {
|
||||
{screenWidth / 2, 0, 0, 0},
|
||||
{0, -screenHeight / 2, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
@@ -318,8 +320,7 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 4> TranslationMat(const Vector3& diff) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
@@ -331,8 +332,7 @@ namespace omath
|
||||
constexpr static Mat<4, 4> OrientationMat(const Vector3& forward, const Vector3& right,
|
||||
const Vector3& up) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
return {
|
||||
{right.x, up.x, forward.x, 0},
|
||||
{right.y, up.y, forward.y, 0},
|
||||
{right.z, up.z, forward.z, 0},
|
||||
@@ -341,42 +341,46 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 4> ProjectionMat(const Type& fieldOfView, const Type& aspectRatio,
|
||||
const Type& near, const Type& far, const Type& lensZoom) noexcept
|
||||
constexpr static Mat<4, 4> ProjectionMat(const Type& fieldOfView, const Type& aspectRatio, const Type& near,
|
||||
const Type& far, const Type& lensZoom) noexcept
|
||||
{
|
||||
const Type& fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2);
|
||||
const Type& frustumHeight = far - near;
|
||||
|
||||
return
|
||||
{
|
||||
{-1 / (aspectRatio * fovHalfTan) * lensZoom, 0, 0, 0},
|
||||
return {{-1 / (aspectRatio * fovHalfTan) * lensZoom, 0, 0, 0},
|
||||
{0, -1 / fovHalfTan * lensZoom, 0, 0},
|
||||
{0, 0, -far / frustumHeight, -1},
|
||||
{0, 0, near * far / frustumHeight, 0}
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 1> MatRowFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
return {{vector.x, vector.y, vector.z, 1}};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<1, 4> MatColumnFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
vector.x,
|
||||
vector.y,
|
||||
vector.z,
|
||||
1
|
||||
}
|
||||
};
|
||||
{0, 0, near * far / frustumHeight, 0}};
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<Type, Rows * Columns> m_data;
|
||||
};
|
||||
|
||||
template<class T = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<1, 4, T, St> MatRowFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
return {{vector.x, vector.y, vector.z, 1}};
|
||||
}
|
||||
|
||||
template<class T = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 1, T, St> MatColumnFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
return {
|
||||
{vector.x}, {vector.y}, {vector.z}, {1}};
|
||||
}
|
||||
|
||||
template<class T = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
constexpr Mat<4, 4, T, St> MatTranslation(const Vector3& diff) noexcept
|
||||
{
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{diff.x, diff.y, diff.z, 1},
|
||||
};
|
||||
}
|
||||
} // namespace omath
|
||||
|
||||
@@ -216,10 +216,6 @@ namespace omath
|
||||
|
||||
[[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const;
|
||||
|
||||
[[nodiscard]] static Vector3 ForwardVector(float pitch, float yaw);
|
||||
[[nodiscard]] static Vector3 RightVector(float pitch, float yaw, float roll);
|
||||
[[nodiscard]] static Vector3 UpVector(float pitch, float yaw, float roll);
|
||||
|
||||
[[nodiscard]] std::tuple<float, float, float> AsTuple() const
|
||||
{
|
||||
return std::make_tuple(x, y, z);
|
||||
|
||||
@@ -2,34 +2,14 @@
|
||||
// Created by Orange on 11/30/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <__algorithm/clamp.h>
|
||||
|
||||
#include "omath/Angles.hpp"
|
||||
|
||||
|
||||
namespace omath
|
||||
{
|
||||
template<class Type, Type min = 0, Type max = 360>
|
||||
requires std::is_arithmetic_v<Type>
|
||||
class ViewAngles
|
||||
template<class PitchType, class YawType, class RollType>
|
||||
struct ViewAngles
|
||||
{
|
||||
Type pitch;
|
||||
Type yaw;
|
||||
Type roll;
|
||||
|
||||
constexpr void SetPitch(const Type& newPitch)
|
||||
{
|
||||
pitch = std::clamp(newPitch, min, max);
|
||||
}
|
||||
void SetYaw(const Type& newYaw)
|
||||
{
|
||||
yaw = std::clamp(newYaw, min, max);
|
||||
}
|
||||
void SetRoll(const Type& newRoll)
|
||||
{
|
||||
roll = angles::WrapAngle(newRoll, min, max);
|
||||
}
|
||||
|
||||
PitchType pitch;
|
||||
YawType yaw;
|
||||
RollType roll;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
// Created by Orange on 11/24/2024.
|
||||
//
|
||||
#pragma once
|
||||
#include "omath/Vector3.hpp"
|
||||
#include "omath/Mat.hpp"
|
||||
#include "omath/Vector3.hpp"
|
||||
|
||||
#include <omath/Angle.hpp>
|
||||
#include <omath/ViewAngles.hpp>
|
||||
#include <omath/projection/Camera.hpp>
|
||||
|
||||
namespace omath::source
|
||||
{
|
||||
@@ -11,22 +15,119 @@ namespace omath::source
|
||||
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>;
|
||||
|
||||
|
||||
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)
|
||||
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::COLUMN_MAJOR> ViewMatrixFromVecs(const Vector3& forward, const Vector3& right,
|
||||
const Vector3& up, const Vector3& camera_pos)
|
||||
{
|
||||
return MatTranslation<float, MatStoreType::COLUMN_MAJOR>(-camera_pos) * 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},
|
||||
{0, 0, 0, 1},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
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 ViewAngles& angles, const Vector3& cam_origin)
|
||||
{
|
||||
return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), 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 Type& fieldOfView, const Type& aspectRatio, const Type& near, const Type& far)
|
||||
{
|
||||
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2);
|
||||
|
||||
return
|
||||
{
|
||||
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
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
#include <omath/Vector3.hpp>
|
||||
#include <omath/Mat.hpp>
|
||||
#include <omath/Vector3.hpp>
|
||||
#include "ErrorCodes.hpp"
|
||||
#include <omath/Angle.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace omath::projection
|
||||
@@ -18,29 +20,60 @@ namespace omath::projection
|
||||
float m_width;
|
||||
float m_height;
|
||||
|
||||
[[nodiscard]] constexpr float AspectRatio() const {return m_width / m_height;}
|
||||
[[nodiscard]] constexpr float AspectRatio() const
|
||||
{
|
||||
return m_width / m_height;
|
||||
}
|
||||
};
|
||||
|
||||
template<class ViewAnglesType, class ViewMatFunc, class ProjectionFunc>
|
||||
requires std::is_same_v<std::invoke_result_t<ViewMatFunc, const ViewAnglesType&, const Vector3&>,
|
||||
std::invoke_result_t<ProjectionFunc, const float&, const float&, const float&, const float&>>
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort,
|
||||
float fov, float near, float far, float lensZoom);
|
||||
void SetViewAngles(const Vector3& viewAngles);
|
||||
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) :
|
||||
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
|
||||
m_viewAngles(viewAngles), m_origin(position), CreateViewMatrix(viewMatFunc), CreateProjectionMatrix(projFunc)
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] Mat<4, 4> GetViewMatrix() const;
|
||||
void LookAt(const Vector3& target);
|
||||
|
||||
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Vector3& worldPosition) const;
|
||||
[[nodiscard]] auto GetViewMatrix() const
|
||||
{
|
||||
return CreateViewMatrix(m_viewAngles, m_origin);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto GetProjectionMatrix() const
|
||||
{
|
||||
return CreateProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen([[maybe_unused]] const Vector3& worldPosition) const
|
||||
{
|
||||
using mat = std::invoke_result_t<ViewMatFunc, const ViewAnglesType&, const Vector3&>;
|
||||
const auto vecAsMatrix = MatColumnFromVector<float, mat::GetStoreOrdering()>(worldPosition);
|
||||
|
||||
const auto projected = GetViewMatrix().Transposed() * vecAsMatrix;
|
||||
|
||||
|
||||
return Vector3{projected.At(0,0), projected.At(1,0), projected.At(2,0)};
|
||||
}
|
||||
|
||||
ViewPort m_viewPort{};
|
||||
float m_fieldOfView;
|
||||
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
|
||||
|
||||
float m_farPlaneDistance;
|
||||
float m_nearPlaneDistance;
|
||||
float m_lensZoom;
|
||||
|
||||
private:
|
||||
Vector3 m_viewAngles;
|
||||
ViewAnglesType m_viewAngles;
|
||||
Vector3 m_origin;
|
||||
|
||||
std::function<ViewMatFunc> CreateViewMatrix;
|
||||
std::function<ProjectionFunc> CreateProjectionMatrix;
|
||||
};
|
||||
}
|
||||
} // namespace omath::projection
|
||||
|
||||
@@ -20,50 +20,4 @@ namespace omath
|
||||
0.f
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 Vector3::ForwardVector(const float pitch, const float yaw)
|
||||
{
|
||||
const auto cosPitch = std::cos(angles::DegreesToRadians(pitch));
|
||||
const auto sinPitch = std::sin(angles::DegreesToRadians(pitch));
|
||||
|
||||
const auto cosYaw = std::cos(angles::DegreesToRadians(yaw));
|
||||
const auto sinYaw = std::sin(angles::DegreesToRadians(yaw));
|
||||
|
||||
|
||||
return
|
||||
{
|
||||
cosPitch*cosYaw,
|
||||
cosPitch*sinYaw,
|
||||
sinPitch
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 Vector3::RightVector(const float pitch, const float yaw, const float roll)
|
||||
{
|
||||
const auto radPitch = angles::DegreesToRadians(pitch);
|
||||
const auto radYaw = angles::DegreesToRadians(yaw);
|
||||
const auto radRoll = angles::DegreesToRadians(roll);
|
||||
|
||||
const auto cosPitch = std::cos(radPitch);
|
||||
const auto sinPitch = std::sin(radPitch);
|
||||
|
||||
const auto cosYaw = std::cos(radYaw);
|
||||
const auto sinYaw = std::sin(radYaw);
|
||||
|
||||
const auto cosRoll = std::cos(radRoll);
|
||||
const auto sinRoll = std::sin(radRoll);
|
||||
|
||||
|
||||
return
|
||||
{
|
||||
sinRoll*sinPitch*cosYaw + cosRoll*sinYaw,
|
||||
sinRoll*sinPitch*sinYaw - cosRoll*cosYaw,
|
||||
-sinRoll*cosPitch
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 Vector3::UpVector(float pitch, float yaw, float roll)
|
||||
{
|
||||
return RightVector(pitch, yaw, roll).Cross(ForwardVector(pitch, yaw));
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
#include "omath/prediction/Projectile.hpp"
|
||||
#include <cmath>
|
||||
|
||||
#include <omath/engines/Source.hpp>
|
||||
|
||||
namespace omath::prediction
|
||||
{
|
||||
Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
|
||||
{
|
||||
auto currentPos = m_origin + Vector3::ForwardVector(pitch, yaw) * m_launchSpeed * time;
|
||||
auto currentPos = m_origin + omath::source::ForwardVector({source::PitchAngle::FromDegrees(pitch), source::YawAngle::FromDegrees(yaw), source::RollAngle::FromDegrees(0)}) * m_launchSpeed * time;
|
||||
currentPos.z -= (gravity * m_gravityScale) * std::pow(time, 2.f) * 0.5f;
|
||||
|
||||
return currentPos;
|
||||
|
||||
@@ -6,49 +6,4 @@
|
||||
|
||||
namespace omath::projection
|
||||
{
|
||||
Camera::Camera(const Vector3 &position, const Vector3 &viewAngles, const ViewPort &viewPort,
|
||||
const float fov, const float near, const float far, const float lensZoom)
|
||||
{
|
||||
m_origin = position;
|
||||
m_viewAngles = viewAngles;
|
||||
m_viewPort = viewPort;
|
||||
m_fieldOfView = fov;
|
||||
m_nearPlaneDistance = near;
|
||||
m_farPlaneDistance = far;
|
||||
m_lensZoom = lensZoom;
|
||||
}
|
||||
|
||||
Mat<4, 4> Camera::GetViewMatrix() const
|
||||
{
|
||||
const auto forward = Vector3::ForwardVector(m_viewAngles.x, m_viewAngles.y);
|
||||
const auto right = Vector3::RightVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z);
|
||||
const auto up = Vector3::UpVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z);
|
||||
|
||||
return Mat<>::TranslationMat(-m_origin) * Mat<>::OrientationMat(forward, right, up);
|
||||
}
|
||||
|
||||
std::expected<Vector3, Error> Camera::WorldToScreen(const Vector3& worldPosition) const
|
||||
{
|
||||
const auto posVecAsMatrix = Mat<>::MatColumnFromVector(worldPosition);
|
||||
|
||||
|
||||
const auto projectionMatrix = Mat<>::ProjectionMat(m_fieldOfView, m_viewPort.AspectRatio(),
|
||||
m_nearPlaneDistance, m_farPlaneDistance, m_lensZoom);
|
||||
|
||||
Mat<1, 4> projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix);
|
||||
|
||||
if (projected.At(0, 3) == 0.f)
|
||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||
|
||||
projected /= projected.At(0, 3);
|
||||
|
||||
if (projected.At(0, 0) < -1.f || projected.At(0, 0) > 1.f ||
|
||||
projected.At(0, 1) < -1.f || projected.At(0, 1) > 1.f ||
|
||||
projected.At(0, 2) < -1.f || projected.At(0, 2) > 1.f)
|
||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||
|
||||
projected *= Mat<4, 4>::ToScreenMat(m_viewPort.m_width, m_viewPort.m_height);
|
||||
|
||||
return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ add_executable(unit-tests
|
||||
general/UnitTestLineTrace.cpp
|
||||
general/UnitTestAngles.cpp
|
||||
general/UnitTestViewAngles.cpp
|
||||
general/UnitTestAngle.cpp
|
||||
|
||||
engines/UnitTestOpenGL.cpp
|
||||
engines/UnitTestUnityEngine.cpp
|
||||
@@ -24,6 +25,6 @@ add_executable(unit-tests
|
||||
|
||||
)
|
||||
|
||||
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath glm)
|
||||
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath)
|
||||
|
||||
gtest_discover_tests(unit-tests)
|
||||
@@ -7,17 +7,17 @@
|
||||
#include <print>
|
||||
#include <omath/engines/OpenGL.hpp>
|
||||
#include <omath/engines/Source.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
// #include <glm/glm.hpp>
|
||||
|
||||
#include "glm/ext/matrix_clip_space.hpp"
|
||||
#include "glm/ext/matrix_transform.hpp"
|
||||
// #include "glm/ext/matrix_clip_space.hpp"
|
||||
// #include "glm/ext/matrix_transform.hpp"
|
||||
|
||||
|
||||
TEST(UnitTestOpenGL, Projection)
|
||||
{
|
||||
|
||||
const auto proj_glm = glm::perspective(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||
const auto proj_glm2 = glm::perspectiveLH_NO(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||
/*const auto proj_glm = glm::perspective(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||
// const auto proj_glm2 = glm::perspectiveLH_NO(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||
// const auto proj_omath = omath::Mat<4, 4, float, omath::MatStoreType::COLUMN_MAJOR>((const float*)&proj_glm);
|
||||
// EXPECT_EQ(omath::opengl::PerspectiveProjectionMatrix(90, 16.f / 9.f, 0.1f, 1000.f), proj_omath);
|
||||
|
||||
@@ -34,7 +34,7 @@ TEST(UnitTestOpenGL, Projection)
|
||||
|
||||
//auto ndc_omath = proj_omath * cords_omath;
|
||||
// ndc_omath /= ndc_omath.At(3, 0);
|
||||
|
||||
*/
|
||||
}
|
||||
TEST(UnitTestOpenGL, Projection2)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,29 @@
|
||||
//
|
||||
// Created by Orange on 11/27/2024.
|
||||
// Created by Orange on 11/23/2024.
|
||||
//
|
||||
#include <gtest/gtest.h>
|
||||
#include <omath/engines/Source.hpp>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TEST(UnitTestSourceEngine, ForwardVector)
|
||||
{
|
||||
const auto forward = omath::source::ForwardVector({});
|
||||
|
||||
EXPECT_EQ(forward, omath::source::kAbsForward);
|
||||
}
|
||||
|
||||
TEST(UnitTestSourceEngine, RightVector)
|
||||
{
|
||||
const auto right = omath::source::RightVector({});
|
||||
|
||||
EXPECT_EQ(right, omath::source::kAbsRight);
|
||||
}
|
||||
|
||||
TEST(UnitTestSourceEngine, UpVector)
|
||||
{
|
||||
const auto up = omath::source::UpVector({});
|
||||
EXPECT_EQ(up, omath::source::kAbsUp);
|
||||
}
|
||||
3
tests/general/UnitTestAngle.cpp
Normal file
3
tests/general/UnitTestAngle.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
//
|
||||
// Created by Orange on 11/30/2024.
|
||||
//
|
||||
@@ -4,16 +4,15 @@
|
||||
#include <complex>
|
||||
#include <gtest/gtest.h>
|
||||
#include <omath/Matrix.hpp>
|
||||
#include <print>
|
||||
#include <omath/engines/Source.hpp>
|
||||
#include <omath/projection/Camera.hpp>
|
||||
#include <print>
|
||||
|
||||
TEST(UnitTestProjection, Projection)
|
||||
{
|
||||
const omath::projection::Camera camera({0.f, 0.f, 0.f}, {0, 0.f, 0.f} , {1920.f, 1080.f}, 110.f, 0.375f, 5000.f, 1.335f);
|
||||
auto x = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::FromDegrees(90.f);
|
||||
auto cam = omath::source::CreateCamera({-10, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.1f, 1000.f);
|
||||
|
||||
const auto projected = camera.WorldToScreen({5000, 0, 0});
|
||||
|
||||
|
||||
EXPECT_TRUE(projected.has_value());
|
||||
EXPECT_EQ(projected->z, 1.f);
|
||||
const auto projected = cam.WorldToScreen({10, 0, 0});
|
||||
std::print("{} {} {}", projected->x, projected->y, projected->z);
|
||||
}
|
||||
Reference in New Issue
Block a user