38 Commits

Author SHA1 Message Date
812850393b force disabled tests 2025-10-27 11:22:24 +03:00
98f8875dfc Merge pull request #92 from orange-cpp/feature/projection_utility
added vcpkg integration
2025-10-27 11:11:28 +03:00
659072cf4c considered to switch to v4 2025-10-27 11:05:55 +03:00
0e05e013fe updated version 2025-10-27 10:59:30 +03:00
f4f385bc46 patch 2025-10-27 10:58:26 +03:00
dd5d2d5541 Adds default and artifact registries
Configures the default Vcpkg registry and adds an artifact registry
for the microsoft catalog. This enables the tool to find and use
pre-built packages from the Microsoft catalog.
2025-10-27 10:57:57 +03:00
5c37e39358 Adds Darwin build presets with Vcpkg support
Adds new CMake presets for Darwin platforms, including debug and release configurations with optional Vcpkg integration.
This allows for easier builds on Darwin systems utilizing pre-built libraries from Vcpkg.
2025-10-27 09:57:12 +03:00
0a7f69aeb0 Update CMake configuration for Vcpkg integration and feature enablement.
Enables features and sets build configurations via Vcpkg manifest.
Adds new presets for Windows and Linux debug/release builds using Vcpkg.
Conditionally enables features (imgui, avx2, tests, benchmark) based on Vcpkg manifest features.
2025-10-27 09:55:49 +03:00
eea6195ec2 Fixes invalid NT header check in variant
Ensures the NT header signature check uses a capture to avoid potential issues with variable scope.
2025-10-27 09:22:00 +03:00
969ba6fd34 Disables Vcpkg build override
Disables the automatic override of build options by Vcpkg.

This prevents unintended consequences when using Vcpkg and allows for more control over the build process.
2025-10-27 09:19:51 +03:00
310e4989dd Disables tests and benchmarks by default for VCPKG
Changes the default state of `OMATH_BUILD_TESTS` and `OMATH_BUILD_BENCHMARK` to OFF when built via VCPKG.

Previously, these flags were inherited from the project's top level. This change ensures that these are explicitly enabled via VCPKG manifest features, providing better control over build configuration.
2025-10-27 09:19:09 +03:00
c54ec32864 Links tests to gtest when available
Conditionally links the test target to gtest when it is available,
rather than requiring the OMATH_BUILD_VIA_VCPKG flag to be false.
This allows for a more flexible test setup.
2025-10-27 09:05:40 +03:00
7c63336090 fix 2025-10-27 08:59:42 +03:00
1eadf24553 Removes baseline from omath vcpkg.json
Eliminates the `builtin-baseline` setting from the omath vcpkg.json file.
This setting is no longer necessary.
2025-10-27 08:56:37 +03:00
683b323396 fix 2025-10-27 08:51:58 +03:00
4ae6549405 fix 2025-10-27 08:41:22 +03:00
bc24ee0328 fix 2025-10-27 08:37:55 +03:00
86dc35fb8d fix 2025-10-27 08:36:48 +03:00
62010ae7be Update build system and enable VCPKG
Migrates to CMake presets and enables VCPKG to manage dependencies.
Removes explicit submodule configuration.
Updates benchmark and googletest to be integrated or linked properly.
The goal is to ease the build process and reduce complexity related to linking and dependency management.
2025-10-27 08:34:05 +03:00
3e2a40d5e8 Configures CMake for Vcpkg integration
Sets up CMake presets to utilize the Vcpkg toolchain.

Specifies the Vcpkg root directory and manifest features.

Defines the installation directory for Vcpkg packages.

Forces the usage of Ninja as the make program.
2025-10-27 08:11:13 +03:00
f218e8fff4 Enables Vcpkg usage for CMake builds
Configures CMake to utilize vcpkg for dependency management on both Linux and Windows platforms.
This ensures consistent build environments across different operating systems and simplifies the integration of external libraries.
2025-10-27 08:07:25 +03:00
52b320c642 fix 2025-10-27 08:03:42 +03:00
f2cbdd73a9 Adds Vcpkg setup to CI workflows
Adds vcpkg setup for Arch Linux and Windows CI jobs.

This ensures consistent dependency management and builds via Vcpkg for both platforms and enables OMath to build via vcpkg.
Clones the vcpkg repository and bootstraps it during the job execution.
2025-10-27 08:00:53 +03:00
22c01a83b9 Adds vcpkg integration and updates build configuration
Configures CMakePresets.json to utilize vcpkg for dependency management.
Adds support for building with vcpkg.

