Compare commits

...

44 Commits
3.10 ... v4.1.0

Author SHA1 Message Date
7d194a5c36 Merge pull request #95 from orange-cpp/pathfinding_improvement
removed brackets
2025-10-30 05:44:00 +03:00
eec34c1efb removed brackets
Initial plan

Initial exploration and analysis complete

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>

Optimize performance: A* pathfinding, Vector3 hash, pattern scanner, AVX2 code, and serialization

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>

Add bounds check for navigation mesh serialization

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>

Document serialization limitation for large neighbor counts

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>

Add _codeql_build_dir to gitignore

Co-authored-by: orange-cpp <59374393+orange-cpp@users.noreply.github.com>

Removes codeql detected source root

Eliminates the automatically generated file that was causing issues.

This file was added by codeql and no longer needed.

revert
cleaned up gitignore

moved to anon namespace

Improves navigation mesh serialization and clamping

Ensures correct serialization of navigation meshes by clamping neighbor counts to prevent data corruption when exceeding uint16_t limits.

Updates data types to `std::uint8_t` and `std::size_t` for consistency.
Uses `std::copy_n` instead of `std::memcpy` for deserialization.
2025-10-30 05:38:58 +03:00
765d5e7216 fixed typo 2025-10-30 05:37:34 +03:00
7cb8a4de52 Clarifies release process for stable builds
Explains that changes merged into master won't reach stable users unless the `stable` tag is updated.
2025-10-28 01:21:41 +03:00
d2fbc286b1 Merge pull request #93 from orange-cpp/feaure/small_improvement
removed useless option
2025-10-28 01:19:21 +03:00
64385757af fix 2025-10-28 01:15:36 +03:00
ea7b812645 removed 2025-10-28 01:11:02 +03:00
b214cdf3a1 removed useless option 2025-10-28 01:09:47 +03:00
dccc12ee30 added some comments 2025-10-27 11:25:31 +03:00
60e744978c force disabled tests 2025-10-27 11:22:24 +03:00
495a2a80e4 Merge pull request #92 from orange-cpp/feature/projection_utility
added vcpkg integration
2025-10-27 11:11:28 +03:00
6fbc010fa1 considered to switch to v4 2025-10-27 11:05:55 +03:00
c8f77de4f2 updated version 2025-10-27 10:59:30 +03:00
5c2d09b175 patch 2025-10-27 10:58:26 +03:00
b3646ab708 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
d751eaf132 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
62e7ccb054 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
4d9e055bb3 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
9be7ca886d 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
30568f3633 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
5f22499b66 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
f75afb8354 fix 2025-10-27 08:59:42 +03:00
e38df8bd23 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
ae347c8509 fix 2025-10-27 08:51:58 +03:00
ee40979a2d fix 2025-10-27 08:41:22 +03:00
69d0b7b829 fix 2025-10-27 08:37:55 +03:00
490ccfe983 fix 2025-10-27 08:36:48 +03:00
5630c2708e 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
ed7220dc9c 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
5e4fae9e42 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
063f43e74c fix 2025-10-27 08:03:42 +03:00
171b4ca3da 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
878e3358c0 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
81aef68143 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
e2a37f2c81 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
69575c1cb3 added additional check 2025-10-23 06:43:09 +03:00
8adf5db409 added vcpkg manifest file 2025-10-23 06:35:22 +03:00
2c7e443f52 added contained type alias 2025-10-23 06:26:57 +03:00
6ad4ef29e9 fix 2025-10-23 01:08:19 +03:00
8feb805067 Remove 'future' from affiliation clause in LICENSE 2025-10-23 01:00:40 +03:00
816da38987 added frostbite into global header 2025-10-23 00:55:49 +03:00
0ba795c767 added Frostbite into readme 2025-10-23 00:50:35 +03:00
88b709f531 deleted not needed header 2025-10-23 00:49:54 +03:00
a7eacb529e updated comments 2025-10-23 00:48:54 +03:00
28 changed files with 431 additions and 167 deletions

View File

@@ -56,7 +56,7 @@ SpaceBeforeParensOptions:
AfterIfMacros: true AfterIfMacros: true
AfterOverloadedOperator: false AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: false SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false SpacesInConditionalStatement: false

View File

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

2
.idea/vcs.xml generated
View File

