Compare commits

...

62 Commits

Author SHA1 Message Date
dc43411bd2 fixed unity view matrix building 2025-03-24 06:30:09 +03:00
8959161904 Merge pull request #34 from orange-cpp/u/orange-cpp/add-unity
U/orange cpp/add unity
2025-03-23 01:20:16 +03:00
5d5bd215b2 fix 2025-03-23 01:17:05 +03:00
a48a257648 removed comment 2025-03-23 01:12:46 +03:00
ffba4e256a name fix 2025-03-23 01:06:36 +03:00
d9219cdddb naming fixed 2025-03-23 01:02:11 +03:00
5a1014a239 fix 2025-03-23 00:57:58 +03:00
74f2241bcf uncommented test 2025-03-23 00:52:12 +03:00
8977557a61 fix 2025-03-22 17:41:01 +03:00
481d7b85df improved camera 2025-03-22 17:39:40 +03:00
2b59fb6aa2 updated formulas 2025-03-22 08:36:06 +03:00
4f037a1952 added unity engine tests 2025-03-22 08:12:16 +03:00
ef11183c3f added camera files 2025-03-22 04:26:54 +03:00
326d8baaae Update README.md 2025-03-21 05:31:44 +03:00
e46067b0b9 fixed tests includes 2025-03-21 04:58:28 +03:00
68ac7f7b3d Merge pull request #33 from orange-cpp/u/orange-cpp/changed-file-naming
U/orange cpp/changed file naming
2025-03-21 04:50:56 +03:00
17de6d407c style fix 2025-03-21 04:48:38 +03:00
59d686e252 fix 2025-03-21 04:47:01 +03:00
713af1b772 fix 2025-03-21 04:46:23 +03:00
a8922230b3 fixed name 2025-03-21 04:45:02 +03:00
b8d79eb8b4 fixed example 2025-03-21 04:43:57 +03:00
5acd166d8f fixed include names 2025-03-21 04:40:59 +03:00
c7dda0ff10 changed source files naming 2025-03-21 04:30:17 +03:00
2688d977a9 change 2025-03-21 04:21:31 +03:00
Vladislav Alpatov
b9ac44a901 renamed headers 2025-03-21 04:17:42 +03:00
35658b1f6d Merge pull request #32 from orange-cpp/u/orange-cpp/examples
U/orange cpp/examples
2025-03-19 20:17:45 +03:00
8f4b61319f disabled tests by default 2025-03-19 20:13:06 +03:00
832c2ea5ef removed inline functions 2025-03-19 20:07:44 +03:00
50c336e044 added example 2025-03-19 19:16:22 +03:00
Vladislav Alpatov
e80e22bd5b added some files 2025-03-19 18:58:35 +03:00
27576ed761 added alias 2025-03-19 18:50:47 +03:00
f85243e892 improved print method 2025-03-19 00:56:56 +03:00
9b6d0beb03 Update README.md 2025-03-17 18:20:40 +03:00
ee9829af22 Merge pull request #31 from orange-cpp/u/orange-cpp/IWEngine
Added Infinity Ward Engine Support
2025-03-17 09:20:51 +03:00
cd452b0397 updated comment 2025-03-17 09:14:42 +03:00
2fa0c500a7 added magic number 2025-03-17 08:59:41 +03:00
0740d0778c added iw engine files 2025-03-17 07:20:13 +03:00
f5c271cfa6 changed naming of engines section 2025-03-17 05:27:00 +03:00
064a31f527 Merge pull request #30 from orange-cpp/u/orange-cpp/imgui-integration
ImGUI Vector integration
2025-03-17 04:12:39 +03:00
e5d0adf247 changed default option 2025-03-17 04:11:49 +03:00
8fc107ec0f fix 2025-03-17 04:07:21 +03:00
6dd72d2448 added convertors 2025-03-17 03:56:09 +03:00
c76f6e91b0 fix 2025-03-17 02:41:08 +03:00
d1d06c24ca unit tests buid off by defalut 2025-03-15 19:13:06 +03:00
169011e238 fixed Vec3 Vec4 2025-03-15 19:11:31 +03:00
934ca0da0a added explicit constructor for angle and comment for angle 2025-03-15 18:57:41 +03:00
4200ef63a6 improved mat & camera interface 2025-03-15 18:53:18 +03:00
58e2c3b5b7 fixed members inititalization miss match 2025-03-14 19:43:50 +03:00
Vladislav Alpatov
c3202a3bc3 patch 2025-03-01 21:32:02 +03:00
Vladislav Alpatov
39ab9d065d added option to disable avx2 2025-03-01 21:30:53 +03:00
Vladislav Alpatov
ed372a1c78 fixed for clang support 2025-03-01 21:22:44 +03:00
70313f5ae0 Merge pull request #29 from orange-cpp/u/orange-cpp/template-vectors
Added template Vectors 2d 3d 4d
2025-03-01 21:17:42 +03:00
Vladislav Alpatov
978656b573 refactored 2025-03-01 21:17:03 +03:00
Vladislav Alpatov
a0f746b84c fixed style 2025-03-01 21:15:26 +03:00
Vladislav Alpatov
6d0d267743 now template 2025-03-01 21:11:46 +03:00
9ba3bc754a removed define 2025-02-23 21:56:28 +03:00
3d1844fa0e Merge pull request #28 from orange-cpp/u/orange-cpp/avx2-prediction
U/orange cpp/avx2 prediction
2025-02-23 16:32:27 +03:00
f21d29c6c2 added legacy impl 2025-02-23 10:10:35 +03:00
28a35d5bc9 added more classes 2025-02-23 09:57:29 +03:00
d9684ff73f read me update 2025-02-22 23:34:45 +03:00
900501f37e added language mention 2025-02-22 23:34:45 +03:00
5639cd0eb5 added AVX2 2025-02-22 23:34:45 +03:00
98 changed files with 1645 additions and 834 deletions

View File