Adds error message for missing VCPKG_ROOT environment variable.
Adds explicit VCPKG_MANIFEST_FEATURES and VCPKG_INSTALLED_DIR to CMakePresets.json.
Adds benchmark dependency to vcpkg.json.
2025-10-27 07:53:53 +03:00
61abf6e893 Adds support for tests and benchmarks via Vcpkg features
Enables building unit tests using GTest and benchmarks using Benchmark,
through Vcpkg features.

Adds `tests` and `benchmark` features to `vcpkg.json`,
and adds corresponding CMake logic to control their build based on
Vcpkg manifest features.
2025-10-27 06:42:43 +03:00
e6a5f00f15 Fix formatting and spacing in LICENSE file
Corrected formatting and removed extra spaces in the LICENSE file.
2025-10-27 02:32:06 +03:00
65ba237c6e added additional check 2025-10-23 06:43:09 +03:00
55041384c5 added vcpkg manifest file 2025-10-23 06:35:22 +03:00
25dc212b08 added contained type alias 2025-10-23 06:26:57 +03:00
4f4c911e4d fix 2025-10-23 01:08:19 +03:00
652147f0bb Remove 'future' from affiliation clause in LICENSE 2025-10-23 01:00:40 +03:00
44f8a52c44 added frostbite into global header 2025-10-23 00:55:49 +03:00
555786819f added Frostbite into readme 2025-10-23 00:50:35 +03:00
41bec6c6cd deleted not needed header 2025-10-23 00:49:54 +03:00
93ab7a9b79 updated comments 2025-10-23 00:48:54 +03:00
c0481ef3fa Merge pull request #91 from orange-cpp/feature/frostbite_engine
Defines constants for Frostbite engine
2025-10-23 00:18:07 +03:00
a22feeb1b9 added frostbite sources 2025-10-23 00:08:17 +03:00
2e41aa496f Defines constants for Frostbite engine
Introduces a constants header file for the Frostbite engine,
including common vectors, matrices, and angle types.
This provides a centralized location for defining and accessing
essential mathematical constants used throughout the engine.
2025-10-21 04:56:49 +03:00
29 changed files with 755 additions and 62 deletions

View File

@@ -19,23 +19,28 @@ jobs:
name: Arch Linux (Clang)
runs-on: ubuntu-latest
container: archlinux:latest
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
steps:
- name: Install basic tool-chain with pacman
shell: bash
run: |
pacman -Sy --noconfirm archlinux-keyring
pacman -Syu --noconfirm --needed \
git base-devel clang cmake ninja
git base-devel clang cmake ninja zip unzip fmt
- name: Checkout repository (with sub-modules)
uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up vcpkg
shell: bash
run: |
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
- name: Configure (cmake --preset)
shell: bash
run: cmake --preset linux-release -DOMATH_BUILD_TESTS=ON -DOMATH_BUILD_BENCHMARK=OFF
run: cmake --preset linux-release -DOMATH_BUILD_TESTS=ON -DOMATH_BUILD_BENCHMARK=OFF -DOMATH_BUILD_VIA_VCPKG=ON -DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
- name: Build
shell: bash
@@ -47,12 +52,14 @@ jobs:
##############################################################################
# 2) Windows MSVC / Ninja
##############################################################################
##############################################################################
# 2) Windows MSVC / Ninja
##############################################################################
windows-build-and-test:
name: Windows (MSVC)
runs-on: windows-latest
env:
OMATH_BUILD_VIA_VCPKG: ON
steps:
- name: Checkout repository (with sub-modules)
@@ -68,7 +75,7 @@ jobs:
- name: Configure (cmake --preset)
shell: bash
run: cmake --preset windows-release -DOMATH_BUILD_TESTS=ON -DOMATH_BUILD_BENCHMARK=OFF
run: cmake --preset windows-release -DOMATH_BUILD_TESTS=ON -DOMATH_BUILD_BENCHMARK=OFF -DOMATH_BUILD_VIA_VCPKG=ON -DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests"
- name: Build
shell: bash

6
.gitmodules vendored
View File

