added new class

This commit is contained in:
2024-11-30 13:54:06 +03:00
parent a33ee638b9
commit 1fe5e6e276
10 changed files with 280 additions and 47 deletions

View File

@@ -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
View 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);
}
};
}

View File

@@ -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;
}
} }

View File

@@ -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;
} }

View File

@@ -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;

View 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);
}
};
}

View File

@@ -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},
}; };
} }
} }

View File

@@ -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

View File

@@ -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);
}

View File

@@ -0,0 +1,4 @@
//
// Created by Orange on 11/30/2024.
//
#include <omath/ViewAngles.hpp>