Compare commits

..

9 Commits

Author SHA1 Message Date
a097c0a2f4 Merge pull request #57 from orange-cpp/feature/added_formatters
Adds std::format support for math types
2025-08-26 12:37:13 +03:00
20ae2b4dd1 Adds formatters for Angle and Color
Adds formatters for `omath::Angle` and `omath::Color` to allow for easy formatting using `std::format`.

This allows users to easily output Angle and Color values in a human-readable format.
2025-08-26 12:35:40 +03:00
115b5a3471 Adds std::format support for math types
Adds `std::formatter` specializations for `Mat`, `Vector2`, `Vector3`, and `Vector4` types, enabling the use of `std::format` for these types.

This simplifies formatting and printing of these mathematical objects, improving code readability and consistency.

Also adds a hash function specialization for Vector3.
2025-08-26 12:22:33 +03:00
77893629f9 Adds omath library header
Creates the main omath header file that includes all
omath library components. This provides a single point
of inclusion for the entire library, simplifying usage
and dependency management.

Also, adjusts the return types for projectile prediction
functions within the legacy engine to explicitly use
the `Vector3` type for consistency and clarity.
2025-08-25 22:33:00 +03:00
afb27b1aa9 Adds build test status message
Adds a status message to the build process that displays whether unit tests are enabled.

This provides better visibility into the build configuration.
2025-08-25 22:11:39 +03:00
61006122ae Displays build configuration options
Prints the values of various CMake configuration options to the console during the build process.

This provides better visibility into the build configuration and helps with debugging build-related issues.
2025-08-25 22:10:10 +03:00
4eb0f59fc0 Updates build status message
Updates the build status message in CMake to include the project name, providing more context during the build process.
2025-08-25 21:59:25 +03:00
3b4bf24a16 Updates project version to 3.3.0
Increments the project version number in CMakeLists.txt
from 3.2.1 to 3.3.0.
2025-08-25 21:57:07 +03:00
51d93c4464 Removes outdated header comments
Removes redundant and outdated header comments. These comments are no longer necessary for maintaining the codebase.
2025-08-25 21:54:59 +03:00
11 changed files with 208 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.26) cmake_minimum_required(VERSION 3.26)
project(omath VERSION 3.2.1 LANGUAGES CXX) project(omath VERSION 3.3.0 LANGUAGES CXX)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
@@ -16,6 +16,16 @@ option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" ON) option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" ON)
option(OMATH_ENABLE_LEGACY "Will enable legacy classes that MUST be used ONLY for backward compatibility" OFF) option(OMATH_ENABLE_LEGACY "Will enable legacy classes that MUST be used ONLY for backward compatibility" OFF)
message(STATUS "[${PROJECT_NAME}]: Building on ${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "[${PROJECT_NAME}]: Warnings as errors ${OMATH_THREAT_WARNING_AS_ERROR}")
message(STATUS "[${PROJECT_NAME}]: Build unit tests ${OMATH_BUILD_TESTS}")
message(STATUS "[${PROJECT_NAME}]: As dynamic library ${OMATH_BUILD_AS_SHARED_LIBRARY}")
message(STATUS "[${PROJECT_NAME}]: Static C++ runtime ${OMATH_STATIC_MSVC_RUNTIME_LIBRARY}")
message(STATUS "[${PROJECT_NAME}]: CMake unity build ${OMATH_USE_UNITY_BUILD}")
message(STATUS "[${PROJECT_NAME}]: Example projects ${OMATH_BUILD_EXAMPLES}")
message(STATUS "[${PROJECT_NAME}]: AVX2 feature status ${OMATH_USE_AVX2}")
message(STATUS "[${PROJECT_NAME}]: ImGUI integration feature status ${OMATH_IMGUI_INTEGRATION}")
message(STATUS "[${PROJECT_NAME}]: Legacy features support ${OMATH_ENABLE_LEGACY}")
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp") file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp") file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
@@ -27,8 +37,6 @@ else ()
add_library(${PROJECT_NAME} STATIC ${OMATH_SOURCES} ${OMATH_HEADERS}) add_library(${PROJECT_NAME} STATIC ${OMATH_SOURCES} ${OMATH_HEADERS})
endif () endif ()
message(STATUS "[OMATH]: Building on ${CMAKE_HOST_SYSTEM_NAME}")
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
if (OMATH_IMGUI_INTEGRATION) if (OMATH_IMGUI_INTEGRATION)

View File