@@ -1,6 +0,0 @@
[submodule "extlibs/googletest"]
path = extlibs/googletest
url = https://github.com/google/googletest.git
[submodule "extlibs/benchmark"]
path = extlibs/benchmark
url = https://github.com/google/benchmark.git

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.26)
project(omath VERSION 3.9.2 LANGUAGES CXX)
project(omath VERSION 4.0.0 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
include(CheckCXXCompilerFlag)
@@ -11,8 +11,8 @@ else ()
check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2)
endif ()
option(OMATH_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL})
option(OMATH_BUILD_BENCHMARK "Build benchmarks" ${PROJECT_IS_TOP_LEVEL})
option(OMATH_BUILD_TESTS "Build unit tests" OFF)
option(OMATH_BUILD_BENCHMARK "Build benchmarks" OFF)
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ${COMPILER_SUPPORTS_AVX2})
@@ -21,7 +21,28 @@ option(OMATH_BUILD_EXAMPLES "Build example projects with you can learn & play" O
option(OMATH_STATIC_MSVC_RUNTIME_LIBRARY "Force Omath to link static runtime" OFF)
option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build to improve general performance" ON)
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" OFF)
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" ON)
option(OMATH_BUILD_VIA_VCPKG "Will enable building using vcpkg, vcpkg will override some options that were set in vcpkg.json file, and search for dependencies using vcpkg" OFF)
if (OMATH_BUILD_VIA_VCPKG AND NOT CMAKE_TOOLCHAIN_FILE)
message(FATAL_ERROR "[${PROJECT_NAME}] CMAKE_TOOLCHAIN_FILE IS EMPTY! Please set env variable called 'VCPKG_ROOT' to vcpkg root folder here is an example: 'C:/vcpkg' or '/home/user/vcpkg' ")
endif ()
if (OMATH_BUILD_VIA_VCPKG AND VCPKG_MANIFEST_FEATURES)
foreach (omath_feature IN LISTS VCPKG_MANIFEST_FEATURES)
if (omath_feature STREQUAL "imgui")
set(OMATH_IMGUI_INTEGRATION ON)
elseif (omath_feature STREQUAL "avx2")
set(OMATH_USE_AVX2 ${COMPILER_SUPPORTS_AVX2})
elseif (omath_feature STREQUAL "tests")
set(OMATH_BUILD_TESTS ON)
elseif (omath_feature STREQUAL "benchmark")
set(OMATH_BUILD_BENCHMARK ON)
endif ()
endforeach ()
endif ()
if (OMATH_USE_AVX2 AND NOT COMPILER_SUPPORTS_AVX2)
message(WARNING "OMATH_USE_AVX2 requested, but compiler/target does not support AVX2. Disabling.")
@@ -40,6 +61,7 @@ if (${PROJECT_IS_TOP_LEVEL})
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}")
message(STATUS "[${PROJECT_NAME}]: Building using vcpkg ${OMATH_BUILD_VIA_VCPKG}")
endif ()
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
@@ -84,7 +106,7 @@ if (OMATH_SUPRESS_SAFETY_CHECKS)
endif ()
if (OMATH_ENABLE_LEGACY)
target_compile_options(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY)
endif ()
set_target_properties(${PROJECT_NAME} PROPERTIES
@@ -117,9 +139,6 @@ endif ()
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
add_subdirectory(extlibs)
if (OMATH_BUILD_TESTS)
add_subdirectory(tests)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS)

View File

@@ -8,7 +8,10 @@
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "cl.exe"
"CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"CMAKE_MAKE_PROGRAM": "Ninja"
},
"condition": {
"type": "equals",
@@ -24,6 +27,25 @@
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "windows-debug-vcpkg",
"displayName": "Debug",
"inherits": "windows-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"OMATH_BUILD_VIA_VCPKG": "ON",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
}
},
{
"name": "windows-release-vcpkg",
"displayName": "Release",
"inherits": "windows-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{
"name": "windows-release",
"displayName": "Release",
@@ -39,7 +61,10 @@
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": {
"CMAKE_CXX_COMPILER": "clang++"
"CMAKE_CXX_COMPILER": "clang++",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"CMAKE_MAKE_PROGRAM": "ninja"
},
"condition": {
"type": "equals",
@@ -55,6 +80,15 @@
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "linux-debug-vcpkg",
"displayName": "Linux Debug",
"inherits": "linux-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{
"name": "linux-release",
"displayName": "Linux Release",
@@ -63,6 +97,15 @@
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "linux-release-vcpkg",
"displayName": "Linux Release",
"inherits": "linux-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{
"name": "darwin-base",
"hidden": true,
@@ -86,6 +129,15 @@
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "darwin-debug-vcpkg",
"displayName": "Darwin Debug",
"inherits": "darwin-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{
"name": "darwin-release",
"displayName": "Darwin Release",
@@ -93,6 +145,15 @@
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "darwin-release-vcpkg",
"displayName": "Darwin Release",
"inherits": "darwin-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
}
]
}

38
LICENSE
View File

