diff --git a/CMakeLists.txt b/CMakeLists.txt index b2cab68..3a11eaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ project(omath) set(CMAKE_CXX_STANDARD 26) option(BUILD_TESTS "Build unit tests" ON) - +option(THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to threat them as errors" ON) add_library(omath STATIC source/Vector3.cpp) add_subdirectory(source) @@ -16,4 +16,10 @@ if(BUILD_TESTS) add_subdirectory(tests) endif () +if (WIN32 AND THREAT_WARNING_AS_ERROR) + target_compile_options(omath PRIVATE /W4 /WX) +elseif(UNIX AND THREAT_WARNING_AS_ERROR) + target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic) +endif() + target_include_directories(omath PUBLIC include) \ No newline at end of file diff --git a/include/omath/angles.h b/include/omath/Angles.h similarity index 100% rename from include/omath/angles.h rename to include/omath/Angles.h diff --git a/include/omath/Color.h b/include/omath/Color.h new file mode 100644 index 0000000..e8da221 --- /dev/null +++ b/include/omath/Color.h @@ -0,0 +1,123 @@ +// +// Created by vlad on 2/4/24. +// + +#pragma once + +#include "omath/Vector3.h" +#include +#include "omath/Vector4.h" + + +namespace omath +{ + struct HSV + { + float m_hue{}; + float m_saturation{}; + float m_value{}; + }; + + + class Color final : public Vector4 + { + public: + constexpr Color(float r, float g, float b, float a) : Vector4(r,g,b,a) + { + Clamp(0.f, 1.f); + } + + constexpr explicit Color() : Vector4() + { + + } + [[nodiscard]] + constexpr static Color FromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a) + { + return Color{Vector4(r, g, b, a) / 255.f}; + } + + [[nodiscard]] + constexpr static Color FromHSV(float hue, float saturation, float value) + { + float r{}, g{}, b{}; + + hue = std::clamp(hue, 0.f, 1.f); + + const int i = static_cast(hue * 6.f); + const float f = hue * 6 - i; + const float p = value * (1 - saturation); + const float q = value * (1 - f * saturation); + const float t = value * (1 - (1 - f) * saturation); + + switch (i % 6) + { + case 0: r = value, g = t, b = p; break; + case 1: r = q, g = value, b = p; break; + case 2: r = p, g = value, b = t; break; + case 3: r = p, g = q, b = value; break; + case 4: r = t, g = p, b = value; break; + case 5: r = value, g = p, b = q; break; + + default: return {0.f, 0.f, 0.f, 0.f}; + } + + return {r, g, b, 1.f}; + } + + [[nodiscard]] + constexpr HSV ToHSV() const + { + HSV hsvData; + + const float& red = x; + const float& green = y; + const float& blue = z; + + const float max = std::max({red, green, blue}); + const float min = std::min({red, green, blue}); + const float delta = max - min; + + + if (delta == 0.f) + hsvData.m_hue = 0.f; + + else if (max == red) + hsvData.m_hue = 60.f * (std::fmodf(((green - blue) / delta), 6.f)); + else if (max == green) + hsvData.m_hue = 60.f * (((blue - red) / delta) + 2.f); + else if (max == blue) + hsvData.m_hue = 60.f * (((red - green) / delta) + 4.f); + + if (hsvData.m_hue < 0.f) + hsvData.m_hue += 360.f; + + hsvData.m_hue /= 360.f; + hsvData.m_saturation = max == 0.f ? 0.f : delta / max; + hsvData.m_value = max; + + return hsvData; + } + + constexpr explicit Color(const Vector4& vec) : Vector4(vec) + { + Clamp(0.f, 1.f); + } + + [[nodiscard]] + constexpr Color Blend(const Color& other, float ratio) const + { + return Color( (*this * (1.f - ratio)) + (other * ratio) ); + } + + [[nodiscard]] static constexpr Color Red() {return {1.f, 0.f, 0.f, 1.f};} + [[nodiscard]] static constexpr Color Green() {return {0.f, 1.f, 0.f, 1.f};} + [[nodiscard]] static constexpr Color Blue() {return {0.f, 0.f, 1.f, 1.f};} + }; + + [[nodiscard]] + constexpr Color Blend(const Color& first, const Color& second, float ratio) + { + return Color{first * (1.f - std::clamp(ratio, 0.f, 1.f)) + second * ratio}; + } +} \ No newline at end of file diff --git a/include/omath/Matrix.h b/include/omath/Matrix.h index a8d0028..c157127 100644 --- a/include/omath/Matrix.h +++ b/include/omath/Matrix.h @@ -26,7 +26,7 @@ namespace omath static Matrix OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up); [[nodiscard]] - static Matrix ProjectionMatrix(float fielOfView, float aspectRatio,float near, float far); + static Matrix ProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far); Matrix(const Matrix &other); diff --git a/include/omath/Vector2.h b/include/omath/Vector2.h index a19e3b4..f04da2d 100644 --- a/include/omath/Vector2.h +++ b/include/omath/Vector2.h @@ -4,6 +4,7 @@ #pragma once #include +#include namespace omath @@ -15,60 +16,169 @@ namespace omath float y = 0.f; // Constructors - Vector2() = default; - Vector2(float x, float y); + constexpr Vector2() : x(0.f), y(0.f) {} + + constexpr Vector2(float x, float y) : x(x), y(y) {} // Equality operators - bool operator==(const Vector2& src) const; - bool operator!=(const Vector2& src) const; + [[nodiscard]] + constexpr bool operator==(const Vector2& src) const + { + return x == src.x && y == src.y; + } + + [[nodiscard]] + constexpr bool operator!=(const Vector2& src) const + { + return !(*this == src); + } // Compound assignment operators - Vector2& operator+=(const Vector2& v); - Vector2& operator-=(const Vector2& v); - Vector2& operator*=(const Vector2& v); - Vector2& operator/=(const Vector2& v); + constexpr Vector2& operator+=(const Vector2& v) + { + x += v.x; + y += v.y; - Vector2& operator*=(float fl); - Vector2& operator/=(float fl); - Vector2& operator+=(float fl); - Vector2& operator-=(float fl); + return *this; + } + + constexpr Vector2& operator-=(const Vector2& v) + { + x -= v.x; + y -= v.y; + + return *this; + } + + constexpr Vector2& operator*=(const Vector2& v) + { + x *= v.x; + y *= v.y; + + return *this; + } + + constexpr Vector2& operator/=(const Vector2& v) + { + x /= v.x; + y /= v.y; + + return *this; + } + + constexpr Vector2& operator*=(float fl) + { + x *= fl; + y *= fl; + + return *this; + } + + constexpr Vector2& operator/=(float fl) + { + x /= fl; + y /= fl; + + return *this; + } + + constexpr Vector2& operator+=(float fl) + { + x += fl; + y += fl; + + return *this; + } + + constexpr Vector2& operator-=(float fl) + { + x -= fl; + y -= fl; + + return *this; + } // Basic vector operations - [[nodiscard]] float DistTo(const Vector2& vOther) const; - [[nodiscard]] float DistToSqr(const Vector2& vOther) const; - [[nodiscard]] float Dot(const Vector2& vOther) const; + [[nodiscard]] float DistTo(const Vector2& vOther) const + { + return std::sqrt(DistToSqr(vOther)); + } + + [[nodiscard]] constexpr float DistToSqr(const Vector2& vOther) const + { + return (x - vOther.x) * (x - vOther.x) + (y - vOther.y) * (y - vOther.y); + } + + [[nodiscard]] constexpr float Dot(const Vector2& vOther) const + { + return x * vOther.x + y * vOther.y; + } + [[nodiscard]] float Length() const; - [[nodiscard]] float LengthSqr() const; - Vector2& Abs(); + + [[nodiscard]] constexpr float LengthSqr() const + { + return x * x + y * y; + } + + constexpr Vector2& Abs() + { + //FIXME: Replace with std::abs, if it will become constexprable + x = x < 0 ? -x : x; + y = y < 0 ? -y : y; + return *this; + } template - const type& As() const + [[nodiscard]] constexpr const type& As() const { return *reinterpret_cast(this); } template - type& As() + [[nodiscard]] constexpr type& As() { return *reinterpret_cast(this); } - // Unary negation operator - Vector2 operator-() const; + [[nodiscard]] constexpr Vector2 operator-() const + { + return {-x, -y}; + } // Binary arithmetic operators - Vector2 operator+(const Vector2& v) const; - Vector2 operator-(const Vector2& v) const; - Vector2 operator*(float fl) const; - Vector2 operator/(float fl) const; + [[nodiscard]] constexpr Vector2 operator+(const Vector2& v) const + { + return {x + v.x, y + v.y}; + } + [[nodiscard]] constexpr Vector2 operator-(const Vector2& v) const + { + return {x - v.x, y - v.y}; + } + + [[nodiscard]] constexpr Vector2 operator*(float fl) const + { + return {x * fl, y * fl}; + } + + [[nodiscard]] constexpr Vector2 operator/(float fl) const + { + return {x / fl, y / fl}; + } // Normalize the vector [[nodiscard]] Vector2 Normalized() const; - // Sum of elements - [[nodiscard]] float Sum() const; + // Sum of elements + [[nodiscard]] constexpr float Sum() const + { + return x + y; + } [[nodiscard]] - std::tuple AsTuple() const; + constexpr std::tuple AsTuple() const + { + return std::make_tuple(x, y); + } }; } \ No newline at end of file diff --git a/include/omath/Vector3.h b/include/omath/Vector3.h index b3cc2bf..0ec441b 100644 --- a/include/omath/Vector3.h +++ b/include/omath/Vector3.h @@ -15,42 +15,166 @@ namespace omath { public: float z = 0.f; - Vector3(float x, float y, float z); - Vector3() = default; + constexpr Vector3(float x, float y, float z) : Vector2(x, y), z(z) { } + constexpr Vector3() : Vector2(), z(0.f) {}; - bool operator==(const Vector3& src) const; - bool operator!=(const Vector3& src) const; + [[nodiscard]] constexpr bool operator==(const Vector3& src) const + { + return Vector2::operator==(src) && (src.z == z); + } - Vector3& operator+=(const Vector3& v); - Vector3& operator-=(const Vector3& v); - Vector3& operator*=(float fl); - Vector3& operator*=(const Vector3& v); - Vector3& operator/=(const Vector3& v); - Vector3& operator+=(float fl); - Vector3& operator/=(float fl); - Vector3& operator-=(float fl); + [[nodiscard]] constexpr bool operator!=(const Vector3& src) const + { + return !(*this == src); + } - [[nodiscard]] float DistTo(const Vector3& vOther) const; - Vector3& Abs(); - [[nodiscard]] float DistToSqr(const Vector3& vOther) const; - [[nodiscard]] float Dot(const Vector3& vOther) const; + constexpr Vector3& operator+=(const Vector3& v) + { + Vector2::operator+=(v); + z += v.z; + + return *this; + } + + constexpr Vector3& operator-=(const Vector3& v) + { + Vector2::operator-=(v); + z -= v.z; + + return *this; + } + + constexpr Vector3& operator*=(float fl) + { + Vector2::operator*=(fl); + z *= fl; + + return *this; + } + + constexpr Vector3& operator*=(const Vector3& v) + { + Vector2::operator*=(v); + z *= v.z; + + return *this; + } + + constexpr Vector3& operator/=(const Vector3& v) + { + Vector2::operator/=(v); + z /= v.z; + + return *this; + } + + constexpr Vector3& operator+=(float fl) + { + Vector2::operator+=(fl); + z += fl; + + return *this; + } + + constexpr Vector3& operator/=(float fl) + { + Vector2::operator/=(fl); + z /= fl; + + return *this; + } + + constexpr Vector3& operator-=(float fl) + { + Vector2::operator-=(fl); + z -= fl; + + return *this; + } + + [[nodiscard]] + float DistTo(const Vector3& vOther) const; + + constexpr Vector3& Abs() + { + Vector2::Abs(); + z = z < 0.f ? -z : z; + + return *this; + } + + [[nodiscard]] constexpr float DistToSqr(const Vector3& vOther) const + { + return (*this - vOther).LengthSqr(); + } + + [[nodiscard]] constexpr float Dot(const Vector3& vOther) const + { + return Vector2::Dot(vOther) + z * vOther.z; + } [[nodiscard]] float Length() const; - [[nodiscard]] float LengthSqr() const; + + [[nodiscard]] constexpr float LengthSqr() const + { + return Vector2::LengthSqr() + z * z; + } + [[nodiscard]] float Length2D() const; - Vector3 operator-() const; - Vector3 operator+(const Vector3& v) const; - Vector3 operator-(const Vector3& v) const; - Vector3 operator*(float fl) const; - Vector3 operator*(const Vector3& v) const; - Vector3 operator/(float fl) const; - Vector3 operator/(const Vector3& v) const; + [[nodiscard]] constexpr Vector3 operator-() const + { + return {-x, -y, -z}; + } + [[nodiscard]] constexpr Vector3 operator+(const Vector3& v) const + { + return {x + v.x, y + v.y, z + v.z}; + } + + [[nodiscard]] constexpr Vector3 operator-(const Vector3& v) const + { + return {x - v.x, y - v.y, z - v.z}; + } + + [[nodiscard]] constexpr Vector3 operator*(float fl) const + { + return {x * fl, y * fl, z * fl}; + } + + [[nodiscard]] constexpr Vector3 operator*(const Vector3& v) const + { + return {x * v.x, y * v.y, z * v.z}; + } + + [[nodiscard]] constexpr Vector3 operator/(float fl) const + { + return {x / fl, y / fl, z / fl}; + } + + [[nodiscard]] constexpr Vector3 operator/(const Vector3& v) const + { + return {x / v.x, y / v.y, z / v.z}; + } + + [[nodiscard]] constexpr Vector3 Cross(const Vector3 &v) const + { + return + { + y * v.z - z * v.y, + z * v.x - x * v.z, + x * v.y - y * v.x + }; + } + [[nodiscard]] constexpr float Sum() const + { + return Vector3::Sum2D() + z; + } + + [[nodiscard]] constexpr float Sum2D() const + { + return Vector2::Sum(); + } - [[nodiscard]] Vector3 Cross(const Vector3 &v) const; - [[nodiscard]] static Vector3 CreateVelocity(float pitch, float yaw, float speed); - [[nodiscard]] float Sum() const; - [[nodiscard]] float Sum2D() const; [[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const; [[nodiscard]] static Vector3 ForwardVector(float pitch, float yaw); @@ -61,7 +185,10 @@ namespace omath [[nodiscard]] Vector3 Normalized() const; - [[nodiscard]] std::tuple AsTuple() const; + [[nodiscard]] std::tuple AsTuple() const + { + return std::make_tuple(x, y, z); + } }; } // ReSharper disable once CppRedundantNamespaceDefinition diff --git a/include/omath/Vector4.h b/include/omath/Vector4.h index 32fa324..46d61ae 100644 --- a/include/omath/Vector4.h +++ b/include/omath/Vector4.h @@ -4,59 +4,152 @@ #pragma once #include +#include + namespace omath { class Vector4 : public Vector3 { public: - float w = 0.f; + float w; - Vector4(const float x = 0.f, const float y = 0.f, const float z = 0.f, const float w = 0.f) : Vector3(x, y, z), w(w) {} - Vector4(); + constexpr Vector4(float x, float y, float z, float w) : Vector3(x, y, z), w(w) {} + constexpr Vector4() : Vector3(), w(0.f) {}; [[nodiscard]] - bool operator==(const Vector4& src) const; + constexpr bool operator==(const Vector4& src) const + { + return Vector3::operator==(src) && w == src.w; + } [[nodiscard]] - bool operator!=(const Vector4& src) const; + constexpr bool operator!=(const Vector4& src) const + { + return !(*this == src); + } - Vector4& operator+=(const Vector4& v); - Vector4& operator-=(const Vector4& v); - Vector4& operator*=(float scalar); - Vector4& operator*=(const Vector4& v); - Vector4& operator/=(float scalar); - Vector4& operator/=(const Vector4& v); + constexpr Vector4& operator+=(const Vector4& v) + { + Vector3::operator+=(v); + w += v.w; + + return *this; + } + + constexpr Vector4& operator-=(const Vector4& v) + { + Vector3::operator-=(v); + w -= v.w; + + return *this; + } + + constexpr Vector4& operator*=(float scalar) + { + Vector3::operator*=(scalar); + w *= scalar; + + return *this; + } + + constexpr Vector4& operator*=(const Vector4& v) + { + Vector3::operator*=(v); + w *= v.w; + + return *this; + } + + constexpr Vector4& operator/=(float scalar) + { + Vector3::operator/=(scalar); + w /= scalar; + + return *this; + } + + constexpr Vector4& operator/=(const Vector4& v) + { + Vector3::operator/=(v); + w /= v.w; + return *this; + } + + [[nodiscard]] constexpr float LengthSqr() const + { + return Vector3::LengthSqr() + w * w; + } + + [[nodiscard]] constexpr float Dot(const Vector4& vOther) const + { + return Vector3::Dot(vOther) + w * vOther.w; + } [[nodiscard]] float Length() const; - [[nodiscard]] float LengthSqr() const; - [[nodiscard]] float Dot(const Vector4& vOther) const; - Vector4& Abs(); - Vector4& Clamp(float min, float max); + constexpr Vector4& Abs() + { + Vector3::Abs(); + w = w < 0.f ? -w : w; + + return *this; + } + constexpr Vector4& Clamp(float min, float max) + { + x = std::clamp(x, min, max); + y = std::clamp(y, min, max); + z = std::clamp(z, min, max); + + return *this; + } [[nodiscard]] - Vector4 operator-() const; + constexpr Vector4 operator-() const + { + return {-x, -y, -z, -w}; + } [[nodiscard]] - Vector4 operator+(const Vector4& v) const; + constexpr Vector4 operator+(const Vector4& v) const + { + return {x + v.x, y + v.y, z + v.z, w + v.w}; + } [[nodiscard]] - Vector4 operator-(const Vector4& v) const; + constexpr Vector4 operator-(const Vector4& v) const + { + return {x - v.x, y - v.y, z - v.z, w - v.w}; + } [[nodiscard]] - Vector4 operator*(float scalar) const; + constexpr Vector4 operator*(float scalar) const + { + return {x * scalar, y * scalar, z * scalar, w * scalar}; + } [[nodiscard]] - Vector4 operator*(const Vector4& v) const; + constexpr Vector4 operator*(const Vector4& v) const + { + return {x * v.x, y * v.y, z * v.z, w * v.w}; + } [[nodiscard]] - Vector4 operator/(float scalar) const; + constexpr Vector4 operator/(float scalar) const + { + return {x / scalar, y / scalar, z / scalar, w / scalar}; + } [[nodiscard]] - Vector4 operator/(const Vector4& v) const; + constexpr Vector4 operator/(const Vector4& v) const + { + return {x / v.x, y / v.y, z / v.z, w / v.w}; + } [[nodiscard]] - float Sum() const; + constexpr float Sum() const + { + return Vector3::Sum() + w; + } }; } diff --git a/include/omath/color.h b/include/omath/color.h deleted file mode 100644 index 2a5f2ba..0000000 --- a/include/omath/color.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by vlad on 2/4/24. -// - -#pragma once - -#include "omath/Vector3.h" -#include -#include "omath/Vector4.h" - - -namespace omath::color -{ - struct HSV - { - float m_hue{}; - float m_saturation{}; - float m_value{}; - }; - - [[nodiscard]] - Vector3 Blend(const Vector3& first, const Vector3& second, float ratio); - - class Color final : public Vector4 - { - public: - Color(float r, float g, float b, float a); - explicit Color(); - [[nodiscard]] - static Color FromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a); - - [[nodiscard]] - static Color FromHSV(float hue, float saturation, float value); - - [[nodiscard]] - HSV ToHSV() const; - - explicit Color(Vector4 vec); - - [[nodiscard]] - Color Blend(const Color& other, float ratio) const; - - [[nodiscard]] static Color Red() {return {1.f, 0.f, 0.f, 1.f};} - [[nodiscard]] static Color Green() {return {0.f, 1.f, 0.f, 1.f};} - [[nodiscard]] static Color Blue() {return {0.f, 0.f, 1.f, 1.f};} - }; -} \ No newline at end of file diff --git a/include/omath/pathfinding/Astar.h b/include/omath/pathfinding/Astar.h index 0525679..64bfc88 100644 --- a/include/omath/pathfinding/Astar.h +++ b/include/omath/pathfinding/Astar.h @@ -10,7 +10,7 @@ namespace omath::pathfinding { - class Astar + class Astar final { public: [[nodiscard]] diff --git a/include/omath/pathfinding/NavigationMesh.h b/include/omath/pathfinding/NavigationMesh.h index 7b4ffa6..11e08bb 100644 --- a/include/omath/pathfinding/NavigationMesh.h +++ b/include/omath/pathfinding/NavigationMesh.h @@ -12,19 +12,12 @@ namespace omath::pathfinding { - struct NavigationVertex - { - Vector3 origin; - std::vector connections; - }; - - class NavigationMesh final { public: [[nodiscard]] - std::expected GetClossestVertex(const Vector3& point) const; + std::expected GetClosestVertex(const Vector3& point) const; [[nodiscard]] diff --git a/include/omath/prediction/Engine.h b/include/omath/prediction/Engine.h index 3a32f92..af7876f 100644 --- a/include/omath/prediction/Engine.h +++ b/include/omath/prediction/Engine.h @@ -12,7 +12,7 @@ namespace omath::prediction { - class Engine + class Engine final { public: explicit Engine(float gravityConstant, float simulationTimeStep, diff --git a/include/omath/prediction/Projectile.h b/include/omath/prediction/Projectile.h index 48038f8..1249e97 100644 --- a/include/omath/prediction/Projectile.h +++ b/include/omath/prediction/Projectile.h @@ -12,9 +12,6 @@ namespace omath::prediction { public: - [[nodiscard]] - Vector3 CalculateVelocity(float pitch, float yaw) const; - [[nodiscard]] Vector3 PredictPosition(float pitch, float yaw, float time, float gravity) const; diff --git a/include/omath/prediction/Target.h b/include/omath/prediction/Target.h index bb21fb0..0332c53 100644 --- a/include/omath/prediction/Target.h +++ b/include/omath/prediction/Target.h @@ -13,7 +13,15 @@ namespace omath::prediction public: [[nodiscard]] - Vector3 PredictPosition(float time, float gravity) const; + constexpr Vector3 PredictPosition(float time, float gravity) const + { + auto predicted = m_origin + m_velocity * time; + + if (m_isAirborne) + predicted.z -= gravity * std::pow(time, 2.f) * 0.5f; + + return predicted; + } Vector3 m_origin; Vector3 m_velocity; diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index 4bbd069..a7ab73b 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -8,6 +8,7 @@ #include #include #include +#include "ErrorCodes.h" namespace omath::projection @@ -18,7 +19,7 @@ namespace omath::projection float m_width; float m_height; - [[nodiscard]] float AspectRatio() const {return m_width / m_height;} + [[nodiscard]] constexpr float AspectRatio() const {return m_width / m_height;} }; class Camera @@ -27,13 +28,9 @@ namespace omath::projection Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); - [[nodiscard]] const Vector3& GetViewAngles() const; [[nodiscard]] Matrix GetViewMatrix() const; - [[nodiscard]] Matrix GetProjectionMatrix() const; - [[nodiscard]] Matrix GetTranslationMatrix() const; - [[nodiscard]] Matrix GetOrientationMatrix() const; - [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const; + [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const; ViewPort m_viewPort{}; float m_fieldOfView; diff --git a/include/omath/projection/ErrorCodes.h b/include/omath/projection/ErrorCodes.h new file mode 100644 index 0000000..968a15e --- /dev/null +++ b/include/omath/projection/ErrorCodes.h @@ -0,0 +1,16 @@ +// +// Created by Vlad on 03.09.2024. +// + +#pragma once +#include + + +namespace omath::projection +{ + enum class Error : uint16_t + { + WORLD_POSITION_IS_BEHIND_CAMERA = 0, + WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS, + }; +} \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 495eacc..9d79f16 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -1,6 +1,6 @@ target_sources(omath PRIVATE Vector3.cpp - matrix.cpp + Matrix.cpp color.cpp Vector4.cpp Vector2.cpp) diff --git a/source/matrix.cpp b/source/Matrix.cpp similarity index 97% rename from source/matrix.cpp rename to source/Matrix.cpp index 37a5742..6d2e11b 100644 --- a/source/matrix.cpp +++ b/source/Matrix.cpp @@ -1,6 +1,6 @@ #include "omath/Matrix.h" #include "omath/Vector3.h" -#include "omath/angles.h" +#include "omath/Angles.h" #include @@ -200,8 +200,8 @@ namespace omath m_columns = other.m_columns; m_data = std::move(other.m_data); - other.m_rows = 0.f; - other.m_columns = 0.f; + other.m_rows = 0; + other.m_columns = 0; return *this; @@ -350,10 +350,10 @@ namespace omath }; } - Matrix Matrix::ProjectionMatrix(const float fielOfView, const float aspectRatio, const float near, + Matrix Matrix::ProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far) { - const float fovHalfTan = std::tan(angles::DegreesToRadians(fielOfView) / 2.f); + const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f); return { diff --git a/source/Vector2.cpp b/source/Vector2.cpp index bdba7af..66dc4f0 100644 --- a/source/Vector2.cpp +++ b/source/Vector2.cpp @@ -7,157 +7,19 @@ namespace omath { - // Constructors - Vector2::Vector2(const float x, const float y) : x(x), y(y) {} - // Equality operators - bool Vector2::operator==(const Vector2& src) const + Vector2 Vector2::Normalized() const { - return x == src.x && y == src.y; - } + const float len = Length(); - bool Vector2::operator!=(const Vector2& src) const - { - return !(*this == src); - } + if (len > 0.f) + return {x / len, y / len}; - // Compound assignment operators - Vector2& Vector2::operator+=(const Vector2& v) - { - x += v.x; - y += v.y; - return *this; - } - - Vector2& Vector2::operator-=(const Vector2& v) - { - x -= v.x; - y -= v.y; - return *this; - } - - Vector2& Vector2::operator*=(float fl) - { - x *= fl; - y *= fl; - return *this; - } - - Vector2& Vector2::operator/=(float fl) - { - x /= fl; - y /= fl; - return *this; - } - - Vector2& Vector2::operator+=(float fl) - { - x += fl; - y += fl; - return *this; - } - - Vector2& Vector2::operator-=(float fl) - { - x -= fl; - y -= fl; - return *this; - } - - // Basic vector operations - float Vector2::DistTo(const Vector2& vOther) const - { - return std::sqrt(DistToSqr(vOther)); - } - - float Vector2::DistToSqr(const Vector2& vOther) const - { - return (x - vOther.x) * (x - vOther.x) + (y - vOther.y) * (y - vOther.y); - } - - float Vector2::Dot(const Vector2& vOther) const - { - return x * vOther.x + y * vOther.y; + return {0.f, 0.f}; } float Vector2::Length() const { return std::sqrt(x * x + y * y); } - - float Vector2::LengthSqr() const - { - return x * x + y * y; - } - - Vector2& Vector2::Abs() - { - x = std::abs(x); - y = std::abs(y); - return *this; - } - - // Unary negation operator - Vector2 Vector2::operator-() const - { - return {-x, -y}; - } - - // Binary arithmetic operators - Vector2 Vector2::operator+(const Vector2& v) const - { - return {x + v.x, y + v.y}; - } - - Vector2 Vector2::operator-(const Vector2& v) const - { - return {x - v.x, y - v.y}; - } - - Vector2 Vector2::operator*(float fl) const - { - return {x * fl, y * fl}; - } - - Vector2 Vector2::operator/(float fl) const - { - return {x / fl, y / fl}; - } - - // Normalize the vector - Vector2 Vector2::Normalized() const - { - float len = Length(); - if (len > 0.f) { - return {x / len, y / len}; - } - return {0.f, 0.f}; - } - - // Sum of elements - float Vector2::Sum() const - { - return x + y; - } - - Vector2 &Vector2::operator*=(const Vector2 &v) - { - x *= v.x; - y *= v.y; - - return *this; - } - - Vector2 &Vector2::operator/=(const Vector2 &v) - { - x /= v.x; - y /= v.y; - - return *this; - } - - std::tuple Vector2::AsTuple() const - { - return std::make_tuple(x, y); - } } \ No newline at end of file diff --git a/source/Vector3.cpp b/source/Vector3.cpp index fcbd061..b74ef6e 100644 --- a/source/Vector3.cpp +++ b/source/Vector3.cpp @@ -4,183 +4,27 @@ #include #include -#include +#include namespace omath { - Vector3::Vector3(const float x, const float y, const float z) : Vector2(x, y), z(z) - { - - } - - bool Vector3::operator==(const Vector3 &src) const - { - return Vector2::operator==(src) && (src.z == z); - } - - bool Vector3::operator!=(const Vector3 &src) const - { - return !(*this == src); - } - - Vector3 &Vector3::operator+=(const Vector3 &v) - { - Vector2::operator+=(v); - z += v.z; - - return *this; - } - - Vector3 &Vector3::operator-=(const Vector3 &v) - { - Vector2::operator-=(v); - z -= v.z; - - return *this; - } - - Vector3 &Vector3::operator*=(const float fl) - { - Vector2::operator*=(fl); - z *= fl; - - return *this; - } - - Vector3 &Vector3::operator*=(const Vector3 &v) - { - Vector2::operator*=(v); - z *= v.z; - - return *this; - } - - Vector3 &Vector3::operator/=(const Vector3 &v) - { - Vector2::operator/=(v); - z /= v.z; - - return *this; - } - - Vector3 &Vector3::operator+=(const float fl) - { - Vector2::operator+=(fl); - z += fl; - - return *this; - } - - Vector3 &Vector3::operator/=(const float fl) - { - Vector2::operator/=(fl); - z /= fl; - - return *this; - } - - Vector3 &Vector3::operator-=(const float fl) - { - Vector2::operator-=(fl); - z -= fl; - - return *this; - } - float Vector3::DistTo(const Vector3 &vOther) const { return (*this - vOther).Length(); } - Vector3 &Vector3::Abs() - { - Vector2::Abs(); - z = std::abs(z); - - return *this; - } - - float Vector3::DistToSqr(const Vector3 &vOther) const - { - return (*this - vOther).LengthSqr(); - } - - float Vector3::Dot(const Vector3 &vOther) const - { - return Vector2::Dot(vOther) + z * vOther.z; - } - float Vector3::Length() const { return std::sqrt(Vector2::LengthSqr() + z * z); } - float Vector3::LengthSqr() const - { - return Vector2::LengthSqr() + z * z; - } float Vector3::Length2D() const { return Vector2::Length(); } - Vector3 Vector3::operator-() const - { - return {-x, -y, -z}; - } - - Vector3 Vector3::operator+(const Vector3 &v) const - { - return {x + v.x, y + v.y, z + v.z}; - } - - Vector3 Vector3::operator-(const Vector3 &v) const - { - return {x - v.x, y - v.y, z - v.z}; - } - - Vector3 Vector3::operator*(float fl) const - { - return {x * fl, y * fl, z * fl}; - } - - Vector3 Vector3::operator*(const Vector3 &v) const - { - return {x * v.x, y * v.y, z * v.z}; - } - - Vector3 Vector3::operator/(const float fl) const - { - return {x / fl, y / fl, z / fl}; - } - - Vector3 Vector3::operator/(const Vector3 &v) const - { - return {x / v.x, y / v.y, z / v.z}; - } - - Vector3 Vector3::CreateVelocity(const float pitch, const float yaw, const float speed) - { - return - { - std::cos(angles::DegreesToRadians(pitch)) * std::cos(angles::DegreesToRadians(yaw)) * speed, - std::cos(angles::DegreesToRadians(pitch)) * std::sin(angles::DegreesToRadians(yaw)) * speed, - std::sin(angles::DegreesToRadians(pitch)) * speed, - }; - } - - float Vector3::Sum() const - { - return Vector3::Sum2D() + z; - } - - float Vector3::Sum2D() const - { - return Vector2::Sum(); - } - Vector3 Vector3::ViewAngleTo(const Vector3 &other) const { const float distance = DistTo(other); @@ -233,15 +77,6 @@ namespace omath return RightVector(pitch, yaw, roll).Cross(ForwardVector(pitch, yaw)); } - Vector3 Vector3::Cross(const Vector3 &v) const - { - return - { - y * v.z - z * v.y, - z * v.x - x * v.z, - x * v.y - y * v.x - }; - } Vector3 Vector3::Normalized() const { @@ -249,9 +84,4 @@ namespace omath return length != 0 ? *this / length : *this; } - - std::tuple Vector3::AsTuple() const - { - return std::make_tuple(x, y, z); - } } \ No newline at end of file diff --git a/source/Vector4.cpp b/source/Vector4.cpp index 43ee175..1d54d80 100644 --- a/source/Vector4.cpp +++ b/source/Vector4.cpp @@ -3,139 +3,14 @@ // #include "omath/Vector4.h" - -#include #include + namespace omath { - bool Vector4::operator==(const Vector4& src) const - { - return Vector3::operator==(src) && w == src.w; - } - - bool Vector4::operator!=(const Vector4& src) const - { - return !(*this == src); - } - - Vector4& Vector4::operator+=(const Vector4& v) - { - Vector3::operator+=(v); - w += v.w; - return *this; - } - - Vector4& Vector4::operator-=(const Vector4& v) - { - Vector3::operator-=(v); - w -= v.w; - return *this; - } - - Vector4& Vector4::operator*=(float scalar) - { - Vector3::operator*=(scalar); - w *= scalar; - return *this; - } - - Vector4& Vector4::operator*=(const Vector4& v) - { - Vector3::operator*=(v); - w *= v.w; - return *this; - } - - Vector4& Vector4::operator/=(float scalar) - { - Vector3::operator/=(scalar); - w /= scalar; - return *this; - } - - Vector4& Vector4::operator/=(const Vector4& v) - { - Vector3::operator/=(v); - w /= v.w; - return *this; - } float Vector4::Length() const { return std::sqrt(LengthSqr()); } - - float Vector4::LengthSqr() const - { - return Vector3::LengthSqr() + w * w; - } - - float Vector4::Dot(const Vector4& vOther) const - { - return Vector3::Dot(vOther) + w * vOther.w; - } - - Vector4& Vector4::Abs() - { - Vector3::Abs(); - w = std::abs(w); - return *this; - } - - Vector4& Vector4::Clamp(const float min, const float max) - { - x = std::clamp(x, min, max); - y = std::clamp(y, min, max); - z = std::clamp(z, min, max); - - return *this; - } - - Vector4 Vector4::operator-() const - { - return {-x, -y, -z, -w}; - } - - Vector4 Vector4::operator+(const Vector4& v) const - { - return {x + v.x, y + v.y, z + v.z, w + v.w}; - } - - Vector4 Vector4::operator-(const Vector4& v) const - { - return {x - v.x, y - v.y, z - v.z, w - v.w}; - } - - Vector4 Vector4::operator*(float scalar) const - { - return {x * scalar, y * scalar, z * scalar, w * scalar}; - } - - Vector4 Vector4::operator*(const Vector4& v) const - { - return {x * v.x, y * v.y, z * v.z, w * v.w}; - } - - Vector4 Vector4::operator/(float scalar) const - { - return {x / scalar, y / scalar, z / scalar, w / scalar}; - } - - Vector4 Vector4::operator/(const Vector4& v) const - { - return {x / v.x, y / v.y, z / v.z, w / v.w}; - } - - float Vector4::Sum() const - { - return x + y + z + w; - } - - Vector4::Vector4() - { - x = 0.f; - y = 0.f; - z = 0.f; - } } diff --git a/source/color.cpp b/source/color.cpp index cbe1995..1de3bfd 100644 --- a/source/color.cpp +++ b/source/color.cpp @@ -2,102 +2,12 @@ // Created by vlad on 2/4/24. // -#include "omath/color.h" +#include "omath/Color.h" #include #include -namespace omath::color +namespace omath { - Vector3 Blend(const Vector3 &first, const Vector3 &second, float ratio) - { - return first * (1.f - std::clamp(ratio, 0.f, 1.f)) + second * ratio; - } - - Color Color::Blend(const Color &other, float ratio) const - { - return Color( (*this * (1.f - ratio)) + (other * ratio) ); - } - Color::Color(const float r, const float g, const float b, const float a) - : Vector4(std::clamp(r, 0.f, 1.f), - std::clamp(g, 0.f, 1.f), - std::clamp(b, 0.f, 1.f), - std::clamp(a, 0.f, 1.f)) - { - - } - - Color::Color(Vector4 vec) : Vector4(vec.Clamp(0.f, 1.f)) - { - - } - - Color Color::FromRGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) - { - return Color{Vector4(r, g, b, a) / 255.f}; - } - - Color Color::FromHSV(float hue, const float saturation, const float value) { - float r{}, g{}, b{}; - - hue = std::clamp(hue, 0.f, 1.f); - - const int i = static_cast(hue * 6.f); - const float f = hue * 6 - i; - const float p = value * (1 - saturation); - const float q = value * (1 - f * saturation); - const float t = value * (1 - (1 - f) * saturation); - - switch (i % 6) - { - case 0: r = value, g = t, b = p; break; - case 1: r = q, g = value, b = p; break; - case 2: r = p, g = value, b = t; break; - case 3: r = p, g = q, b = value; break; - case 4: r = t, g = p, b = value; break; - case 5: r = value, g = p, b = q; break; - - default: return {0.f, 0.f, 0.f, 0.f}; - } - - return {r, g, b, 1.f}; - } - - HSV Color::ToHSV() const { - HSV hsvData; - - const float& red = x; - const float& green = y; - const float& blue = z; - - const float max = std::max({red, green, blue}); - const float min = std::min({red, green, blue}); - const float delta = max - min; - - - if (delta == 0.f) - hsvData.m_hue = 0.f; - - else if (max == red) - hsvData.m_hue = 60.f * (std::fmodf(((green - blue) / delta), 6.f)); - else if (max == green) - hsvData.m_hue = 60.f * (((blue - red) / delta) + 2.f); - else if (max == blue) - hsvData.m_hue = 60.f * (((red - green) / delta) + 4.f); - - if (hsvData.m_hue < 0.f) - hsvData.m_hue += 360.f; - - hsvData.m_hue /= 360.f; - hsvData.m_saturation = max == 0.f ? 0.f : delta / max; - hsvData.m_value = max; - - return hsvData; - } - - Color::Color() : Vector4(0.f, 0.f, 0.f, 0.f) - { - - } } diff --git a/source/pathfinding/Astar.cpp b/source/pathfinding/Astar.cpp index a5002e9..10a03e9 100644 --- a/source/pathfinding/Astar.cpp +++ b/source/pathfinding/Astar.cpp @@ -23,8 +23,8 @@ namespace omath::pathfinding std::unordered_map closedList; std::unordered_map openList; - const auto startVertex = navMesh.GetClossestVertex(start).value(); - const auto endVertex = navMesh.GetClossestVertex(end).value(); + const auto startVertex = navMesh.GetClosestVertex(start).value(); + const auto endVertex = navMesh.GetClosestVertex(end).value(); openList.emplace(startVertex, PathNode{std::nullopt, 0.f}); diff --git a/source/pathfinding/NavigationMesh.cpp b/source/pathfinding/NavigationMesh.cpp index 766558e..1a106df 100644 --- a/source/pathfinding/NavigationMesh.cpp +++ b/source/pathfinding/NavigationMesh.cpp @@ -7,7 +7,7 @@ #include namespace omath::pathfinding { - std::expected NavigationMesh::GetClossestVertex(const Vector3 &point) const + std::expected NavigationMesh::GetClosestVertex(const Vector3 &point) const { const auto res = std::ranges::min_element(m_verTextMap, [&point](const auto& a, const auto& b) @@ -43,7 +43,7 @@ namespace omath::pathfinding for (const auto& [vertex, neighbors] : m_verTextMap) { - const uint16_t neighborsCount = neighbors.size(); + const auto neighborsCount = neighbors.size(); dumpToVector(vertex, raw); dumpToVector(neighborsCount, raw); diff --git a/source/prediction/Engine.cpp b/source/prediction/Engine.cpp index 80cf447..47d5ea5 100644 --- a/source/prediction/Engine.cpp +++ b/source/prediction/Engine.cpp @@ -5,7 +5,7 @@ #include "omath/prediction/Engine.h" #include -#include +#include namespace omath::prediction @@ -45,7 +45,7 @@ namespace omath::prediction const Vector3 &targetPosition) const { const auto bulletGravity = m_gravityConstant * projectile.m_gravityScale; - const auto delta = targetPosition - projectile.m_origin;; + const auto delta = targetPosition - projectile.m_origin; const auto distance2d = delta.Length2D(); diff --git a/source/prediction/Projectile.cpp b/source/prediction/Projectile.cpp index 3ce5164..32cbe68 100644 --- a/source/prediction/Projectile.cpp +++ b/source/prediction/Projectile.cpp @@ -8,14 +8,9 @@ namespace omath::prediction { - Vector3 Projectile::CalculateVelocity(const float pitch, const float yaw) const - { - return Vector3::CreateVelocity(pitch, yaw, m_launchSpeed); - } - Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const { - auto currentPos = m_origin + Vector3::CreateVelocity(pitch, yaw, m_launchSpeed) * time; + auto currentPos = m_origin + Vector3::ForwardVector(pitch, yaw) * m_launchSpeed * time; currentPos.z -= (gravity * m_gravityScale) * std::pow(time, 2.f) * 0.5f; return currentPos; diff --git a/source/prediction/Target.cpp b/source/prediction/Target.cpp index 64c58a1..3b4c2da 100644 --- a/source/prediction/Target.cpp +++ b/source/prediction/Target.cpp @@ -3,18 +3,9 @@ // #include "omath/prediction/Target.h" -#include namespace omath::prediction { - Vector3 Target::PredictPosition(const float time, const float gravity) const - { - auto predicted = m_origin + m_velocity * time; - if (m_isAirborne) - predicted.z -= gravity * std::pow(time, 2.f) * 0.5f; - - return predicted; - } } diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 35c79df..f0f7baf 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -5,7 +5,7 @@ #include -#include "omath/angles.h" +#include "omath/Angles.h" namespace omath::projection @@ -30,7 +30,7 @@ namespace omath::projection return Matrix::TranslationMatrix(-m_origin) * Matrix::OrientationMatrix(forward, right, up); } - std::expected Camera::WorldToScreen(const Vector3 &worldPosition) const + std::expected Camera::WorldToScreen(const Vector3 &worldPosition) const { const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); @@ -41,13 +41,13 @@ namespace omath::projection auto projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix); if (projected.At(0, 3) <= 0.f) - return std::unexpected("Projection point is out of camera field of view"); + return std::unexpected(Error::WORLD_POSITION_IS_BEHIND_CAMERA); 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) - return std::unexpected("Projection point is out screen bounds"); + return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); projected *= Matrix::ToScreenMatrix(m_viewPort.m_width, m_viewPort.m_height); diff --git a/tests/UnitTestColor.cpp b/tests/UnitTestColor.cpp index ffe828c..a78276d 100644 --- a/tests/UnitTestColor.cpp +++ b/tests/UnitTestColor.cpp @@ -5,7 +5,7 @@ #include -using namespace omath::color; +using namespace omath; class UnitTestColor : public ::testing::Test { @@ -23,7 +23,7 @@ protected: // Test constructors TEST_F(UnitTestColor, Constructor_Float) { - Color color(0.5f, 0.5f, 0.5f, 1.0f); + constexpr Color color(0.5f, 0.5f, 0.5f, 1.0f); EXPECT_FLOAT_EQ(color.x, 0.5f); EXPECT_FLOAT_EQ(color.y, 0.5f); EXPECT_FLOAT_EQ(color.z, 0.5f); @@ -32,7 +32,7 @@ TEST_F(UnitTestColor, Constructor_Float) TEST_F(UnitTestColor, Constructor_Vector4) { - omath::Vector4 vec(0.2f, 0.4f, 0.6f, 0.8f); + constexpr omath::Vector4 vec(0.2f, 0.4f, 0.6f, 0.8f); Color color(vec); EXPECT_FLOAT_EQ(color.x, 0.2f); EXPECT_FLOAT_EQ(color.y, 0.4f); @@ -43,7 +43,7 @@ TEST_F(UnitTestColor, Constructor_Vector4) // Test static methods for color creation TEST_F(UnitTestColor, FromRGBA) { - Color color = Color::FromRGBA(128, 64, 32, 255); + constexpr Color color = Color::FromRGBA(128, 64, 32, 255); EXPECT_FLOAT_EQ(color.x, 128.0f / 255.0f); EXPECT_FLOAT_EQ(color.y, 64.0f / 255.0f); EXPECT_FLOAT_EQ(color.z, 32.0f / 255.0f); @@ -52,7 +52,7 @@ TEST_F(UnitTestColor, FromRGBA) TEST_F(UnitTestColor, FromHSV) { - Color color = Color::FromHSV(0.0f, 1.0f, 1.0f); // Red in HSV + constexpr Color color = Color::FromHSV(0.0f, 1.0f, 1.0f); // Red in HSV EXPECT_FLOAT_EQ(color.x, 1.0f); EXPECT_FLOAT_EQ(color.y, 0.0f); EXPECT_FLOAT_EQ(color.z, 0.0f); @@ -81,9 +81,9 @@ TEST_F(UnitTestColor, Blend) // Test predefined colors TEST_F(UnitTestColor, PredefinedColors) { - Color red = Color::Red(); - Color green = Color::Green(); - Color blue = Color::Blue(); + constexpr Color red = Color::Red(); + constexpr Color green = Color::Green(); + constexpr Color blue = Color::Blue(); EXPECT_FLOAT_EQ(red.x, 1.0f); EXPECT_FLOAT_EQ(red.y, 0.0f); @@ -104,9 +104,9 @@ TEST_F(UnitTestColor, PredefinedColors) // Test non-member function: Blend for Vector3 TEST_F(UnitTestColor, BlendVector3) { - omath::Vector3 v1(1.0f, 0.0f, 0.0f); // Red - omath::Vector3 v2(0.0f, 1.0f, 0.0f); // Green - omath::Vector3 blended = Blend(v1, v2, 0.5f); + constexpr Color v1(1.0f, 0.0f, 0.0f, 1.f); // Red + constexpr Color v2(0.0f, 1.0f, 0.0f, 1.f); // Green + constexpr Color blended = Blend(v1, v2, 0.5f); EXPECT_FLOAT_EQ(blended.x, 0.5f); EXPECT_FLOAT_EQ(blended.y, 0.5f); EXPECT_FLOAT_EQ(blended.z, 0.0f); diff --git a/tests/UnitTestMatrix.cpp b/tests/UnitTestMatrix.cpp index c2f0840..fb9566f 100644 --- a/tests/UnitTestMatrix.cpp +++ b/tests/UnitTestMatrix.cpp @@ -14,7 +14,8 @@ protected: Matrix m1; Matrix m2; - void SetUp() override { + void SetUp() override + { m1 = Matrix(2, 2); m2 = Matrix{{1.0f, 2.0f}, {3.0f, 4.0f}}; } diff --git a/tests/UnitTestVector2.cpp b/tests/UnitTestVector2.cpp index b75cc3d..3e9740d 100644 --- a/tests/UnitTestVector2.cpp +++ b/tests/UnitTestVector2.cpp @@ -15,7 +15,7 @@ protected: Vector2 v1; Vector2 v2; - void SetUp() override + constexpr void SetUp() override { v1 = Vector2(1.0f, 2.0f); v2 = Vector2(4.0f, 5.0f); @@ -25,14 +25,14 @@ protected: // Test constructor and default values TEST_F(UnitTestVector2, Constructor_Default) { - Vector2 v; + constexpr Vector2 v; EXPECT_FLOAT_EQ(v.x, 0.0f); EXPECT_FLOAT_EQ(v.y, 0.0f); } TEST_F(UnitTestVector2, Constructor_Values) { - Vector2 v(1.0f, 2.0f); + constexpr Vector2 v(1.0f, 2.0f); EXPECT_FLOAT_EQ(v.x, 1.0f); EXPECT_FLOAT_EQ(v.y, 2.0f); } @@ -40,14 +40,14 @@ TEST_F(UnitTestVector2, Constructor_Values) // Test equality operators TEST_F(UnitTestVector2, EqualityOperator) { - Vector2 v3(1.0f, 2.0f); + constexpr Vector2 v3(1.0f, 2.0f); EXPECT_TRUE(v1 == v3); EXPECT_FALSE(v1 == v2); } TEST_F(UnitTestVector2, InequalityOperator) { - Vector2 v3(1.0f, 2.0f); + constexpr Vector2 v3(1.0f, 2.0f); EXPECT_FALSE(v1 != v3); EXPECT_TRUE(v1 != v2); } @@ -55,28 +55,28 @@ TEST_F(UnitTestVector2, InequalityOperator) // Test arithmetic operators TEST_F(UnitTestVector2, AdditionOperator) { - Vector2 v3 = v1 + v2; + constexpr Vector2 v3 = Vector2(1.0f, 2.0f) + Vector2(4.0f, 5.0f); EXPECT_FLOAT_EQ(v3.x, 5.0f); EXPECT_FLOAT_EQ(v3.y, 7.0f); } TEST_F(UnitTestVector2, SubtractionOperator) { - Vector2 v3 = v2 - v1; + constexpr Vector2 v3 = Vector2(4.0f, 5.0f) - Vector2(1.0f, 2.0f); EXPECT_FLOAT_EQ(v3.x, 3.0f); EXPECT_FLOAT_EQ(v3.y, 3.0f); } TEST_F(UnitTestVector2, MultiplicationOperator) { - Vector2 v3 = v1 * 2.0f; + constexpr Vector2 v3 = Vector2(1.0f, 2.0f) * 2.0f; EXPECT_FLOAT_EQ(v3.x, 2.0f); EXPECT_FLOAT_EQ(v3.y, 4.0f); } TEST_F(UnitTestVector2, DivisionOperator) { - Vector2 v3 = v2 / 2.0f; + constexpr Vector2 v3 = Vector2(4.0f, 5.0f) / 2.0f; EXPECT_FLOAT_EQ(v3.x, 2.0f); EXPECT_FLOAT_EQ(v3.y, 2.5f); } @@ -112,59 +112,62 @@ TEST_F(UnitTestVector2, DivisionAssignmentOperator) TEST_F(UnitTestVector2, NegationOperator) { - Vector2 v3 = -v1; + constexpr Vector2 v3 = -Vector2(1.0f, 2.0f); EXPECT_FLOAT_EQ(v3.x, -1.0f); EXPECT_FLOAT_EQ(v3.y, -2.0f); } - // Test other member functions TEST_F(UnitTestVector2, DistTo) { - float dist = v1.DistTo(v2); - EXPECT_FLOAT_EQ(dist, sqrt(18.0f)); + const float dist = v1.DistTo(v2); + EXPECT_FLOAT_EQ(dist, std::sqrt(18.0f)); } TEST_F(UnitTestVector2, DistToSqr) { - float distSqr = v1.DistToSqr(v2); + constexpr float distSqr = Vector2(1.0f, 2.0f).DistToSqr(Vector2(4.0f, 5.0f)); EXPECT_FLOAT_EQ(distSqr, 18.0f); } TEST_F(UnitTestVector2, DotProduct) { - float dot = v1.Dot(v2); + constexpr float dot = Vector2(1.0f, 2.0f).Dot(Vector2(4.0f, 5.0f)); EXPECT_FLOAT_EQ(dot, 14.0f); } TEST_F(UnitTestVector2, Length) { - float length = v1.Length(); - EXPECT_FLOAT_EQ(length, sqrt(5.0f)); + const float length = v1.Length(); + EXPECT_FLOAT_EQ(length, std::sqrt(5.0f)); } TEST_F(UnitTestVector2, LengthSqr) { - float lengthSqr = v1.LengthSqr(); + constexpr float lengthSqr = Vector2(1.0f, 2.0f).LengthSqr(); EXPECT_FLOAT_EQ(lengthSqr, 5.0f); } TEST_F(UnitTestVector2, Abs) { - Vector2 v3(-1.0f, -2.0f); - v3.Abs(); + constexpr Vector2 v3 = Vector2(-1.0f, -2.0f).Abs(); EXPECT_FLOAT_EQ(v3.x, 1.0f); EXPECT_FLOAT_EQ(v3.y, 2.0f); } TEST_F(UnitTestVector2, Sum) { - float sum = v1.Sum(); + constexpr float sum = Vector2(1.0f, 2.0f).Sum(); EXPECT_FLOAT_EQ(sum, 3.0f); } TEST_F(UnitTestVector2, Normalized) { - Vector2 v3 = v1.Normalized(); + const Vector2 v3 = v1.Normalized(); EXPECT_NEAR(v3.x, 0.44721f, 0.0001f); EXPECT_NEAR(v3.y, 0.89443f, 0.0001f); } + +static_assert(Vector2(1.0f, 2.0f).LengthSqr() == 5.0f, "LengthSqr should be 5"); +static_assert(Vector2(1.0f, 2.0f).Dot(Vector2(4.0f, 5.0f)) == 14.0f, "Dot product should be 14"); +static_assert(Vector2(4.0f, 5.0f).DistToSqr(Vector2(1.0f, 2.0f)) == 18.0f, "DistToSqr should be 18"); +static_assert(Vector2(-1.0f, -2.0f).Abs() == Vector2(1.0f, 2.0f), "Abs should convert negative values to positive"); diff --git a/tests/UnitTestVector3.cpp b/tests/UnitTestVector3.cpp index e55b786..daa59dc 100644 --- a/tests/UnitTestVector3.cpp +++ b/tests/UnitTestVector3.cpp @@ -3,6 +3,7 @@ // #include #include +#include using namespace omath; @@ -12,7 +13,7 @@ protected: Vector3 v1; Vector3 v2; - void SetUp() override + constexpr void SetUp() override { v1 = Vector3(1.0f, 2.0f, 3.0f); v2 = Vector3(4.0f, 5.0f, 6.0f); @@ -22,7 +23,7 @@ protected: // Test constructor and default values TEST_F(UnitTestVector3, Constructor_Default) { - Vector3 v; + constexpr Vector3 v; EXPECT_FLOAT_EQ(v.x, 0.0f); EXPECT_FLOAT_EQ(v.y, 0.0f); EXPECT_FLOAT_EQ(v.z, 0.0f); @@ -30,7 +31,7 @@ TEST_F(UnitTestVector3, Constructor_Default) TEST_F(UnitTestVector3, Constructor_Values) { - Vector3 v(1.0f, 2.0f, 3.0f); + constexpr Vector3 v(1.0f, 2.0f, 3.0f); EXPECT_FLOAT_EQ(v.x, 1.0f); EXPECT_FLOAT_EQ(v.y, 2.0f); EXPECT_FLOAT_EQ(v.z, 3.0f); @@ -39,14 +40,14 @@ TEST_F(UnitTestVector3, Constructor_Values) // Test equality operators TEST_F(UnitTestVector3, EqualityOperator) { - Vector3 v3(1.0f, 2.0f, 3.0f); + constexpr Vector3 v3(1.0f, 2.0f, 3.0f); EXPECT_TRUE(v1 == v3); EXPECT_FALSE(v1 == v2); } TEST_F(UnitTestVector3, InequalityOperator) { - Vector3 v3(1.0f, 2.0f, 3.0f); + constexpr Vector3 v3(1.0f, 2.0f, 3.0f); EXPECT_FALSE(v1 != v3); EXPECT_TRUE(v1 != v2); } @@ -54,7 +55,7 @@ TEST_F(UnitTestVector3, InequalityOperator) // Test arithmetic operators TEST_F(UnitTestVector3, AdditionOperator) { - Vector3 v3 = v1 + v2; + constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f) + Vector3(4.0f, 5.0f, 6.0f); EXPECT_FLOAT_EQ(v3.x, 5.0f); EXPECT_FLOAT_EQ(v3.y, 7.0f); EXPECT_FLOAT_EQ(v3.z, 9.0f); @@ -62,7 +63,7 @@ TEST_F(UnitTestVector3, AdditionOperator) TEST_F(UnitTestVector3, SubtractionOperator) { - Vector3 v3 = v2 - v1; + constexpr Vector3 v3 = Vector3(4.0f, 5.0f, 6.0f) - Vector3(1.0f, 2.0f, 3.0f); EXPECT_FLOAT_EQ(v3.x, 3.0f); EXPECT_FLOAT_EQ(v3.y, 3.0f); EXPECT_FLOAT_EQ(v3.z, 3.0f); @@ -70,7 +71,7 @@ TEST_F(UnitTestVector3, SubtractionOperator) TEST_F(UnitTestVector3, MultiplicationOperator) { - Vector3 v3 = v1 * 2.0f; + constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f) * 2.0f; EXPECT_FLOAT_EQ(v3.x, 2.0f); EXPECT_FLOAT_EQ(v3.y, 4.0f); EXPECT_FLOAT_EQ(v3.z, 6.0f); @@ -78,7 +79,7 @@ TEST_F(UnitTestVector3, MultiplicationOperator) TEST_F(UnitTestVector3, MultiplicationWithVectorOperator) { - Vector3 v3 = v1 * v2; + constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f) * Vector3(4.0f, 5.0f, 6.0f); EXPECT_FLOAT_EQ(v3.x, 4.0f); EXPECT_FLOAT_EQ(v3.y, 10.0f); EXPECT_FLOAT_EQ(v3.z, 18.0f); @@ -86,7 +87,7 @@ TEST_F(UnitTestVector3, MultiplicationWithVectorOperator) TEST_F(UnitTestVector3, DivisionOperator) { - Vector3 v3 = v2 / 2.0f; + constexpr Vector3 v3 = Vector3(4.0f, 5.0f, 6.0f) / 2.0f; EXPECT_FLOAT_EQ(v3.x, 2.0f); EXPECT_FLOAT_EQ(v3.y, 2.5f); EXPECT_FLOAT_EQ(v3.z, 3.0f); @@ -94,7 +95,7 @@ TEST_F(UnitTestVector3, DivisionOperator) TEST_F(UnitTestVector3, DivisionWithVectorOperator) { - Vector3 v3 = v2 / v1; + constexpr Vector3 v3 = Vector3(4.0f, 5.0f, 6.0f) / Vector3(1.0f, 2.0f, 3.0f); EXPECT_FLOAT_EQ(v3.x, 4.0f); EXPECT_FLOAT_EQ(v3.y, 2.5f); EXPECT_FLOAT_EQ(v3.z, 2.0f); @@ -151,61 +152,34 @@ TEST_F(UnitTestVector3, DivisionWithVectorAssignmentOperator) TEST_F(UnitTestVector3, NegationOperator) { - Vector3 v3 = -v1; + constexpr Vector3 v3 = -Vector3(1.0f, 2.0f, 3.0f); EXPECT_FLOAT_EQ(v3.x, -1.0f); EXPECT_FLOAT_EQ(v3.y, -2.0f); EXPECT_FLOAT_EQ(v3.z, -3.0f); } // Test other member functions -TEST_F(UnitTestVector3, DistTo) -{ - float dist = v1.DistTo(v2); - EXPECT_FLOAT_EQ(dist, sqrt(27.0f)); -} - TEST_F(UnitTestVector3, DistToSqr) { - float distSqr = v1.DistToSqr(v2); + constexpr float distSqr = Vector3(1.0f, 2.0f, 3.0f).DistToSqr(Vector3(4.0f, 5.0f, 6.0f)); EXPECT_FLOAT_EQ(distSqr, 27.0f); } TEST_F(UnitTestVector3, DotProduct) { - float dot = v1.Dot(v2); + constexpr float dot = Vector3(1.0f, 2.0f, 3.0f).Dot(Vector3(4.0f, 5.0f, 6.0f)); EXPECT_FLOAT_EQ(dot, 32.0f); } -TEST_F(UnitTestVector3, CrossProduct) -{ - Vector3 v3 = v1.Cross(v2); - EXPECT_FLOAT_EQ(v3.x, -3.0f); - EXPECT_FLOAT_EQ(v3.y, 6.0f); - EXPECT_FLOAT_EQ(v3.z, -3.0f); -} - -TEST_F(UnitTestVector3, Length) -{ - float length = v1.Length(); - EXPECT_FLOAT_EQ(length, sqrt(14.0f)); -} - TEST_F(UnitTestVector3, LengthSqr) { - float lengthSqr = v1.LengthSqr(); + constexpr float lengthSqr = Vector3(1.0f, 2.0f, 3.0f).LengthSqr(); EXPECT_FLOAT_EQ(lengthSqr, 14.0f); } -TEST_F(UnitTestVector3, Length2D) -{ - float length2D = v1.Length2D(); - EXPECT_FLOAT_EQ(length2D, sqrt(5.0f)); -} - TEST_F(UnitTestVector3, Abs) { - Vector3 v3(-1.0f, -2.0f, -3.0f); - v3.Abs(); + constexpr Vector3 v3 = Vector3(-1.0f, -2.0f, -3.0f).Abs(); EXPECT_FLOAT_EQ(v3.x, 1.0f); EXPECT_FLOAT_EQ(v3.y, 2.0f); EXPECT_FLOAT_EQ(v3.z, 3.0f); @@ -213,51 +187,26 @@ TEST_F(UnitTestVector3, Abs) TEST_F(UnitTestVector3, Sum) { - float sum = v1.Sum(); + constexpr float sum = Vector3(1.0f, 2.0f, 3.0f).Sum(); EXPECT_FLOAT_EQ(sum, 6.0f); } TEST_F(UnitTestVector3, Sum2D) { - float sum2D = v1.Sum2D(); + constexpr float sum2D = Vector3(1.0f, 2.0f, 3.0f).Sum2D(); EXPECT_FLOAT_EQ(sum2D, 3.0f); } -TEST_F(UnitTestVector3, ViewAngleTo) +TEST_F(UnitTestVector3, CrossProduct) { - Vector3 angle = v1.ViewAngleTo(v1 + Vector3(0.f, 0.f, 5.f)); - EXPECT_NEAR(angle.x, 90.f, 0.01f); // Approximate values, you can fine-tune the expected values - EXPECT_NEAR(angle.y, 0.f, 0.01f); + constexpr Vector3 v3 = Vector3(1.0f, 2.0f, 3.0f).Cross(Vector3(4.0f, 5.0f, 6.0f)); + EXPECT_FLOAT_EQ(v3.x, -3.0f); + EXPECT_FLOAT_EQ(v3.y, 6.0f); + EXPECT_FLOAT_EQ(v3.z, -3.0f); } -TEST_F(UnitTestVector3, ForwardVector) -{ - Vector3 forward = Vector3::ForwardVector(0.0f, 0.0f); - EXPECT_FLOAT_EQ(forward.x, 1.0f); - EXPECT_FLOAT_EQ(forward.y, 0.0f); - EXPECT_FLOAT_EQ(forward.z, 0.0f); -} - -TEST_F(UnitTestVector3, RightVector) -{ - Vector3 right = Vector3::RightVector(0.0f, 0.0f, 0.0f); - EXPECT_FLOAT_EQ(right.x, 0.0f); - EXPECT_FLOAT_EQ(right.y, -1.0f); - EXPECT_FLOAT_EQ(right.z, 0.0f); -} - -TEST_F(UnitTestVector3, UpVector) -{ - Vector3 up = Vector3::UpVector(0.f, 0.0f, 0.0f); - EXPECT_FLOAT_EQ(up.x, 0.0f); - EXPECT_FLOAT_EQ(up.y, 0.0f); - EXPECT_FLOAT_EQ(up.z, 1.0f); -} - -TEST_F(UnitTestVector3, Normalized) -{ - Vector3 v3 = v1.Normalized(); - EXPECT_NEAR(v3.x, 0.26726f, 0.0001f); - EXPECT_NEAR(v3.y, 0.53452f, 0.0001f); - EXPECT_NEAR(v3.z, 0.80178f, 0.0001f); -} \ No newline at end of file +// Test constexpr with static_assert +static_assert(Vector3(1.0f, 2.0f, 3.0f).LengthSqr() == 14.0f, "LengthSqr should be 14"); +static_assert(Vector3(1.0f, 2.0f, 3.0f).Dot(Vector3(4.0f, 5.0f, 6.0f)) == 32.0f, "Dot product should be 32"); +static_assert(Vector3(4.0f, 5.0f, 6.0f).DistToSqr(Vector3(1.0f, 2.0f, 3.0f)) == 27.0f, "DistToSqr should be 27"); +static_assert(Vector3(-1.0f, -2.0f, -3.0f).Abs() == Vector3(1.0f, 2.0f, 3.0f), "Abs should convert negative values to positive");