@@ -1,22 +1,31 @@
cmake_minimum_required(VERSION 3.26)
project(omath VERSION 1.0.1)
project(omath VERSION 1.0.1 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
option(OMATH_BUILD_TESTS "Build unit tests" ON)
option(OMATH_BUILD_TESTS "Build unit tests" OFF)
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ON)
option(OMATH_IMGUI_INTEGRATION "Omath will define method to convert omath types to imgui types" OFF)
option(OMATH_BUILD_EXAMPLES "Build example projects with you can learn & play" OFF)
if (OMATH_BUILD_AS_SHARED_LIBRARY)
add_library(omath SHARED source/Vector3.cpp)
add_library(omath SHARED source/Matrix.cpp)
else()
add_library(omath STATIC source/Vector3.cpp
include/omath/engines/OpenGL/Constants.hpp
include/omath/engines/OpenGL/Formulas.hpp
include/omath/engines/OpenGL/Camera.hpp)
add_library(omath STATIC source/Matrix.cpp)
endif()
add_library(omath::omath ALIAS omath)
if (OMATH_IMGUI_INTEGRATION)
target_compile_definitions(omath PUBLIC OMATH_IMGUI_INTEGRATION)
endif()
if (OMATH_USE_AVX2)
target_compile_definitions(omath PUBLIC OMATH_USE_AVX2)
endif()
set_target_properties(omath PROPERTIES
@@ -27,10 +36,12 @@ set_target_properties(omath PROPERTIES
CXX_STANDARD 23
CXX_STANDARD_REQUIRED ON)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(omath PRIVATE -mavx2 -mfma)
endif()
target_compile_features(omath PUBLIC cxx_std_23)
target_compile_definitions(omath PUBLIC OMATH_EXPORT)
add_subdirectory(source)
@@ -39,6 +50,10 @@ if(OMATH_BUILD_TESTS)
add_subdirectory(tests)
endif()
if (OMATH_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND OMATH_THREAT_WARNING_AS_ERROR)
target_compile_options(omath PRIVATE /W4 /WX)
elseif(OMATH_THREAT_WARNING_AS_ERROR)

View File

@@ -1,6 +1,6 @@
<div align = center>
![banner](https://i.imgur.com/sjtpKi8.png)
![banner](https://i.imgur.com/SM9ccP6.png)
![GitHub License](https://img.shields.io/github/license/orange-cpp/omath)
![GitHub contributors](https://img.shields.io/github/contributors/orange-cpp/omath)
@@ -12,14 +12,14 @@
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.
## 👁‍🗨 Features
- **Efficiency**: Optimized for performance, ensuring quick computations.
- **Efficiency**: Optimized for performance, ensuring quick computations using AVX2.
- **Versatility**: Includes a wide array of mathematical functions and algorithms.
- **Ease of Use**: Simplified interface for convenient integration into various projects.
- **Projectile Prediction**: Projectile prediction engine with O(N) algo complexity, that can power you projectile aim-bot.
- **3D Projection**: No need to find view-projection matrix anymore you can make your own projection pipeline.
- **Collision Detection**: Production ready code to handle collision detection by using simple interfaces.
- **No Additional Dependencies**: No additional dependencies need to use OMath except unit test execution
- **Ready for meta-programming**: Omath use templates for common types like Vectors, Matrixes etc, to handle all types!
## ⏬ Getting Started
### Prerequisites
- C++ Compiler
@@ -51,7 +51,7 @@ For detailed commands on installing different versions and more information, ple
3. Build the project using CMake:
```
cmake --preset windows-release -S .
cmake --build cmake-build/build/windows-release --target server -j 6
cmake --build cmake-build/build/windows-release --target omath -j 6
```
Use **\<platform\>-\<build configuration\>** preset to build siutable version for yourself. Like **windows-release** or **linux-release**.
## ❔ Usage
@@ -72,8 +72,11 @@ TEST(UnitTestProjection, IsPointOnScreen)
With `omath/projection` module you can achieve simple ESP hack for powered by Source/Unreal/Unity engine games, like [Apex Legends](https://store.steampowered.com/app/1172470/Apex_Legends/).
![banner](https://i.imgur.com/lcJrfcZ.png)
![Watch Video](https://youtu.be/lM_NJ1yCunw?si=5E87OrQMeypxSJ3E)
Or for InfinityWard Engine based games. Like Call of Duty Black Ops 2!
![banner](https://i.imgur.com/F8dmdoo.png)
Or even advanced projectile aimbot
[Watch Video](https://youtu.be/lM_NJ1yCunw?si=5E87OrQMeypxSJ3E)
</details>
## 🫵🏻 Contributing

4
examples/CMakeLists.txt Normal file
View File

@@ -0,0 +1,4 @@
project(examples)
add_executable(ExampleProjectionMatrixBuilder example_proj_mat_builder.cpp)
target_link_libraries(ExampleProjectionMatrixBuilder PRIVATE omath::omath)

View File

@@ -0,0 +1,40 @@
//
// Created by Vlad on 3/19/2025.
//
#include <iostream>
#include <print>
#include <omath/engines/opengl_engine/formulas.hpp>
int main()
{
std::println("OMATH Projection Matrix Builder");
float fov = 0;
float near = 0;
float far = 0;
float viewPortWidth = 0;
float viewPortHeight = 0;
std::print("Enter camera fov: ");
std::cin >> fov;
std::print("Enter camera z near: ");
std::cin >> near;
std::print("Enter camera z far: ");
std::cin >> far;
std::print("Enter camera screen width: ");
std::cin >> viewPortWidth;
std::print("Enter camera screen height: ");
std::cin >> viewPortHeight;
const auto mat =
omath::opengl_engine::CalcPerspectiveProjectionMatrix(fov, viewPortWidth / viewPortHeight, near, far);
std::print("{}", mat.ToString());
};

View File

@@ -1,154 +0,0 @@
//
// Vector4.h
//
#pragma once
#include <omath/Vector3.hpp>
#include <algorithm>
namespace omath
{
class Vector4 : public Vector3
{
public:
float w;
constexpr Vector4(const float x, const float y, const float z, const float w) : Vector3(x, y, z), w(w) {}
constexpr Vector4() : Vector3(), w(0.f) {};
[[nodiscard]]
constexpr bool operator==(const Vector4& src) const
{
return Vector3::operator==(src) && w == src.w;
}
[[nodiscard]]
constexpr bool operator!=(const Vector4& src) const
{
return !(*this == src);
}
constexpr Vector4& operator+=(const Vector4& v)
{
Vector3::operator+=(v);
w += v.w;
return *this;
}
constexpr Vector4& operator-=(const Vector4& v)
{
Vector3::operator-=(v);
w -= v.w;
return *this;
}
constexpr Vector4& operator*=(const float scalar)
{
Vector3::operator*=(scalar);
w *= scalar;
return *this;
}
constexpr Vector4& operator*=(const Vector4& v)
{
Vector3::operator*=(v);
w *= v.w;
return *this;
}
constexpr Vector4& operator/=(const float scalar)
{
Vector3::operator/=(scalar);
w /= scalar;
return *this;
}
constexpr Vector4& operator/=(const Vector4& v)
{
Vector3::operator/=(v);
w /= v.w;
return *this;
}
[[nodiscard]] constexpr float LengthSqr() const
{
return Vector3::LengthSqr() + w * w;
}
[[nodiscard]] constexpr float Dot(const Vector4& vOther) const
{
return Vector3::Dot(vOther) + w * vOther.w;
}
[[nodiscard]] float Length() const;
constexpr Vector4& Abs()
{
Vector3::Abs();
w = w < 0.f ? -w : w;
return *this;
}
constexpr Vector4& Clamp(const float min, const float max)
{
x = std::clamp(x, min, max);
y = std::clamp(y, min, max);
z = std::clamp(z, min, max);
return *this;
}
[[nodiscard]]
constexpr Vector4 operator-() const
{
return {-x, -y, -z, -w};
}
[[nodiscard]]
constexpr Vector4 operator+(const Vector4& v) const
{
return {x + v.x, y + v.y, z + v.z, w + v.w};
}
[[nodiscard]]
constexpr Vector4 operator-(const Vector4& v) const
{
return {x - v.x, y - v.y, z - v.z, w - v.w};
}
[[nodiscard]]
constexpr Vector4 operator*(const float scalar) const
{
return {x * scalar, y * scalar, z * scalar, w * scalar};
}
[[nodiscard]]
constexpr Vector4 operator*(const Vector4& v) const
{
return {x * v.x, y * v.y, z * v.z, w * v.w};
}
[[nodiscard]]
constexpr Vector4 operator/(const float scalar) const
{
return {x / scalar, y / scalar, z / scalar, w / scalar};
}
[[nodiscard]]
constexpr Vector4 operator/(const Vector4& v) const
{
return {x / v.x, y / v.y, z / v.z, w / v.w};
}
[[nodiscard]]
constexpr float Sum() const
{
return Vector3::Sum() + w;
}
};
}

View File

@@ -3,7 +3,7 @@
//
#pragma once
#include "omath/Angles.hpp"
#include "omath/angles.hpp"
#include <algorithm>
namespace omath
@@ -19,7 +19,7 @@ namespace omath
class Angle
{
Type m_angle;
constexpr Angle(const Type& degrees)
constexpr explicit Angle(const Type& degrees)
{
if constexpr (flags == AngleFlags::Normalized)
m_angle = angles::WrapAngle(degrees, min, max);
@@ -36,7 +36,7 @@ namespace omath
[[nodiscard]]
constexpr static Angle FromDegrees(const Type& degrees)
{
return {degrees};
return Angle{degrees};
}
constexpr Angle() : m_angle(0)
{
@@ -45,7 +45,7 @@ namespace omath
[[nodiscard]]
constexpr static Angle FromRadians(const Type& degrees)
{
return {angles::RadiansToDegrees<Type>(degrees)};
return Angle{angles::RadiansToDegrees<Type>(degrees)};
}
[[nodiscard]]
@@ -96,7 +96,6 @@ namespace omath
return Cos() / Sin();
}
[[nodiscard]]
constexpr Angle& operator+=(const Angle& other)
{
if constexpr (flags == AngleFlags::Normalized)
@@ -116,7 +115,6 @@ namespace omath
[[nodiscard]]
constexpr std::partial_ordering operator<=>(const Angle& other) const = default;
[[nodiscard]]
constexpr Angle& operator-=(const Angle& other)
{
return operator+=(-other);
@@ -146,7 +144,7 @@ namespace omath
[[nodiscard]]
constexpr Angle operator-() const
{
return {-m_angle};
return Angle{-m_angle};
}
};
}

View File

@@ -3,8 +3,8 @@
//
#pragma once
#include <numbers>
#include <cmath>
#include <numbers>
namespace omath::angles
{

View File

@@ -3,22 +3,22 @@
//
#pragma once
#include "omath/Vector3.hpp"
#include "omath/Triangle.hpp"
#include "omath/triangle.hpp"
#include "omath/vector3.hpp"
namespace omath::collision
{
class Ray
{
public:
Vector3 start;
Vector3 end;
Vector3<float> start;
Vector3<float> end;
[[nodiscard]]
Vector3 DirectionVector() const;
Vector3<float> DirectionVector() const;
[[nodiscard]]
Vector3 DirectionVectorNormalized() const;
Vector3<float> DirectionVectorNormalized() const;
};
class LineTracer
{
@@ -27,12 +27,12 @@ namespace omath::collision
[[nodiscard]]
static bool CanTraceLine(const Ray& ray, const Triangle<Vector3>& triangle);
static bool CanTraceLine(const Ray& ray, const Triangle<Vector3<float>>& triangle);
// Realization of MöllerTrumbore intersection algorithm
// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
[[nodiscard]]
static Vector3 GetRayHitPoint(const Ray& ray, const Triangle<Vector3>& triangle);
static Vector3<float> GetRayHitPoint(const Ray& ray, const Triangle<Vector3<float>>& triangle);
};
}

View File

@@ -4,9 +4,9 @@
#pragma once
#include "omath/Vector3.hpp"
#include <cstdint>
#include "omath/Vector4.hpp"
#include "omath/vector3.hpp"
#include "omath/vector4.hpp"
namespace omath
{
@@ -18,10 +18,10 @@ namespace omath
};
class Color final : public Vector4
class Color final : public Vector4<float>
{
public:
constexpr Color(float r, float g, float b, float a) : Vector4(r,g,b,a)
constexpr Color(const float r, const float g, const float b, const float a) : Vector4(r,g,b,a)
{
Clamp(0.f, 1.f);
}

View File

@@ -1,54 +0,0 @@
//
// Created by Orange on 12/23/2024.
//
#pragma once
#include "Constants.hpp"
namespace omath::opengl
{
[[nodiscard]]
inline Vector3 ForwardVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]]
inline Vector3 RightVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]]
inline Vector3 UpVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]] inline Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
{
return MatCameraView<float, MatStoreType::COLUMN_MAJOR>(-ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
[[nodiscard]]
inline Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
return {
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, -1, 0},
};
}
}

View File

@@ -0,0 +1,21 @@
//
// Created by Vlad on 3/17/2025.
//
#pragma once
#include "omath/engines/iw_engine/constants.hpp"
#include "omath/projection/camera.hpp"
namespace omath::iw_engine
{
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
{
public:
Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
void LookAt(const Vector3<float>& target) override;
protected:
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
};
}

View File

@@ -0,0 +1,25 @@
//
// Created by Vlad on 3/17/2025.
//
#pragma once
#include <omath/vector3.hpp>
#include <omath/mat.hpp>
#include <omath/angle.hpp>
#include <omath/view_angles.hpp>
namespace omath::iw_engine
{
constexpr Vector3<float> kAbsUp = {0, 0, 1};
constexpr Vector3<float> kAbsRight = {0, -1, 0};
constexpr Vector3<float> kAbsForward = {1, 0, 0};
using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat1x3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
}

View File

@@ -0,0 +1,24 @@
//
// Created by Vlad on 3/17/2025.
//
#pragma once
#include "omath/engines/iw_engine/constants.hpp"
namespace omath::iw_engine
{
[[nodiscard]]
Vector3<float> ForwardVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> RightVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> UpVector(const ViewAngles& angles);
[[nodiscard]] Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin);
[[nodiscard]]
Mat4x4 CalcPerspectiveProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
} // namespace omath::iw_engine

View File

@@ -2,17 +2,17 @@
// Created by Orange on 12/23/2024.
//
#pragma once
#include "Constants.hpp"
#include "omath/projection/Camera.hpp"
#include "omath/engines/opengl_engine/constants.hpp"
#include "omath/projection/camera.hpp"
namespace omath::opengl
namespace omath::opengl_engine
{
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
{
public:
Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
void LookAt(const Vector3& target) override;
void LookAt(const Vector3<float>& target) override;
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
};

View File

@@ -3,16 +3,16 @@
//
#pragma once
#include <omath/Vector3.hpp>
#include <omath/Mat.hpp>
#include <omath/Angle.hpp>
#include <omath/ViewAngles.hpp>
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::opengl
namespace omath::opengl_engine
{
constexpr Vector3 kAbsUp = {0, 1, 0};
constexpr Vector3 kAbsRight = {1, 0, 0};
constexpr Vector3 kAbsForward = {0, 0, -1};
constexpr Vector3<float> kAbsUp = {0, 1, 0};
constexpr Vector3<float> kAbsRight = {1, 0, 0};
constexpr Vector3<float> kAbsForward = {0, 0, -1};
using Mat4x4 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>;
using Mat3x3 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>;

View File

@@ -0,0 +1,24 @@
//
// Created by Orange on 12/23/2024.
//
#pragma once
#include "omath/engines/opengl_engine/constants.hpp"
namespace omath::opengl_engine
{
[[nodiscard]]
Vector3<float> ForwardVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> RightVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> UpVector(const ViewAngles& angles);
[[nodiscard]] Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin);
[[nodiscard]]
Mat4x4 CalcPerspectiveProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
} // namespace omath::opengl_engine

View File

@@ -2,17 +2,18 @@
// Created by Orange on 12/4/2024.
//
#pragma once
#include "Constants.hpp"
#include "omath/projection/Camera.hpp"
#include "omath/engines/source_engine/constants.hpp"
#include "omath/projection/camera.hpp"
namespace omath::source
namespace omath::source_engine
{
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
{
public:
Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
void LookAt(const Vector3& target) override;
void LookAt(const Vector3<float>& target) override;
protected:
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
};

View File

@@ -3,15 +3,16 @@
//
#pragma once
#include <omath/Vector3.hpp>
#include <omath/Mat.hpp>
#include <omath/Angle.hpp>
#include <omath/ViewAngles.hpp>
namespace omath::source
#include <omath/vector3.hpp>
#include <omath/mat.hpp>
#include <omath/angle.hpp>
#include <omath/view_angles.hpp>
namespace omath::source_engine
{
constexpr Vector3 kAbsUp = {0, 0, 1};
constexpr Vector3 kAbsRight = {0, -1, 0};
constexpr Vector3 kAbsForward = {1, 0, 0};
constexpr Vector3<float> kAbsUp = {0, 0, 1};
constexpr Vector3<float> kAbsRight = {0, -1, 0};
constexpr Vector3<float> kAbsForward = {1, 0, 0};
using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;

View File

@@ -0,0 +1,23 @@
//
// Created by Orange on 12/4/2024.
//
#pragma once
#include "omath/engines/source_engine/constants.hpp"
namespace omath::source_engine
{
[[nodiscard]]
Vector3<float> ForwardVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> RightVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> UpVector(const ViewAngles& angles);
[[nodiscard]] Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin);
[[nodiscard]]
Mat4x4 CalcPerspectiveProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
} // namespace omath::source

View File

@@ -0,0 +1,21 @@
//
// Created by Vlad on 3/22/2025.
//
#pragma once
#include "omath/engines/unity_engine/constants.hpp"
#include "omath/projection/camera.hpp"
namespace omath::unity_engine
{
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
{
public:
Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, float near, float far);
void LookAt(const Vector3<float>& target) override;
protected:
[[nodiscard]] Mat4x4 CalcViewMatrix() const override;
[[nodiscard]] Mat4x4 CalcProjectionMatrix() const override;
};
}

View File

@@ -0,0 +1,26 @@
//
// Created by Vlad on 3/22/2025.
//
#pragma once
#include <omath/vector3.hpp>
#include <omath/mat.hpp>
#include <omath/angle.hpp>
#include <omath/view_angles.hpp>
namespace omath::unity_engine
{
constexpr Vector3<float> kAbsUp = {0, 1, 0};
constexpr Vector3<float> kAbsRight = {1, 0, 0};
constexpr Vector3<float> kAbsForward = {0, 0, 1};
using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>;
using Mat1x3 = Mat<1, 3, float, MatStoreType::ROW_MAJOR>;
using PitchAngle = Angle<float, -89.f, 89.f, AngleFlags::Clamped>;
using YawAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using RollAngle = Angle<float, -180.f, 180.f, AngleFlags::Normalized>;
using ViewAngles = omath::ViewAngles<PitchAngle, YawAngle, RollAngle>;
} // namespace omath::source

View File

@@ -0,0 +1,24 @@
//
// Created by Vlad on 3/22/2025.
//
#pragma once
#include "omath/engines/unity_engine/constants.hpp"
namespace omath::unity_engine
{
[[nodiscard]]
Vector3<float> ForwardVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> RightVector(const ViewAngles& angles);
[[nodiscard]]
Vector3<float> UpVector(const ViewAngles& angles);
[[nodiscard]] Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin);
[[nodiscard]]
Mat4x4 CalcPerspectiveProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
} // namespace omath::source

View File

@@ -4,10 +4,11 @@
#pragma once
#include <algorithm>
#include <array>
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <utility>
#include "Vector3.hpp"
#include "omath/vector3.hpp"
namespace omath
{
@@ -34,11 +35,13 @@ namespace omath
class Mat final
{
public:
constexpr Mat()
constexpr Mat() noexcept
{
Clear();
}
constexpr static MatStoreType GetStoreOrdering()
[[nodiscard]]
constexpr static MatStoreType GetStoreOrdering() noexcept
{
return StoreType;
}
@@ -72,6 +75,7 @@ namespace omath
m_data = other.m_data;
}
[[nodiscard]]
constexpr Type& operator[](const size_t row, const size_t col)
{
return At(row, col);
@@ -100,7 +104,8 @@ namespace omath
return {Rows, Columns};
}
[[nodiscard]] constexpr const Type& At(const size_t rowIndex, const size_t columnIndex) const
[[nodiscard]]
constexpr const Type& At(const size_t rowIndex, const size_t columnIndex) const
{
if (rowIndex >= Rows || columnIndex >= Columns)
throw std::out_of_range("Index out of range");
@@ -177,6 +182,7 @@ namespace omath
return *this = *this * other;
}
[[nodiscard]]
constexpr Mat operator*(const Type& f) const noexcept
{
Mat result(*this);
@@ -192,6 +198,7 @@ namespace omath
return *this;
}
[[nodiscard]]
constexpr Mat operator/(const Type& f) const noexcept
{
Mat result(*this);
@@ -290,15 +297,20 @@ namespace omath
std::string ToString() const noexcept
{
std::ostringstream oss;
oss << "[[";
for (size_t i = 0; i < Rows; ++i)
{
if (i > 0)
oss << " [";
for (size_t j = 0; j < Columns; ++j)
{
oss << At(i, j);
oss << std::setw(9) << std::fixed << std::setprecision(3) << At(i, j);
if (j != Columns - 1)
oss << ' ';
oss << ", ";
}
oss << '\n';
oss << (i == Rows - 1 ? "]]" : "]\n");
}
return oss.str();
}
@@ -333,21 +345,21 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
constexpr static Mat<1, 4, Type, St> MatRowFromVector(const Vector3& vector) noexcept
constexpr static Mat<1, 4, Type, St> MatRowFromVector(const Vector3<Type>& vector) noexcept
{
return {{vector.x, vector.y, vector.z, 1}};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
constexpr static Mat<4, 1, Type, St> MatColumnFromVector(const Vector3& vector) noexcept
constexpr static Mat<4, 1, Type, St> MatColumnFromVector(const Vector3<Type>& vector) noexcept
{
return {{vector.x}, {vector.y}, {vector.z}, {1}};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
constexpr Mat<4, 4, Type, St> MatTranslation(const Vector3& diff) noexcept
constexpr Mat<4, 4, Type, St> MatTranslation(const Vector3<Type>& diff) noexcept
{
return
{
@@ -399,8 +411,8 @@ namespace omath
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
static Mat<4, 4, Type, St> MatCameraView(const Vector3& forward, const Vector3& right, const Vector3& up,
const Vector3& cameraOrigin) noexcept
static Mat<4, 4, Type, St> MatCameraView(const Vector3<Type>& forward, const Vector3<Type>& right,
const Vector3<Type>& up, const Vector3<Type>& cameraOrigin) noexcept
{
return Mat<4, 4, Type, St>
{
@@ -418,4 +430,30 @@ namespace omath
{
return MatRotationAxisZ(angles.yaw) * MatRotationAxisY(angles.pitch) * MatRotationAxisX(angles.roll);
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
Mat<4, 4, Type, St> MatPerspectiveLeftHanded(const float fieldOfView, const float aspectRatio, const float near,
const float far) noexcept
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
return {{1.f / (aspectRatio * fovHalfTan), 0.f, 0.f, 0.f},
{0.f, 1.f / fovHalfTan, 0.f, 0.f},
{0.f, 0.f, (far + near) / (far - near), -(2.f * near * far) / (far - near)},
{0.f, 0.f, 1.f, 0.f}};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
Mat<4, 4, Type, St> MatPerspectiveRightHanded(const float fieldOfView, const float aspectRatio, const float near,
const float far) noexcept
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
return {{1.f / (aspectRatio * fovHalfTan), 0.f, 0.f, 0.f},
{0.f, 1.f / fovHalfTan, 0.f, 0.f},
{0.f, 0.f, -(far + near) / (far - near), -(2.f * near * far) / (far - near)},
{0.f, 0.f, -1.f, 0.f}};
}
} // namespace omath

View File

@@ -2,10 +2,10 @@
#include <initializer_list>
#include <memory>
#include <string>
#include "omath/vector3.hpp"
namespace omath
{
class Vector3;
class Matrix final
{
@@ -19,10 +19,10 @@ namespace omath
static Matrix ToScreenMatrix(float screenWidth, float screenHeight);
[[nodiscard]]
static Matrix TranslationMatrix(const Vector3& diff);
static Matrix TranslationMatrix(const Vector3<float>& diff);
[[nodiscard]]
static Matrix OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up);
static Matrix OrientationMatrix(const Vector3<float>& forward, const Vector3<float>& right, const Vector3<float>& up);
[[nodiscard]]
static Matrix ProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);

View File

@@ -1,25 +0,0 @@
//
// Created by Vlad on 28.07.2024.
//
#pragma once
#include <vector>
#include "NavigationMesh.hpp"
#include "omath/Vector3.hpp"
namespace omath::pathfinding
{
struct PathNode;
class Astar final
{
public:
[[nodiscard]]
static std::vector<Vector3> FindPath(const Vector3& start, const Vector3& end, const NavigationMesh& navMesh);
private:
[[nodiscard]]
static std::vector<Vector3> ReconstructFinalPath(const std::unordered_map<Vector3, PathNode>& closedList, const Vector3& current);
[[nodiscard]]
static auto GetPerfectNode(const std::unordered_map<Vector3, PathNode>& openList, const Vector3& endVertex);
};
}

View File

@@ -0,0 +1,30 @@
//
// Created by Vlad on 28.07.2024.
//
#pragma once
#include <vector>
#include "omath/pathfinding/navigation_mesh.hpp"
#include "omath/vector3.hpp"
namespace omath::pathfinding
{
struct PathNode;
class Astar final
{
public:
[[nodiscard]]
static std::vector<Vector3<float>> FindPath(const Vector3<float>& start, const Vector3<float>& end,
const NavigationMesh& navMesh);
private:
[[nodiscard]]
static std::vector<Vector3<float>>
ReconstructFinalPath(const std::unordered_map<Vector3<float>, PathNode>& closedList,
const Vector3<float>& current);
[[nodiscard]]
static auto GetPerfectNode(const std::unordered_map<Vector3<float>, PathNode>& openList,
const Vector3<float>& endVertex);
};
} // namespace omath::pathfinding

View File

@@ -4,35 +4,35 @@
#pragma once
#include "omath/Vector3.hpp"
#include <expected>
#include <vector>
#include <string>
#include <vector>
#include "omath/vector3.hpp"
namespace omath::pathfinding
{
enum Error
{
};
class NavigationMesh final
{
public:
[[nodiscard]]
std::expected<Vector3<float>, std::string> GetClosestVertex(const Vector3<float>& point) const;
[[nodiscard]]
std::expected<Vector3, std::string> GetClosestVertex(const Vector3& point) const;
[[nodiscard]]
const std::vector<Vector3>& GetNeighbors(const Vector3& vertex) const;
const std::vector<Vector3<float>>& GetNeighbors(const Vector3<float>& vertex) const;
[[nodiscard]]
bool Empty() const;
[[nodiscard]] std::vector<uint8_t> Serialize() const;
void Deserialize(const std::vector<uint8_t>& raw);
std::unordered_map<Vector3, std::vector<Vector3>> m_verTextMap;
std::unordered_map<Vector3<float>, std::vector<Vector3<float>>> m_verTextMap;
};
}
} // namespace omath::pathfinding

View File

@@ -1,38 +0,0 @@
//
// Created by Vlad on 6/9/2024.
//
#pragma once
#include <optional>
#include "omath/Vector3.hpp"
#include "omath/prediction/Projectile.hpp"
#include "omath/prediction/Target.hpp"
namespace omath::prediction
{
class Engine final
{
public:
explicit Engine(float gravityConstant, float simulationTimeStep,
float maximumSimulationTime, float distanceTolerance);
[[nodiscard]]
std::optional<Vector3> MaybeCalculateAimPoint(const Projectile& projectile, const Target& target) const;
private:
const float m_gravityConstant;
const float m_simulationTimeStep;
const float m_maximumSimulationTime;
const float m_distanceTolerance;
[[nodiscard]]
std::optional<float> MaybeCalculateProjectileLaunchPitchAngle(const Projectile& projectile,
const Vector3& targetPosition) const;
[[nodiscard]]
bool IsProjectileReachedTarget(const Vector3& targetPosition, const Projectile& projectile, float pitch, float time) const;
};
}

View File

@@ -1,21 +0,0 @@
//
// Created by Vlad on 6/9/2024.
//
#pragma once
#include "omath/Vector3.hpp"
namespace omath::prediction
{
class Projectile final
{
public:
[[nodiscard]]
Vector3 PredictPosition(float pitch, float yaw, float time, float gravity) const;
Vector3 m_origin;
float m_launchSpeed{};
float m_gravityScale{};
};
}

View File

@@ -0,0 +1,20 @@
//
// Created by Vlad on 2/23/2025.
//
#pragma once
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/vector3.hpp"
namespace omath::projectile_prediction
{
class ProjPredEngine
{
public:
[[nodiscard]]
virtual std::optional<Vector3<float>> MaybeCalculateAimPoint(const Projectile& projectile,
const Target& target) const = 0;
virtual ~ProjPredEngine() = default;
};
} // namespace omath::projectile_prediction

View File

@@ -0,0 +1,26 @@
//
// Created by Vlad on 2/23/2025.
//
#pragma once
#include "omath/projectile_prediction/proj_pred_engine.hpp"
namespace omath::projectile_prediction
{
class ProjPredEngineAVX2 final : public ProjPredEngine
{
public:
[[nodiscard]] std::optional<Vector3<float>> MaybeCalculateAimPoint(const Projectile& projectile,
const Target& target) const override;
ProjPredEngineAVX2(float gravityConstant, float simulationTimeStep, float maximumSimulationTime);
~ProjPredEngineAVX2() override = default;
private:
[[nodiscard]] static std::optional<float> CalculatePitch(const Vector3<float>& projOrigin, const Vector3<float>& targetPos,
float bulletGravity, float v0, float time);
const float m_gravityConstant;
const float m_simulationTimeStep;
const float m_maximumSimulationTime;
};
} // namespace omath::projectile_prediction

View File

@@ -0,0 +1,41 @@
//
// Created by Vlad on 6/9/2024.
//
#pragma once
#include <optional>
#include "omath/projectile_prediction/proj_pred_engine.hpp"
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/vector3.hpp"
namespace omath::projectile_prediction
{
class ProjPredEngineLegacy final : public ProjPredEngine
{
public:
explicit ProjPredEngineLegacy(float gravityConstant, float simulationTimeStep, float maximumSimulationTime,
float distanceTolerance);
[[nodiscard]]
std::optional<Vector3<float>> MaybeCalculateAimPoint(const Projectile& projectile,
const Target& target) const override;
private:
const float m_gravityConstant;
const float m_simulationTimeStep;
const float m_maximumSimulationTime;
const float m_distanceTolerance;
[[nodiscard]]
std::optional<float> MaybeCalculateProjectileLaunchPitchAngle(const Projectile& projectile,
const Vector3<float>& targetPosition) const;
[[nodiscard]]
bool IsProjectileReachedTarget(const Vector3<float>& targetPosition, const Projectile& projectile, float pitch,
float time) const;
};
} // namespace omath::projectile_prediction

View File

@@ -0,0 +1,21 @@
//
// Created by Vlad on 6/9/2024.
//
#pragma once
#include "omath/vector3.hpp"
namespace omath::projectile_prediction
{
class Projectile final
{
public:
[[nodiscard]]
Vector3<float> PredictPosition(float pitch, float yaw, float time, float gravity) const;
Vector3<float> m_origin;
float m_launchSpeed{};
float m_gravityScale{};
};
}

View File

@@ -3,16 +3,16 @@
//
#pragma once
#include "omath/Vector3.hpp"
#include "omath/vector3.hpp"
namespace omath::prediction
namespace omath::projectile_prediction
{
class Target final
{
public:
[[nodiscard]]
constexpr Vector3 PredictPosition(const float time, const float gravity) const
constexpr Vector3<float> PredictPosition(const float time, const float gravity) const
{
auto predicted = m_origin + m_velocity * time;
@@ -22,8 +22,8 @@ namespace omath::prediction
return predicted;
}
Vector3 m_origin;
Vector3 m_velocity;
Vector3<float> m_origin;
Vector3<float> m_velocity;
bool m_isAirborne{};
};
}

View File

@@ -5,11 +5,11 @@
#pragma once
#include <expected>
#include <omath/Mat.hpp>
#include <omath/Vector3.hpp>
#include "ErrorCodes.hpp"
#include <omath/Angle.hpp>
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <type_traits>
#include "omath/projection/error_codes.hpp"
namespace omath::projection
{
@@ -31,15 +31,15 @@ namespace omath::projection
{
public:
virtual ~Camera() = default;
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
Camera(const Vector3<float>& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
const FieldOfView& fov, const float near, const float far) :
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
m_viewAngles(viewAngles), m_origin(position)
{
}
virtual void LookAt(const Vector3& target) = 0;
protected:
virtual void LookAt(const Vector3<float>& target) = 0;
[[nodiscard]] virtual Mat4x4Type CalcViewMatrix() const = 0;
@@ -50,40 +50,43 @@ namespace omath::projection
return CalcProjectionMatrix() * CalcViewMatrix();
}
public:
[[nodiscard]] const Mat4x4Type& GetViewProjectionMatrix() const
{
if (!m_viewProjectionMatrix.has_value())
m_viewProjectionMatrix = CalcViewProjectionMatrix();
return m_viewProjectionMatrix.value();
}
void SetFieldOfView(const FieldOfView& fov)
{
m_fieldOfView = fov;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetNearPlane(const float near)
{
m_nearPlaneDistance = near;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetFarPlane(const float far)
{
m_farPlaneDistance = far;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetViewAngles(const ViewAnglesType& viewAngles)
{
m_viewAngles = viewAngles;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetOrigin(const Vector3& origin)
void SetOrigin(const Vector3<float>& origin)
{
m_origin = origin;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
void SetViewPort(const ViewPort& viewPort)
{
m_viewPort = viewPort;
m_viewProjectionMatrix = CalcViewProjectionMatrix();
}
[[nodiscard]] const FieldOfView& GetFieldOfView() const
@@ -106,17 +109,26 @@ namespace omath::projection
return m_viewAngles;
}
[[nodiscard]] const Vector3& GetOrigin() const
[[nodiscard]] const Vector3<float>& GetOrigin() const
{
return m_origin;
}
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Vector3& worldPosition) const
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToScreen(const Vector3<float>& worldPosition) const
{
if (!m_viewProjectionMatrix.has_value())
m_viewProjectionMatrix = CalcViewProjectionMatrix();
auto normalizedCords = WorldToViewPort(worldPosition);
auto projected = m_viewProjectionMatrix.value() * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
if (!normalizedCords.has_value())
return std::unexpected{normalizedCords.error()};
return NdcToScreenPosition(*normalizedCords);
}
[[nodiscard]] std::expected<Vector3<float>, Error> WorldToViewPort(const Vector3<float>& worldPosition) const
{
auto projected = GetViewProjectionMatrix() *
MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
if (projected.At(3, 0) == 0.0f)
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
@@ -126,10 +138,7 @@ namespace omath::projection
if (IsNdcOutOfBounds(projected))
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
const auto screenPositionX = (projected.At(0,0)+1.f) / 2.f * m_viewPort.m_width;
const auto screenPositionY = (-projected.At(1,0)+1) / 2.f * m_viewPort.m_height;
return Vector3{screenPositionX, screenPositionY, projected.At(2,0)};
return Vector3<float>{projected.At(0, 0), projected.At(1, 0), projected.At(2, 0)};
}
protected:
@@ -143,14 +152,24 @@ namespace omath::projection
ViewAnglesType m_viewAngles;
Vector3 m_origin;
Vector3<float> m_origin;
private:
template<class Type>
[[nodiscard]]
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
{
return std::ranges::any_of( ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
return std::ranges::any_of(ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
}
[[nodiscard]] Vector3<float> NdcToScreenPosition(const Vector3<float>& ndc) const
{
return
{
(ndc.x + 1.f) / 2.f * m_viewPort.m_width,
(1.f - ndc.y) / 2.f * m_viewPort.m_height,
ndc.z
};
}
};
} // namespace omath::projection

View File

@@ -2,10 +2,20 @@
// Created by Orange on 11/13/2024.
//
#pragma once
#include "omath/Vector3.hpp"
#include "omath/vector3.hpp"
namespace omath
{
/*
|\
| \
a | \ hypot
| \
-----
b
*/
template<class Vector>
class Triangle final
{
@@ -16,12 +26,12 @@ namespace omath
{
}
Vector3 m_vertex1;
Vector3 m_vertex2;
Vector3 m_vertex3;
Vector3<float> m_vertex1;
Vector3<float> m_vertex2;
Vector3<float> m_vertex3;
[[nodiscard]]
constexpr Vector3 CalculateNormal() const
constexpr Vector3<float> CalculateNormal() const
{
const auto b = SideBVector();
const auto a = SideAVector();
@@ -41,7 +51,7 @@ namespace omath
}
[[nodiscard]]
constexpr Vector3 SideAVector() const
constexpr Vector3<float> SideAVector() const
{
return m_vertex1 - m_vertex2;
}
@@ -61,12 +71,12 @@ namespace omath
return std::abs(sideA*sideA + sideB*sideB - hypot*hypot) <= 0.0001f;
}
[[nodiscard]]
constexpr Vector3 SideBVector() const
constexpr Vector3<float> SideBVector() const
{
return m_vertex3 - m_vertex2;
}
[[nodiscard]]
constexpr Vector3 MidPoint() const
constexpr Vector3<float> MidPoint() const
{
return (m_vertex1 + m_vertex2 + m_vertex3) / 3;
}

View File

@@ -3,21 +3,31 @@
//
#pragma once
#include <tuple>
#include <cmath>
#include <tuple>
#ifdef OMATH_IMGUI_INTEGRATION
#include <imgui.h>
#endif
namespace omath
{
template<class Type>
requires std::is_arithmetic_v<Type>
class Vector2
{
public:
float x = 0.f;
float y = 0.f;
Type x = static_cast<Type>(0);
Type y = static_cast<Type>(0);
// Constructors
constexpr Vector2() = default;
constexpr Vector2(const float x, const float y) : x(x), y(y) {}
constexpr Vector2(const Type& x, const Type& y) : x(x), y(y)
{
}
// Equality operators
[[nodiscard]]
@@ -65,7 +75,7 @@ namespace omath
return *this;
}
constexpr Vector2& operator*=(const float fl)
constexpr Vector2& operator*=(const Type& fl)
{
x *= fl;
y *= fl;
@@ -73,7 +83,7 @@ namespace omath
return *this;
}
constexpr Vector2& operator/=(const float fl)
constexpr Vector2& operator/=(const Type& fl)
{
x /= fl;
y /= fl;
@@ -81,7 +91,7 @@ namespace omath
return *this;
}
constexpr Vector2& operator+=(const float fl)
constexpr Vector2& operator+=(const Type& fl)
{
x += fl;
y += fl;
@@ -89,7 +99,7 @@ namespace omath
return *this;
}
constexpr Vector2& operator-=(const float fl)
constexpr Vector2& operator-=(const Type& fl)
{
x -= fl;
y -= fl;
@@ -98,68 +108,57 @@ namespace omath
}
// Basic vector operations
[[nodiscard]] float DistTo(const Vector2& vOther) const
[[nodiscard]] Type DistTo(const Vector2& vOther) const
{
return std::sqrt(DistToSqr(vOther));
}
[[nodiscard]] constexpr float DistToSqr(const Vector2& vOther) const
[[nodiscard]] constexpr Type DistToSqr(const Vector2& vOther) const
{
return (x - vOther.x) * (x - vOther.x) + (y - vOther.y) * (y - vOther.y);
}
[[nodiscard]] constexpr float Dot(const Vector2& vOther) const
[[nodiscard]] constexpr Type Dot(const Vector2& vOther) const
{
return x * vOther.x + y * vOther.y;
}
#ifndef _MSC_VER
[[nodiscard]] constexpr float Length() const
[[nodiscard]] constexpr Type& Length() const
{
return std::hypot(x, y);
}
[[nodiscard]] constexpr Vector2 Normalized() const
{
const float len = Length();
const Type len = Length();
return len > 0.f ? *this / len : *this;
}
#else
[[nodiscard]] float Length() const
[[nodiscard]] Type Length() const
{
return std::hypot(x, y);
}
[[nodiscard]] Vector2 Normalized() const
{
const float len = Length();
const Type len = Length();
return len > 0.f ? *this / len : *this;
}
#endif
[[nodiscard]] constexpr float LengthSqr() const
[[nodiscard]] constexpr Type LengthSqr() const
{
return x * x + y * y;
}
constexpr Vector2& Abs()
{
//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;
y = y < 0 ? -y : y;
return *this;
}
template<class type>
[[nodiscard]] constexpr const type& As() const
{
return *reinterpret_cast<const type*>(this);
}
template<class type>
[[nodiscard]] constexpr type& As()
{
return *reinterpret_cast<type*>(this);
}
[[nodiscard]] constexpr Vector2 operator-() const
{
return {-x, -y};
@@ -186,16 +185,24 @@ namespace omath
return {x / fl, y / fl};
}
// Sum of elements
[[nodiscard]] constexpr float Sum() const
// Sum of elements
[[nodiscard]] constexpr Type Sum() const
{
return x + y;
}
[[nodiscard]]
constexpr std::tuple<float, float> AsTuple() const
constexpr std::tuple<Type, Type> AsTuple() const
{
return std::make_tuple(x, y);
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
ImVec2 ToImVec2() const
{
return {static_cast<float>(this->x), static_cast<float>(this->y)};
}
#endif
};
}
} // namespace omath

View File

@@ -5,12 +5,10 @@
#pragma once
#include <cstdint>
#include <functional>
#include "omath/Vector2.hpp"
#include "omath/Angle.hpp"
#include <expected>
#include <immintrin.h>
#include <functional>
#include "omath/angle.hpp"
#include "omath/vector2.hpp"
namespace omath
{
@@ -20,16 +18,17 @@ namespace omath
IMPOSSIBLE_BETWEEN_ANGLE,
};
class Vector3 : public Vector2
template<class Type> requires std::is_arithmetic_v<Type>
class Vector3 : public Vector2<Type>
{
public:
float z = 0.f;
constexpr Vector3(const float x, const float y, const float z) : Vector2(x, y), z(z) { }
constexpr Vector3() : Vector2() {};
Type z = static_cast<Type>(0);
constexpr Vector3(const Type& x, const Type& y, const Type& z) : Vector2<Type>(x, y), z(z) { }
constexpr Vector3() : Vector2<Type>() {};
[[nodiscard]] constexpr bool operator==(const Vector3& src) const
{
return Vector2::operator==(src) && (src.z == z);
return Vector2<Type>::operator==(src) && (src.z == z);
}
[[nodiscard]] constexpr bool operator!=(const Vector3& src) const
@@ -39,7 +38,7 @@ namespace omath
constexpr Vector3& operator+=(const Vector3& v)
{
Vector2::operator+=(v);
Vector2<Type>::operator+=(v);
z += v.z;
return *this;
@@ -47,7 +46,7 @@ namespace omath
constexpr Vector3& operator-=(const Vector3& v)
{
Vector2::operator-=(v);
Vector2<Type>::operator-=(v);
z -= v.z;
return *this;
@@ -55,7 +54,7 @@ namespace omath
constexpr Vector3& operator*=(const float fl)
{
Vector2::operator*=(fl);
Vector2<Type>::operator*=(fl);
z *= fl;
return *this;
@@ -63,7 +62,7 @@ namespace omath
constexpr Vector3& operator*=(const Vector3& v)
{
Vector2::operator*=(v);
Vector2<Type>::operator*=(v);
z *= v.z;
return *this;
@@ -71,7 +70,7 @@ namespace omath
constexpr Vector3& operator/=(const Vector3& v)
{
Vector2::operator/=(v);
Vector2<Type>::operator/=(v);
z /= v.z;
return *this;
@@ -79,7 +78,7 @@ namespace omath
constexpr Vector3& operator+=(const float fl)
{
Vector2::operator+=(fl);
Vector2<Type>::operator+=(fl);
z += fl;
return *this;
@@ -87,7 +86,7 @@ namespace omath
constexpr Vector3& operator/=(const float fl)
{
Vector2::operator/=(fl);
Vector2<Type>::operator/=(fl);
z /= fl;
return *this;
@@ -95,7 +94,7 @@ namespace omath
constexpr Vector3& operator-=(const float fl)
{
Vector2::operator-=(fl);
Vector2<Type>::operator-=(fl);
z -= fl;
return *this;
@@ -103,117 +102,117 @@ namespace omath
constexpr Vector3& Abs()
{
Vector2::Abs();
Vector2<Type>::Abs();
z = z < 0.f ? -z : z;
return *this;
}
[[nodiscard]] constexpr float DistToSqr(const Vector3& vOther) const
[[nodiscard]] constexpr Type DistToSqr(const Vector3& vOther) const
{
return (*this - vOther).LengthSqr();
}
[[nodiscard]] constexpr float Dot(const Vector3& vOther) const
[[nodiscard]] constexpr Type Dot(const Vector3& vOther) const
{
return Vector2::Dot(vOther) + z * vOther.z;
return Vector2<Type>::Dot(vOther) + z * vOther.z;
}
#ifndef _MSC_VER
[[nodiscard]] constexpr float Length() const
[[nodiscard]] constexpr Type Length() const
{
return std::hypot(x, y, z);
}
[[nodiscard]] constexpr float Length2D() const
[[nodiscard]] constexpr Type Length2D() const
{
return Vector2::Length();
}
[[nodiscard]] float DistTo(const Vector3& vOther) const
[[nodiscard]] Type DistTo(const Vector3& vOther) const
{
return (*this - vOther).Length();
}
[[nodiscard]] constexpr Vector3 Normalized() const
{
const float length = this->Length();
const Type length = this->Length();
return length != 0 ? *this / length : *this;
}
#else
[[nodiscard]] float Length() const
[[nodiscard]] Type Length() const
{
return std::hypot(x, y, z);
return std::hypot(this->x, this->y, z);
}
[[nodiscard]] Vector3 Normalized() const
{
const float length = this->Length();
const Type length = this->Length();
return length != 0 ? *this / length : *this;
}
[[nodiscard]] float Length2D() const
[[nodiscard]] Type Length2D() const
{
return Vector2::Length();
return Vector2<Type>::Length();
}
[[nodiscard]] float DistTo(const Vector3& vOther) const
[[nodiscard]] Type DistTo(const Vector3& vOther) const
{
return (*this - vOther).Length();
}
#endif
[[nodiscard]] constexpr float LengthSqr() const
[[nodiscard]] constexpr Type LengthSqr() const
{
return Vector2::LengthSqr() + z * z;
return Vector2<Type>::LengthSqr() + z * z;
}
[[nodiscard]] constexpr Vector3 operator-() const
{
return {-x, -y, -z};
return {-this->x, -this->y, -z};
}
[[nodiscard]] constexpr Vector3 operator+(const Vector3& v) const
{
return {x + v.x, y + v.y, z + v.z};
return {this->x + v.x, this->y + v.y, z + v.z};
}
[[nodiscard]] constexpr Vector3 operator-(const Vector3& v) const
{
return {x - v.x, y - v.y, z - v.z};
return {this->x - v.x, this->y - v.y, z - v.z};
}
[[nodiscard]] constexpr Vector3 operator*(const float fl) const
{
return {x * fl, y * fl, z * fl};
return {this->x * fl, this->y * fl, z * fl};
}
[[nodiscard]] constexpr Vector3 operator*(const Vector3& v) const
{
return {x * v.x, y * v.y, z * v.z};
return {this->x * v.x, this->y * v.y, z * v.z};
}
[[nodiscard]] constexpr Vector3 operator/(const float fl) const
{
return {x / fl, y / fl, z / fl};
return {this->x / fl, this->y / fl, z / fl};
}
[[nodiscard]] constexpr Vector3 operator/(const Vector3& v) const
{
return {x / v.x, y / v.y, z / v.z};
return {this->x / v.x, this->y / v.y, z / v.z};
}
[[nodiscard]] constexpr Vector3 Cross(const Vector3 &v) const
{
return
{
y * v.z - z * v.y,
z * v.x - x * v.z,
x * v.y - y * v.x
this->y * v.z - z * v.y,
z * v.x - this->x * v.z,
this->x * v.y - this->y * v.x
};
}
[[nodiscard]] constexpr float Sum() const
[[nodiscard]] constexpr Type Sum() const
{
return Sum2D() + z;
}
@@ -237,16 +236,27 @@ namespace omath
return false;
}
[[nodiscard]] constexpr float Sum2D() const
[[nodiscard]] constexpr Type Sum2D() const
{
return Vector2::Sum();
return Vector2<Type>::Sum();
}
[[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const;
[[nodiscard]] constexpr std::tuple<float, float, float> AsTuple() const
[[nodiscard]] constexpr std::tuple<Type, Type, Type> AsTuple() const
{
return std::make_tuple(x, y, z);
return std::make_tuple(this->x, this->y, z);
}
[[nodiscard]] Vector3 ViewAngleTo(const Vector3 &other) const
{
const float distance = DistTo(other);
const auto delta = other - *this;
return
{
angles::RadiansToDegrees(std::asin(delta.z / distance)),
angles::RadiansToDegrees(std::atan2(delta.y, delta.x)),
0
};
}
};
}
@@ -254,9 +264,9 @@ namespace omath
namespace std
{
template<>
struct hash<omath::Vector3>
struct hash<omath::Vector3<float>>
{
std::size_t operator()(const omath::Vector3& vec) const noexcept
std::size_t operator()(const omath::Vector3<float>& vec) const noexcept
{
std::size_t hash = 0;
constexpr std::hash<float> hasher;

173
include/omath/vector4.hpp Normal file
View File

@@ -0,0 +1,173 @@
//
// Vector4.h
//
#pragma once
#include <algorithm>
#include <omath/vector3.hpp>
namespace omath
{
template <class Type>
class Vector4 : public Vector3<Type>
{
public:
Type w;
constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w) : Vector3<Type>(x, y, z), w(w) {}
constexpr Vector4() : Vector3<Type>(), w(0) {};
[[nodiscard]]
constexpr bool operator==(const Vector4& src) const
{
return Vector3<Type>::operator==(src) && w == src.w;
}
[[nodiscard]]
constexpr bool operator!=(const Vector4& src) const
{
return !(*this == src);
}
constexpr Vector4& operator+=(const Vector4& v)
{
Vector3<Type>::operator+=(v);
w += v.w;
return *this;
}
constexpr Vector4& operator-=(const Vector4& v)
{
Vector3<Type>::operator-=(v);
w -= v.w;
return *this;
}
constexpr Vector4& operator*=(const float scalar)
{
Vector3<Type>::operator*=(scalar);
w *= scalar;
return *this;
}
constexpr Vector4& operator*=(const Vector4& v)
{
Vector3<Type>::operator*=(v);
w *= v.w;
return *this;
}
constexpr Vector4& operator/=(const float scalar)
{
Vector3<Type>::operator/=(scalar);
w /= scalar;
return *this;
}
constexpr Vector4& operator/=(const Vector4& v)
{
Vector3<Type>::operator/=(v);
w /= v.w;
return *this;
}
[[nodiscard]] constexpr Type LengthSqr() const
{
return Vector3<Type>::LengthSqr() + w * w;
}
[[nodiscard]] constexpr Type Dot(const Vector4& vOther) const
{
return Vector3<Type>::Dot(vOther) + w * vOther.w;
}
[[nodiscard]] Vector3<Type> Length() const
{
return std::sqrt(LengthSqr());
}
constexpr Vector4& Abs()
{
Vector3<Type>::Abs();
w = w < 0.f ? -w : w;
return *this;
}
constexpr Vector4& Clamp(const Type& min, const Type& max)
{
this->x = std::clamp(this->x, min, max);
this->y = std::clamp(this->y, min, max);
this->z = std::clamp(this->z, min, max);
return *this;
}
[[nodiscard]]
constexpr Vector4 operator-() const
{
return {-this->x, -this->y, -this->z, -w};
}
[[nodiscard]]
constexpr Vector4 operator+(const Vector4& v) const
{
return {this->x + v.x, this->y + v.y, this->z + v.z, w + v.w};
}
[[nodiscard]]
constexpr Vector4 operator-(const Vector4& v) const
{
return {this->x - v.x, this->y - v.y, this->z - v.z, w - v.w};
}
[[nodiscard]]
constexpr Vector4 operator*(const Type& scalar) const
{
return {this->x * scalar, this->y * scalar, this->z * scalar, w * scalar};
}
[[nodiscard]]
constexpr Vector4 operator*(const Vector4& v) const
{
return {this->x * v.x, this->y * v.y, this->z * v.z, w * v.w};
}
[[nodiscard]]
constexpr Vector4 operator/(const Type& scalar) const
{
return {this->x / scalar, this->y / scalar, this->z / scalar, w / scalar};
}
[[nodiscard]]
constexpr Vector4 operator/(const Vector4& v) const
{
return {this->x / v.x, this->y / v.y, this->z / v.z, w / v.w};
}
[[nodiscard]]
constexpr Type Sum() const
{
return Vector3<Type>::Sum() + w;
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
ImVec4 ToImVec4() const
{
return
{
static_cast<float>(this->x),
static_cast<float>(this->y),
static_cast<float>(this->z),
static_cast<float>(w),
};
}
#endif
};
}

View File

@@ -1,12 +1,9 @@
target_sources(omath PRIVATE
Vector3.cpp
Matrix.cpp
matrix.cpp
color.cpp
Vector4.cpp
Vector2.cpp
)
add_subdirectory(prediction)
add_subdirectory(projectile_prediction)
add_subdirectory(pathfinding)
add_subdirectory(projection)
add_subdirectory(collision)

View File

@@ -1,11 +0,0 @@
//
// Created by Vlad on 02.09.2024.
//
#include "omath/Vector2.hpp"
#include <cmath>
namespace omath
{
}

View File

@@ -1,23 +0,0 @@
//
// Created by vlad on 10/28/23.
//
#include <omath/Vector3.hpp>
#include <cmath>
#include <omath/Angles.hpp>
namespace omath
{
Vector3 Vector3::ViewAngleTo(const Vector3 &other) const
{
const float distance = DistTo(other);
const auto delta = other - *this;
return
{
angles::RadiansToDegrees(std::asin(delta.z / distance)),
angles::RadiansToDegrees(std::atan2(delta.y, delta.x)),
0.f
};
}
}

View File

@@ -1,16 +0,0 @@
//
// Vector4.cpp
//
#include "omath/Vector4.hpp"
#include <cmath>
namespace omath
{
float Vector4::Length() const
{
return std::sqrt(LengthSqr());
}
}

View File

@@ -1,3 +1,3 @@
target_sources(omath PRIVATE
LineTracer.cpp
line_tracer.cpp
)

View File

@@ -1,25 +1,25 @@
//
// Created by Orange on 11/13/2024.
//
#include "omath/collision/LineTracer.hpp"
#include "omath/collision/line_tracer.hpp"
namespace omath::collision
{
bool LineTracer::CanTraceLine(const Ray& ray, const Triangle<Vector3>& triangle)
bool LineTracer::CanTraceLine(const Ray& ray, const Triangle<Vector3<float>>& triangle)
{
return GetRayHitPoint(ray, triangle) == ray.end;
}
Vector3 Ray::DirectionVector() const
Vector3<float> Ray::DirectionVector() const
{
return end - start;
}
Vector3 Ray::DirectionVectorNormalized() const
Vector3<float> Ray::DirectionVectorNormalized() const
{
return DirectionVector().Normalized();
}
Vector3 LineTracer::GetRayHitPoint(const Ray& ray, const Triangle<Vector3>& triangle)
Vector3<float> LineTracer::GetRayHitPoint(const Ray& ray, const Triangle<Vector3<float>>& triangle)
{
constexpr float kEpsilon = std::numeric_limits<float>::epsilon();

View File

@@ -1,2 +1,4 @@
add_subdirectory(Source)
add_subdirectory(OpenGL)
add_subdirectory(source_engine)
add_subdirectory(opengl_engine)
add_subdirectory(iw_engine)
add_subdirectory(unity_engine)

View File

@@ -1 +0,0 @@
target_sources(omath PRIVATE Camera.cpp)

View File

@@ -1 +0,0 @@
target_sources(omath PRIVATE Camera.cpp)

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE camera.cpp formulas.cpp)

View File

@@ -0,0 +1,34 @@
//
// 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& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far) :
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
{
}
void Camera::LookAt([[maybe_unused]] const Vector3<float>& target)
{
const float distance = m_origin.DistTo(target);
const auto delta = target - m_origin;
m_viewAngles.pitch = PitchAngle::FromRadians(std::asin(delta.z / distance));
m_viewAngles.yaw = -YawAngle::FromRadians(std::atan2(delta.y, delta.x));
m_viewAngles.roll = RollAngle::FromRadians(0.f);
}
Mat4x4 Camera::CalcViewMatrix() const
{
return iw_engine::CalcViewMatrix(m_viewAngles, m_origin);
}
Mat4x4 Camera::CalcProjectionMatrix() const
{
return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance,
m_farPlaneDistance);
}
} // namespace omath::openg

View File

@@ -0,0 +1,50 @@
//
// Created by Vlad on 3/19/2025.
//
#include "omath/engines/iw_engine/formulas.hpp"
namespace omath::iw_engine
{
Vector3<float> ForwardVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> RightVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> UpVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
{
// NOTE: Need magic number to fix fov calculation, since IW engine inherit Quake proj matrix calculation
constexpr auto kMultiplyFactor = 0.75f;
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f) * kMultiplyFactor;
return {
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, 1, 0},
};
};
} // namespace omath::iw_engine

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE camera.cpp formulas.cpp)

View File

@@ -1,19 +1,19 @@
//
// Created by Orange on 12/23/2024.
//
#include "omath/engines/OpenGL/Camera.hpp"
#include "omath/engines/OpenGL/Formulas.hpp"
#include "omath/engines/opengl_engine/camera.hpp"
#include "omath/engines/opengl_engine/formulas.hpp"
namespace omath::opengl
namespace omath::opengl_engine
{
Camera::Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
Camera::Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const Angle<float, 0.f, 180.f, AngleFlags::Clamped>& fov, const float near, const float far) :
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
{
}
void Camera::LookAt([[maybe_unused]] const Vector3& target)
void Camera::LookAt([[maybe_unused]] const Vector3<float>& target)
{
const float distance = m_origin.DistTo(target);
const auto delta = target - m_origin;
@@ -25,7 +25,7 @@ namespace omath::opengl
}
Mat4x4 Camera::CalcViewMatrix() const
{
return opengl::CalcViewMatrix(m_viewAngles, m_origin);
return opengl_engine::CalcViewMatrix(m_viewAngles, m_origin);
}
Mat4x4 Camera::CalcProjectionMatrix() const
{

View File

@@ -0,0 +1,45 @@
//
// Created by Vlad on 3/19/2025.
//
#include "omath/engines/opengl_engine/formulas.hpp"
namespace omath::opengl_engine
{
Vector3<float> ForwardVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> RightVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> UpVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView<float, MatStoreType::COLUMN_MAJOR>(-ForwardVector(angles), RightVector(angles),
UpVector(angles), cam_origin);
}
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
return {
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, -(far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, -1, 0},
};
}
} // namespace omath::opengl_engine

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE camera.cpp formulas.cpp)

View File

@@ -1,19 +1,19 @@
//
// Created by Orange on 12/4/2024.
//
#include "omath/engines/Source/Camera.hpp"
#include "omath/engines/Source/Formulas.hpp"
#include "omath/engines/source_engine/camera.hpp"
#include "omath/engines/source_engine/formulas.hpp"
namespace omath::source
namespace omath::source_engine
{
Camera::Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
Camera::Camera(const Vector3<float>& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
const projection::FieldOfView& fov, const float near, const float far) :
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
{
}
void Camera::LookAt(const Vector3& target)
void Camera::LookAt(const Vector3<float>& target)
{
const float distance = m_origin.DistTo(target);
const auto delta = target - m_origin;
@@ -26,7 +26,7 @@ namespace omath::source
Mat4x4 Camera::CalcViewMatrix() const
{
return source::CalcViewMatrix(m_viewAngles, m_origin);
return source_engine::CalcViewMatrix(m_viewAngles, m_origin);
}
Mat4x4 Camera::CalcProjectionMatrix() const

View File

@@ -1,47 +1,40 @@
//
// Created by Orange on 12/4/2024.
// Created by Vlad on 3/19/2025.
//
#pragma once
#include "Constants.hpp"
#include <omath/engines/source_engine/formulas.hpp>
namespace omath::source
namespace omath::source_engine
{
[[nodiscard]]
inline Vector3 ForwardVector(const ViewAngles& angles)
Vector3<float> ForwardVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]]
inline Vector3 RightVector(const ViewAngles& angles)
Vector3<float> RightVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]]
inline Vector3 UpVector(const ViewAngles& angles)
Vector3<float> UpVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
[[nodiscard]] inline Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin)
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
}
[[nodiscard]]
inline Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
{
// NOTE: Needed tp make thing draw normal, since source is wierd
// and use tricky projection matrix formula.
// NOTE: Need magic number to fix fov calculation, since source inherit Quake proj matrix calculation
constexpr auto kMultiplyFactor = 0.75f;
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f) * kMultiplyFactor;
@@ -51,7 +44,6 @@ namespace omath::source
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, 1, 0},
};
}
} // namespace omath::source
} // namespace omath::source_engine

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE formulas.cpp camera.cpp)

View File

@@ -0,0 +1,28 @@
//
// 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& viewAngles, const projection::ViewPort& viewPort,
const projection::FieldOfView& fov, const float near, const float far) :
projection::Camera<Mat4x4, ViewAngles>(position, viewAngles, viewPort, fov, near, far)
{
}
void Camera::LookAt([[maybe_unused]] const Vector3<float>& target)
{
throw std::runtime_error("Not implemented");
}
Mat4x4 Camera::CalcViewMatrix() const
{
return unity_engine::CalcViewMatrix(m_viewAngles, m_origin);
}
Mat4x4 Camera::CalcProjectionMatrix() const
{
return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance,
m_farPlaneDistance);
}
} // namespace omath::unity_engine

View File

@@ -0,0 +1,45 @@
//
// Created by Vlad on 3/22/2025.
//
#include "omath/engines/unity_engine/formulas.hpp"
namespace omath::unity_engine
{
Vector3<float> unity_engine::ForwardVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> RightVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Vector3<float> UpVector(const ViewAngles& angles)
{
const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp);
return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)};
}
Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3<float>& cam_origin)
{
return MatCameraView<float, MatStoreType::ROW_MAJOR>(ForwardVector(angles), -RightVector(angles),
UpVector(angles), cam_origin);
}
Mat4x4 CalcPerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
const float far)
{
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
return {
{1.f / (aspectRatio * fovHalfTan), 0, 0, 0},
{0, 1.f / (fovHalfTan), 0, 0},
{0, 0, (far + near) / (far - near), -(2.f * far * near) / (far - near)},
{0, 0, -1.f, 0},
};
}
} // namespace omath::unity_engine

View File

@@ -315,7 +315,7 @@ namespace omath
};
}
Matrix Matrix::TranslationMatrix(const Vector3& diff)
Matrix Matrix::TranslationMatrix(const Vector3<float>& diff)
{
return {
{1.f, 0.f, 0.f, 0.f},
@@ -325,7 +325,7 @@ namespace omath
};
}
Matrix Matrix::OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up)
Matrix Matrix::OrientationMatrix(const Vector3<float>& forward, const Vector3<float>& right, const Vector3<float>& up)
{
return {
{right.x, up.x, forward.x, 0.f},

View File

@@ -1 +1 @@
target_sources(omath PRIVATE NavigationMesh.cpp Astar.cpp)
target_sources(omath PRIVATE navigation_mesh.cpp a_star.cpp)

View File

@@ -1,7 +1,7 @@
//
// Created by Vlad on 28.07.2024.
//
#include "omath/pathfinding/Astar.hpp"
#include "omath/pathfinding/a_star.hpp"
#include <algorithm>
#include <optional>
@@ -13,15 +13,15 @@ namespace omath::pathfinding
{
struct PathNode final
{
std::optional<Vector3> cameFrom;
std::optional<Vector3<float>> cameFrom;
float gCost = 0.f;
};
std::vector<Vector3> Astar::ReconstructFinalPath(const std::unordered_map<Vector3, PathNode>& closedList,
const Vector3& current)
std::vector<Vector3<float>> Astar::ReconstructFinalPath(const std::unordered_map<Vector3<float>, PathNode>& closedList,
const Vector3<float>& current)
{
std::vector<Vector3> path;
std::vector<Vector3<float>> path;
std::optional currentOpt = current;
while (currentOpt)
@@ -39,7 +39,7 @@ namespace omath::pathfinding
std::ranges::reverse(path);
return path;
}
auto Astar::GetPerfectNode(const std::unordered_map<Vector3, PathNode>& openList, const Vector3& endVertex)
auto Astar::GetPerfectNode(const std::unordered_map<Vector3<float>, PathNode>& openList, const Vector3<float>& endVertex)
{
return std::ranges::min_element(openList,
[&endVertex](const auto& a, const auto& b)
@@ -50,10 +50,10 @@ namespace omath::pathfinding
});
}
std::vector<Vector3> Astar::FindPath(const Vector3& start, const Vector3& end, const NavigationMesh& navMesh)
std::vector<Vector3<float>> Astar::FindPath(const Vector3<float>& start, const Vector3<float>& end, const NavigationMesh& navMesh)
{
std::unordered_map<Vector3, PathNode> closedList;
std::unordered_map<Vector3, PathNode> openList;
std::unordered_map<Vector3<float>, PathNode> closedList;
std::unordered_map<Vector3<float>, PathNode> openList;
auto maybeStartVertex = navMesh.GetClosestVertex(start);
auto maybeEndVertex = navMesh.GetClosestVertex(end);

View File

@@ -1,13 +1,13 @@
//
// Created by Vlad on 28.07.2024.
//
#include "omath/pathfinding/NavigationMesh.hpp"
#include "omath/pathfinding/navigation_mesh.hpp"
#include <stdexcept>
#include <algorithm>
#include <stdexcept>
namespace omath::pathfinding
{
std::expected<Vector3, std::string> NavigationMesh::GetClosestVertex(const Vector3 &point) const
std::expected<Vector3<float>, std::string> NavigationMesh::GetClosestVertex(const Vector3<float> &point) const
{
const auto res = std::ranges::min_element(m_verTextMap,
[&point](const auto& a, const auto& b)
@@ -21,7 +21,7 @@ namespace omath::pathfinding
return res->first;
}
const std::vector<Vector3>& NavigationMesh::GetNeighbors(const Vector3 &vertex) const
const std::vector<Vector3<float>>& NavigationMesh::GetNeighbors(const Vector3<float> &vertex) const
{
return m_verTextMap.at(vertex);
}
@@ -73,18 +73,18 @@ namespace omath::pathfinding
while (offset < raw.size())
{
Vector3 vertex;
Vector3<float> vertex;
loadFromVector(raw, offset, vertex);
uint16_t neighborsCount;
loadFromVector(raw, offset, neighborsCount);
std::vector<Vector3> neighbors;
std::vector<Vector3<float>> neighbors;
neighbors.reserve(neighborsCount);
for (size_t i = 0; i < neighborsCount; ++i)
{
Vector3 neighbor;
Vector3<float> neighbor;
loadFromVector(raw, offset, neighbor);
neighbors.push_back(neighbor);
}

View File

@@ -1 +0,0 @@
target_sources(omath PRIVATE Engine.cpp Projectile.cpp Target.cpp)

View File

@@ -1,21 +0,0 @@
//
// Created by Vlad on 6/9/2024.
//
#include "omath/prediction/Projectile.hpp"
#include <cmath>
#include <omath/engines/Source/Formulas.hpp>
namespace omath::prediction
{
Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
{
auto currentPos = m_origin + source::ForwardVector({source::PitchAngle::FromDegrees(-pitch),
source::YawAngle::FromDegrees(yaw),
source::RollAngle::FromDegrees(0)}) *
m_launchSpeed * time;
currentPos.z -= (gravity * m_gravityScale) * (time * time) * 0.5f;
return currentPos;
}
} // namespace omath::prediction

View File

@@ -0,0 +1 @@
target_sources(omath PRIVATE proj_pred_engine_legacy.cpp projectile.cpp target.cpp proj_pred_engine_avx2.cpp proj_pred_engine.cpp)

View File

@@ -0,0 +1,10 @@
//
// Created by Vlad on 2/23/2025.
//
#include "omath/projectile_prediction/proj_pred_engine.hpp"
namespace omath::projectile_prediction
{
} // namespace omath::projectile_prediction

View File

@@ -0,0 +1,145 @@
//
// Created by Vlad on 2/23/2025.
//
#include "omath/projectile_prediction/proj_pred_engine_avx2.hpp"
#include "source_location"
namespace omath::projectile_prediction
{
std::optional<Vector3<float>>
ProjPredEngineAVX2::MaybeCalculateAimPoint([[maybe_unused]] const Projectile& projectile,
[[maybe_unused]] const Target& target) const
{
#ifdef OMATH_USE_AVX2
const float bulletGravity = m_gravityConstant * projectile.m_gravityScale;
const float v0 = projectile.m_launchSpeed;
const float v0Sqr = v0 * v0;
const Vector3 projOrigin = projectile.m_origin;
constexpr int SIMD_FACTOR = 8;
float currentTime = m_simulationTimeStep;
for (; currentTime <= m_maximumSimulationTime; currentTime += m_simulationTimeStep * SIMD_FACTOR)
{
const __m256 times =
_mm256_setr_ps(currentTime, currentTime + m_simulationTimeStep,
currentTime + m_simulationTimeStep * 2, currentTime + m_simulationTimeStep * 3,
currentTime + m_simulationTimeStep * 4, currentTime + m_simulationTimeStep * 5,
currentTime + m_simulationTimeStep * 6, currentTime + m_simulationTimeStep * 7);
const __m256 targetX =
_mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.x), times, _mm256_set1_ps(target.m_origin.x));
const __m256 targetY =
_mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.y), times, _mm256_set1_ps(target.m_origin.y));
const __m256 timesSq = _mm256_mul_ps(times, times);
const __m256 targetZ = _mm256_fmadd_ps(_mm256_set1_ps(target.m_velocity.z), times,
_mm256_fnmadd_ps(_mm256_set1_ps(0.5f * m_gravityConstant), timesSq,
_mm256_set1_ps(target.m_origin.z)));
const __m256 deltaX = _mm256_sub_ps(targetX, _mm256_set1_ps(projOrigin.x));
const __m256 deltaY = _mm256_sub_ps(targetY, _mm256_set1_ps(projOrigin.y));
const __m256 deltaZ = _mm256_sub_ps(targetZ, _mm256_set1_ps(projOrigin.z));
const __m256 dSqr = _mm256_add_ps(_mm256_mul_ps(deltaX, deltaX), _mm256_mul_ps(deltaY, deltaY));
const __m256 bgTimesSq = _mm256_mul_ps(_mm256_set1_ps(bulletGravity), timesSq);
const __m256 term = _mm256_add_ps(deltaZ, _mm256_mul_ps(_mm256_set1_ps(0.5f), bgTimesSq));
const __m256 termSq = _mm256_mul_ps(term, term);
const __m256 numerator = _mm256_add_ps(dSqr, termSq);
const __m256 denominator = _mm256_add_ps(timesSq, _mm256_set1_ps(1e-8f)); // Avoid division by zero
const __m256 requiredV0Sqr = _mm256_div_ps(numerator, denominator);
const __m256 v0SqrVec = _mm256_set1_ps(v0Sqr + 1e-3f);
const __m256 mask = _mm256_cmp_ps(requiredV0Sqr, v0SqrVec, _CMP_LE_OQ);
const unsigned validMask = _mm256_movemask_ps(mask);
if (!validMask)
continue;
alignas(32) float validTimes[SIMD_FACTOR];
_mm256_store_ps(validTimes, times);
for (int i = 0; i < SIMD_FACTOR; ++i)
{
if (!(validMask & (1 << i)))
continue;
const float candidateTime = validTimes[i];
if (candidateTime > m_maximumSimulationTime)
continue;
// Fine search around candidate time
for (float fineTime = candidateTime - m_simulationTimeStep * 2;
fineTime <= candidateTime + m_simulationTimeStep * 2; fineTime += m_simulationTimeStep)
{
if (fineTime < 0)
continue;
const Vector3 targetPos = target.PredictPosition(fineTime, m_gravityConstant);
const auto pitch = CalculatePitch(projOrigin, targetPos, bulletGravity, v0, fineTime);
if (!pitch)
continue;
const Vector3 delta = targetPos - projOrigin;
const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y);
const float height = d * std::tan(angles::DegreesToRadians(*pitch));
return Vector3(targetPos.x, targetPos.y, projOrigin.z + height);
}
}
}
// Fallback scalar processing for remaining times
for (; currentTime <= m_maximumSimulationTime; currentTime += m_simulationTimeStep)
{
const Vector3 targetPos = target.PredictPosition(currentTime, m_gravityConstant);
const auto pitch = CalculatePitch(projOrigin, targetPos, bulletGravity, v0, currentTime);
if (!pitch)
continue;
const Vector3 delta = targetPos - projOrigin;
const float d = std::sqrt(delta.x * delta.x + delta.y * delta.y);
const float height = d * std::tan(angles::DegreesToRadians(*pitch));
return Vector3(targetPos.x, targetPos.y, projOrigin.z + height);
}
return std::nullopt;
}
ProjPredEngineAVX2::ProjPredEngineAVX2(const float gravityConstant, const float simulationTimeStep,
const float maximumSimulationTime) :
m_gravityConstant(gravityConstant), m_simulationTimeStep(simulationTimeStep),
m_maximumSimulationTime(maximumSimulationTime)
{
}
std::optional<float> ProjPredEngineAVX2::CalculatePitch(const Vector3<float>& projOrigin,
const Vector3<float>& targetPos, const float bulletGravity,
const float v0, const float time)
{
if (time <= 0.0f)
return std::nullopt;
const Vector3 delta = targetPos - projOrigin;
const float dSqr = delta.x * delta.x + delta.y * delta.y;
const float h = delta.z;
const float term = h + 0.5f * bulletGravity * time * time;
const float requiredV0Sqr = (dSqr + term * term) / (time * time);
const float v0Sqr = v0 * v0;
if (requiredV0Sqr > v0Sqr + 1e-3f)
return std::nullopt;
if (dSqr == 0.0f)
return term >= 0.0f ? 90.0f : -90.0f;
const float d = std::sqrt(dSqr);
const float tanTheta = term / d;
return angles::RadiansToDegrees(std::atan(tanTheta));
#else
throw std::runtime_error(
std::format("{} AVX2 feature is not enabled!", std::source_location::current().function_name()));
#endif
}
} // namespace omath::projectile_prediction

View File

@@ -1,25 +1,18 @@
//
// Created by Vlad on 6/9/2024.
//
#include "omath/prediction/Engine.hpp"
#include "omath/projectile_prediction/proj_pred_engine_legacy.hpp"
#include <cmath>
#include <omath/Angles.hpp>
#include <omath/angles.hpp>
namespace omath::prediction
namespace omath::projectile_prediction
{
Engine::Engine(const float gravityConstant, const float simulationTimeStep,
const float maximumSimulationTime, const float distanceTolerance)
: m_gravityConstant(gravityConstant),
m_simulationTimeStep(simulationTimeStep),
m_maximumSimulationTime(maximumSimulationTime),
m_distanceTolerance(distanceTolerance)
ProjPredEngineLegacy::ProjPredEngineLegacy(const float gravityConstant, const float simulationTimeStep,
const float maximumSimulationTime, const float distanceTolerance) :
m_gravityConstant(gravityConstant), m_simulationTimeStep(simulationTimeStep),
m_maximumSimulationTime(maximumSimulationTime), m_distanceTolerance(distanceTolerance)
{
}
std::optional<Vector3> Engine::MaybeCalculateAimPoint(const Projectile &projectile, const Target &target) const
std::optional<Vector3<float>> ProjPredEngineLegacy::MaybeCalculateAimPoint(const Projectile& projectile,
const Target& target) const
{
for (float time = 0.f; time < m_maximumSimulationTime; time += m_simulationTimeStep)
{
@@ -28,7 +21,7 @@ namespace omath::prediction
const auto projectilePitch = MaybeCalculateProjectileLaunchPitchAngle(projectile, predictedTargetPosition);
if (!projectilePitch.has_value()) [[unlikely]]
continue;
continue;
if (!IsProjectileReachedTarget(predictedTargetPosition, projectile, projectilePitch.value(), time))
continue;
@@ -41,8 +34,9 @@ namespace omath::prediction
return std::nullopt;
}
std::optional<float> Engine::MaybeCalculateProjectileLaunchPitchAngle(const Projectile &projectile,
const Vector3 &targetPosition) const
std::optional<float>
ProjPredEngineLegacy::MaybeCalculateProjectileLaunchPitchAngle(const Projectile& projectile,
const Vector3<float>& targetPosition) const
{
const auto bulletGravity = m_gravityConstant * projectile.m_gravityScale;
const auto delta = targetPosition - projectile.m_origin;
@@ -51,11 +45,11 @@ namespace omath::prediction
const auto distance2dSqr = distance2d * distance2d;
const auto launchSpeedSqr = projectile.m_launchSpeed * projectile.m_launchSpeed;
float root = launchSpeedSqr * launchSpeedSqr - bulletGravity * (bulletGravity *
distance2dSqr + 2.0f * delta.z * launchSpeedSqr);
float root = launchSpeedSqr * launchSpeedSqr -
bulletGravity * (bulletGravity * distance2dSqr + 2.0f * delta.z * launchSpeedSqr);
if (root < 0.0f) [[unlikely]]
return std::nullopt;
return std::nullopt;
root = std::sqrt(root);
const float angle = std::atan((launchSpeedSqr - root) / (bulletGravity * distance2d));
@@ -63,12 +57,12 @@ namespace omath::prediction
return angles::RadiansToDegrees(angle);
}
bool Engine::IsProjectileReachedTarget(const Vector3 &targetPosition, const Projectile &projectile,
const float pitch, const float time) const
bool ProjPredEngineLegacy::IsProjectileReachedTarget(const Vector3<float>& targetPosition, const Projectile& projectile,
const float pitch, const float time) const
{
const auto yaw = projectile.m_origin.ViewAngleTo(targetPosition).y;
const auto projectilePosition = projectile.PredictPosition(pitch, yaw, time, m_gravityConstant);
return projectilePosition.DistTo(targetPosition) <= m_distanceTolerance;
}
}
} // namespace omath::projectile_prediction

View File

@@ -0,0 +1,21 @@
//
// Created by Vlad on 6/9/2024.
//
#include "omath/projectile_prediction/projectile.hpp"
#include <omath/engines/source_engine/formulas.hpp>
namespace omath::projectile_prediction
{
Vector3<float> Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
{
auto currentPos = m_origin + source_engine::ForwardVector({source_engine::PitchAngle::FromDegrees(-pitch),
source_engine::YawAngle::FromDegrees(yaw),
source_engine::RollAngle::FromDegrees(0)}) *
m_launchSpeed * time;
currentPos.z -= (gravity * m_gravityScale) * (time * time) * 0.5f;
return currentPos;
}
} // namespace omath::prediction

View File

@@ -2,7 +2,7 @@
// Created by Vlad on 6/9/2024.
//
#include "omath/prediction/Target.hpp"
#include "omath/projectile_prediction/projectile.hpp"
namespace omath::prediction

View File

@@ -1 +1 @@
target_sources(omath PRIVATE Camera.cpp)
target_sources(omath PRIVATE camera.cpp)

View File

@@ -1,7 +1,7 @@
//
// Created by Vlad on 27.08.2024.
//
#include "omath/projection/Camera.hpp"
#include "omath/projection/camera.hpp"
namespace omath::projection

View File

@@ -4,24 +4,25 @@ project(unit-tests)
include(GoogleTest)
add_executable(unit-tests
general/UnitTestPrediction.cpp
general/UnitTestMatrix.cpp
general/UnitTestMat.cpp
general/UnitTestAstar.cpp
general/UnitTestProjection.cpp
general/UnitTestVector3.cpp
general/UnitTestVector2.cpp
general/UnitTestColor.cpp
general/UnitTestVector4.cpp
general/UnitTestLineTrace.cpp
general/UnitTestAngles.cpp
general/UnitTestViewAngles.cpp
general/UnitTestAngle.cpp
general/UnitTestTriangle.cpp
general/unit_test_prediction.cpp
general/unit_test_matrix.cpp
general/unit_test_mat.cpp
general/unit_test_a_star.cpp
general/unit_test_projection.cpp
general/unit_test_vector3.cpp
general/unit_test_vector2.cpp
general/unit_test_color.cpp
general/unit_test_vector4.cpp
general/unit_test_line_trace.cpp
general/unit_test_angles.cpp
general/unit_test_view_angles.cpp
general/unit_test_angle.cpp
general/unit_test_triangle.cpp
engines/UnitTestOpenGL.cpp
engines/UnitTestUnityEngine.cpp
engines/UnitTestSourceEngine.cpp
engines/unit_test_open_gl.cpp
engines/unit_test_unity_engine.cpp
engines/unit_test_source_engine.cpp
engines/unit_test_iw_engine.cpp
)
@@ -34,6 +35,6 @@ set_target_properties(unit-tests PROPERTIES
CXX_STANDARD_REQUIRED ON)
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath)
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath::omath)
gtest_discover_tests(unit-tests)

View File

@@ -1,69 +0,0 @@
//
// Created by Orange on 11/23/2024.
//
#include <gtest/gtest.h>
#include <omath/engines/Source/Camera.hpp>
#include <omath/engines/Source/Constants.hpp>
#include <omath/engines/Source/Formulas.hpp>
TEST(UnitTestSourceEngine, ForwardVector)
{
const auto forward = omath::source::ForwardVector({});
EXPECT_EQ(forward, omath::source::kAbsForward);
}
TEST(UnitTestSourceEngine, RightVector)
{
const auto right = omath::source::RightVector({});
EXPECT_EQ(right, omath::source::kAbsRight);
}
TEST(UnitTestSourceEngine, UpVector)
{
const auto up = omath::source::UpVector({});
EXPECT_EQ(up, omath::source::kAbsUp);
}
TEST(UnitTestSourceEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
{
const auto projected = cam.WorldToScreen({distance, 0, 0});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_NEAR(projected->x, 960, 0.00001f);
EXPECT_NEAR(projected->y, 540, 0.00001f);
}
}
TEST(UnitTestSourceEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}
TEST(UnitTestSourceEngine, CameraSetAndGetOrigin)
{
auto cam = omath::source::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}

View File

@@ -1,3 +0,0 @@
//
// Created by Orange on 11/27/2024.
//

View File

@@ -0,0 +1,69 @@
//
// Created by Vlad on 3/17/2025.
//
#include <gtest/gtest.h>
#include <omath/engines/iw_engine/camera.hpp>
#include <omath/engines/iw_engine/constants.hpp>
#include <omath/engines/iw_engine/formulas.hpp>
TEST(UnitTestIwEngine, ForwardVector)
{
const auto forward = omath::iw_engine::ForwardVector({});
EXPECT_EQ(forward, omath::iw_engine::kAbsForward);
}
TEST(UnitTestIwEngine, RightVector)
{
const auto right = omath::iw_engine::RightVector({});
EXPECT_EQ(right, omath::iw_engine::kAbsRight);
}
TEST(UnitTestIwEngine, UpVector)
{
const auto up = omath::iw_engine::UpVector({});
EXPECT_EQ(up, omath::iw_engine::kAbsUp);
}
TEST(UnitTestIwEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
const auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
{
const auto projected = cam.WorldToScreen({distance, 0, 0});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_NEAR(projected->x, 960, 0.00001f);
EXPECT_NEAR(projected->y, 540, 0.00001f);
}
}
TEST(UnitTestIwEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}
TEST(UnitTestIwEngine, CameraSetAndGetOrigin)
{
auto cam = omath::iw_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}

View File

@@ -2,35 +2,35 @@
// Created by Orange on 11/23/2024.
//
#include <gtest/gtest.h>
#include <omath/engines/OpenGL/Camera.hpp>
#include <omath/engines/OpenGL/Constants.hpp>
#include <omath/engines/OpenGL/Formulas.hpp>
#include <omath/engines/opengl_engine/camera.hpp>
#include <omath/engines/opengl_engine/constants.hpp>
#include <omath/engines/opengl_engine/formulas.hpp>
TEST(UnitTestOpenGL, ForwardVector)
{
const auto forward = omath::opengl::ForwardVector({});
const auto forward = omath::opengl_engine::ForwardVector({});
EXPECT_EQ(forward, omath::opengl::kAbsForward);
EXPECT_EQ(forward, omath::opengl_engine::kAbsForward);
}
TEST(UnitTestOpenGL, RightVector)
{
const auto right = omath::opengl::RightVector({});
const auto right = omath::opengl_engine::RightVector({});
EXPECT_EQ(right, omath::opengl::kAbsRight);
EXPECT_EQ(right, omath::opengl_engine::kAbsRight);
}
TEST(UnitTestOpenGL, UpVector)
{
const auto up = omath::opengl::UpVector({});
EXPECT_EQ(up, omath::opengl::kAbsUp);
const auto up = omath::opengl_engine::UpVector({});
EXPECT_EQ(up, omath::opengl_engine::kAbsUp);
}
TEST(UnitTestOpenGL, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
const auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
for (float distance = -10.f; distance > -1000.f; distance -= 0.01f)
@@ -50,7 +50,7 @@ TEST(UnitTestOpenGL, ProjectTargetMovedFromCamera)
TEST(UnitTestOpenGL, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
@@ -60,9 +60,9 @@ TEST(UnitTestOpenGL, CameraSetAndGetFov)
TEST(UnitTestOpenGL, CameraSetAndGetOrigin)
{
auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
auto cam = omath::opengl_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3{});
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);

View File

@@ -0,0 +1,89 @@
//
// Created by Orange on 11/23/2024.
//
#include <gtest/gtest.h>
#include <omath/engines/source_engine/camera.hpp>
#include <omath/engines/source_engine/constants.hpp>
#include <omath/engines/source_engine/formulas.hpp>
TEST(UnitTestSourceEngine, ForwardVector)
{
const auto forward = omath::source_engine::ForwardVector({});
EXPECT_EQ(forward, omath::source_engine::kAbsForward);
}
TEST(UnitTestSourceEngine, RightVector)
{
const auto right = omath::source_engine::RightVector({});
EXPECT_EQ(right, omath::source_engine::kAbsRight);
}
TEST(UnitTestSourceEngine, UpVector)
{
const auto up = omath::source_engine::UpVector({});
EXPECT_EQ(up, omath::source_engine::kAbsUp);
}
TEST(UnitTestSourceEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
const auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
{
const auto projected = cam.WorldToScreen({distance, 0, 0});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_NEAR(projected->x, 960, 0.00001f);
EXPECT_NEAR(projected->y, 540, 0.00001f);
}
}
TEST(UnitTestSourceEngine, ProjectTargetMovedUp)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
const auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
auto prev = 1080.f;
for (float distance = 0.0f; distance < 10.f; distance += 1.f)
{
const auto projected = cam.WorldToScreen({100.f, 0, distance});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_TRUE(projected->y < prev);
prev = projected->y;
}
}
TEST(UnitTestSourceEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}
TEST(UnitTestSourceEngine, CameraSetAndGetOrigin)
{
auto cam = omath::source_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}

View File

@@ -0,0 +1,77 @@
//
// Created by Orange on 11/27/2024.
//
#include <gtest/gtest.h>
#include <omath/engines/unity_engine/camera.hpp>
#include <omath/engines/unity_engine/constants.hpp>
#include <omath/engines/unity_engine/formulas.hpp>
TEST(UnitTestUnityEngine, ForwardVector)
{
const auto forward = omath::unity_engine::ForwardVector({});
EXPECT_EQ(forward, omath::unity_engine::kAbsForward);
}
TEST(UnitTestUnityEngine, RightVector)
{
const auto right = omath::unity_engine::RightVector({});
EXPECT_EQ(right, omath::unity_engine::kAbsRight);
}
TEST(UnitTestUnityEngine, UpVector)
{
const auto up = omath::unity_engine::UpVector({});
EXPECT_EQ(up, omath::unity_engine::kAbsUp);
}
TEST(UnitTestUnityEngine, ProjectTargetMovedFromCamera)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(60.f);
const auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.01f, 1000.f);
for (float distance = 0.02f; distance < 100.f; distance += 0.01f)
{
const auto projected = cam.WorldToScreen({0, 0, distance});
EXPECT_TRUE(projected.has_value());
if (!projected.has_value())
continue;
EXPECT_NEAR(projected->x, 640, 0.00001f);
EXPECT_NEAR(projected->y, 360, 0.00001f);
}
}
TEST(UnitTestUnityEngine, Project)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(60.f);
const auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.03f, 1000.f);
const auto proj = cam.WorldToScreen({5.f, 3, 10.f});
std::println("{} {}", proj->x, proj->y);
}
TEST(UnitTestUnityEngine, CameraSetAndGetFov)
{
constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f);
auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f);
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f);
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}
TEST(UnitTestUnityEngine, CameraSetAndGetOrigin)
{
auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f);
EXPECT_EQ(cam.GetOrigin(), omath::Vector3<float>{});
cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f));
EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f);
}