@@ -1,7 +1,7 @@
Copyright (C) 2024-2025 Orange++ <orange_github@proton.me>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
@@ -16,14 +16,44 @@ freely, subject to the following restrictions:
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
4. If you are an employee, contractor, volunteer, representative,
or have any other affiliation (past, present, or future)
or have any other affiliation (past or present)
with any of the following entities:
* "Advertising Placement Services" LLC
* "NEW SOLUTIONS VERTICALS" LLC
* "Autoexpert" LLC
* "Creditit" LLC
* "Yandex.Taxi" LLC
* "Yandex.Eda" LLC
* "Yandex.Lavka" LLC
* "Yandex.Telecom" LLC
* "Yandex.Cloud" LLC
* "Micromobility" LLC
* "MM-Tech" LLC
* "Carsharing" LLC
* "Yandex.Drive" LLC
* "EDADIL PROMO" LLC
* "Kinopoisk" LLC
* "Yandex.Music" LLC
* "Refueling (Yandex.Zapravki)" LLC
* "Yandex.Pay" LLC
* "Financial and Payment Technologies" LLC
* "Yandex.Delivery" LLC
* "Delivery Club" LLC
* "Yandex.Check" LLC
* "SMB-Service" LLC
* "ADV-TECH" LLC
* "Yandex Fantech" LLC
* "Yandex Smena" LLC
* "Market.Operations" LLC
* "Yandex.Market" LLC
* "ID Tech" LLC
* "Yandex.Crowd" LLC
* "Yandex" LLC
* "Rutube" LLC
* "Kaspersky" LLC
Or if you represent or are associated with any legal, organizational, or
professional entity providing services to or on behalf of the aforementioned entities:
You are expressly forbidden from accessing, using, modifying, distributing, or
interacting with the Software and its source code in any form. You must immediately
delete or destroy any physical or digital copies of the Software and/or
interacting with the Software and its source code in any form. You must immediately
delete or destroy any physical or digital copies of the Software and/or
its source code, including any derivative works, tools, or information obtained from the Software.

View File

@@ -52,7 +52,7 @@ It provides the latest features, is highly customizable, has all for cheat devel
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
- **Engine support**: Supports coordinate systems of Source, Unity, Unreal, IWEngine and canonical OpenGL.
- **Engine support**: Supports coordinate systems of **Source, Unity, Unreal, Frostbite, IWEngine and canonical OpenGL**.
- **Cross platform**: Supports Windows, MacOS and Linux.
- **Algorithms**: Has ability to scan for byte pattern with wildcards in PE files/modules, binary slices, works even with Wine apps.
<div align = center>

View File

@@ -1 +1 @@
3.9.2
4.0.0

View File

@@ -11,5 +11,9 @@ set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 23
CXX_STANDARD_REQUIRED ON)
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
if (TARGET benchmark::benchmark)
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
else()
find_package(benchmark CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
endif ()

View File

@@ -1,9 +0,0 @@
if (OMATH_BUILD_TESTS)
add_subdirectory(googletest)
endif ()
if (OMATH_BUILD_BENCHMARK)
set(BENCHMARK_ENABLE_TESTING OFF)
add_subdirectory(benchmark)
endif ()

View File

@@ -0,0 +1,13 @@
//
// Created by Vlad on 3/22/2025.
//
#pragma once
#include "omath/engines/frostbite_engine/constants.hpp"
#include "omath/projection/camera.hpp"
#include "traits/camera_trait.hpp"
namespace omath::frostbite_engine
{
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
} // namespace omath::unity_engine

View File

@@ -0,0 +1,25 @@
//
// Created by Vlad on 10/21/2025.
//
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/trigonometry/angle.hpp>
#include <omath/trigonometry/view_angles.hpp>
namespace omath::frostbite_engine
{
constexpr Vector3<float> k_abs_up = {0, 1, 0};
constexpr Vector3<float> k_abs_right = {1, 0, 0};
constexpr Vector3<float> k_abs_forward = {0, 0, 1};
using Mat4X4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3X3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat1X3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
using PitchAngle = Angle<float, -90.f, 90.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>;
} // namespace omath::frostbite_engine

View File

@@ -0,0 +1,26 @@
//
// Created by Vlad on 3/22/2025.
//
#pragma once
#include "omath/engines/frostbite_engine/constants.hpp"
namespace omath::frostbite_engine
{
[[nodiscard]]
Vector3<float> forward_vector(const ViewAngles& angles) noexcept;
[[nodiscard]]
Vector3<float> right_vector(const ViewAngles& angles) noexcept;
[[nodiscard]]
Vector3<float> up_vector(const ViewAngles& angles) noexcept;
[[nodiscard]] Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
[[nodiscard]]
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept;
[[nodiscard]]
Mat4X4 calc_perspective_projection_matrix(float field_of_view, float aspect_ratio, float near, float far) noexcept;
} // namespace omath::unity_engine

View File

@@ -0,0 +1,24 @@
//
// Created by Vlad on 8/10/2025.
//
#pragma once
#include "omath/engines/frostbite_engine/formulas.hpp"
#include "omath/projection/camera.hpp"
namespace omath::frostbite_engine
{
class CameraTrait final
{
public:
[[nodiscard]]
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;
[[nodiscard]]
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
[[nodiscard]]
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
float near, float far) noexcept;
};
} // namespace omath::unreal_engine