@@ -2,7 +2,5 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/extlibs/benchmark" vcs="Git" />
<mapping directory="$PROJECT_DIR$/extlibs/googletest" vcs="Git" />
</component> </component>
</project> </project>

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.26) 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(CMakePackageConfigHelpers)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
@@ -11,8 +11,8 @@ else ()
check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2) check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2)
endif () endif ()
option(OMATH_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL}) option(OMATH_BUILD_TESTS "Build unit tests" OFF)
option(OMATH_BUILD_BENCHMARK "Build benchmarks" ${PROJECT_IS_TOP_LEVEL}) 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_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_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}) option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ${COMPILER_SUPPORTS_AVX2})
@@ -21,7 +21,23 @@ 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_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_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_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)
if (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) if (OMATH_USE_AVX2 AND NOT COMPILER_SUPPORTS_AVX2)
message(WARNING "OMATH_USE_AVX2 requested, but compiler/target does not support AVX2. Disabling.") message(WARNING "OMATH_USE_AVX2 requested, but compiler/target does not support AVX2. Disabling.")
@@ -40,6 +56,7 @@ if (${PROJECT_IS_TOP_LEVEL})
message(STATUS "[${PROJECT_NAME}]: AVX2 feature status ${OMATH_USE_AVX2}") 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}]: ImGUI integration feature status ${OMATH_IMGUI_INTEGRATION}")
message(STATUS "[${PROJECT_NAME}]: Legacy features support ${OMATH_ENABLE_LEGACY}") message(STATUS "[${PROJECT_NAME}]: Legacy features support ${OMATH_ENABLE_LEGACY}")
message(STATUS "[${PROJECT_NAME}]: Building using vcpkg ${OMATH_BUILD_VIA_VCPKG}")
endif () endif ()
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")
@@ -84,7 +101,7 @@ if (OMATH_SUPRESS_SAFETY_CHECKS)
endif () endif ()
if (OMATH_ENABLE_LEGACY) if (OMATH_ENABLE_LEGACY)
target_compile_options(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY) target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY)
endif () endif ()
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
@@ -117,9 +134,6 @@ endif ()
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
add_subdirectory(extlibs)
if (OMATH_BUILD_TESTS) if (OMATH_BUILD_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS) target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS)

View File

@@ -8,7 +8,8 @@
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}", "binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}", "installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": { "cacheVariables": {
"CMAKE_CXX_COMPILER": "cl.exe" "CMAKE_CXX_COMPILER": "cl.exe",
"CMAKE_MAKE_PROGRAM": "Ninja"
}, },
"condition": { "condition": {
"type": "equals", "type": "equals",
@@ -16,6 +17,17 @@
"rhs": "Windows" "rhs": "Windows"
} }
}, },
{
"name": "windows-base-vcpkg",
"hidden": true,
"inherits": "windows-base",
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
}
},
{ {
"name": "windows-debug", "name": "windows-debug",
"displayName": "Debug", "displayName": "Debug",
@@ -24,6 +36,23 @@
"CMAKE_BUILD_TYPE": "Debug" "CMAKE_BUILD_TYPE": "Debug"
} }
}, },
{
"name": "windows-debug-vcpkg",
"displayName": "Debug",
"inherits": "windows-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "windows-release-vcpkg",
"displayName": "Release",
"inherits": "windows-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"OMATH_BUILD_VIA_VCPKG": "ON"
}
},
{ {
"name": "windows-release", "name": "windows-release",
"displayName": "Release", "displayName": "Release",
@@ -39,7 +68,8 @@
"binaryDir": "${sourceDir}/cmake-build/build/${presetName}", "binaryDir": "${sourceDir}/cmake-build/build/${presetName}",
"installDir": "${sourceDir}/cmake-build/install/${presetName}", "installDir": "${sourceDir}/cmake-build/install/${presetName}",
"cacheVariables": { "cacheVariables": {
"CMAKE_CXX_COMPILER": "clang++" "CMAKE_CXX_COMPILER": "clang++",
"CMAKE_MAKE_PROGRAM": "ninja"
}, },
"condition": { "condition": {
"type": "equals", "type": "equals",
@@ -47,6 +77,17 @@
"rhs": "Linux" "rhs": "Linux"
} }
}, },
{
"name": "linux-base-vcpkg",
"hidden": true,
"inherits": "linux-base",
"cacheVariables": {
"OMATH_BUILD_VIA_VCPKG": "ON",
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"VCPKG_INSTALLED_DIR": "${sourceDir}/cmake-build/vcpkg_installed",
"VCPKG_MANIFEST_FEATURES": "tests;imgui;avx2"
}
},
{ {
"name": "linux-debug", "name": "linux-debug",
"displayName": "Linux Debug", "displayName": "Linux Debug",
@@ -55,6 +96,14 @@
"CMAKE_BUILD_TYPE": "Debug" "CMAKE_BUILD_TYPE": "Debug"
} }
}, },
{
"name": "linux-debug-vcpkg",
"displayName": "Linux Debug",
"inherits": "linux-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{ {
"name": "linux-release", "name": "linux-release",
"displayName": "Linux Release", "displayName": "Linux Release",
@@ -63,6 +112,14 @@
"CMAKE_BUILD_TYPE": "Release" "CMAKE_BUILD_TYPE": "Release"
} }
}, },
{
"name": "linux-release-vcpkg",
"displayName": "Linux Release",
"inherits": "linux-base-vcpkg",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{ {
"name": "darwin-base", "name": "darwin-base",
"hidden": true, "hidden": true,
@@ -86,6 +143,14 @@
"CMAKE_BUILD_TYPE": "Debug" "CMAKE_BUILD_TYPE": "Debug"
} }
}, },
{
"name": "darwin-debug-vcpkg",
"displayName": "Darwin Debug",
"inherits": "darwin-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{ {
"name": "darwin-release", "name": "darwin-release",
"displayName": "Darwin Release", "displayName": "Darwin Release",
@@ -93,6 +158,14 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release" "CMAKE_BUILD_TYPE": "Release"
} }
},
{
"name": "darwin-release-vcpkg",
"displayName": "Darwin Release",
"inherits": "darwin-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
} }
] ]
} }