@@ -6,6 +6,7 @@
#include "omath/angles.hpp" #include "omath/angles.hpp"
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <format>
namespace omath namespace omath
{ {
@@ -149,3 +150,17 @@ namespace omath
} }
}; };
} // namespace omath } // namespace omath
template<class Type, Type min, Type max, omath::AngleFlags flags>
struct std::formatter<omath::Angle<Type, min, max, flags>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Angle<Type, min, max, flags>& deg, std::format_context& ctx)
{
return std::format_to(ctx.out(), "{}deg", deg.as_degrees());
}
};

View File

@@ -167,3 +167,21 @@ namespace omath
#endif #endif
}; };
} // namespace omath } // namespace omath
template<>
struct std::formatter<omath::Color> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Color& col, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[r:{}, g:{}, b:{}, a:{}]",
static_cast<int>(col.x * 255.f),
static_cast<int>(col.y * 255.f),
static_cast<int>(col.z * 255.f),
static_cast<int>(col.w * 255.f));
}
};

View File

@@ -480,3 +480,19 @@ namespace omath
{0.f, 0.f, -1.f, 0.f}}; {0.f, 0.f, -1.f, 0.f}};
} }
} // namespace omath } // namespace omath
template<size_t Rows, size_t Columns, class Type, omath::MatStoreType StoreType>
struct std::formatter<omath::Mat<Rows, Columns, Type, StoreType>> // NOLINT(*-dcl58-cpp)
{
using MatType = omath::Mat<Rows, Columns, Type, StoreType>;
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const MatType& mat, std::format_context& ctx)
{
return std::format_to(ctx.out(), "{}", mat.to_string());
}
};

84
include/omath/omath.hpp Normal file
View File

@@ -0,0 +1,84 @@
//
// omath.hpp - Main header file that includes all omath library components
// Created for the omath library
//
#pragma once
// Basic math utilities
#include "omath/angles.hpp"
#include "omath/angle.hpp"
// Vector classes (in dependency order)
#include "omath/vector2.hpp"
#include "omath/vector3.hpp"
#include "omath/vector4.hpp"
// Matrix classes
#include "omath/mat.hpp"
#include "omath/matrix.hpp"
// Color functionality
#include "omath/color.hpp"
// Geometric primitives
#include "omath/triangle.hpp"
#include "omath/view_angles.hpp"
// 3D primitives
#include "omath/3d_primitives/box.hpp"
// Collision detection
#include "omath/collision/line_tracer.hpp"
// Pathfinding algorithms
#include "omath/pathfinding/a_star.hpp"
#include "omath/pathfinding/navigation_mesh.hpp"
// Projectile prediction
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/projectile_prediction/proj_pred_engine.hpp"
#include "omath/projectile_prediction/proj_pred_engine_legacy.hpp"
#include "omath/projectile_prediction/proj_pred_engine_avx2.hpp"
// Projection functionality
#include "omath/projection/error_codes.hpp"
#include "omath/projection/camera.hpp"
// Engine-specific implementations
// IW Engine
#include "omath/engines/iw_engine/constants.hpp"
#include "omath/engines/iw_engine/formulas.hpp"
#include "omath/engines/iw_engine/camera.hpp"
#include "omath/engines/iw_engine/traits/camera_trait.hpp"
#include "omath/engines/iw_engine/traits/pred_engine_trait.hpp"
// OpenGL Engine
#include "omath/engines/opengl_engine/constants.hpp"
#include "omath/engines/opengl_engine/formulas.hpp"
#include "omath/engines/opengl_engine/camera.hpp"
#include "omath/engines/opengl_engine/traits/camera_trait.hpp"
#include "omath/engines/opengl_engine/traits/pred_engine_trait.hpp"
// Source Engine
#include "omath/engines/source_engine/constants.hpp"
#include "omath/engines/source_engine/formulas.hpp"
#include "omath/engines/source_engine/camera.hpp"
#include "omath/engines/source_engine/traits/camera_trait.hpp"
#include "omath/engines/source_engine/traits/pred_engine_trait.hpp"
// Unity Engine
#include "omath/engines/unity_engine/constants.hpp"
#include "omath/engines/unity_engine/formulas.hpp"
#include "omath/engines/unity_engine/camera.hpp"
#include "omath/engines/unity_engine/traits/camera_trait.hpp"
#include "omath/engines/unity_engine/traits/pred_engine_trait.hpp"
// Unreal Engine
#include "omath/engines/unreal_engine/constants.hpp"
#include "omath/engines/unreal_engine/formulas.hpp"
#include "omath/engines/unreal_engine/camera.hpp"
#include "omath/engines/unreal_engine/traits/camera_trait.hpp"
#include "omath/engines/unreal_engine/traits/pred_engine_trait.hpp"

View File