View File

@@ -0,0 +1,76 @@
//
// Created by Vlad on 8/6/2025.
//
#pragma once
#include "omath/engines/frostbite_engine/formulas.hpp"
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include <optional>
namespace omath::frostbite_engine
{
class PredEngineTrait final
{
public:
constexpr static Vector3<float> predict_projectile_position(const projectile_prediction::Projectile& projectile,
const float pitch, const float yaw,
const float time, const float gravity) noexcept
{
auto current_pos = projectile.m_origin
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
RollAngle::from_degrees(0)})
* projectile.m_launch_speed * time;
current_pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
return current_pos;
}
[[nodiscard]]
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target& target,
const float time, const float gravity) noexcept
{
auto predicted = target.m_origin + target.m_velocity * time;
if (target.m_is_airborne)
predicted.y -= gravity * (time * time) * 0.5f;
return predicted;
}
[[nodiscard]]
static float calc_vector_2d_distance(const Vector3<float>& delta) noexcept
{
return std::sqrt(delta.x * delta.x + delta.z * delta.z);
}
[[nodiscard]]
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
{
return vec.y;
}
[[nodiscard]]
static Vector3<float> calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
Vector3<float> predicted_target_position,
const std::optional<float> projectile_pitch) noexcept
{
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
}
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
// 89 look up, -89 look down
[[nodiscard]]
static float calc_direct_pitch_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
{
const auto direction = (view_to - origin).normalized();
return angles::radians_to_degrees(std::asin(direction.y));
}
[[nodiscard]]
static float calc_direct_yaw_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
{
const auto direction = (view_to - origin).normalized();
return angles::radians_to_degrees(std::atan2(direction.x, direction.z));
};
};
} // namespace omath::unity_engine

View File