View File

@@ -18,7 +18,7 @@ In order to send code back to the official OMath repository, you must first crea
account ([fork](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)) and account ([fork](https://help.github.com/articles/creating-a-pull-request-from-a-fork/)) and
then [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) back to OMath. then [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork/) back to OMath.
OMath developement is performed on multiple branches. Changes are then pull requested into master. By default, changes OMath development is performed on multiple branches. Changes are then pull requested into master. By default, changes
merged into master will not roll out to stable build users unless the `stable` tag is updated. merged into master will not roll out to stable build users unless the `stable` tag is updated.
### 📜 Code-Style ### 📜 Code-Style

38
LICENSE
View File

@@ -1,7 +1,7 @@
Copyright (C) 2024-2025 Orange++ <orange_github@proton.me> Copyright (C) 2024-2025 Orange++ <orange_github@proton.me>
This software is provided 'as-is', without any express or implied 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. arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, 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. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
4. If you are an employee, contractor, volunteer, representative, 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: 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 * "Yandex" LLC
* "Rutube" LLC * "Rutube" LLC
* "Kaspersky" LLC * "Kaspersky" LLC
Or if you represent or are associated with any legal, organizational, or Or if you represent or are associated with any legal, organizational, or
professional entity providing services to or on behalf of the aforementioned entities: professional entity providing services to or on behalf of the aforementioned entities:
You are expressly forbidden from accessing, using, modifying, distributing, or You are expressly forbidden from accessing, using, modifying, distributing, or
interacting with the Software and its source code in any form. You must immediately 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 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. 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. - **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 - **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! - **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. - **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. - **Algorithms**: Has ability to scan for byte pattern with wildcards in PE files/modules, binary slices, works even with Wine apps.
<div align = center> <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 23
CXX_STANDARD_REQUIRED ON) CXX_STANDARD_REQUIRED ON)
if (TARGET benchmark::benchmark) # Benchmark is being linked as submodule
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath) target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)
else()
find_package(benchmark CONFIG REQUIRED) # Benchmark is being linked as vcpkg package
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

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

View File

@@ -221,7 +221,7 @@ namespace omath
} }
#ifdef OMATH_IMGUI_INTEGRATION #ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]] [[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)}; return {static_cast<float>(this->x), static_cast<float>(this->y)};
} }

View File

