mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 15:03:27 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 858314fa0a | |||
| f277b1038c | |||
| 15c055beb7 | |||
| 4d24815f3e | |||
| d96b0cd2f7 | |||
| d238bd137f | |||
| 17b150499d | |||
| c7228c9674 | |||
| 7a9f5d4966 | |||
| a16050242a | |||
| ea8f3d8d51 | |||
| 08d2ccc03a | |||
| 21ec23d77b | |||
| 2c4ff37062 | |||
| 695a8035b5 | |||
| d12b236e56 | |||
| 7a5090d9f6 | |||
| ec76a7239c | |||
| 2758f549a3 | |||
| 493931ef0f | |||
| 9e1990942b |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
10
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
name: Custom issue template
|
||||||
|
about: Describe this issue template's purpose here.
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
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)
|
||||||
|
|||||||
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.
|
||||||
@@ -9,6 +9,9 @@
|
|||||||

|

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

|

|
||||||
|
[](https://discord.gg/eDgdaWbqwZ)
|
||||||
|
[](https://t.me/orangennotes)
|
||||||
|
|
||||||
</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.
|
||||||
|
|||||||
Submodule extlibs/googletest updated: d83fee138a...52eb8108c5
@@ -5,18 +5,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "omath/engines/iw_engine/constants.hpp"
|
#include "omath/engines/iw_engine/constants.hpp"
|
||||||
#include "omath/projection/camera.hpp"
|
#include "omath/projection/camera.hpp"
|
||||||
|
#include "traits/camera_trait.hpp"
|
||||||
|
|
||||||
namespace omath::iw_engine
|
namespace omath::iw_engine
|
||||||
{
|
{
|
||||||
class Camera final : public projection::Camera<Mat4X4, ViewAngles>
|
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
|
|
||||||
void look_at(const Vector3<float>& target) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
[[nodiscard]] Mat4X4 calc_view_matrix() const noexcept override;
|
|
||||||
[[nodiscard]] Mat4X4 calc_projection_matrix() const noexcept override;
|
|
||||||
};
|
|
||||||
} // namespace omath::iw_engine
|
} // namespace omath::iw_engine
|
||||||
24
include/omath/engines/iw_engine/traits/camera_trait.hpp
Normal file
24
include/omath/engines/iw_engine/traits/camera_trait.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/10/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/iw_engine/constants.hpp"
|
||||||
|
#include "omath/projection/camera.hpp"
|
||||||
|
|
||||||
|
namespace omath::iw_engine
|
||||||
|
{
|
||||||
|
class CameraTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::iw_engine
|
||||||
79
include/omath/engines/iw_engine/traits/pred_engine_trait.hpp
Normal file
79
include/omath/engines/iw_engine/traits/pred_engine_trait.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// 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::iw_engine
|
||||||
|
{
|
||||||
|
class PredEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
const float pitch, const float yaw,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
|
||||||
|
RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.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_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
const std::optional<float> projectile_pitch) noexcept
|
||||||
|
{
|
||||||
|
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||||
|
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||||
|
|
||||||
|
return {predicted_target_position.x, predicted_target_position.y, 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::iw_engine
|
||||||
@@ -4,16 +4,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "omath/engines/opengl_engine/constants.hpp"
|
#include "omath/engines/opengl_engine/constants.hpp"
|
||||||
#include "omath/projection/camera.hpp"
|
#include "omath/projection/camera.hpp"
|
||||||
|
#include "traits/camera_trait.hpp"
|
||||||
|
|
||||||
namespace omath::opengl_engine
|
namespace omath::opengl_engine
|
||||||
{
|
{
|
||||||
class Camera final : public projection::Camera<Mat4X4, ViewAngles>
|
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
|
|
||||||
void look_at(const Vector3<float>& target) override;
|
|
||||||
[[nodiscard]] Mat4X4 calc_view_matrix() const noexcept override;
|
|
||||||
[[nodiscard]] Mat4X4 calc_projection_matrix() const noexcept override;
|
|
||||||
};
|
|
||||||
} // namespace omath::opengl_engine
|
} // namespace omath::opengl_engine
|
||||||
24
include/omath/engines/opengl_engine/traits/camera_trait.hpp
Normal file
24
include/omath/engines/opengl_engine/traits/camera_trait.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/10/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/opengl_engine/constants.hpp"
|
||||||
|
#include "omath/projection/camera.hpp"
|
||||||
|
|
||||||
|
namespace omath::opengl_engine
|
||||||
|
{
|
||||||
|
class CameraTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// 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::opengl_engine
|
||||||
|
{
|
||||||
|
class PredEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
const float pitch, const float yaw,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
|
||||||
|
RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.y -= gravity * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return predicted;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_vector_2d_distance(const Vector3<float>& delta) noexcept
|
||||||
|
{
|
||||||
|
return std::sqrt(delta.x * delta.x + delta.z * delta.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
|
||||||
|
{
|
||||||
|
return vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
const std::optional<float> projectile_pitch) noexcept
|
||||||
|
{
|
||||||
|
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||||
|
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||||
|
|
||||||
|
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
|
||||||
|
}
|
||||||
|
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
|
||||||
|
// 89 look up, -89 look down
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_pitch_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto 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::opengl_engine
|
||||||
@@ -4,18 +4,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "omath/engines/source_engine/constants.hpp"
|
#include "omath/engines/source_engine/constants.hpp"
|
||||||
#include "omath/projection/camera.hpp"
|
#include "omath/projection/camera.hpp"
|
||||||
|
#include "traits/camera_trait.hpp"
|
||||||
namespace omath::source_engine
|
namespace omath::source_engine
|
||||||
{
|
{
|
||||||
class Camera final : public projection::Camera<Mat4X4, ViewAngles>
|
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
|
|
||||||
void look_at(const Vector3<float>& target) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
[[nodiscard]] Mat4X4 calc_view_matrix() const noexcept override;
|
|
||||||
[[nodiscard]] Mat4X4 calc_projection_matrix() const noexcept override;
|
|
||||||
};
|
|
||||||
} // namespace omath::source_engine
|
} // namespace omath::source_engine
|
||||||
24
include/omath/engines/source_engine/traits/camera_trait.hpp
Normal file
24
include/omath/engines/source_engine/traits/camera_trait.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/10/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/source_engine/constants.hpp"
|
||||||
|
#include "omath/projection/camera.hpp"
|
||||||
|
|
||||||
|
namespace omath::source_engine
|
||||||
|
{
|
||||||
|
class CameraTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::source_engine
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// 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::source_engine
|
||||||
|
{
|
||||||
|
class PredEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
const float pitch, const float yaw,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
|
||||||
|
RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.z -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.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_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
const std::optional<float> projectile_pitch) noexcept
|
||||||
|
{
|
||||||
|
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||||
|
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||||
|
|
||||||
|
return {predicted_target_position.x, predicted_target_position.y, 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::source_engine
|
||||||
@@ -5,18 +5,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "omath/engines/unity_engine/constants.hpp"
|
#include "omath/engines/unity_engine/constants.hpp"
|
||||||
#include "omath/projection/camera.hpp"
|
#include "omath/projection/camera.hpp"
|
||||||
|
#include "traits/camera_trait.hpp"
|
||||||
|
|
||||||
namespace omath::unity_engine
|
namespace omath::unity_engine
|
||||||
{
|
{
|
||||||
class Camera final : public projection::Camera<Mat4X4, ViewAngles>
|
using Camera = projection::Camera<Mat4X4, ViewAngles, CameraTrait>;
|
||||||
{
|
|
||||||
public:
|
|
||||||
Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
|
|
||||||
void look_at(const Vector3<float>& target) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
[[nodiscard]] Mat4X4 calc_view_matrix() const noexcept override;
|
|
||||||
[[nodiscard]] Mat4X4 calc_projection_matrix() const noexcept override;
|
|
||||||
};
|
|
||||||
} // namespace omath::unity_engine
|
} // namespace omath::unity_engine
|
||||||
24
include/omath/engines/unity_engine/traits/camera_trait.hpp
Normal file
24
include/omath/engines/unity_engine/traits/camera_trait.hpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/10/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/engines/unity_engine/formulas.hpp"
|
||||||
|
#include "omath/projection/camera.hpp"
|
||||||
|
|
||||||
|
namespace omath::unity_engine
|
||||||
|
{
|
||||||
|
class CameraTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
static ViewAngles calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept;
|
||||||
|
[[nodiscard]]
|
||||||
|
static Mat4X4 calc_projection_matrix(const projection::FieldOfView& fov, const projection::ViewPort& view_port,
|
||||||
|
float near, float far) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace omath::unity_engine
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// 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::unity_engine
|
||||||
|
{
|
||||||
|
class PredEngineTrait final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
constexpr static Vector3<float> predict_projectile_position(const projectile_prediction::Projectile& projectile,
|
||||||
|
const float pitch, const float yaw,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto current_pos = projectile.m_origin
|
||||||
|
+ forward_vector({PitchAngle::from_degrees(-pitch), YawAngle::from_degrees(yaw),
|
||||||
|
RollAngle::from_degrees(0)})
|
||||||
|
* projectile.m_launch_speed * time;
|
||||||
|
current_pos.y -= (gravity * projectile.m_gravity_scale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return current_pos;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr Vector3<float> predict_target_position(const projectile_prediction::Target& target,
|
||||||
|
const float time, const float gravity) noexcept
|
||||||
|
{
|
||||||
|
auto predicted = target.m_origin + target.m_velocity * time;
|
||||||
|
|
||||||
|
if (target.m_is_airborne)
|
||||||
|
predicted.y -= gravity * (time * time) * 0.5f;
|
||||||
|
|
||||||
|
return predicted;
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_vector_2d_distance(const Vector3<float>& delta) noexcept
|
||||||
|
{
|
||||||
|
return std::sqrt(delta.x * delta.x + delta.z * delta.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static float get_vector_height_coordinate(const Vector3<float>& vec) noexcept
|
||||||
|
{
|
||||||
|
return vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static Vector3<float> calc_viewpoint_from_angles(const projectile_prediction::Projectile& projectile,
|
||||||
|
Vector3<float> predicted_target_position,
|
||||||
|
const std::optional<float> projectile_pitch) noexcept
|
||||||
|
{
|
||||||
|
const auto delta2d = calc_vector_2d_distance(predicted_target_position - projectile.m_origin);
|
||||||
|
const auto height = delta2d * std::tan(angles::degrees_to_radians(projectile_pitch.value()));
|
||||||
|
|
||||||
|
return {predicted_target_position.x, predicted_target_position.y + height, projectile.m_origin.z};
|
||||||
|
}
|
||||||
|
// Due to specification of maybe_calculate_projectile_launch_pitch_angle, pitch angle must be:
|
||||||
|
// 89 look up, -89 look down
|
||||||
|
[[nodiscard]]
|
||||||
|
static float calc_direct_pitch_angle(const Vector3<float>& origin, const Vector3<float>& view_to) noexcept
|
||||||
|
{
|
||||||
|
const auto 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::unity_engine
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "omath/engines/source_engine/traits/pred_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,16 +13,40 @@
|
|||||||
|
|
||||||
namespace omath::projectile_prediction
|
namespace omath::projectile_prediction
|
||||||
{
|
{
|
||||||
// ReSharper disable once CppClassCanBeFinal
|
template<class EngineTrait = source_engine::PredEngineTrait>
|
||||||
class ProjPredEngineLegacy : public ProjPredEngineInterface
|
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;
|
||||||
@@ -44,30 +69,41 @@ namespace omath::projectile_prediction
|
|||||||
[[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);
|
||||||
|
|
||||||
protected:
|
return projectile_position.distance_to(target_position) <= m_distance_tolerance;
|
||||||
// NOTE: Override this if you need to use engine with different coordinate system
|
}
|
||||||
// Like where Z is not height coordinate
|
|
||||||
// ===============================================================================================
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual float calc_vector_2d_distance(const Vector3<float>& delta) const;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual float get_vector_height_coordinate(const Vector3<float>& vec) const;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual Vector3<float> calc_viewpoint_from_angles(const Projectile& projectile,
|
|
||||||
Vector3<float> predicted_target_position,
|
|
||||||
std::optional<float> projectile_pitch) const;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual Vector3<float> predict_projectile_position(const Projectile& projectile, float pitch, float yaw,
|
|
||||||
float time, float gravity) const;
|
|
||||||
// ===============================================================================================
|
|
||||||
};
|
};
|
||||||
} // namespace omath::projectile_prediction
|
} // namespace omath::projectile_prediction
|
||||||
|
|||||||
@@ -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{};
|
||||||
|
|||||||
@@ -26,11 +26,11 @@ namespace omath::projection
|
|||||||
};
|
};
|
||||||
using FieldOfView = Angle<float, 0.f, 180.f, AngleFlags::Clamped>;
|
using FieldOfView = Angle<float, 0.f, 180.f, AngleFlags::Clamped>;
|
||||||
|
|
||||||
template<class Mat4X4Type, class ViewAnglesType>
|
template<class Mat4X4Type, class ViewAnglesType, class TraitClass>
|
||||||
class Camera
|
class Camera final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Camera() = default;
|
~Camera() = default;
|
||||||
Camera(const Vector3<float>& position, const ViewAnglesType& view_angles, const ViewPort& view_port,
|
Camera(const Vector3<float>& position, const ViewAnglesType& view_angles, const ViewPort& view_port,
|
||||||
const FieldOfView& fov, const float near, const float far) noexcept
|
const FieldOfView& fov, const float near, const float far) noexcept
|
||||||
: m_view_port(view_port), m_field_of_view(fov), m_far_plane_distance(far), m_near_plane_distance(near),
|
: m_view_port(view_port), m_field_of_view(fov), m_far_plane_distance(far), m_near_plane_distance(near),
|
||||||
@@ -39,15 +39,16 @@ namespace omath::projection
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void look_at(const Vector3<float>& target) = 0;
|
void look_at(const Vector3<float>& target)
|
||||||
|
{
|
||||||
[[nodiscard]] virtual Mat4X4Type calc_view_matrix() const noexcept = 0;
|
m_view_angles = TraitClass::calc_look_at_angle(m_origin, target);
|
||||||
|
}
|
||||||
[[nodiscard]] virtual Mat4X4Type calc_projection_matrix() const noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] Mat4X4Type calc_view_projection_matrix() const noexcept
|
[[nodiscard]] Mat4X4Type calc_view_projection_matrix() const noexcept
|
||||||
{
|
{
|
||||||
return calc_projection_matrix() * calc_view_matrix();
|
return TraitClass::calc_projection_matrix(m_field_of_view, m_view_port, m_near_plane_distance,
|
||||||
|
m_far_plane_distance)
|
||||||
|
* TraitClass::calc_view_matrix(m_view_angles, m_origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +190,29 @@ namespace omath
|
|||||||
return x + y;
|
return x + y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<(const Vector2& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() < other.length();
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>(const Vector2& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() > other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<=(const Vector2& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() <= other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>=(const Vector2& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() >= other.length();
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr std::tuple<Type, Type> as_tuple() const noexcept
|
constexpr std::tuple<Type, Type> as_tuple() const noexcept
|
||||||
{
|
{
|
||||||
@@ -202,6 +225,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;
|
||||||
}
|
}
|
||||||
@@ -253,6 +253,30 @@ namespace omath
|
|||||||
return {angles::radians_to_degrees(std::asin(delta.z / distance)),
|
return {angles::radians_to_degrees(std::asin(delta.z / distance)),
|
||||||
angles::radians_to_degrees(std::atan2(delta.y, delta.x)), 0};
|
angles::radians_to_degrees(std::atan2(delta.y, delta.x)), 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<(const Vector3& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() < other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>(const Vector3& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() > other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<=(const Vector3& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() <= other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>=(const Vector3& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() >= other.length();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace omath
|
} // namespace omath
|
||||||
// ReSharper disable once CppRedundantNamespaceDefinition
|
// ReSharper disable once CppRedundantNamespaceDefinition
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -89,7 +89,7 @@ namespace omath
|
|||||||
return Vector3<Type>::dot(other) + w * other.w;
|
return Vector3<Type>::dot(other) + w * other.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Vector3<Type> length() const noexcept
|
[[nodiscard]] Type length() const noexcept
|
||||||
{
|
{
|
||||||
return std::sqrt(length_sqr());
|
return std::sqrt(length_sqr());
|
||||||
}
|
}
|
||||||
@@ -158,6 +158,30 @@ namespace omath
|
|||||||
return Vector3<Type>::sum() + w;
|
return Vector3<Type>::sum() + w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<(const Vector4& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() < other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>(const Vector4& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() > other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator<=(const Vector4& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() <= other.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator>=(const Vector4& other) const noexcept
|
||||||
|
{
|
||||||
|
return length() >= other.length();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OMATH_IMGUI_INTEGRATION
|
#ifdef OMATH_IMGUI_INTEGRATION
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ImVec4 to_im_vec4() const noexcept
|
ImVec4 to_im_vec4() const noexcept
|
||||||
@@ -169,6 +193,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,33 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Vlad on 3/17/2025.
|
|
||||||
//
|
|
||||||
#include "omath/engines/iw_engine/camera.hpp"
|
|
||||||
#include "omath/engines/iw_engine/formulas.hpp"
|
|
||||||
|
|
||||||
namespace omath::iw_engine
|
|
||||||
{
|
|
||||||
|
|
||||||
Camera::Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far)
|
|
||||||
: projection::Camera<Mat4X4, ViewAngles>(position, view_angles, view_port, fov, near, far)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void Camera::look_at([[maybe_unused]] const Vector3<float>& target)
|
|
||||||
{
|
|
||||||
const float distance = m_origin.distance_to(target);
|
|
||||||
const auto delta = target - m_origin;
|
|
||||||
|
|
||||||
m_view_angles.pitch = PitchAngle::from_radians(std::asin(delta.z / distance));
|
|
||||||
m_view_angles.yaw = -YawAngle::from_radians(std::atan2(delta.y, delta.x));
|
|
||||||
m_view_angles.roll = RollAngle::from_radians(0.f);
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_view_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return iw_engine::calc_view_matrix(m_view_angles, m_origin);
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_projection_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return calc_perspective_projection_matrix(m_field_of_view.as_degrees(), m_view_port.aspect_ratio(),
|
|
||||||
m_near_plane_distance, m_far_plane_distance);
|
|
||||||
}
|
|
||||||
} // namespace omath::iw_engine
|
|
||||||
27
source/engines/iw_engine/traits/camera_trait.cpp
Normal file
27
source/engines/iw_engine/traits/camera_trait.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/11/2025.
|
||||||
|
//
|
||||||
|
#include "omath/engines/iw_engine/traits/camera_trait.hpp"
|
||||||
|
|
||||||
|
namespace omath::iw_engine
|
||||||
|
{
|
||||||
|
|
||||||
|
ViewAngles CameraTrait::calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept
|
||||||
|
{
|
||||||
|
const auto distance = cam_origin.distance_to(look_at);
|
||||||
|
const auto delta = cam_origin - look_at;
|
||||||
|
|
||||||
|
return {PitchAngle::from_radians(-std::asin(delta.z / distance)),
|
||||||
|
YawAngle::from_radians(std::atan2(delta.y, delta.x)), RollAngle::from_radians(0.f)};
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
|
||||||
|
{
|
||||||
|
return iw_engine::calc_view_matrix(angles, cam_origin);
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port, const float near,
|
||||||
|
const float far) noexcept
|
||||||
|
{
|
||||||
|
return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far);
|
||||||
|
}
|
||||||
|
} // namespace omath::iw_engine
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Orange on 12/23/2024.
|
|
||||||
//
|
|
||||||
#include "omath/engines/opengl_engine/camera.hpp"
|
|
||||||
#include "omath/engines/opengl_engine/formulas.hpp"
|
|
||||||
|
|
||||||
namespace omath::opengl_engine
|
|
||||||
{
|
|
||||||
|
|
||||||
Camera::Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far)
|
|
||||||
: projection::Camera<Mat4X4, ViewAngles>(position, view_angles, view_port, fov, near, far)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void Camera::look_at([[maybe_unused]] const Vector3<float>& target)
|
|
||||||
{
|
|
||||||
const float distance = m_origin.distance_to(target);
|
|
||||||
const auto delta = target - m_origin;
|
|
||||||
|
|
||||||
m_view_angles.pitch = PitchAngle::from_radians(std::asin(delta.z / distance));
|
|
||||||
m_view_angles.yaw = -YawAngle::from_radians(std::atan2(delta.y, delta.x));
|
|
||||||
m_view_angles.roll = RollAngle::from_radians(0.f);
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_view_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return opengl_engine::calc_view_matrix(m_view_angles, m_origin);
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_projection_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return calc_perspective_projection_matrix(m_field_of_view.as_degrees(), m_view_port.aspect_ratio(),
|
|
||||||
m_near_plane_distance, m_far_plane_distance);
|
|
||||||
}
|
|
||||||
} // namespace omath::opengl_engine
|
|
||||||
28
source/engines/opengl_engine/traits/camera_trait.cpp
Normal file
28
source/engines/opengl_engine/traits/camera_trait.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/11/2025.
|
||||||
|
//
|
||||||
|
#include "omath/engines/opengl_engine/traits/camera_trait.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace omath::opengl_engine
|
||||||
|
{
|
||||||
|
|
||||||
|
ViewAngles CameraTrait::calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept
|
||||||
|
{
|
||||||
|
const auto distance = cam_origin.distance_to(look_at);
|
||||||
|
const auto delta = cam_origin - look_at;
|
||||||
|
|
||||||
|
return {PitchAngle::from_radians(-std::asin(delta.y / distance)),
|
||||||
|
YawAngle::from_radians(std::atan2(delta.z, delta.x)), RollAngle::from_radians(0.f)};
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
|
||||||
|
{
|
||||||
|
return opengl_engine::calc_view_matrix(angles, cam_origin);
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port, const float near,
|
||||||
|
const float far) noexcept
|
||||||
|
{
|
||||||
|
return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far);
|
||||||
|
}
|
||||||
|
} // namespace omath::opengl_engine
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Orange on 12/4/2024.
|
|
||||||
//
|
|
||||||
#include "omath/engines/source_engine/camera.hpp"
|
|
||||||
#include "omath/engines/source_engine/formulas.hpp"
|
|
||||||
|
|
||||||
namespace omath::source_engine
|
|
||||||
{
|
|
||||||
|
|
||||||
Camera::Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const projection::FieldOfView& fov, const float near, const float far)
|
|
||||||
: projection::Camera<Mat4X4, ViewAngles>(position, view_angles, view_port, fov, near, far)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void Camera::look_at(const Vector3<float>& target)
|
|
||||||
{
|
|
||||||
const float distance = m_origin.distance_to(target);
|
|
||||||
const auto delta = target - m_origin;
|
|
||||||
|
|
||||||
m_view_angles.pitch = PitchAngle::from_radians(std::asin(delta.z / distance));
|
|
||||||
m_view_angles.yaw = -YawAngle::from_radians(std::atan2(delta.y, delta.x));
|
|
||||||
m_view_angles.roll = RollAngle::from_radians(0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4X4 Camera::calc_view_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return source_engine::calc_view_matrix(m_view_angles, m_origin);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat4X4 Camera::calc_projection_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return calc_perspective_projection_matrix(m_field_of_view.as_degrees(), m_view_port.aspect_ratio(),
|
|
||||||
m_near_plane_distance, m_far_plane_distance);
|
|
||||||
}
|
|
||||||
} // namespace omath::source_engine
|
|
||||||
27
source/engines/source_engine/traits/camera_trait.cpp
Normal file
27
source/engines/source_engine/traits/camera_trait.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/11/2025.
|
||||||
|
//
|
||||||
|
#include "omath/engines/source_engine/traits/camera_trait.hpp"
|
||||||
|
|
||||||
|
namespace omath::source_engine
|
||||||
|
{
|
||||||
|
|
||||||
|
ViewAngles CameraTrait::calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept
|
||||||
|
{
|
||||||
|
const auto distance = cam_origin.distance_to(look_at);
|
||||||
|
const auto delta = cam_origin - look_at;
|
||||||
|
|
||||||
|
return {PitchAngle::from_radians(-std::asin(delta.z / distance)),
|
||||||
|
YawAngle::from_radians(std::atan2(delta.y, delta.x)), RollAngle::from_radians(0.f)};
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
|
||||||
|
{
|
||||||
|
return source_engine::calc_view_matrix(angles, cam_origin);
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port, const float near,
|
||||||
|
const float far) noexcept
|
||||||
|
{
|
||||||
|
return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far);
|
||||||
|
}
|
||||||
|
} // namespace omath::source_engine
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Vlad on 3/22/2025.
|
|
||||||
//
|
|
||||||
#include <omath/engines/unity_engine/camera.hpp>
|
|
||||||
#include <omath/engines/unity_engine/formulas.hpp>
|
|
||||||
|
|
||||||
namespace omath::unity_engine
|
|
||||||
{
|
|
||||||
Camera::Camera(const Vector3<float>& position, const ViewAngles& view_angles, const projection::ViewPort& view_port,
|
|
||||||
const projection::FieldOfView& fov, const float near, const float far)
|
|
||||||
: projection::Camera<Mat4X4, ViewAngles>(position, view_angles, view_port, fov, near, far)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void Camera::look_at([[maybe_unused]] const Vector3<float>& target)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Not implemented");
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_view_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return unity_engine::calc_view_matrix(m_view_angles, m_origin);
|
|
||||||
}
|
|
||||||
Mat4X4 Camera::calc_projection_matrix() const noexcept
|
|
||||||
{
|
|
||||||
return calc_perspective_projection_matrix(m_field_of_view.as_degrees(), m_view_port.aspect_ratio(),
|
|
||||||
m_near_plane_distance, m_far_plane_distance);
|
|
||||||
}
|
|
||||||
} // namespace omath::unity_engine
|
|
||||||
27
source/engines/unity_engine/traits/camera_trait.cpp
Normal file
27
source/engines/unity_engine/traits/camera_trait.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 8/11/2025.
|
||||||
|
//
|
||||||
|
#include "omath/engines/unity_engine/traits/camera_trait.hpp"
|
||||||
|
|
||||||
|
namespace omath::unity_engine
|
||||||
|
{
|
||||||
|
|
||||||
|
ViewAngles CameraTrait::calc_look_at_angle(const Vector3<float>& cam_origin, const Vector3<float>& look_at) noexcept
|
||||||
|
{
|
||||||
|
const auto distance = cam_origin.distance_to(look_at);
|
||||||
|
const auto delta = cam_origin - look_at;
|
||||||
|
|
||||||
|
return {PitchAngle::from_radians(-std::asin(delta.y / distance)),
|
||||||
|
YawAngle::from_radians(std::atan2(delta.z, delta.x)), RollAngle::from_radians(0.f)};
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3<float>& cam_origin) noexcept
|
||||||
|
{
|
||||||
|
return unity_engine::calc_view_matrix(angles, cam_origin);
|
||||||
|
}
|
||||||
|
Mat4X4 CameraTrait::calc_projection_matrix(const projection::FieldOfView& fov,
|
||||||
|
const projection::ViewPort& view_port, const float near,
|
||||||
|
const float far) noexcept
|
||||||
|
{
|
||||||
|
return calc_perspective_projection_matrix(fov.as_degrees(), view_port.aspect_ratio(), near, far);
|
||||||
|
}
|
||||||
|
} // namespace omath::unity_engine
|
||||||
@@ -1,100 +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;
|
|
||||||
|
|
||||||
return calc_viewpoint_from_angles(projectile, predicted_target_position, projectile_pitch);
|
|
||||||
}
|
|
||||||
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 = 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 * 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = predict_projectile_position(projectile, pitch, yaw, time, m_gravity_constant);
|
|
||||||
|
|
||||||
return projectile_position.distance_to(target_position) <= m_distance_tolerance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float ProjPredEngineLegacy::calc_vector_2d_distance(const Vector3<float>& delta) const
|
|
||||||
{
|
|
||||||
return std::sqrt(delta.x * delta.x + delta.y * delta.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ProjPredEngineLegacy::get_vector_height_coordinate(const Vector3<float>& vec) const
|
|
||||||
{
|
|
||||||
return vec.z;
|
|
||||||
}
|
|
||||||
Vector3<float> ProjPredEngineLegacy::calc_viewpoint_from_angles(const Projectile& projectile,
|
|
||||||
const Vector3<float> predicted_target_position,
|
|
||||||
const std::optional<float> projectile_pitch) const
|
|
||||||
{
|
|
||||||
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};
|
|
||||||
}
|
|
||||||
Vector3<float> ProjPredEngineLegacy::predict_projectile_position(const Projectile& projectile, const float pitch,
|
|
||||||
const float yaw, const float time,
|
|
||||||
const float gravity) const
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
} // namespace omath::projectile_prediction
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Vlad on 6/9/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "omath/projectile_prediction/projectile.hpp"
|
|
||||||
#include <omath/engines/source_engine/formulas.hpp>
|
|
||||||
|
|
||||||
namespace omath::projectile_prediction
|
|
||||||
{
|
|
||||||
} // namespace omath::projectile_prediction
|
|
||||||
@@ -346,6 +346,28 @@ TEST_F(UnitTestVector2, NegationOperator_ZeroVector)
|
|||||||
EXPECT_FLOAT_EQ(result.y, -0.0f);
|
EXPECT_FLOAT_EQ(result.y, -0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector2, LessOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v1 < v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector2, GreaterOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v2 > v1);
|
||||||
|
}
|
||||||
|
TEST_F(UnitTestVector2, LessEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector2<float>{} <= omath::Vector2<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector2<float>{} <= omath::Vector2(1.f, 1.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector2, GreaterEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector2<float>{} >= omath::Vector2<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector2(1.f, 1.f) >= omath::Vector2<float>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Static assertions (compile-time checks)
|
// Static assertions (compile-time checks)
|
||||||
static_assert(Vector2(1.0f, 2.0f).length_sqr() == 5.0f, "LengthSqr should be 5");
|
static_assert(Vector2(1.0f, 2.0f).length_sqr() == 5.0f, "LengthSqr should be 5");
|
||||||
static_assert(Vector2(1.0f, 2.0f).dot(Vector2(4.0f, 5.0f)) == 14.0f, "Dot product should be 14");
|
static_assert(Vector2(1.0f, 2.0f).dot(Vector2(4.0f, 5.0f)) == 14.0f, "Dot product should be 14");
|
||||||
|
|||||||
@@ -402,6 +402,27 @@ TEST_F(UnitTestVector3, IsPerpendicular)
|
|||||||
EXPECT_FALSE(Vector3(0.0f, 0.0f, 0.0f).is_perpendicular({0.0f, 0.0f, 1.0f}));
|
EXPECT_FALSE(Vector3(0.0f, 0.0f, 0.0f).is_perpendicular({0.0f, 0.0f, 1.0f}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector3, LessOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v1 < v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector3, GreaterOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v2 > v1);
|
||||||
|
}
|
||||||
|
TEST_F(UnitTestVector3, LessEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector3<float>{} <= omath::Vector3<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector3<float>{} <= omath::Vector3(1.f, 1.f, 1.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector3, GreaterEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector3<float>{} >= omath::Vector3<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector3(1.f, 1.f, 1.f) >= omath::Vector3<float>{});
|
||||||
|
}
|
||||||
|
|
||||||
// Static assertions (compile-time checks)
|
// Static assertions (compile-time checks)
|
||||||
static_assert(Vector3(1.0f, 2.0f, 3.0f).length_sqr() == 14.0f, "LengthSqr should be 14");
|
static_assert(Vector3(1.0f, 2.0f, 3.0f).length_sqr() == 14.0f, "LengthSqr should be 14");
|
||||||
static_assert(Vector3(1.0f, 2.0f, 3.0f).dot(Vector3(4.0f, 5.0f, 6.0f)) == 32.0f, "Dot product should be 32");
|
static_assert(Vector3(1.0f, 2.0f, 3.0f).dot(Vector3(4.0f, 5.0f, 6.0f)) == 32.0f, "Dot product should be 32");
|
||||||
|
|||||||
@@ -215,3 +215,23 @@ TEST_F(UnitTestVector4, Clamp)
|
|||||||
EXPECT_FLOAT_EQ(v3.z, 2.5f);
|
EXPECT_FLOAT_EQ(v3.z, 2.5f);
|
||||||
EXPECT_FLOAT_EQ(v3.w, 4.0f); // w is not clamped in this method
|
EXPECT_FLOAT_EQ(v3.w, 4.0f); // w is not clamped in this method
|
||||||
}
|
}
|
||||||
|
TEST_F(UnitTestVector4, LessOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v1 < v2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector4, GreaterOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(v2 > v1);
|
||||||
|
}
|
||||||
|
TEST_F(UnitTestVector4, LessEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector4<float>{} <= omath::Vector4<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector4<float>{} <= omath::Vector4(1.f, 1.f, 1.f, 1.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UnitTestVector4, GreaterEqualOperator)
|
||||||
|
{
|
||||||
|
EXPECT_TRUE(omath::Vector4<float>{} >= omath::Vector4<float>{});
|
||||||
|
EXPECT_TRUE(omath::Vector4(1.f, 1.f, 1.f, 1.f) >= omath::Vector4<float>{});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user