@@ -39,6 +39,7 @@ namespace omath
class Mat final
{
public:
using ContainedType = Type;
constexpr Mat() noexcept
{
clear();

View File

@@ -221,7 +221,7 @@ namespace omath
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
ImVec2 to_im_vec2() const noexcept
constexpr ImVec2 to_im_vec2() const noexcept
{
return {static_cast<float>(this->x), static_cast<float>(this->y)};
}

View File

@@ -184,7 +184,7 @@ namespace omath
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
ImVec4 to_im_vec4() const noexcept
constexpr ImVec4 to_im_vec4() const noexcept
{
return {
static_cast<float>(this->x),

View File

@@ -76,6 +76,14 @@
#include "omath/engines/unity_engine/traits/camera_trait.hpp"
#include "omath/engines/unity_engine/traits/pred_engine_trait.hpp"
//Frostbite Engine
#include "omath/engines/frostbite_engine/constants.hpp"
#include "omath/engines/frostbite_engine/formulas.hpp"
#include "omath/engines/frostbite_engine/camera.hpp"
#include "omath/engines/frostbite_engine/traits/camera_trait.hpp"
#include "omath/engines/frostbite_engine/traits/pred_engine_trait.hpp"
// Unreal Engine
#include "omath/engines/unreal_engine/constants.hpp"
#include "omath/engines/unreal_engine/formulas.hpp"

View File

@@ -238,10 +238,8 @@ namespace omath::projection
return std::ranges::any_of(ndc.raw_array(), [](const auto& val) { return val < -1 || val > 1; });
}
[[nodiscard]] Vector3<float>
ndc_to_screen_position_from_top_left_corner(const Vector3<float>& ndc) const noexcept
{
/*
// NDC REPRESENTATION:
/*
^
| y
1 |
@@ -254,6 +252,20 @@ namespace omath::projection
v
*/
[[nodiscard]] Vector3<float>
ndc_to_screen_position_from_top_left_corner(const Vector3<float>& ndc) const noexcept
{
/*
+------------------------>
| (0, 0)
|
|
|
|
|
|
*/
return {(ndc.x + 1.f) / 2.f * m_view_port.m_width, (ndc.y / -2.f + 0.5f) * m_view_port.m_height, ndc.z};
}
@@ -261,18 +273,16 @@ namespace omath::projection
ndc_to_screen_position_from_bottom_left_corner(const Vector3<float>& ndc) const noexcept
{
/*
^
| y
1 |
|
|
-1 ---------0--------- 1 --> x
|
|
-1 |
v
*/
^
|
|
|
|
|
|
| (0, 0)
+------------------------>
*/
return {(ndc.x + 1.f) / 2.f * m_view_port.m_width, (ndc.y / 2.f + 0.5f) * m_view_port.m_height, ndc.z};
}

View File

@@ -0,0 +1,42 @@
//
// Created by Vlad on 3/22/2025.
//
#include "omath/engines/frostbite_engine/formulas.hpp"
namespace omath::frostbite_engine
{
Vector3<float> forward_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_forward);
return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Vector3<float> right_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_right);
return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Vector3<float> up_vector(const ViewAngles& angles) noexcept
{
const auto vec = rotation_matrix(angles) * mat_column_from_vector(k_abs_up);
return {vec.at(0, 0), vec.at(1, 0), vec.at(2, 0)};
}
Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
{
return mat_camera_view<float, MatStoreType::ROW_MAJOR>(forward_vector(angles), right_vector(angles),
up_vector(angles), cam_origin);
}
Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept
{
return mat_rotation_axis_z<float, MatStoreType::ROW_MAJOR>(angles.roll)
* mat_rotation_axis_y<float, MatStoreType::ROW_MAJOR>(angles.yaw)
* mat_rotation_axis_x<float, MatStoreType::ROW_MAJOR>(angles.pitch);
}
Mat4X4 calc_perspective_projection_matrix(const float field_of_view, const float aspect_ratio, const float near,
const float far) noexcept
{
return mat_perspective_left_handed(field_of_view, aspect_ratio, near, far);
}
} // namespace omath::unity_engine

View File

@@ -0,0 +1,26 @@
//
// Created by Vlad on 8/11/2025.
//
#include "omath/engines/frostbite_engine/traits/camera_trait.hpp"
namespace omath::frostbite_engine
{
ViewAngles CameraTrait::calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept
{
const auto direction = (look_at - cam_origin).normalized();
return {PitchAngle::from_radians(-std::asin(direction.y)),
YawAngle::from_radians(std::atan2(direction.x, direction.z)), RollAngle::from_radians(0.f)};
}
Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
{
return frostbite_engine::calc_view_matrix(angles, cam_origin);
}
Mat4X4 CameraTrait::calc_projection_matrix(const projection::FieldOfView& fov,
const projection::ViewPort& view_port, const float near,
const float far) noexcept
{
return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far);
}
} // namespace omath::unity_engine

View File

@@ -233,7 +233,8 @@ namespace
constexpr bool invalid_nt_header_file(const NtHeaderVariant& variant)
{
constexpr std::uint32_t nt_hdr_magic = 0x4550;
return std::visit([](const auto& header) -> bool { return header.signature != nt_hdr_magic; }, variant);
return std::visit([&nt_hdr_magic](const auto& header) -> bool { return header.signature != nt_hdr_magic; },
variant);
}
struct ExtractedSection

View File

@@ -15,5 +15,11 @@ set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD_REQUIRED ON)
target_link_libraries(${PROJECT_NAME} PRIVATE gtest gtest_main omath::omath)
if (TARGET gtest)
target_link_libraries(${PROJECT_NAME} PRIVATE gtest gtest_main omath::omath)
else()
find_package(GTest CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest GTest::gtest_main omath::omath)
endif()
gtest_discover_tests(${PROJECT_NAME})

View File