@@ -184,7 +184,7 @@ namespace omath
#ifdef OMATH_IMGUI_INTEGRATION #ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]] [[nodiscard]]
ImVec4 to_im_vec4() const noexcept constexpr ImVec4 to_im_vec4() const noexcept
{ {
return { return {
static_cast<float>(this->x), 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/camera_trait.hpp"
#include "omath/engines/unity_engine/traits/pred_engine_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 // Unreal Engine
#include "omath/engines/unreal_engine/constants.hpp" #include "omath/engines/unreal_engine/constants.hpp"
#include "omath/engines/unreal_engine/formulas.hpp" #include "omath/engines/unreal_engine/formulas.hpp"

View File

@@ -22,9 +22,5 @@ namespace omath::pathfinding
static std::vector<Vector3<float>> static std::vector<Vector3<float>>
reconstruct_final_path(const std::unordered_map<Vector3<float>, PathNode>& closed_list, reconstruct_final_path(const std::unordered_map<Vector3<float>, PathNode>& closed_list,
const Vector3<float>& current) noexcept; const Vector3<float>& current) noexcept;
[[nodiscard]]
static auto get_perfect_node(const std::unordered_map<Vector3<float>, PathNode>& open_list,
const Vector3<float>& end_vertex) noexcept;
}; };
} // namespace omath::pathfinding } // namespace omath::pathfinding

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; }); return std::ranges::any_of(ndc.raw_array(), [](const auto& val) { return val < -1 || val > 1; });
} }
[[nodiscard]] Vector3<float> // NDC REPRESENTATION:
ndc_to_screen_position_from_top_left_corner(const Vector3<float>& ndc) const noexcept /*
{
/*
^ ^
| y | y
1 | 1 |
@@ -254,6 +252,20 @@ namespace omath::projection
v 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}; 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 ndc_to_screen_position_from_bottom_left_corner(const Vector3<float>& ndc) const noexcept
{ {
/* /*
^ ^
| y |
1 | |
| |
| |
-1 ---------0--------- 1 --> x |
| |
| | (0, 0)
-1 | +------------------------>
v */
*/
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}; 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