@@ -20,11 +20,11 @@ namespace omath::projectile_prediction
Vector3<float> v3, // by-value for calc_viewpoint_from_angles Vector3<float> v3, // by-value for calc_viewpoint_from_angles
float pitch, float yaw, float time, float gravity, std::optional<float> maybe_pitch) { float pitch, float yaw, float time, float gravity, std::optional<float> maybe_pitch) {
// Presence + return types // Presence + return types
{ T::predict_projectile_position(projectile, pitch, yaw, time, gravity) } -> std::same_as<Vec3>; { T::predict_projectile_position(projectile, pitch, yaw, time, gravity) } -> std::same_as<Vector3<float>>;
{ T::predict_target_position(target, time, gravity) } -> std::same_as<Vec3>; { T::predict_target_position(target, time, gravity) } -> std::same_as<Vector3<float>>;
{ T::calc_vector_2d_distance(vec_a) } -> std::same_as<float>; { T::calc_vector_2d_distance(vec_a) } -> std::same_as<float>;
{ T::get_vector_height_coordinate(vec_b) } -> std::same_as<float>; { T::get_vector_height_coordinate(vec_b) } -> std::same_as<float>;
{ T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as<Vec3>; { T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as<Vector3<float>>;
{ T::calc_direct_pitch_angle(vec_a, vec_b) } -> std::same_as<float>; { T::calc_direct_pitch_angle(vec_a, vec_b) } -> std::same_as<float>;
{ T::calc_direct_yaw_angle(vec_a, vec_b) } -> std::same_as<float>; { T::calc_direct_yaw_angle(vec_a, vec_b) } -> std::same_as<float>;

View File

@@ -3,7 +3,9 @@
// //
#pragma once #pragma once
#include "vector3.hpp"
#include <cmath> #include <cmath>
#include <format>
#include <tuple> #include <tuple>
#ifdef OMATH_IMGUI_INTEGRATION #ifdef OMATH_IMGUI_INTEGRATION
@@ -218,7 +220,6 @@ namespace omath
{ {
return std::make_tuple(x, y); return std::make_tuple(x, y);
} }
#ifdef OMATH_IMGUI_INTEGRATION #ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]] [[nodiscard]]
ImVec2 to_im_vec2() const noexcept ImVec2 to_im_vec2() const noexcept
@@ -233,3 +234,18 @@ namespace omath
#endif #endif
}; };
} // namespace omath } // namespace omath
template<class Type>
struct std::formatter<omath::Vector2<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector2<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y);
}
};

View File

@@ -159,9 +159,9 @@ namespace omath
return Vector2<Type>::length(); return Vector2<Type>::length();
} }
[[nodiscard]] Type distance_to(const Vector3& vOther) const noexcept [[nodiscard]] Type distance_to(const Vector3& v_other) const noexcept
{ {
return (*this - vOther).length(); return (*this - v_other).length();
} }
#endif #endif
@@ -279,21 +279,33 @@ namespace omath
} }
}; };
} // namespace omath } // namespace omath
// ReSharper disable once CppRedundantNamespaceDefinition
namespace std template<> struct std::hash<omath::Vector3<float>>
{ {
template<> struct hash<omath::Vector3<float>> std::size_t operator()(const omath::Vector3<float>& vec) const noexcept
{ {
std::size_t operator()(const omath::Vector3<float>& vec) const noexcept std::size_t hash = 0;
{ constexpr std::hash<float> hasher;
std::size_t hash = 0;
constexpr std::hash<float> hasher;
hash ^= hasher(vec.x) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.x) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.z) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.z) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
return hash; return hash;
} }
}; };
} // namespace std
template<class Type>
struct std::formatter<omath::Vector3<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector3<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}, {}]", vec.x, vec.y, vec.z);
}
};

View File

@@ -201,3 +201,18 @@ namespace omath
#endif #endif
}; };
} // namespace omath } // namespace omath
template<class Type>
struct std::formatter<omath::Vector4<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector4<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}, {}, {}]", vec.x, vec.y, vec.z, vec.w);
}
};

View File

@@ -1,7 +1,4 @@
// //
// Created by Vlad on 8/25/2025.
//
//
// Created by Orange on 11/27/2024. // Created by Orange on 11/27/2024.
// //
#include <gtest/gtest.h> #include <gtest/gtest.h>

View File

@@ -125,7 +125,7 @@ TEST_F(UnitTestMat, Clear)
TEST_F(UnitTestMat, ToString) TEST_F(UnitTestMat, ToString)
{ {
const std::string str = m2.to_string(); const std::string str = std::format("{}", m2);
EXPECT_FALSE(str.empty()); EXPECT_FALSE(str.empty());
EXPECT_EQ(str, "[[ 1.000, 2.000]\n [ 3.000, 4.000]]"); EXPECT_EQ(str, "[[ 1.000, 2.000]\n [ 3.000, 4.000]]");
} }