@@ -0,0 +1,236 @@
//
// Created by Vlad on 10/23/2025.
//
#include <gtest/gtest.h>
#include <omath/engines/frostbite_engine/camera.hpp>
#include <omath/engines/frostbite_engine/constants.hpp>
#include <omath/engines/frostbite_engine/formulas.hpp>
#include <print>
#include <random>
TEST(unit_test_frostbite_engine, ForwardVector)
{
const auto forward = omath::frostbite_engine::forward_vector({});
EXPECT_EQ(forward, omath::frostbite_engine::k_abs_forward);
}
TEST(unit_test_frostbite_engine, ForwardVectorRotationYaw)
{
omath::frostbite_engine::ViewAngles angles;
angles.yaw = omath::frostbite_engine::YawAngle::from_degrees(90.f);
const auto forward = omath::frostbite_engine::forward_vector(angles);
EXPECT_NEAR(forward.x, omath::frostbite_engine::k_abs_right.x, 0.00001f);
EXPECT_NEAR(forward.y, omath::frostbite_engine::k_abs_right.y, 0.00001f);
EXPECT_NEAR(forward.z, omath::frostbite_engine::k_abs_right.z, 0.00001f);
}
TEST(unit_test_frostbite_engine, ForwardVectorRotationPitch)
{
omath::frostbite_engine::ViewAngles angles;
angles.pitch = omath::frostbite_engine::PitchAngle::from_degrees(-90.f);
const auto forward = omath::frostbite_engine::forward_vector(angles);
EXPECT_NEAR(forward.x, omath::frostbite_engine::k_abs_up.x, 0.00001f);
EXPECT_NEAR(forward.y, omath::frostbite_engine::k_abs_up.y, 0.00001f);
EXPECT_NEAR(forward.z, omath::frostbite_engine::k_abs_up.z, 0.00001f);
}
TEST(unit_test_frostbite_engine, ForwardVectorRotationRoll)
{
omath::frostbite_engine::ViewAngles angles;
angles.roll = omath::frostbite_engine::RollAngle::from_degrees(-90.f);
const auto forward = omath::frostbite_engine::up_vector(angles);
EXPECT_NEAR(forward.x, omath::frostbite_engine::k_abs_right.x, 0.00001f);
EXPECT_NEAR(forward.y, omath::frostbite_engine::k_abs_right.y, 0.00001f);
EXPECT_NEAR(forward.z, omath::frostbite_engine::k_abs_right.z, 0.00001f);
}
TEST(unit_test_frostbite_engine, RightVector)
{
const auto right = omath::frostbite_engine::right_vector({});
EXPECT_EQ(right, omath::frostbite_engine::k_abs_right);
}
TEST(unit_test_frostbite_engine, UpVector)
{
const auto up = omath::frostbite_engine::up_vector({});
EXPECT_EQ(up, omath::frostbite_engine::k_abs_up);
}
TEST(unit_test_frostbite_engine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::from_degrees(60.f);
const auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 100.f; distance += 0.01f)
{
const auto projected = cam.world_to_screen({0, 0, distance});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_NEAR(projected->x, 640, 0.00001f);
EXPECT_NEAR(projected->y, 360, 0.00001f);
}
}
TEST(unit_test_frostbite_engine, Project)
{
constexpr auto fov = omath::projection::FieldOfView::from_degrees(60.f);
const auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.03f, 1000.f);
const auto proj = cam.world_to_screen<omath::frostbite_engine::Camera::ScreenStart::BOTTOM_LEFT_CORNER>({10.f, 3, 10.f});
EXPECT_NEAR(proj->x, 1263.538, 0.001f);
EXPECT_NEAR(proj->y, 547.061f, 0.001f);
}
TEST(unit_test_frostbite_engine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.get_field_of_view().as_degrees(), 90.f);
cam.set_field_of_view(omath::projection::FieldOfView::from_degrees(50.f));
EXPECT_EQ(cam.get_field_of_view().as_degrees(), 50.f);
}
TEST(unit_test_frostbite_engine, CameraSetAndGetOrigin)
{
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.get_origin(), omath::Vector3<float>{});
cam.set_field_of_view(omath::projection::FieldOfView::from_degrees(50.f));
EXPECT_EQ(cam.get_field_of_view().as_degrees(), 50.f);
}
TEST(unit_test_frostbite_engine, loook_at_random_all_axis)
{
std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source
std::uniform_real_distribution<float> dist(-1000.f, 1000.f);
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f);
std::size_t failed_points = 0;
for (int i = 0; i < 1000; i++)
{
const auto position_to_look = omath::Vector3<float>{dist(gen), dist(gen), dist(gen)};
if (cam.get_origin().distance_to(position_to_look) < 10)
continue;
cam.look_at(position_to_look);
auto projected_pos = cam.world_to_view_port(position_to_look);
EXPECT_TRUE(projected_pos.has_value());
if (!projected_pos)
continue;
if (std::abs(projected_pos->x - 0.f) >= 0.0001f || std::abs(projected_pos->y - 0.f) >= 0.0001f)
failed_points++;
}
EXPECT_LE(failed_points, 100);
}
TEST(unit_test_frostbite_engine, loook_at_random_x_axis)
{
std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source
std::uniform_real_distribution<float> dist(-1000.f, 1000.f);
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f);
std::size_t failed_points = 0;
for (int i = 0; i < 1000; i++)
{
const auto position_to_look = omath::Vector3<float>{dist(gen), 0.f, 0.f};
if (cam.get_origin().distance_to(position_to_look) < 10)
continue;
cam.look_at(position_to_look);
auto projected_pos = cam.world_to_view_port(position_to_look);
EXPECT_TRUE(projected_pos.has_value());
if (!projected_pos)
continue;
if (std::abs(projected_pos->x - 0.f) >= 0.001f || std::abs(projected_pos->y - 0.f) >= 0.001f)
failed_points++;
}
EXPECT_LE(failed_points, 100);
}
TEST(unit_test_frostbite_engine, loook_at_random_y_axis)
{
std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source
std::uniform_real_distribution<float> dist(-1000.f, 1000.f);
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f);
std::size_t failed_points = 0;
for (int i = 0; i < 1000; i++)
{
const auto position_to_look = omath::Vector3<float>{0.f, dist(gen), 0.f};
if (cam.get_origin().distance_to(position_to_look) < 10)
continue;
cam.look_at(position_to_look);
auto projected_pos = cam.world_to_view_port(position_to_look);
EXPECT_TRUE(projected_pos.has_value());
if (!projected_pos)
continue;
if (std::abs(projected_pos->x - 0.f) >= 0.01f || std::abs(projected_pos->y - 0.f) >= 0.01f)
failed_points++;
}
EXPECT_LE(failed_points, 100);
}
TEST(unit_test_frostbite_engine, loook_at_random_z_axis)
{
std::mt19937 gen(std::random_device{}()); // Seed with a non-deterministic source
std::uniform_real_distribution<float> dist(-1000.f, 1000.f);
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
auto cam = omath::frostbite_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.001f, 10000.f);
std::size_t failed_points = 0;
for (int i = 0; i < 1000; i++)
{
const auto position_to_look = omath::Vector3<float>{0.f, 0.f, dist(gen)};
if (cam.get_origin().distance_to(position_to_look) < 10)
continue;
cam.look_at(position_to_look);
auto projected_pos = cam.world_to_view_port(position_to_look);
EXPECT_TRUE(projected_pos.has_value());
if (!projected_pos)
continue;
if (std::abs(projected_pos->x - 0.f) >= 0.01f || std::abs(projected_pos->y - 0.f) >= 0.01f)
failed_points++;
}
EXPECT_LE(failed_points, 100);
}