@@ -4,9 +4,25 @@
#include "omath/pathfinding/a_star.hpp" #include "omath/pathfinding/a_star.hpp"
#include <algorithm> #include <algorithm>
#include <optional> #include <optional>
#include <queue>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
namespace
{
struct OpenListNode final
{
omath::Vector3<float> position;
float f_cost;
[[nodiscard]]
bool operator>(const OpenListNode& other) const noexcept
{
return f_cost > other.f_cost;
}
};
}
namespace omath::pathfinding namespace omath::pathfinding
{ {
struct PathNode final struct PathNode final
@@ -37,23 +53,13 @@ namespace omath::pathfinding
std::ranges::reverse(path); std::ranges::reverse(path);
return path; return path;
} }
auto Astar::get_perfect_node(const std::unordered_map<Vector3<float>, PathNode>& open_list,
const Vector3<float>& end_vertex) noexcept
{
return std::ranges::min_element(open_list,
[&end_vertex](const auto& a, const auto& b)
{
const float fa = a.second.g_cost + a.first.distance_to(end_vertex);
const float fb = b.second.g_cost + b.first.distance_to(end_vertex);
return fa < fb;
});
}
std::vector<Vector3<float>> Astar::find_path(const Vector3<float>& start, const Vector3<float>& end, std::vector<Vector3<float>> Astar::find_path(const Vector3<float>& start, const Vector3<float>& end,
const NavigationMesh& nav_mesh) noexcept const NavigationMesh& nav_mesh) noexcept
{ {
std::unordered_map<Vector3<float>, PathNode> closed_list; std::unordered_map<Vector3<float>, PathNode> closed_list;
std::unordered_map<Vector3<float>, PathNode> open_list; std::unordered_map<Vector3<float>, PathNode> node_data;
std::priority_queue<OpenListNode, std::vector<OpenListNode>, std::greater<>> open_list;
auto maybe_start_vertex = nav_mesh.get_closest_vertex(start); auto maybe_start_vertex = nav_mesh.get_closest_vertex(start);
auto maybe_end_vertex = nav_mesh.get_closest_vertex(end); auto maybe_end_vertex = nav_mesh.get_closest_vertex(end);
@@ -64,20 +70,27 @@ namespace omath::pathfinding
const auto start_vertex = maybe_start_vertex.value(); const auto start_vertex = maybe_start_vertex.value();
const auto end_vertex = maybe_end_vertex.value(); const auto end_vertex = maybe_end_vertex.value();
open_list.emplace(start_vertex, PathNode{std::nullopt, 0.f}); node_data.emplace(start_vertex, PathNode{std::nullopt, 0.f});
open_list.push({start_vertex, start_vertex.distance_to(end_vertex)});
while (!open_list.empty()) while (!open_list.empty())
{ {
auto current_it = get_perfect_node(open_list, end_vertex); auto current = open_list.top().position;
open_list.pop();
const auto current = current_it->first; if (closed_list.contains(current))
const auto current_node = current_it->second; continue;
auto current_node_it = node_data.find(current);
if (current_node_it == node_data.end())
continue;
const auto current_node = current_node_it->second;
if (current == end_vertex) if (current == end_vertex)
return reconstruct_final_path(closed_list, current); return reconstruct_final_path(closed_list, current);
closed_list.emplace(current, current_node); closed_list.emplace(current, current_node);
open_list.erase(current_it);
for (const auto& neighbor: nav_mesh.get_neighbors(current)) for (const auto& neighbor: nav_mesh.get_neighbors(current))
{ {
@@ -86,11 +99,14 @@ namespace omath::pathfinding
const float tentative_g_cost = current_node.g_cost + neighbor.distance_to(current); const float tentative_g_cost = current_node.g_cost + neighbor.distance_to(current);
// ReSharper disable once CppTooWideScopeInitStatement auto node_it = node_data.find(neighbor);
const auto open_it = open_list.find(neighbor);
if (open_it == open_list.end() || tentative_g_cost < open_it->second.g_cost) if (node_it == node_data.end() || tentative_g_cost < node_it->second.g_cost)
open_list[neighbor] = PathNode{current, tentative_g_cost}; {
node_data[neighbor] = PathNode{current, tentative_g_cost};
const float f_cost = tentative_g_cost + neighbor.distance_to(end_vertex);
open_list.push({neighbor, f_cost});
}
} }
} }

View File

@@ -3,6 +3,8 @@
// //
#include "omath/pathfinding/navigation_mesh.hpp" #include "omath/pathfinding/navigation_mesh.hpp"
#include <algorithm> #include <algorithm>
#include <cstring>
#include <limits>
#include <stdexcept> #include <stdexcept>
namespace omath::pathfinding namespace omath::pathfinding
{ {
@@ -13,7 +15,7 @@ namespace omath::pathfinding
{ return a.first.distance_to(point) < b.first.distance_to(point); }); { return a.first.distance_to(point) < b.first.distance_to(point); });
if (res == m_vertex_map.cend()) if (res == m_vertex_map.cend())
return std::unexpected("Failed to get clossest point"); return std::unexpected("Failed to get closest point");
return res->first; return res->first;
} }
@@ -30,55 +32,68 @@ namespace omath::pathfinding
std::vector<uint8_t> NavigationMesh::serialize() const noexcept std::vector<uint8_t> NavigationMesh::serialize() const noexcept
{ {
auto dump_to_vector = []<typename T>(const T& t, std::vector<uint8_t>& vec) std::vector<std::uint8_t> raw;
// Pre-calculate total size for better performance
std::size_t total_size = 0;
for (const auto& [vertex, neighbors] : m_vertex_map)
{ {
for (size_t i = 0; i < sizeof(t); i++) total_size += sizeof(vertex) + sizeof(std::uint16_t) + sizeof(Vector3<float>) * neighbors.size();
vec.push_back(*(reinterpret_cast<const uint8_t*>(&t) + i)); }
raw.reserve(total_size);
auto dump_to_vector = [&raw]<typename T>(const T& t)
{
const auto* byte_ptr = reinterpret_cast<const std::uint8_t*>(&t);
raw.insert(raw.end(), byte_ptr, byte_ptr + sizeof(T));
}; };
std::vector<uint8_t> raw; for (const auto& [vertex, neighbors] : m_vertex_map)
for (const auto& [vertex, neighbors]: m_vertex_map)
{ {
const auto neighbors_count = neighbors.size(); // Clamp neighbors count to fit in uint16_t (prevents silent data corruption)
// NOTE: If neighbors.size() > 65535, only the first 65535 neighbors will be serialized.
// This is a limitation of the current serialization format using uint16_t for count.
const auto clamped_count =
std::min<std::size_t>(neighbors.size(), std::numeric_limits<std::uint16_t>::max());
const auto neighbors_count = static_cast<std::uint16_t>(clamped_count);
dump_to_vector(vertex, raw); dump_to_vector(vertex);
dump_to_vector(neighbors_count, raw); dump_to_vector(neighbors_count);
for (const auto& neighbor: neighbors) // Only serialize up to the clamped count
dump_to_vector(neighbor, raw); for (std::size_t i = 0; i < clamped_count; ++i)
dump_to_vector(neighbors[i]);
} }
return raw; return raw;
} }
void NavigationMesh::deserialize(const std::vector<uint8_t>& raw) noexcept void NavigationMesh::deserialize(const std::vector<uint8_t>& raw) noexcept
{ {
auto load_from_vector = [](const std::vector<uint8_t>& vec, size_t& offset, auto& value) auto load_from_vector = [](const std::vector<uint8_t>& vec, std::size_t& offset, auto& value)
{ {
if (offset + sizeof(value) > vec.size()) if (offset + sizeof(value) > vec.size())
{
throw std::runtime_error("Deserialize: Invalid input data size."); throw std::runtime_error("Deserialize: Invalid input data size.");
}
std::copy_n(vec.data() + offset, sizeof(value), reinterpret_cast<uint8_t*>(&value)); std::copy_n(vec.data() + offset, sizeof(value), reinterpret_cast<uint8_t*>(&value));
offset += sizeof(value); offset += sizeof(value);
}; };
m_vertex_map.clear(); m_vertex_map.clear();
size_t offset = 0; std::size_t offset = 0;
while (offset < raw.size()) while (offset < raw.size())
{ {
Vector3<float> vertex; Vector3<float> vertex;
load_from_vector(raw, offset, vertex); load_from_vector(raw, offset, vertex);
uint16_t neighbors_count; std::uint16_t neighbors_count;
load_from_vector(raw, offset, neighbors_count); load_from_vector(raw, offset, neighbors_count);
std::vector<Vector3<float>> neighbors; std::vector<Vector3<float>> neighbors;
neighbors.reserve(neighbors_count); neighbors.reserve(neighbors_count);
for (size_t i = 0; i < neighbors_count; ++i) for (std::size_t i = 0; i < neighbors_count; ++i)
{ {
Vector3<float> neighbor; Vector3<float> neighbor;
load_from_vector(raw, offset, neighbor); load_from_vector(raw, offset, neighbor);

View File

@@ -18,97 +18,104 @@ namespace omath::projectile_prediction
[[maybe_unused]] const Target& target) const [[maybe_unused]] const Target& target) const
{ {
#if defined(OMATH_USE_AVX2) && defined(__i386__) && defined(__x86_64__) #if defined(OMATH_USE_AVX2) && defined(__i386__) && defined(__x86_64__)
const float bulletGravity = m_gravityConstant * projectile.m_gravityScale; const float bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
const float v0 = projectile.m_launchSpeed; const float v0 = projectile.m_launch_speed;
const float v0Sqr = v0 * v0; const float v0_sqr = v0 * v0;
const Vector3 projOrigin = projectile.m_origin; const Vector3 proj_origin = projectile.m_origin;
constexpr int SIMD_FACTOR = 8; constexpr int SIMD_FACTOR = 8;
float currentTime = m_simulationTimeStep; float current_time = m_simulation_time_step;
for (; currentTime <= m_maximumSimulationTime; currentTime += m_simulationTimeStep * SIMD_FACTOR) for (; current_time <= m_maximum_simulation_time; current_time += m_simulation_time_step * SIMD_FACTOR)
{ {
const __m256 times const __m256 times
= _mm256_setr_ps(currentTime, currentTime + m_simulationTimeStep, = _mm256_setr_ps(current_time, current_time + m_simulation_time_step,
currentTime + m_simulationTimeStep * 2, currentTime + m_simulationTimeStep * 3, current_time + m_simulation_time_step * 2, current_time + m_simulation_time_step * 3,
currentTime + m_simulationTimeStep * 4, currentTime + m_simulationTimeStep * 5, current_time + m_simulation_time_step * 4, current_time + m_simulation_time_step * 5,
currentTime + m_simulationTimeStep * 6, currentTime + m_simulationTimeStep * 7); current_time + m_simulation_time_step * 6, current_time + m_simulation_time_step * 7);
const __m256 targetX const __m256 target_x
= _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.x), times, _mm256_set1_ps(target.m_origin.x)); = _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.x), times, _mm256_set1_ps(target.m_origin.x));
const __m256 targetY const __m256 target_y
= _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.y), times, _mm256_set1_ps(target.m_origin.y)); = _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.y), times, _mm256_set1_ps(target.m_origin.y));
const __m256 timesSq = _mm256_mul_ps(times, times); const __m256 times_sq = _mm256_mul_ps(times, times);
const __m256 targetZ = _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.z), times, const __m256 target_z = _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.z), times,
_mm256_fnmadd_ps(_mm256_set1_ps(0.5f * m_gravityConstant), timesSq, _mm256_fnmadd_ps(_mm256_set1_ps(0.5f * m_gravity_constant), times_sq,
_mm256_set1_ps(target.m_origin.z))); _mm256_set1_ps(target.m_origin.z)));
const __m256 deltaX = _mm256_sub_ps(targetX, _mm256_set1_ps(projOrigin.x)); const __m256 delta_x = _mm256_sub_ps(target_x, _mm256_set1_ps(proj_origin.x));
const __m256 deltaY = _mm256_sub_ps(targetY, _mm256_set1_ps(projOrigin.y)); const __m256 delta_y = _mm256_sub_ps(target_y, _mm256_set1_ps(proj_origin.y));
const __m256 deltaZ = _mm256_sub_ps(targetZ, _mm256_set1_ps(projOrigin.z)); const __m256 delta_z = _mm256_sub_ps(target_z, _mm256_set1_ps(proj_origin.z));
const __m256 dSqr = _mm256_add_ps(_mm256_mul_ps(deltaX, deltaX), _mm256_mul_ps(deltaY, deltaY)); const __m256 d_sqr = _mm256_add_ps(_mm256_mul_ps(delta_x, delta_x), _mm256_mul_ps(delta_y, delta_y));
const __m256 bgTimesSq = _mm256_mul_ps(_mm256_set1_ps(bulletGravity), timesSq); const __m256 bg_times_sq = _mm256_mul_ps(_mm256_set1_ps(bullet_gravity), times_sq);
const __m256 term = _mm256_add_ps(deltaZ, _mm256_mul_ps(_mm256_set1_ps(0.5f), bgTimesSq)); const __m256 term = _mm256_add_ps(delta_z, _mm256_mul_ps(_mm256_set1_ps(0.5f), bg_times_sq));
const __m256 termSq = _mm256_mul_ps(term, term); const __m256 term_sq = _mm256_mul_ps(term, term);
const __m256 numerator = _mm256_add_ps(dSqr, termSq); const __m256 numerator = _mm256_add_ps(d_sqr, term_sq);
const __m256 denominator = _mm256_add_ps(timesSq, _mm256_set1_ps(1e-8f)); // Avoid division by zero const __m256 denominator = _mm256_add_ps(times_sq, _mm256_set1_ps(1e-8f)); // Avoid division by zero
const __m256 requiredV0Sqr = _mm256_div_ps(numerator, denominator); const __m256 required_v0_sqr = _mm256_div_ps(numerator, denominator);
const __m256 v0SqrVec = _mm256_set1_ps(v0Sqr + 1e-3f); const __m256 v0_sqr_vec = _mm256_set1_ps(v0_sqr + 1e-3f);
const __m256 mask = _mm256_cmp_ps(requiredV0Sqr, v0SqrVec, _CMP_LE_OQ); const __m256 mask = _mm256_cmp_ps(required_v0_sqr, v0_sqr_vec, _CMP_LE_OQ);
const unsigned validMask = _mm256_movemask_ps(mask); const unsigned valid_mask = _mm256_movemask_ps(mask);
if (!validMask) if (!valid_mask)
continue; continue;
alignas(32) float validTimes[SIMD_FACTOR]; alignas(32) float valid_times[SIMD_FACTOR];
_mm256_store_ps(validTimes, times); _mm256_store_ps(valid_times, times);
for (int i = 0; i < SIMD_FACTOR; ++i) for (int i = 0; i < SIMD_FACTOR; ++i)
{ {
if (!(validMask & (1 << i))) if (!(valid_mask & (1 << i)))
continue; continue;
const float candidateTime = validTimes[i]; const float candidate_time = valid_times[i];
if (candidateTime > m_maximumSimulationTime) if (candidate_time > m_maximum_simulation_time)
continue; continue;
// Fine search around candidate time // Fine search around candidate time
for (float fineTime = candidateTime - m_simulationTimeStep * 2; for (float fine_time = candidate_time - m_simulation_time_step * 2;
fineTime <= candidateTime + m_simulationTimeStep * 2; fineTime += m_simulationTimeStep) fine_time <= candidate_time + m_simulation_time_step * 2; fine_time += m_simulation_time_step)
{ {
if (fineTime < 0) if (fine_time < 0)
continue; continue;
const Vector3 targetPos = target.PredictPosition(fineTime, m_gravityConstant); // Manually compute predicted target position to avoid adding method to Target
const auto pitch = CalculatePitch(projOrigin, targetPos, bulletGravity, v0, fineTime); Vector3 target_pos = target.m_origin + target.m_velocity * fine_time;
if (target.m_is_airborne)
target_pos.z -= 0.5f * m_gravity_constant * fine_time * fine_time;
const auto pitch = calculate_pitch(proj_origin, target_pos, bullet_gravity, v0, fine_time);
if (!pitch) if (!pitch)
continue; continue;
const Vector3 delta = targetPos - projOrigin; const Vector3 delta = target_pos - proj_origin;
const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y); const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y);
const float height = d * std::tan(angles::DegreesToRadians(*pitch)); const float height = d * std::tan(angles::degrees_to_radians(*pitch));
return Vector3(targetPos.x, targetPos.y, projOrigin.z + height); return Vector3(target_pos.x, target_pos.y, proj_origin.z + height);
} }
} }
} }
// Fallback scalar processing for remaining times // Fallback scalar processing for remaining times
for (; currentTime <= m_maximumSimulationTime; currentTime += m_simulationTimeStep) for (; current_time <= m_maximum_simulation_time; current_time += m_simulation_time_step)
{ {
const Vector3 targetPos = target.PredictPosition(currentTime, m_gravityConstant); Vector3 target_pos = target.m_origin + target.m_velocity * current_time;
const auto pitch = CalculatePitch(projOrigin, targetPos, bulletGravity, v0, currentTime); if (target.m_is_airborne)
target_pos.z -= 0.5f * m_gravity_constant * current_time * current_time;
const auto pitch = calculate_pitch(proj_origin, target_pos, bullet_gravity, v0, current_time);
if (!pitch) if (!pitch)
continue; continue;
const Vector3 delta = targetPos - projOrigin; const Vector3 delta = target_pos - proj_origin;
const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y); const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y);
const float height = d * std::tan(angles::DegreesToRadians(*pitch)); const float height = d * std::tan(angles::degrees_to_radians(*pitch));
return Vector3(targetPos.x, targetPos.y, projOrigin.z + height); return Vector3(target_pos.x, target_pos.y, proj_origin.z + height);
} }
return std::nullopt; return std::nullopt;
@@ -134,22 +141,22 @@ namespace omath::projectile_prediction
return std::nullopt; return std::nullopt;
const Vector3 delta = target_pos - proj_origin; const Vector3 delta = target_pos - proj_origin;
const float dSqr = delta.x * delta.x + delta.y * delta.y; const float d_sqr = delta.x * delta.x + delta.y * delta.y;
const float h = delta.z; const float h = delta.z;
const float term = h + 0.5f * bullet_gravity * time * time; const float term = h + 0.5f * bullet_gravity * time * time;
const float requiredV0Sqr = (dSqr + term * term) / (time * time); const float required_v0_sqr = (d_sqr + term * term) / (time * time);
const float v0Sqr = v0 * v0; const float v0_sqr = v0 * v0;
if (requiredV0Sqr > v0Sqr + 1e-3f) if (required_v0_sqr > v0_sqr + 1e-3f)
return std::nullopt; return std::nullopt;
if (dSqr == 0.0f) if (d_sqr == 0.0f)
return term >= 0.0f ? 90.0f : -90.0f; return term >= 0.0f ? 90.0f : -90.0f;
const float d = std::sqrt(dSqr); const float d = std::sqrt(d_sqr);
const float tanTheta = term / d; const float tan_theta = term / d;
return angles::RadiansToDegrees(std::atan(tanTheta)); return angles::radians_to_degrees(std::atan(tan_theta));
#else #else
throw std::runtime_error( throw std::runtime_error(
std::format("{} AVX2 feature is not enabled!", std::source_location::current().function_name())); std::format("{} AVX2 feature is not enabled!", std::source_location::current().function_name()));

View File

@@ -233,7 +233,8 @@ namespace
constexpr bool invalid_nt_header_file(const NtHeaderVariant& variant) constexpr bool invalid_nt_header_file(const NtHeaderVariant& variant)
{ {
constexpr std::uint32_t nt_hdr_magic = 0x4550; 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 struct ExtractedSection

View File

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

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"
]
}
}
}