mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 23:13:26 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ea8f3d8d51 | |||
| 08d2ccc03a | |||
| 21ec23d77b | |||
| 2c4ff37062 | |||
| 695a8035b5 | |||
| d12b236e56 | |||
| 7a5090d9f6 | |||
| ec76a7239c | |||
| 2758f549a3 | |||
| 493931ef0f | |||
| 9e1990942b | |||
| f1984fbe46 | |||
| f1fbea21a7 | |||
| 4b44ce0667 | |||
| 231ef35a0a | |||
| 1aa62cb396 | |||
| 8e411771c2 | |||
| d65852d1a4 | |||
| 21f5e82a20 | |||
|
|
851ec37350 | ||
| f1cd9dbeb3 | |||
| 7a1c7d6cc4 | |||
| cb704b3621 | |||
|
|
646d295876 | ||
| 8e09556c25 | |||
| 7dbebc996d | |||
| 278ffba0ff | |||
| 647cf02a38 | |||
| 4be2986681 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
/cmake-build/
|
/cmake-build/
|
||||||
/.idea
|
/.idea
|
||||||
/out
|
/out
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
/extlibs/vcpkg
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.26)
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
|
||||||
project(omath VERSION 3.0.2 LANGUAGES CXX)
|
project(omath VERSION 3.0.4.1 LANGUAGES CXX)
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
|
||||||
option(OMATH_BUILD_TESTS "Build unit tests" OFF)
|
option(OMATH_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL})
|
||||||
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" ON)
|
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ON)
|
||||||
@@ -14,6 +14,8 @@ 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" ON)
|
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" ON)
|
||||||
|
option(OMATH_ENABLE_LEGACY "Will enable legacy classes that MUST be used ONLY for backward compatibility" OFF)
|
||||||
|
|
||||||
|
|
||||||
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
|
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
|
||||||
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
|
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
|
||||||
@@ -56,6 +58,10 @@ if (OMATH_SUPRESS_SAFETY_CHECKS)
|
|||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_SUPRESS_SAFETY_CHECKS)
|
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_SUPRESS_SAFETY_CHECKS)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (OMATH_ENABLE_LEGACY)
|
||||||
|
target_compile_options(${PROJECT_NAME} PUBLIC OMATH_ENABLE_LEGACY)
|
||||||
|
endif ()
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
||||||
|
|||||||
32
CONTRIBUTING.md
Normal file
32
CONTRIBUTING.md
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
## 🤝 Contributing to OMath or other Orange's Projects
|
||||||
|
|
||||||
|
### ❕ Prerequisites
|
||||||
|
|
||||||
|
- A working up-to-date OMath installation
|
||||||
|
- C++ knowledge
|
||||||
|
- Git knowledge
|
||||||
|
- Ability to ask for help (Feel free to create empty pull-request or PM a maintainer
|
||||||
|
in [Telegram](https://t.me/orange_cpp))
|
||||||
|
|
||||||
|
### ⏬ Setting up OMath
|
||||||
|
|
||||||
|
Please read INSTALL.md file in repository
|
||||||
|
|
||||||
|
### 🔀 Pull requests and Branches
|
||||||
|
|
||||||
|
In order to send code back to the official OMath repository, you must first create a copy of OMath on your github
|
||||||
|
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.
|
||||||
|
|
||||||
|
OMath developement 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.
|
||||||
|
|
||||||
|
### 📜 Code-Style
|
||||||
|
|
||||||
|
The orange code-style can be found in `.clang-format`.
|
||||||
|
|
||||||
|
### 📦 Building
|
||||||
|
|
||||||
|
OMath has already created the `cmake-build` and `out` directories where cmake/bin files are located. By default, you
|
||||||
|
can build OMath by running `cmake --build cmake-build/build/windows-release --target omath -j 6` in the source
|
||||||
|
directory.
|
||||||
14
INSTALL.md
14
INSTALL.md
@@ -14,6 +14,20 @@ target_link_libraries(main PRIVATE omath::omath)
|
|||||||
```
|
```
|
||||||
For detailed commands on installing different versions and more information, please refer to Microsoft's [official instructions](https://learn.microsoft.com/en-us/vcpkg/get_started/overview).
|
For detailed commands on installing different versions and more information, please refer to Microsoft's [official instructions](https://learn.microsoft.com/en-us/vcpkg/get_started/overview).
|
||||||
|
|
||||||
|
## <img width="28px" src="https://xmake.io/assets/img/logo.svg" /> Using xrepo
|
||||||
|
**Note**: Support xrepo for package management
|
||||||
|
1. Install [xmake](https://xmake.io/)
|
||||||
|
2. Run the following command to install the omath package:
|
||||||
|
```
|
||||||
|
xrepo install omath
|
||||||
|
```
|
||||||
|
xmake.lua
|
||||||
|
```xmake
|
||||||
|
add_requires("omath")
|
||||||
|
target("...")
|
||||||
|
add_packages("omath")
|
||||||
|
```
|
||||||
|
|
||||||
## <img width="28px" src="https://upload.wikimedia.org/wikipedia/commons/e/ef/CMake_logo.svg?" /> Build from source using CMake
|
## <img width="28px" src="https://upload.wikimedia.org/wikipedia/commons/e/ef/CMake_logo.svg?" /> Build from source using CMake
|
||||||
1. **Preparation**
|
1. **Preparation**
|
||||||
|
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -7,11 +7,22 @@
|
|||||||

|

|
||||||
[](https://www.codefactor.io/repository/github/orange-cpp/omath)
|
[](https://www.codefactor.io/repository/github/orange-cpp/omath)
|
||||||

|

|
||||||
|
[](https://repology.org/project/orange-math/versions)
|
||||||

|

|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Oranges's Math Library (omath) is a comprehensive, open-source library aimed at providing efficient, reliable, and versatile mathematical functions and algorithms. Developed primarily in C++, this library is designed to cater to a wide range of mathematical operations essential in scientific computing, engineering, and academic research.
|
Oranges's Math Library (omath) is a comprehensive, open-source library aimed at providing efficient, reliable, and versatile mathematical functions and algorithms. Developed primarily in C++, this library is designed to cater to a wide range of mathematical operations essential in scientific computing, engineering, and academic research.
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
## 👁🗨 Features
|
## 👁🗨 Features
|
||||||
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
|
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
|
||||||
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
|
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
|
||||||
@@ -71,7 +82,7 @@ Or even advanced projectile aimbot
|
|||||||
Contributions to `omath` are welcome! Please read `CONTRIBUTING.md` for details on our code of conduct and the process for submitting pull requests.
|
Contributions to `omath` are welcome! Please read `CONTRIBUTING.md` for details on our code of conduct and the process for submitting pull requests.
|
||||||
|
|
||||||
## 📜 License
|
## 📜 License
|
||||||
This project is licensed under the MIT - see the `LICENSE` file for details.
|
This project is licensed under the ZLIB - see the `LICENSE` file for details.
|
||||||
|
|
||||||
## 💘 Acknowledgments
|
## 💘 Acknowledgments
|
||||||
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
|
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef OMATH_ENABLE_LEGACY
|
||||||
|
|
||||||
#include "omath/vector3.hpp"
|
#include "omath/vector3.hpp"
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -106,3 +109,4 @@ namespace omath
|
|||||||
std::unique_ptr<float[]> m_data;
|
std::unique_ptr<float[]> m_data;
|
||||||
};
|
};
|
||||||
} // namespace omath
|
} // namespace omath
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/6/2025.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "omath/engines/iw_engine/formulas.hpp"
|
||||||
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace omath::projectile_prediction::traits
|
||||||
|
{
|
||||||
|
class IwEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const Projectile& projectile, const float pitch,
|
||||||
|
const float yaw, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ iw_engine::forward_vector({iw_engine::PitchAngle::from_degrees(-pitch),
|
||||||
|
iw_engine::YawAngle::from_degrees(yaw),
|
||||||
|
iw_engine::RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const Target& target, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.z -= 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.y * delta.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
|
||||||
|
{
|
||||||
|
return vec.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> calc_viewpoint_from_angles(const 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, projectile.m_origin.z + height};
|
||||||
|
}
|
||||||
|
// 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 distance = origin.distance_to(view_to);
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::asin(delta.z / distance));
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_yaw_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::atan2(delta.y, delta.x));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace omath::projectile_prediction::traits
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/6/2025.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/opengl_engine/formulas.hpp"
|
||||||
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace omath::projectile_prediction::traits
|
||||||
|
{
|
||||||
|
class OpenGlEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const Projectile& projectile, const float pitch,
|
||||||
|
const float yaw, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ opengl_engine::forward_vector({opengl_engine::PitchAngle::from_degrees(-pitch),
|
||||||
|
opengl_engine::YawAngle::from_degrees(yaw),
|
||||||
|
opengl_engine::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 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& 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 distance = origin.distance_to(view_to);
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::asin(delta.y / distance));
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_yaw_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::atan2(delta.z, delta.x));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace omath::projectile_prediction::traits
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/3/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/source_engine/formulas.hpp"
|
||||||
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace omath::projectile_prediction::traits
|
||||||
|
{
|
||||||
|
class SourceEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const Projectile& projectile, const float pitch,
|
||||||
|
const float yaw, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ source_engine::forward_vector({source_engine::PitchAngle::from_degrees(-pitch),
|
||||||
|
source_engine::YawAngle::from_degrees(yaw),
|
||||||
|
source_engine::RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const Target& target, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.z -= 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.y * delta.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
|
||||||
|
{
|
||||||
|
return vec.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> calc_viewpoint_from_angles(const 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, projectile.m_origin.z + height};
|
||||||
|
}
|
||||||
|
// 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 distance = origin.distance_to(view_to);
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::asin(delta.z / distance));
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_yaw_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::atan2(delta.y, delta.x));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace omath::projectile_prediction::traits
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/6/2025.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/unity_engine/formulas.hpp"
|
||||||
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace omath::projectile_prediction::traits
|
||||||
|
{
|
||||||
|
class UnityEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const Projectile& projectile, const float pitch,
|
||||||
|
const float yaw, const float time,
|
||||||
|
const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ unity_engine::forward_vector({unity_engine::PitchAngle::from_degrees(-pitch),
|
||||||
|
unity_engine::YawAngle::from_degrees(yaw),
|
||||||
|
unity_engine::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 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& 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 distance = origin.distance_to(view_to);
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::asin(delta.y / distance));
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_yaw_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto delta = view_to - origin;
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(std::atan2(delta.z, delta.x));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace omath::projectile_prediction::traits
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngine
|
class ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
virtual std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
||||||
const Target& target) const = 0;
|
const Target& target) const = 0;
|
||||||
virtual ~ProjPredEngine() = default;
|
virtual ~ProjPredEngineInterface() = default;
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngineAvx2 final : public ProjPredEngine
|
class ProjPredEngineAvx2 final : public ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] std::optional<Vector3<float>>
|
[[nodiscard]] std::optional<Vector3<float>>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "engine_traits/source_engine_trait.hpp"
|
||||||
#include "omath/projectile_prediction/proj_pred_engine.hpp"
|
#include "omath/projectile_prediction/proj_pred_engine.hpp"
|
||||||
#include "omath/projectile_prediction/projectile.hpp"
|
#include "omath/projectile_prediction/projectile.hpp"
|
||||||
#include "omath/projectile_prediction/target.hpp"
|
#include "omath/projectile_prediction/target.hpp"
|
||||||
@@ -12,15 +13,40 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
class ProjPredEngineLegacy final : public ProjPredEngine
|
template<class EngineTrait = traits::SourceEngineTrait>
|
||||||
|
class ProjPredEngineLegacy final : public ProjPredEngineInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ProjPredEngineLegacy(float gravity_constant, float simulation_time_step, float maximum_simulation_time,
|
explicit ProjPredEngineLegacy(const float gravity_constant, const float simulation_time_step,
|
||||||
float distance_tolerance);
|
const float maximum_simulation_time, const float distance_tolerance)
|
||||||
|
: m_gravity_constant(gravity_constant), m_simulation_time_step(simulation_time_step),
|
||||||
|
m_maximum_simulation_time(maximum_simulation_time), m_distance_tolerance(distance_tolerance)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
std::optional<Vector3<float>> maybe_calculate_aim_point(const Projectile& projectile,
|
||||||
const Target& target) const override;
|
const Target& target) const override
|
||||||
|
{
|
||||||
|
for (float time = 0.f; time < m_maximum_simulation_time; time += m_simulation_time_step)
|
||||||
|
{
|
||||||
|
const auto predicted_target_position =
|
||||||
|
EngineTrait::predict_target_position(target, time, m_gravity_constant);
|
||||||
|
|
||||||
|
const auto projectile_pitch =
|
||||||
|
maybe_calculate_projectile_launch_pitch_angle(projectile, predicted_target_position);
|
||||||
|
|
||||||
|
if (!projectile_pitch.has_value()) [[unlikely]]
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!is_projectile_reached_target(predicted_target_position, projectile, projectile_pitch.value(),
|
||||||
|
time))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return EngineTrait::calc_viewpoint_from_angles(projectile, predicted_target_position, projectile_pitch);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const float m_gravity_constant;
|
const float m_gravity_constant;
|
||||||
@@ -28,13 +54,56 @@ namespace omath::projectile_prediction
|
|||||||
const float m_maximum_simulation_time;
|
const float m_maximum_simulation_time;
|
||||||
const float m_distance_tolerance;
|
const float m_distance_tolerance;
|
||||||
|
|
||||||
|
// Realization of this formula:
|
||||||
|
// https://stackoverflow.com/questions/54917375/how-to-calculate-the-angle-to-shoot-a-bullet-in-order-to-hit-a-moving-target
|
||||||
|
/*
|
||||||
|
\[
|
||||||
|
\theta \;=\; \arctan\!\Biggl(
|
||||||
|
\frac{%
|
||||||
|
v^{2}\;\pm\;\sqrt{\,v^{4}-g\!\left(gx^{2}+2yv^{2}\right)\,}
|
||||||
|
}{%
|
||||||
|
gx
|
||||||
|
}\Biggr)
|
||||||
|
\]
|
||||||
|
*/
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
std::optional<float>
|
std::optional<float>
|
||||||
maybe_calculate_projectile_launch_pitch_angle(const Projectile& projectile,
|
maybe_calculate_projectile_launch_pitch_angle(const Projectile& projectile,
|
||||||
const Vector3<float>& target_position) const noexcept;
|
const Vector3<float>& target_position) const noexcept
|
||||||
|
{
|
||||||
|
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
||||||
|
|
||||||
|
if (bullet_gravity == 0.f)
|
||||||
|
return EngineTrait::calc_direct_pitch_angle(projectile.m_origin, target_position);
|
||||||
|
|
||||||
|
const auto delta = target_position - projectile.m_origin;
|
||||||
|
|
||||||
|
const auto distance2d = EngineTrait::calc_vector_2d_distance(delta);
|
||||||
|
const auto distance2d_sqr = distance2d * distance2d;
|
||||||
|
const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed;
|
||||||
|
|
||||||
|
float root = launch_speed_sqr * launch_speed_sqr
|
||||||
|
- bullet_gravity
|
||||||
|
* (bullet_gravity * distance2d_sqr
|
||||||
|
+ 2.0f * EngineTrait::get_vector_height_coordinate(delta) * launch_speed_sqr);
|
||||||
|
|
||||||
|
if (root < 0.0f) [[unlikely]]
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
root = std::sqrt(root);
|
||||||
|
const float angle = std::atan((launch_speed_sqr - root) / (bullet_gravity * distance2d));
|
||||||
|
|
||||||
|
return angles::radians_to_degrees(angle);
|
||||||
|
}
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool is_projectile_reached_target(const Vector3<float>& target_position, const Projectile& projectile,
|
bool is_projectile_reached_target(const Vector3<float>& target_position, const Projectile& projectile,
|
||||||
float pitch, float time) const noexcept;
|
const float pitch, const float time) const noexcept
|
||||||
|
{
|
||||||
|
const auto yaw = EngineTrait::calc_direct_yaw_angle(projectile.m_origin, target_position);
|
||||||
|
const auto projectile_position =
|
||||||
|
EngineTrait::predict_projectile_position(projectile, pitch, yaw, time, m_gravity_constant);
|
||||||
|
|
||||||
|
return projectile_position.distance_to(target_position) <= m_distance_tolerance;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ namespace omath::projectile_prediction
|
|||||||
class Projectile final
|
class Projectile final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
|
||||||
Vector3<float> predict_position(float pitch, float yaw, float time, float gravity) const noexcept;
|
|
||||||
|
|
||||||
Vector3<float> m_origin;
|
Vector3<float> m_origin;
|
||||||
float m_launch_speed{};
|
float m_launch_speed{};
|
||||||
float m_gravity_scale{};
|
float m_gravity_scale{};
|
||||||
|
|||||||
@@ -10,17 +10,6 @@ namespace omath::projectile_prediction
|
|||||||
class Target final
|
class Target final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[nodiscard]]
|
|
||||||
constexpr Vector3<float> predict_position(const float time, const float gravity) const noexcept
|
|
||||||
{
|
|
||||||
auto predicted = m_origin + m_velocity * time;
|
|
||||||
|
|
||||||
if (m_is_airborne)
|
|
||||||
predicted.z -= gravity * (time*time) * 0.5f;
|
|
||||||
|
|
||||||
return predicted;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3<float> m_origin;
|
Vector3<float> m_origin;
|
||||||
Vector3<float> m_velocity;
|
Vector3<float> m_velocity;
|
||||||
bool m_is_airborne{};
|
bool m_is_airborne{};
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ namespace omath
|
|||||||
[[nodiscard]] Vector2 normalized() const noexcept
|
[[nodiscard]] Vector2 normalized() const noexcept
|
||||||
{
|
{
|
||||||
const Type len = length();
|
const Type len = length();
|
||||||
return len > 0.f ? *this / len : *this;
|
return len > static_cast<Type>(0) ? *this / len : *this;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
[[nodiscard]] constexpr Type length_sqr() const noexcept
|
[[nodiscard]] constexpr Type length_sqr() const noexcept
|
||||||
@@ -153,8 +153,8 @@ namespace omath
|
|||||||
constexpr Vector2& abs() noexcept
|
constexpr Vector2& abs() noexcept
|
||||||
{
|
{
|
||||||
// FIXME: Replace with std::abs, if it will become constexprable
|
// FIXME: Replace with std::abs, if it will become constexprable
|
||||||
x = x < 0 ? -x : x;
|
x = x < static_cast<Type>(0) ? -x : x;
|
||||||
y = y < 0 ? -y : y;
|
y = y < static_cast<Type>(0) ? -y : y;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +202,11 @@ namespace omath
|
|||||||
{
|
{
|
||||||
return {static_cast<float>(this->x), static_cast<float>(this->y)};
|
return {static_cast<float>(this->x), static_cast<float>(this->y)};
|
||||||
}
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> from_im_vec2(const ImVec2& other) noexcept
|
||||||
|
{
|
||||||
|
return {static_cast<Type>(other.x), static_cast<Type>(other.y)};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
} // namespace omath
|
} // namespace omath
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ namespace omath
|
|||||||
{
|
{
|
||||||
const Type len = this->length();
|
const Type len = this->length();
|
||||||
|
|
||||||
return len != 0 ? *this / len : *this;
|
return len != static_cast<Type>(0) ? *this / len : *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Type length_2d() const noexcept
|
[[nodiscard]] Type length_2d() const noexcept
|
||||||
@@ -221,7 +221,7 @@ namespace omath
|
|||||||
{
|
{
|
||||||
const auto bottom = length() * other.length();
|
const auto bottom = length() * other.length();
|
||||||
|
|
||||||
if (bottom == 0.f)
|
if (bottom == static_cast<Type>(0))
|
||||||
return std::unexpected(Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE);
|
return std::unexpected(Vector3Error::IMPOSSIBLE_BETWEEN_ANGLE);
|
||||||
|
|
||||||
return Angle<float, 0.f, 180.f, AngleFlags::Clamped>::from_radians(std::acos(dot(other) / bottom));
|
return Angle<float, 0.f, 180.f, AngleFlags::Clamped>::from_radians(std::acos(dot(other) / bottom));
|
||||||
@@ -230,7 +230,7 @@ namespace omath
|
|||||||
[[nodiscard]] bool is_perpendicular(const Vector3& other) const noexcept
|
[[nodiscard]] bool is_perpendicular(const Vector3& other) const noexcept
|
||||||
{
|
{
|
||||||
if (const auto angle = angle_between(other))
|
if (const auto angle = angle_between(other))
|
||||||
return angle->as_degrees() == 90.f;
|
return angle->as_degrees() == static_cast<Type>(90);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace omath
|
|||||||
constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w): Vector3<Type>(x, y, z), w(w)
|
constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w): Vector3<Type>(x, y, z), w(w)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
constexpr Vector4() noexcept : Vector3<Type>(), w(0) {};
|
constexpr Vector4() noexcept: Vector3<Type>(), w(static_cast<Type>(0)) {};
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr bool operator==(const Vector4& other) const noexcept
|
constexpr bool operator==(const Vector4& other) const noexcept
|
||||||
@@ -169,6 +169,12 @@ namespace omath
|
|||||||
static_cast<float>(w),
|
static_cast<float>(w),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector4<float> from_im_vec4(const ImVec4& other) noexcept
|
||||||
|
{
|
||||||
|
return {static_cast<Type>(other.x), static_cast<Type>(other.y), static_cast<Type>(other.z)};
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
} // namespace omath
|
} // namespace omath
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef OMATH_ENABLE_LEGACY
|
||||||
|
|
||||||
#include "omath/matrix.hpp"
|
#include "omath/matrix.hpp"
|
||||||
#include "omath/angles.hpp"
|
#include "omath/angles.hpp"
|
||||||
#include "omath/vector3.hpp"
|
#include "omath/vector3.hpp"
|
||||||
@@ -359,3 +361,4 @@ namespace omath
|
|||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
} // namespace omath
|
} // namespace omath
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
#include "omath/projectile_prediction/proj_pred_engine_legacy.hpp"
|
|
||||||
#include <cmath>
|
|
||||||
#include <omath/angles.hpp>
|
|
||||||
|
|
||||||
namespace omath::projectile_prediction
|
|
||||||
{
|
|
||||||
ProjPredEngineLegacy::ProjPredEngineLegacy(const float gravity_constant, const float simulation_time_step,
|
|
||||||
const float maximum_simulation_time, const float distance_tolerance)
|
|
||||||
: m_gravity_constant(gravity_constant), m_simulation_time_step(simulation_time_step),
|
|
||||||
m_maximum_simulation_time(maximum_simulation_time), m_distance_tolerance(distance_tolerance)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<Vector3<float>> ProjPredEngineLegacy::maybe_calculate_aim_point(const Projectile& projectile,
|
|
||||||
const Target& target) const
|
|
||||||
{
|
|
||||||
for (float time = 0.f; time < m_maximum_simulation_time; time += m_simulation_time_step)
|
|
||||||
{
|
|
||||||
const auto predicted_target_position = target.predict_position(time, m_gravity_constant);
|
|
||||||
|
|
||||||
const auto projectile_pitch =
|
|
||||||
maybe_calculate_projectile_launch_pitch_angle(projectile, predicted_target_position);
|
|
||||||
|
|
||||||
if (!projectile_pitch.has_value()) [[unlikely]]
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!is_projectile_reached_target(predicted_target_position, projectile, projectile_pitch.value(), time))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto delta2d = (predicted_target_position - projectile.m_origin).length_2d();
|
|
||||||
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
|
||||||
|
|
||||||
return Vector3(predicted_target_position.x, predicted_target_position.y, projectile.m_origin.z + height);
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<float> ProjPredEngineLegacy::maybe_calculate_projectile_launch_pitch_angle(
|
|
||||||
const Projectile& projectile, const Vector3<float>& target_position) const noexcept
|
|
||||||
{
|
|
||||||
const auto bullet_gravity = m_gravity_constant * projectile.m_gravity_scale;
|
|
||||||
const auto delta = target_position - projectile.m_origin;
|
|
||||||
|
|
||||||
const auto distance2d = delta.length_2d();
|
|
||||||
const auto distance2d_sqr = distance2d * distance2d;
|
|
||||||
const auto launch_speed_sqr = projectile.m_launch_speed * projectile.m_launch_speed;
|
|
||||||
|
|
||||||
float root = launch_speed_sqr * launch_speed_sqr
|
|
||||||
- bullet_gravity * (bullet_gravity * distance2d_sqr + 2.0f * delta.z * launch_speed_sqr);
|
|
||||||
|
|
||||||
if (root < 0.0f) [[unlikely]]
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
root = std::sqrt(root);
|
|
||||||
const float angle = std::atan((launch_speed_sqr - root) / (bullet_gravity * distance2d));
|
|
||||||
|
|
||||||
return angles::radians_to_degrees(angle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProjPredEngineLegacy::is_projectile_reached_target(const Vector3<float>& target_position,
|
|
||||||
const Projectile& projectile, const float pitch,
|
|
||||||
const float time) const noexcept
|
|
||||||
{
|
|
||||||
const auto yaw = projectile.m_origin.view_angle_to(target_position).y;
|
|
||||||
const auto projectile_position = projectile.predict_position(pitch, yaw, time, m_gravity_constant);
|
|
||||||
|
|
||||||
return projectile_position.distance_to(target_position) <= m_distance_tolerance;
|
|
||||||
}
|
|
||||||
} // namespace omath::projectile_prediction
|
|
||||||
@@ -7,16 +7,4 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
Vector3<float> Projectile::predict_position(const float pitch, const float yaw, const float time,
|
|
||||||
const float gravity) const noexcept
|
|
||||||
{
|
|
||||||
auto current_pos = m_origin
|
|
||||||
+ source_engine::forward_vector({source_engine::PitchAngle::from_degrees(-pitch),
|
|
||||||
source_engine::YawAngle::from_degrees(yaw),
|
|
||||||
source_engine::RollAngle::from_degrees(0)})
|
|
||||||
* m_launch_speed * time;
|
|
||||||
current_pos.z -= (gravity * m_gravity_scale) * (time * time) * 0.5f;
|
|
||||||
|
|
||||||
return current_pos;
|
|
||||||
}
|
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ namespace
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Fixture with one canonical right‑angled triangle in the XY plane.
|
// Fixture with one canonical right‑angled triangle in the XY plane.
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
class lline_tracer_fixture : public ::testing::Test
|
class line_tracer_fixture : public ::testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
lline_tracer_fixture() :
|
line_tracer_fixture() :
|
||||||
triangle({0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f})
|
triangle({0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ namespace
|
|||||||
bool expected_clear; // true => segment does NOT hit the triangle
|
bool expected_clear; // true => segment does NOT hit the triangle
|
||||||
};
|
};
|
||||||
|
|
||||||
class CanTraceLineParam : public lline_tracer_fixture,
|
class CanTraceLineParam : public line_tracer_fixture,
|
||||||
public ::testing::WithParamInterface<TraceCase>
|
public ::testing::WithParamInterface<TraceCase>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -79,7 +79,7 @@ namespace
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Validate that the reported hit point is correct for a genuine intersection.
|
// Validate that the reported hit point is correct for a genuine intersection.
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
TEST_F(lline_tracer_fixture, HitPointCorrect)
|
TEST_F(line_tracer_fixture, HitPointCorrect)
|
||||||
{
|
{
|
||||||
constexpr Ray ray{{0.3f, 0.3f, -1.f}, {0.3f, 0.3f, 1.f}};
|
constexpr Ray ray{{0.3f, 0.3f, -1.f}, {0.3f, 0.3f, 1.f}};
|
||||||
constexpr Vec3 expected{0.3f, 0.3f, 0.f};
|
constexpr Vec3 expected{0.3f, 0.3f, 0.f};
|
||||||
@@ -92,7 +92,7 @@ namespace
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Triangle far beyond the ray should not block.
|
// Triangle far beyond the ray should not block.
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
TEST_F(lline_tracer_fixture, DistantTriangleClear)
|
TEST_F(line_tracer_fixture, DistantTriangleClear)
|
||||||
{
|
{
|
||||||
constexpr Ray short_ray{{0.f, 0.f, 0.f}, {0.f, 0.f, 1.f}};
|
constexpr Ray short_ray{{0.f, 0.f, 0.f}, {0.f, 0.f, 1.f}};
|
||||||
constexpr Triangle<Vec3> distant{{1000.f, 1000.f, 1000.f},
|
constexpr Triangle<Vec3> distant{{1000.f, 1000.f, 1000.f},
|
||||||
|
|||||||
@@ -167,8 +167,8 @@ TEST_F(unit_test_mat, StaticMethod_ToScreenMat)
|
|||||||
TEST_F(unit_test_mat, Method_At_OutOfRange)
|
TEST_F(unit_test_mat, Method_At_OutOfRange)
|
||||||
{
|
{
|
||||||
#if !defined(NDEBUG) && defined(OMATH_SUPRESS_SAFETY_CHECKS)
|
#if !defined(NDEBUG) && defined(OMATH_SUPRESS_SAFETY_CHECKS)
|
||||||
EXPECT_THROW(std::ignore = m2.At(2, 0), std::out_of_range);
|
EXPECT_THROW(std::ignore = m2.at(2, 0), std::out_of_range);
|
||||||
EXPECT_THROW(std::ignore = m2.At(0, 2), std::out_of_range);
|
EXPECT_THROW(std::ignore = m2.at(0, 2), std::out_of_range);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
//
|
//
|
||||||
// Created by vlad on 5/18/2024.
|
// Created by vlad on 5/18/2024.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifdef OMATH_ENABLE_LEGACY
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <omath/matrix.hpp>
|
#include <omath/matrix.hpp>
|
||||||
#include "omath/vector3.hpp"
|
#include "omath/vector3.hpp"
|
||||||
@@ -177,4 +180,5 @@ TEST_F(UnitTestMatrix, AssignmentOperator_Move)
|
|||||||
EXPECT_FLOAT_EQ(m3.at(0, 0), 1.0f);
|
EXPECT_FLOAT_EQ(m3.at(0, 0), 1.0f);
|
||||||
EXPECT_EQ(m2.row_count(), 0); // m2 should be empty after the move
|
EXPECT_EQ(m2.row_count(), 0); // m2 should be empty after the move
|
||||||
EXPECT_EQ(m2.columns_count(), 0);
|
EXPECT_EQ(m2.columns_count(), 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user