mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
added new class
This commit is contained in:
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Please report security issues to `orange-cpp@yandex.com`
|
Please report security issues to `orange-cpp@yandex.ru`
|
||||||
156
include/omath/Angle.hpp
Normal file
156
include/omath/Angle.hpp
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/Angles.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace omath
|
||||||
|
{
|
||||||
|
enum class AngleFlags
|
||||||
|
{
|
||||||
|
Normalized = 0,
|
||||||
|
Clamped = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Type, Type min = 0, Type max = 360, AngleFlags flags = AngleFlags::Normalized>
|
||||||
|
requires std::is_arithmetic_v<Type>
|
||||||
|
class Angle
|
||||||
|
{
|
||||||
|
Type m_angle;
|
||||||
|
public:
|
||||||
|
|
||||||
|
constexpr explicit Angle(const Type& degrees)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
m_angle = angles::WrapAngle(degrees, min, max);
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
m_angle = std::clamp(degrees, min, max);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert(false);
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static Angle FromDegrees(const Type& degrees)
|
||||||
|
{
|
||||||
|
return {degrees};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static Angle FromRadians(const Type& degrees)
|
||||||
|
{
|
||||||
|
return {angles::RadiansToDegrees(degrees)};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr const Type& operator*() const
|
||||||
|
{
|
||||||
|
return m_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Type& operator*()
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return angles::RadiansToDegrees(m_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Sin() const
|
||||||
|
{
|
||||||
|
return std::sin(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Cos() const
|
||||||
|
{
|
||||||
|
return std::sin(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Tan() const
|
||||||
|
{
|
||||||
|
return std::tan(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Atan() const
|
||||||
|
{
|
||||||
|
return std::atan(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Cot() const
|
||||||
|
{
|
||||||
|
return Cos() / Sin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator+=(const Type& other)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
m_angle = angles::WrapAngle(m_angle + other, min, max);
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
m_angle = std::clamp(m_angle + other, min, max);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert(false);
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator-=(const Type& other)
|
||||||
|
{
|
||||||
|
return operator+=(-other);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator+(const Type& other)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
return {angles::WrapAngle(m_angle + other, min, max)};
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
return {std::clamp(m_angle + other, min, max)};
|
||||||
|
|
||||||
|
else
|
||||||
|
static_assert(false);
|
||||||
|
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator-(const Type& other)
|
||||||
|
{
|
||||||
|
return operator+(-other);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -4,21 +4,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
namespace omath::angles
|
namespace omath::angles
|
||||||
{
|
{
|
||||||
template<class type>
|
template<class Type>
|
||||||
requires std::is_floating_point_v<type>
|
requires std::is_floating_point_v<Type>
|
||||||
[[nodiscard]] constexpr float RadiansToDegrees(const type& radians)
|
[[nodiscard]] constexpr float RadiansToDegrees(const Type& radians)
|
||||||
{
|
{
|
||||||
return radians * (type(180) / std::numbers::pi_v<type>);
|
return radians * (Type(180) / std::numbers::pi_v<Type>);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class type>
|
template<class Type>
|
||||||
requires std::is_floating_point_v<type>
|
requires std::is_floating_point_v<Type>
|
||||||
[[nodiscard]] constexpr float DegreesToRadians(const type& degrees)
|
[[nodiscard]] constexpr float DegreesToRadians(const Type& degrees)
|
||||||
{
|
{
|
||||||
return degrees * (std::numbers::pi_v<type> / type(180));
|
return degrees * (std::numbers::pi_v<Type> / Type(180));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class type>
|
template<class type>
|
||||||
@@ -32,14 +34,31 @@ namespace omath::angles
|
|||||||
return RadiansToDegrees(vertFov);
|
return RadiansToDegrees(vertFov);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class type>
|
template<class Type>
|
||||||
requires std::is_floating_point_v<type>
|
requires std::is_floating_point_v<Type>
|
||||||
[[nodiscard]] type VerticalFovToHorizontal(const type& vertFov, const type& aspect)
|
[[nodiscard]] Type VerticalFovToHorizontal(const Type& vertFov, const Type& aspect)
|
||||||
{
|
{
|
||||||
const auto fovRad = DegreesToRadians(vertFov);
|
const auto fovRad = DegreesToRadians(vertFov);
|
||||||
|
|
||||||
const auto horFov = type(2) * std::atan(std::tan(fovRad / type(2)) * aspect);
|
const auto horFov = Type(2) * std::atan(std::tan(fovRad / Type(2)) * aspect);
|
||||||
|
|
||||||
return RadiansToDegrees(horFov);
|
return RadiansToDegrees(horFov);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
requires std::is_arithmetic_v<Type>
|
||||||
|
[[nodiscard]] Type WrapAngle(const Type& angle, const Type& min, const Type& max)
|
||||||
|
{
|
||||||
|
if (angle <= max && angle >= min)
|
||||||
|
return angle;
|
||||||
|
|
||||||
|
const Type range = max - min;
|
||||||
|
|
||||||
|
Type wrappedAngle = std::fmod(angle - min, range);
|
||||||
|
|
||||||
|
if (wrappedAngle < 0)
|
||||||
|
wrappedAngle += range;
|
||||||
|
|
||||||
|
return wrappedAngle + min;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace omath
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<size_t Rows = 0, size_t Columns = 0, class Type = float, MatStoreType StoreType = MatStoreType::ROW_MAJOR>
|
template<size_t Rows = 0, size_t Columns = 0, class Type = float, MatStoreType StoreType = MatStoreType::ROW_MAJOR>
|
||||||
requires (std::is_floating_point_v<Type> || std::is_integral_v<Type>)
|
requires std::is_arithmetic_v<Type>
|
||||||
class Mat final
|
class Mat final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -133,7 +133,8 @@ namespace omath
|
|||||||
|
|
||||||
// Operator overloading for multiplication with another Mat
|
// Operator overloading for multiplication with another Mat
|
||||||
template<size_t OtherColumns>
|
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;
|
Mat<Rows, OtherColumns, Type, StoreType> result;
|
||||||
|
|
||||||
@@ -157,7 +158,8 @@ namespace omath
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OtherColumns>
|
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;
|
return *this = *this * other;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace omath
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
||||||
|
|
||||||
Vector3 m_vertex1;
|
Vector3 m_vertex1;
|
||||||
Vector3 m_vertex2;
|
Vector3 m_vertex2;
|
||||||
Vector3 m_vertex3;
|
Vector3 m_vertex3;
|
||||||
|
|||||||
35
include/omath/ViewAngles.hpp
Normal file
35
include/omath/ViewAngles.hpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ namespace omath::source
|
|||||||
constexpr Vector3 kAbsForward = {1, 0, 0};
|
constexpr Vector3 kAbsForward = {1, 0, 0};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class Type> requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
|
template<class Type> requires std::is_floating_point_v<Type> || std::is_integral_v<Type>
|
||||||
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> PerspectiveProjectionMatrix(
|
[[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> PerspectiveProjectionMatrix(
|
||||||
const float fieldOfView, const Type &aspectRatio, const Type &near, const Type &far)
|
const float fieldOfView, const Type &aspectRatio, const Type &near, const Type &far)
|
||||||
@@ -26,4 +27,6 @@ namespace omath::source
|
|||||||
{0, 0, 1, 0},
|
{0, 0, 1, 0},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ add_executable(unit-tests
|
|||||||
general/UnitTestVector4.cpp
|
general/UnitTestVector4.cpp
|
||||||
general/UnitTestLineTrace.cpp
|
general/UnitTestLineTrace.cpp
|
||||||
general/UnitTestAngles.cpp
|
general/UnitTestAngles.cpp
|
||||||
|
general/UnitTestViewAngles.cpp
|
||||||
|
|
||||||
engines/UnitTestOpenGL.cpp
|
engines/UnitTestOpenGL.cpp
|
||||||
engines/UnitTestUnityEngine.cpp
|
engines/UnitTestUnityEngine.cpp
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//
|
//
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <omath/Angles.hpp>
|
#include <omath/Angles.hpp>
|
||||||
|
#include <omath/Angle.hpp>
|
||||||
|
|
||||||
TEST(UnitTestAngles, RadiansToDeg)
|
TEST(UnitTestAngles, RadiansToDeg)
|
||||||
{
|
{
|
||||||
@@ -36,3 +36,15 @@ TEST(UnitTestAngles, VerticalToHorizontal)
|
|||||||
|
|
||||||
EXPECT_NEAR(horizontalFov, 89.99f, 0.01f);
|
EXPECT_NEAR(horizontalFov, 89.99f, 0.01f);
|
||||||
}
|
}
|
||||||
|
TEST(UnitTestAngles, WrapAngle)
|
||||||
|
{
|
||||||
|
const float wrapped = omath::angles::WrapAngle(361.f, 0.f, 360.f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(wrapped, 1.f, 0.01f);
|
||||||
|
}
|
||||||
|
TEST(UnitTestAngles, WrapAngleNegativeRange)
|
||||||
|
{
|
||||||
|
const float wrapped = omath::angles::WrapAngle(-90.f, 0.f, 360.f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(wrapped, 270.f, 0.01f);
|
||||||
|
}
|
||||||
4
tests/general/UnitTestViewAngles.cpp
Normal file
4
tests/general/UnitTestViewAngles.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
#include <omath/ViewAngles.hpp>
|
||||||
Reference in New Issue
Block a user