View File

@@ -1,15 +0,0 @@
#include <gtest/gtest.h>
#include <omath/prediction/Engine.hpp>
TEST(UnitTestPrediction, PredictionTest)
{
constexpr omath::prediction::Target target{
.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
constexpr omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4};
const auto viewPoint = omath::prediction::Engine(400, 1.f / 1000.f, 50, 5.f).MaybeCalculateAimPoint(proj, target);
const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple();
EXPECT_NEAR(42.547142, pitch, 0.0001f);
EXPECT_NEAR(-1.181189, yaw, 0.0001f);
}

View File

@@ -2,7 +2,7 @@
// Created by Vlad on 18.08.2024.
//
#include <gtest/gtest.h>
#include <omath/pathfinding/Astar.hpp>
#include <omath/pathfinding/a_star.hpp>
TEST(UnitTestAstar, FindingRightPath)

View File

@@ -2,8 +2,7 @@
// Created by Orange on 11/30/2024.
//
#include <gtest/gtest.h>
#include <omath/Angles.hpp>
#include <omath/Angle.hpp>
#include <omath/angles.hpp>
TEST(UnitTestAngles, RadiansToDeg)
{

View File

@@ -2,7 +2,7 @@
// Created by Vlad on 01.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Color.hpp>
#include <omath/color.hpp>
using namespace omath;

View File

@@ -1,7 +1,7 @@
#include "gtest/gtest.h"
#include "omath/collision/LineTracer.hpp"
#include "omath/Triangle.hpp"
#include "omath/Vector3.hpp"
#include "omath/collision/line_tracer.hpp"
#include "omath/triangle.hpp"
#include "omath/vector3.hpp"
using namespace omath;
using namespace omath::collision;
@@ -10,10 +10,10 @@ class LineTracerTest : public ::testing::Test
{
protected:
// Set up common variables for use in each test
Vector3 vertex1{0.0f, 0.0f, 0.0f};
Vector3 vertex2{1.0f, 0.0f, 0.0f};
Vector3 vertex3{0.0f, 1.0f, 0.0f};
Triangle<Vector3> triangle{vertex1, vertex2, vertex3};
Vector3<float> vertex1{0.0f, 0.0f, 0.0f};
Vector3<float> vertex2{1.0f, 0.0f, 0.0f};
Vector3<float> vertex3{0.0f, 1.0f, 0.0f};
Triangle<Vector3<float>> triangle{vertex1, vertex2, vertex3};
};
// Test that a ray intersecting the triangle returns false for CanTraceLine
@@ -71,7 +71,7 @@ TEST_F(LineTracerTest, TriangleFarBeyondRayEndPoint)
constexpr Ray ray{{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}};
// Define a triangle far beyond the ray's endpoint
constexpr Triangle<Vector3> distantTriangle{
constexpr Triangle<Vector3<float>> distantTriangle{
{1000.0f, 1000.0f, 1000.0f}, {1001.0f, 1000.0f, 1000.0f}, {1000.0f, 1001.0f, 1000.0f}
};

View File

@@ -1,7 +1,7 @@
// UnitTestMat.cpp
#include <gtest/gtest.h>
#include "omath/Mat.hpp"
#include "omath/Vector3.hpp"
#include "omath/mat.hpp"
#include "omath/vector3.hpp"
using namespace omath;
@@ -127,7 +127,7 @@ TEST_F(UnitTestMat, ToString)
{
const std::string str = m2.ToString();
EXPECT_FALSE(str.empty());
EXPECT_EQ(str, "1 2\n3 4\n");
EXPECT_EQ(str, "[[ 1.000, 2.000]\n [ 3.000, 4.000]]");
}
// Test assignment operators

View File

@@ -2,8 +2,8 @@
// Created by vlad on 5/18/2024.
//
#include <gtest/gtest.h>
#include <omath/Matrix.hpp>
#include "omath/Vector3.hpp"
#include <omath/matrix.hpp>
#include "omath/vector3.hpp"
using namespace omath;

View File

@@ -0,0 +1,17 @@
#include <gtest/gtest.h>
#include <omath/projectile_prediction/proj_pred_engine_legacy.hpp>
TEST(UnitTestPrediction, PredictionTest)
{
constexpr omath::projectile_prediction::Target target{
.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
constexpr omath::projectile_prediction::Projectile proj = {
.m_origin = {3, 2, 1}, .m_launchSpeed = 5000, .m_gravityScale = 0.4};
const auto viewPoint =
omath::projectile_prediction::ProjPredEngineLegacy(400, 1.f / 1000.f, 50, 5.f).MaybeCalculateAimPoint(proj, target);
const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple();
EXPECT_NEAR(42.547142, pitch, 0.01f);
EXPECT_NEAR(-1.181189, yaw, 0.01f);
}

View File

@@ -3,15 +3,14 @@
//
#include <complex>
#include <gtest/gtest.h>
#include <omath/Matrix.hpp>
#include <omath/engines/Source/Camera.hpp>
#include <omath/projection/Camera.hpp>
#include <omath/engines/source_engine/camera.hpp>
#include <omath/projection/camera.hpp>
#include <print>
TEST(UnitTestProjection, Projection)
{
const auto x = omath::Angle<float, 0.f, 180.f, omath::AngleFlags::Clamped>::FromDegrees(90.f);
auto cam = omath::source::Camera({0, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.01f, 1000.f);
auto cam = omath::source_engine::Camera({0, 0, 0}, omath::source_engine::ViewAngles{}, {1920.f, 1080.f}, x, 0.01f, 1000.f);
const auto projected = cam.WorldToScreen({1000, 0, 50});
std::print("{} {} {}", projected->x, projected->y, projected->z);

View File

@@ -1,10 +1,10 @@
//
// Created by Orange on 1/6/2025.
//
#include "omath/Triangle.hpp"
#include <cmath> // For std::sqrt, std::isinf, std::isnan
#include <gtest/gtest.h>
#include <omath/Vector3.hpp>
#include <cmath> // For std::sqrt, std::isinf, std::isnan
#include <omath/vector3.hpp>
#include "omath/triangle.hpp"
using namespace omath;
@@ -13,28 +13,28 @@ class UnitTestTriangle : public ::testing::Test
{
protected:
// Define some Triangles to use in tests
Triangle<Vector3> t1;
Triangle<Vector3> t2;
Triangle<Vector3> t3;
Triangle<Vector3<float>> t1;
Triangle<Vector3<float>> t2;
Triangle<Vector3<float>> t3;
constexpr void SetUp() override
{
// Triangle with vertices (0, 0, 0), (1, 0, 0), (0, 1, 0)
t1 = Triangle<Vector3>(
t1 = Triangle<Vector3<float>>(
Vector3(0.0f, 0.0f, 0.0f),
Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f)
);
// Triangle with vertices (1, 2, 3), (4, 5, 6), (7, 8, 9)
t2 = Triangle<Vector3>(
t2 = Triangle<Vector3<float>>(
Vector3(1.0f, 2.0f, 3.0f),
Vector3(4.0f, 5.0f, 6.0f),
Vector3(7.0f, 8.0f, 9.0f)
);
// An isosceles right triangle
t3 = Triangle<Vector3>(
t3 = Triangle<Vector3<float>>(
Vector3(0.0f, 0.0f, 0.0f),
Vector3(2.0f, 0.0f, 0.0f),
Vector3(0.0f, 2.0f, 0.0f)
@@ -45,7 +45,7 @@ protected:
// Test constructor and vertices
TEST_F(UnitTestTriangle, Constructor)
{
constexpr Triangle<Vector3> t(
constexpr Triangle<Vector3<float>> t(
Vector3(1.0f, 2.0f, 3.0f),
Vector3(4.0f, 5.0f, 6.0f),
Vector3(7.0f, 8.0f, 9.0f)
@@ -113,7 +113,7 @@ TEST_F(UnitTestTriangle, SideVectors)
TEST_F(UnitTestTriangle, IsRectangular)
{
EXPECT_TRUE(Triangle<Vector3>({2,0,0}, {}, {0,2,0}).IsRectangular());
EXPECT_TRUE(Triangle<Vector3<float>>({2,0,0}, {}, {0,2,0}).IsRectangular());
}
// Test midpoint
TEST_F(UnitTestTriangle, MidPoint)

View File

@@ -2,18 +2,18 @@
// Created by Vlad on 02.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Vector2.hpp>
#include <cmath> // For std::isinf and std::isnan
#include <cfloat> // For FLT_MAX and FLT_MIN
#include <cmath> // For std::isinf and std::isnan
#include <gtest/gtest.h>
#include <omath/vector2.hpp>
using namespace omath;
class UnitTestVector2 : public ::testing::Test
{
protected:
Vector2 v1;
Vector2 v2;
Vector2<float> v1;
Vector2<float> v2;
constexpr void SetUp() override
{
@@ -25,7 +25,7 @@ protected:
// Test constructor and default values
TEST_F(UnitTestVector2, Constructor_Default)
{
constexpr Vector2 v;
constexpr Vector2<float> v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
}

View File

@@ -2,19 +2,19 @@
// Created by Vlad on 01.09.2024.
//
#include <gtest/gtest.h>
#include <omath/Vector3.hpp>
#include <cmath>
#include <cfloat> // For FLT_MAX, FLT_MIN
#include <cmath>
#include <gtest/gtest.h>
#include <limits> // For std::numeric_limits
#include <omath/vector3.hpp>
using namespace omath;
class UnitTestVector3 : public ::testing::Test
{
protected:
Vector3 v1;
Vector3 v2;
Vector3<float> v1;
Vector3<float> v2;
void SetUp() override
{
@@ -26,7 +26,7 @@ protected:
// Test constructor and default values
TEST_F(UnitTestVector3, Constructor_Default)
{
constexpr Vector3 v;
constexpr Vector3<float> v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
EXPECT_FLOAT_EQ(v.z, 0.0f);
@@ -34,7 +34,7 @@ TEST_F(UnitTestVector3, Constructor_Default)
TEST_F(UnitTestVector3, Constructor_Values)
{
constexpr Vector3 v(1.0f, 2.0f, 3.0f);
constexpr Vector3<float> v(1.0f, 2.0f, 3.0f);
EXPECT_FLOAT_EQ(v.x, 1.0f);
EXPECT_FLOAT_EQ(v.y, 2.0f);
EXPECT_FLOAT_EQ(v.z, 3.0f);

View File

@@ -6,16 +6,16 @@
//
#include <gtest/gtest.h>
#include <omath/Vector4.hpp>
#include <limits> // For std::numeric_limits
#include <omath/vector4.hpp>
using namespace omath;
class UnitTestVector4 : public ::testing::Test
{
protected:
Vector4 v1;
Vector4 v2;
Vector4<float> v1;
Vector4<float> v2;
void SetUp() override
{
@@ -27,7 +27,7 @@ protected:
// Test constructor and default values
TEST_F(UnitTestVector4, Constructor_Default)
{
constexpr Vector4 v;
constexpr Vector4<float> v;
EXPECT_FLOAT_EQ(v.x, 0.0f);
EXPECT_FLOAT_EQ(v.y, 0.0f);
EXPECT_FLOAT_EQ(v.z, 0.0f);

View File

@@ -1,4 +1,4 @@
//
// Created by Orange on 11/30/2024.
//
#include <omath/ViewAngles.hpp>
#include <omath/view_angles.hpp>