View File

@@ -0,0 +1,39 @@
//
// Created by Vlad on 10/23/2025.
//
#ifdef OMATH_IMGUI_INTEGRATION
#include <omath/omath.hpp>
#include <gtest/gtest.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui.h>
using namespace omath;
TEST(unit_test_imgui_intergration, Vector2ToImVec2)
{
constexpr Vector2 omath_vector_2d = {1.f, 2.f};
constexpr ImVec2 imgui_vector_2d = {1, 2.f};
constexpr auto converted = omath_vector_2d.to_im_vec2();
EXPECT_NEAR(converted.x, imgui_vector_2d.x, 1.e-5f);
EXPECT_NEAR(converted.y, imgui_vector_2d.y, 1.e-5f);
}
TEST(unit_test_imgui_intergration, Vector4ToImVec4)
{
constexpr Vector4 omath_vector_2d = {1.f, 2.f, 3.f, 4.f};
constexpr ImVec4 imgui_vector_4d = {1, 2.f, 3.f, 4.f};
constexpr auto converted = omath_vector_2d.to_im_vec4();
EXPECT_NEAR(converted.x, imgui_vector_4d.x, 1.e-5f);
EXPECT_NEAR(converted.y, imgui_vector_4d.y, 1.e-5f);
EXPECT_NEAR(converted.z, imgui_vector_4d.z, 1.e-5f);
EXPECT_NEAR(converted.w, imgui_vector_4d.w, 1.e-5f);
}
#endif

14
vcpkg-configuration.json Normal file
View File

@@ -0,0 +1,14 @@
{
"default-registry": {
"kind": "git",
"baseline": "b1b19307e2d2ec1eefbdb7ea069de7d4bcd31f01",
"repository": "https://github.com/microsoft/vcpkg"
},
"registries": [
{
"kind": "artifact",
"location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip",
"name": "microsoft"
}
]
}

42
vcpkg.json Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "omath",
"version": "3.10.1",
"description": "General purpose math library",
"homepage": "https://github.com/orange-cpp/omath",
"license": "Zlib",
"supports": "windows | linux",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
],
"features": {
"avx2": {
"description": "Omath will use AVX2 to boost performance",
"supports": "!arm"
},
"benchmark": {
"description": "Build benchmarks",
"dependencies": [
"benchmark"
]
},
"imgui": {
"description": "Omath will define method to convert omath types to imgui types",
"dependencies": [
"imgui"
]
},
"tests": {
"description": "Build unit-tests using GTest",
"dependencies": [
"gtest"
]
}
}
}