Compare commits

..

7 Commits

Author SHA1 Message Date
orange 6c8d85b71f removed chart 2026-08-08 08:30:41 +03:00
orange 5dd46c9f1f fixed chart 2026-08-08 08:29:00 +03:00
orange e167a0f9c2 fix 2026-08-06 02:09:59 +03:00
orange 11b2129d6d improved radar 2026-08-05 21:37:18 +03:00
orange 43e2af556f 5.5.2 2026-08-04 23:00:40 +03:00
orange 550a08c24e fix 2026-08-04 22:39:04 +03:00
orange 70fba5addd fix freebsd 2026-08-04 16:08:01 +03:00
7 changed files with 118 additions and 61 deletions
+24 -20
View File
@@ -458,32 +458,36 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Build and Test - name: Start FreeBSD VM
uses: cross-platform-actions/action@v0.31.0 uses: cross-platform-actions/action@v1.3.0
with: with:
operating_system: freebsd operating_system: freebsd
architecture: ${{ matrix.arch }} architecture: ${{ matrix.arch }}
version: '15.0' version: '15.0'
memory: '12G' memory: '12G'
cpu_count: 4 cpu_count: 4
run: |
sudo pkg install -y git curl zip unzip gmake llvm gsed bash perl5 openssl 7-zip coreutils cmake ninja pkgconf patchelf - name: Build and Test
git config --global --add safe.directory `pwd` shell: cpa.sh {0}
# Build vcpkg in /tmp to avoid sshfs timestamp sync issues run: |
export VCPKG_ROOT=/tmp/vcpkg sudo pkg install -y git curl zip unzip gmake llvm gsed bash perl5 openssl 7-zip coreutils cmake ninja pkgconf patchelf
rm -rf "$VCPKG_ROOT" git config --global --add safe.directory `pwd`
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT" # Build vcpkg in /tmp to avoid sshfs timestamp sync issues
cd "$VCPKG_ROOT" export VCPKG_ROOT=/tmp/vcpkg
./bootstrap-vcpkg.sh rm -rf "$VCPKG_ROOT"
cd - # FreeBSD 15 packages CMake 3.31; newer vcpkg requires CMake 4.3.
export VCPKG_FORCE_SYSTEM_BINARIES=0 git clone --branch 2026.06.24 --depth 1 https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
cmake --preset ${{ matrix.preset }} \ cd "$VCPKG_ROOT"
-DOMATH_BUILD_TESTS=ON \ ./bootstrap-vcpkg.sh
-DOMATH_BUILD_BENCHMARK=OFF \ cd -
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua" \ export VCPKG_FORCE_SYSTEM_BINARIES=0
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" cmake --preset ${{ matrix.preset }} \
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath -DOMATH_BUILD_TESTS=ON \
./out/Release/unit_tests -DOMATH_BUILD_BENCHMARK=OFF \
-DVCPKG_MANIFEST_FEATURES="imgui;avx2;tests;lua" \
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported"
cmake --build cmake-build/build/${{ matrix.preset }} --target unit_tests omath
./out/Release/unit_tests
- name: Upload logs on failure - name: Upload logs on failure
if: ${{ failure() }} if: ${{ failure() }}
+25 -21
View File
@@ -375,33 +375,37 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Build and Package - name: Start FreeBSD VM
uses: cross-platform-actions/action@v0.31.0 uses: cross-platform-actions/action@v1.3.0
with: with:
operating_system: freebsd operating_system: freebsd
architecture: ${{ matrix.arch }} architecture: ${{ matrix.arch }}
version: '15.0' version: '15.0'
memory: '12G' memory: '12G'
cpu_count: 4 cpu_count: 4
run: |
sudo pkg install -y git curl zip unzip gmake llvm gsed bash perl5 openssl 7-zip coreutils cmake ninja pkgconf patchelf - name: Build and Package
git config --global --add safe.directory `pwd` shell: cpa.sh {0}
# Build vcpkg in /tmp to avoid sshfs timestamp sync issues run: |
export VCPKG_ROOT=/tmp/vcpkg sudo pkg install -y git curl zip unzip gmake llvm gsed bash perl5 openssl 7-zip coreutils cmake ninja pkgconf patchelf
rm -rf "$VCPKG_ROOT" git config --global --add safe.directory `pwd`
git clone https://github.com/microsoft/vcpkg "$VCPKG_ROOT" # Build vcpkg in /tmp to avoid sshfs timestamp sync issues
cd "$VCPKG_ROOT" export VCPKG_ROOT=/tmp/vcpkg
./bootstrap-vcpkg.sh rm -rf "$VCPKG_ROOT"
cd - # FreeBSD 15 packages CMake 3.31; newer vcpkg requires CMake 4.3.
export VCPKG_FORCE_SYSTEM_BINARIES=0 git clone --branch 2026.06.24 --depth 1 https://github.com/microsoft/vcpkg "$VCPKG_ROOT"
cmake --preset ${{ matrix.preset }} \ cd "$VCPKG_ROOT"
-DOMATH_BUILD_TESTS=OFF \ ./bootstrap-vcpkg.sh
-DOMATH_BUILD_BENCHMARK=OFF \ cd -
-DVCPKG_MANIFEST_FEATURES="imgui;avx2" \ export VCPKG_FORCE_SYSTEM_BINARIES=0
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported" cmake --preset ${{ matrix.preset }} \
cmake --build cmake-build/build/${{ matrix.preset }} --target omath -DOMATH_BUILD_TESTS=OFF \
cmake --install cmake-build/build/${{ matrix.preset }} --prefix staging -DOMATH_BUILD_BENCHMARK=OFF \
tar -czf ${{ matrix.archive }}.tar.gz -C staging . -DVCPKG_MANIFEST_FEATURES="imgui;avx2" \
-DVCPKG_INSTALL_OPTIONS="--allow-unsupported"
cmake --build cmake-build/build/${{ matrix.preset }} --target omath
cmake --install cmake-build/build/${{ matrix.preset }} --prefix staging
tar -czf ${{ matrix.archive }}.tar.gz -C staging .
- name: Upload release asset - name: Upload release asset
env: env:
-10
View File
@@ -35,16 +35,6 @@ It provides the latest features, is highly customizable, has all for cheat devel
</div> </div>
<div align = center>
<a href="https://www.star-history.com/#orange-cpp/omath&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=orange-cpp/omath&type=Date" />
</picture>
</a>
</div>
## Quick Example ## Quick Example
```cpp ```cpp
+1 -1
View File
@@ -1 +1 @@
5.5.1 5.5.2
+28 -8
View File
@@ -3,6 +3,8 @@
// //
#pragma once #pragma once
#include "omath/linear_algebra/vector3.hpp" #include "omath/linear_algebra/vector3.hpp"
#include <functional>
#include <optional>
#include <type_traits> #include <type_traits>
namespace omath::algorithm namespace omath::algorithm
@@ -10,7 +12,10 @@ namespace omath::algorithm
template<class Camera, class FloatingType> template<class Camera, class FloatingType>
requires std::is_floating_point_v<FloatingType> requires std::is_floating_point_v<FloatingType>
[[nodiscard]] [[nodiscard]]
constexpr Vector2<float> world_to_radar(const Camera& camera, const Vector3<FloatingType>& position, const FloatingType scale) constexpr Vector2<float> world_to_radar(
const Camera& camera, const Vector3<FloatingType>& position, const FloatingType scale,
const std::optional<std::function<FloatingType(const Vector3<FloatingType>&, const Vector3<FloatingType>&)>>
calc_distance = std::nullopt)
{ {
const auto look_at_angles = camera.calc_look_at_angles(position); const auto look_at_angles = camera.calc_look_at_angles(position);
const auto current_angles = camera.get_view_angles(); const auto current_angles = camera.get_view_angles();
@@ -18,25 +23,40 @@ namespace omath::algorithm
if consteval if consteval
{ {
const auto right_yaw = current_angles.yaw const auto right_yaw = current_angles.yaw
- camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw
- decltype(current_angles.yaw)::from_degrees(90); - decltype(current_angles.yaw)::from_degrees(90);
const auto sign = right_yaw.cos() < 0 ? -1.f : 1.f; const auto sign = right_yaw.cos() < 0 ? -1.f : 1.f;
const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90); const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90);
auto distance = FloatingType{0};
if (calc_distance.has_value())
distance = calc_distance.value()(camera.get_origin(), position);
else
distance = camera.get_origin().distance_to(position);
return omath::Vector2<float>(static_cast<float>(yaw.cos()) * sign, static_cast<float>(yaw.sin())) return omath::Vector2<float>(static_cast<float>(yaw.cos()) * sign, static_cast<float>(yaw.sin()))
* (camera.get_origin().distance_to(position) * scale); * (distance * scale);
} }
static const auto sign = [&camera, &current_angles] static const auto sign = [&camera, &current_angles]
{ {
const auto right_yaw = current_angles.yaw const auto right_yaw = current_angles.yaw
- camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw - camera.calc_look_at_angles(camera.get_origin() + camera.get_abs_right()).yaw
- decltype(current_angles.yaw)::from_degrees(90); - decltype(current_angles.yaw)::from_degrees(90);
return right_yaw.cos() < 0 ? -1.f : 1.f; return right_yaw.cos() < 0 ? -1.f : 1.f;
}(); }();
const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90); const auto yaw = current_angles.yaw - look_at_angles.yaw - decltype(current_angles.yaw)::from_degrees(90);
auto distance = FloatingType{0};
if (calc_distance.has_value())
distance = calc_distance.value()(camera.get_origin(), position);
else
distance = camera.get_origin().distance_to(position);
return omath::Vector2<float>(static_cast<float>(yaw.cos()) * sign, static_cast<float>(yaw.sin())) return omath::Vector2<float>(static_cast<float>(yaw.cos()) * sign, static_cast<float>(yaw.sin()))
* (camera.get_origin().distance_to(position) * scale); * (distance * scale);
} }
} // namespace omath::algorithm } // namespace omath::algorithm
-1
View File
@@ -1286,7 +1286,6 @@ TEST(UnitTestProjection, TriangleStraddlingFrustumNotCulled)
constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f); constexpr auto fov = omath::projection::FieldOfView::from_degrees(90.f);
constexpr auto cam = omath::source_engine::Camera({0.f, 0.f, 0.f}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); constexpr auto cam = omath::source_engine::Camera({0.f, 0.f, 0.f}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
constexpr auto position = omath::algorithm::world_to_radar(cam, {-1.f, 0.f, 0.f}, 0.1f);
// Large triangle with vertices on both sides of the frustum — should not be culled // Large triangle with vertices on both sides of the frustum — should not be culled
const omath::Triangle<omath::Vector3<float>> tri{{100.f, 0.f, 0.f}, {100.f, 5000.f, 0.f}, {100.f, 0.f, 5000.f}}; const omath::Triangle<omath::Vector3<float>> tri{{100.f, 0.f, 0.f}, {100.f, 5000.f, 0.f}, {100.f, 0.f, 5000.f}};
EXPECT_FALSE(cam.is_culled_by_frustum(tri)); EXPECT_FALSE(cam.is_culled_by_frustum(tri));
+40
View File
@@ -91,6 +91,38 @@ static void verify_world_to_radar_ignores_camera_pitch(const Vector3<NumericType
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f); EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
} }
template<class CameraType, class NumericType>
static void verify_world_to_radar_uses_custom_distance(const Vector3<NumericType>& world_forward)
{
const Vector3<NumericType> origin{NumericType{10}, NumericType{-20}, NumericType{5}};
const NumericType world_distance = NumericType{20};
const NumericType custom_distance = NumericType{6};
const NumericType scale = NumericType{0.5};
const auto radar_distance = static_cast<float>(custom_distance * scale);
CameraType camera{
origin, {}, {1280.f, 720.f}, projection::FieldOfView::from_degrees(90.f), NumericType{0.01},
NumericType{1000}};
const auto forward_position = origin + world_forward * world_distance;
auto custom_distance_called = false;
const std::optional<std::function<NumericType(const Vector3<NumericType>&, const Vector3<NumericType>&)>>
calc_distance{[&custom_distance_called, &origin, &forward_position,
custom_distance](const Vector3<NumericType>& distance_origin,
const Vector3<NumericType>& distance_position)
{
custom_distance_called = true;
EXPECT_EQ(distance_origin, origin);
EXPECT_EQ(distance_position, forward_position);
return custom_distance;
}};
const auto forward_radar = algorithm::world_to_radar(camera, forward_position, scale, calc_distance);
EXPECT_TRUE(custom_distance_called);
EXPECT_NEAR(forward_radar.x, 0.f, 1e-4f);
EXPECT_NEAR(forward_radar.y, -radar_distance, 1e-4f);
}
TEST(WorldToRadarTests, SourceEngineCamera) TEST(WorldToRadarTests, SourceEngineCamera)
{ {
verify_world_to_radar_uses_engine_world_axes<source_engine::Camera, float>(source_engine::k_abs_forward, verify_world_to_radar_uses_engine_world_axes<source_engine::Camera, float>(source_engine::k_abs_forward,
@@ -98,6 +130,7 @@ TEST(WorldToRadarTests, SourceEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<source_engine::Camera, float>(-90.f, source_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<source_engine::Camera, float>(-90.f, source_engine::k_abs_forward,
source_engine::k_abs_right); source_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<source_engine::Camera, float>(source_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<source_engine::Camera, float>(source_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<source_engine::Camera, float>(source_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, IWEngineCamera) TEST(WorldToRadarTests, IWEngineCamera)
@@ -107,6 +140,7 @@ TEST(WorldToRadarTests, IWEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<iw_engine::Camera, float>(-90.f, iw_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<iw_engine::Camera, float>(-90.f, iw_engine::k_abs_forward,
iw_engine::k_abs_right); iw_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<iw_engine::Camera, float>(iw_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<iw_engine::Camera, float>(iw_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<iw_engine::Camera, float>(iw_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, FrostbiteEngineCamera) TEST(WorldToRadarTests, FrostbiteEngineCamera)
@@ -116,6 +150,7 @@ TEST(WorldToRadarTests, FrostbiteEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<frostbite_engine::Camera, float>( verify_world_to_radar_uses_changed_camera_yaw<frostbite_engine::Camera, float>(
90.f, frostbite_engine::k_abs_forward, frostbite_engine::k_abs_right); 90.f, frostbite_engine::k_abs_forward, frostbite_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<frostbite_engine::Camera, float>(frostbite_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<frostbite_engine::Camera, float>(frostbite_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<frostbite_engine::Camera, float>(frostbite_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, OpenGLEngineCamera) TEST(WorldToRadarTests, OpenGLEngineCamera)
@@ -125,6 +160,7 @@ TEST(WorldToRadarTests, OpenGLEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<opengl_engine::Camera, float>(-90.f, opengl_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<opengl_engine::Camera, float>(-90.f, opengl_engine::k_abs_forward,
opengl_engine::k_abs_right); opengl_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<opengl_engine::Camera, float>(opengl_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<opengl_engine::Camera, float>(opengl_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<opengl_engine::Camera, float>(opengl_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, UnityEngineCamera) TEST(WorldToRadarTests, UnityEngineCamera)
@@ -134,6 +170,7 @@ TEST(WorldToRadarTests, UnityEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<unity_engine::Camera, float>(90.f, unity_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<unity_engine::Camera, float>(90.f, unity_engine::k_abs_forward,
unity_engine::k_abs_right); unity_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<unity_engine::Camera, float>(unity_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<unity_engine::Camera, float>(unity_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<unity_engine::Camera, float>(unity_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, CryEngineCamera) TEST(WorldToRadarTests, CryEngineCamera)
@@ -143,6 +180,7 @@ TEST(WorldToRadarTests, CryEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<cry_engine::Camera, float>(-90.f, cry_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<cry_engine::Camera, float>(-90.f, cry_engine::k_abs_forward,
cry_engine::k_abs_right); cry_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<cry_engine::Camera, float>(cry_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<cry_engine::Camera, float>(cry_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<cry_engine::Camera, float>(cry_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, RageEngineCamera) TEST(WorldToRadarTests, RageEngineCamera)
@@ -152,6 +190,7 @@ TEST(WorldToRadarTests, RageEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<rage_engine::Camera, float>(-90.f, rage_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<rage_engine::Camera, float>(-90.f, rage_engine::k_abs_forward,
rage_engine::k_abs_right); rage_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<rage_engine::Camera, float>(rage_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<rage_engine::Camera, float>(rage_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<rage_engine::Camera, float>(rage_engine::k_abs_forward);
} }
TEST(WorldToRadarTests, UnrealEngineCamera) TEST(WorldToRadarTests, UnrealEngineCamera)
@@ -161,4 +200,5 @@ TEST(WorldToRadarTests, UnrealEngineCamera)
verify_world_to_radar_uses_changed_camera_yaw<unreal_engine::Camera, double>(90.f, unreal_engine::k_abs_forward, verify_world_to_radar_uses_changed_camera_yaw<unreal_engine::Camera, double>(90.f, unreal_engine::k_abs_forward,
unreal_engine::k_abs_right); unreal_engine::k_abs_right);
verify_world_to_radar_ignores_camera_pitch<unreal_engine::Camera, double>(unreal_engine::k_abs_forward); verify_world_to_radar_ignores_camera_pitch<unreal_engine::Camera, double>(unreal_engine::k_abs_forward);
verify_world_to_radar_uses_custom_distance<unreal_engine::Camera, double>(unreal_engine::k_abs_forward);
} }