Compare commits

...

61 Commits

Author SHA1 Message Date
1b5a7ed4fd Merge pull request #69 from luadebug/patch-1
Repair omath.hpp by removing unexisting header include
2025-09-15 15:01:04 +03:00
Saikari
362b818a71 Update omath.hpp 2025-09-15 13:13:55 +03:00
29a96d64bb Adds 2D screen to world conversion
Adds an overload for screen_to_world that accepts a 2D screen position.

Renames screen_to_dnc to screen_to_ndc for clarity.
2025-09-14 04:48:56 +03:00
256365e52e patch 2025-09-14 04:43:25 +03:00
e333d81b81 Enables formatting support for Angle objects
Adds a partial specialization of `std::formatter` for `omath::Angle`
to provide formatting support using `std::format`.

This allows `Angle` objects to be easily formatted as strings,
including degree symbol representation, using standard formatting
techniques.
2025-09-14 04:43:01 +03:00
d66f60d419 Removes unnecessary div tag
Removes an empty div tag, which streamlines the HTML structure and contributes to cleaner code.
2025-09-13 20:13:35 +03:00
4a4939b604 Repositions YouTube preview link
Moves the YouTube preview link to improve the README's visual flow.
2025-09-13 20:08:48 +03:00
ebe8d1a90e Improves README readability
Adds a newline to the README file for better visual separation
between the contribute button and the horizontal rule.
2025-09-13 19:55:23 +03:00
1a3376fe6c Improves button aesthetics on README
Adds whitespace to the buttons displayed on the README to improve their appearance.
2025-09-13 19:53:09 +03:00
20188d7043 Updates README with gallery, install and usage
Enhances the README by adding a gallery showcasing OMath's capabilities,
providing a clearer installation guide, and improving usage examples
to facilitate easier adoption.
Also restructures the navigation for better user experience.
2025-09-13 19:50:58 +03:00
f59e0d255f Update README.md 2025-09-13 19:20:37 +03:00
071cb15492 Update README.md 2025-09-13 19:16:19 +03:00
f8812ed9e7 Update README.md 2025-09-09 22:15:00 +03:00
19d310d35f Update README.md 2025-09-09 21:48:54 +03:00
c364879b5f Merge pull request #68 from orange-cpp/feature/screen_to_world
Feature/screen to world
2025-09-09 02:58:32 +03:00
418b7c0e7e Fixes float type conversion in world_to_screen
Fixes a potential type conversion issue by explicitly casting the x-coordinate to float in the world_to_screen test. This prevents possible compiler warnings and ensures the intended behavior.
2025-09-09 02:13:45 +03:00
69f46abce1 Adds projection test for world-to-screen consistency
Adds a test to verify the consistency of world-to-screen and
screen-to-world projections. This ensures that projecting a point
from world to screen and back results in the same point, thereby
validating the correctness of the camera projection transformations.
2025-09-09 01:37:38 +03:00
de61f7a5d8 Adds screen to world space conversion
Adds functionality to convert screen coordinates to world space, including handling for cases where the inverse view projection matrix is singular or when the world position is out of screen bounds.

Also exposes Camera class to unit tests.
2025-09-09 01:31:23 +03:00
07a449b633 Simplifies raycast early exit condition
Combines the infinite length raycast hit check into a single condition.

This clarifies the logic and avoids redundant checks for early exit
in the ray-triangle intersection test, improving performance.
2025-09-08 23:52:35 +03:00
6bb549ef4c Merge pull request #67 from orange-cpp/feature/angle-improvement
Implements angle class with normalization
2025-09-08 20:18:11 +03:00
14fa810ecb Implements angle class with normalization
Adds an angle class with support for different normalization
and clamping strategies. Includes trigonometric functions and
arithmetic operators. Introduces unit tests to verify correct
functionality.

Disables unity builds to address a compilation issue.
2025-09-08 20:15:59 +03:00
b964661030 Merge pull request #66 from orange-cpp/feature/remove-legacy
Removes deprecated Matrix class
2025-09-08 19:59:34 +03:00
9c11551c9a Removes deprecated Matrix class
Removes the deprecated `Matrix` class and its associated source files and unit tests.

This change is to ensure code cleanliness and prevent accidental usage of the slow and outdated `Matrix` class.
The `Mat` class should be used instead.
2025-09-08 19:56:04 +03:00
21fece7c84 Update LICENSE 2025-09-08 15:52:01 +03:00
996618994d updated logo psd 2025-09-06 23:14:14 +03:00
ce8be6dd52 Update README.md 2025-09-04 23:49:07 +03:00
17aac2f80e Update CREDITS.md 2025-09-04 20:36:12 +03:00
ba927734d2 Update LICENSE 2025-09-04 20:35:25 +03:00
c0d5fd18f5 Update SECURITY.md 2025-09-04 20:35:04 +03:00
996a9cf15a Update LICENSE 2025-09-04 19:35:05 +03:00
91078f5701 Update LICENSE 2025-09-04 19:33:59 +03:00
036d3a8992 updated logo 2025-09-03 22:18:54 +03:00
7534fe8969 removed unused defines 2025-09-03 12:52:00 +03:00
8e4f1812cc fix 2025-09-03 12:50:31 +03:00
e8f40218dd Merge pull request #62 from orange-cpp/feaure/added_logo
Feaure/added logo
2025-09-01 17:04:50 +03:00
50054ca937 Acknowledges logo design contribution
Updates the credits to acknowledge the new initial logo design.
2025-09-01 17:04:29 +03:00
63220c0be7 Adds an omath.psd file.
Adds a binary file named omath.psd.
2025-09-01 17:03:31 +03:00
3b6d19782c Updates README with local image links
Updates the README to use local image links instead of Imgur links for the showcase section.

This improves the project's resilience against external link rot and
ensures the images remain accessible even if Imgur experiences issues.
2025-09-01 17:02:23 +03:00
2d58330508 Replaces banner with logo
Replaces the project banner in the README with a dedicated logo.

This change simplifies the banner implementation and improves maintainability
by using a local image file instead of referencing an external URL.
2025-09-01 16:56:43 +03:00
abf57a55ea Updates include paths and removes dependency
Updates the include paths in omath.hpp to be more explicit,
ensuring correct referencing of header files.

Removes unnecessary include of vector3.hpp from vector2.hpp.
2025-09-01 01:28:04 +03:00
463532ba81 Merge pull request #60 from orange-cpp/feature/moved_to_dear
Refactors: Moves linear algebra to new directory
2025-09-01 00:02:00 +03:00
d74c66990a Refactors: Moves linear algebra to new directory
Moves linear algebra headers to a new subdirectory to improve project structure.

Updates includes to reflect the directory change.
Adds vcpkg to the tracked repositories.
2025-08-31 23:36:05 +03:00
7f1bc51905 Updates project version to 3.5.0
Increments the project version number in CMakeLists.txt
from 3.4.0 to 3.5.0.
2025-08-29 22:04:12 +03:00
71127f1f12 Updates project version to 3.4.0
Bumps the project's version number from 3.3.0 to 3.4.0.

Adds a compile definition to expose the project version via the
`OMATH_VERSION` macro.
2025-08-29 22:03:35 +03:00
89041e20ae Merge pull request #59 from orange-cpp/feature/new_primitives
Adds plane primitive generation
2025-08-29 14:41:36 +03:00
a54dd4b52a Fixes plane triangle generation
Corrects the order of vertices when constructing triangles
for the plane primitive, addressing a potential winding order
issue that could lead to incorrect surface normals and rendering.
2025-08-29 00:11:31 +03:00
d7e497b617 Simplifies plane creation logic
Refactors the plane creation function to directly compute the triangle vertices, removing unnecessary intermediate variables. This results in more concise and readable code.
2025-08-28 23:57:22 +03:00
80938cd913 Adds plane primitive generation
Implements a function to generate a plane primitive from two vertices, a direction vector, and a size, returning an array of two triangles.
2025-08-28 23:18:36 +03:00
830505dbe5 Merge pull request #58 from orange-cpp/feature/ortho-proj
Adds left- and right-handed ortho matrices
2025-08-27 23:23:40 +03:00
75565ecf2d Adds left- and right-handed ortho matrices.
Adds functions to generate left- and right-handed orthographic projection matrices.
This provides more flexibility when defining a projection for rendering.
2025-08-27 23:17:56 +03:00
9a7a4c7fff Removed submodule extlibs/glm 2025-08-27 20:22:33 +03:00
c0f0bb3c2e com 2025-08-27 20:07:47 +03:00
a097c0a2f4 Merge pull request #57 from orange-cpp/feature/added_formatters
Adds std::format support for math types
2025-08-26 12:37:13 +03:00
20ae2b4dd1 Adds formatters for Angle and Color
Adds formatters for `omath::Angle` and `omath::Color` to allow for easy formatting using `std::format`.

This allows users to easily output Angle and Color values in a human-readable format.
2025-08-26 12:35:40 +03:00
115b5a3471 Adds std::format support for math types
Adds `std::formatter` specializations for `Mat`, `Vector2`, `Vector3`, and `Vector4` types, enabling the use of `std::format` for these types.

This simplifies formatting and printing of these mathematical objects, improving code readability and consistency.

Also adds a hash function specialization for Vector3.
2025-08-26 12:22:33 +03:00
77893629f9 Adds omath library header
Creates the main omath header file that includes all
omath library components. This provides a single point
of inclusion for the entire library, simplifying usage
and dependency management.

Also, adjusts the return types for projectile prediction
functions within the legacy engine to explicitly use
the `Vector3` type for consistency and clarity.
2025-08-25 22:33:00 +03:00
afb27b1aa9 Adds build test status message
Adds a status message to the build process that displays whether unit tests are enabled.

This provides better visibility into the build configuration.
2025-08-25 22:11:39 +03:00
61006122ae Displays build configuration options
Prints the values of various CMake configuration options to the console during the build process.

This provides better visibility into the build configuration and helps with debugging build-related issues.
2025-08-25 22:10:10 +03:00
4eb0f59fc0 Updates build status message
Updates the build status message in CMake to include the project name, providing more context during the build process.
2025-08-25 21:59:25 +03:00
3b4bf24a16 Updates project version to 3.3.0
Increments the project version number in CMakeLists.txt
from 3.2.1 to 3.3.0.
2025-08-25 21:57:07 +03:00
51d93c4464 Removes outdated header comments
Removes redundant and outdated header comments. These comments are no longer necessary for maintaining the codebase.
2025-08-25 21:54:59 +03:00
52 changed files with 643 additions and 788 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
.github/images/logos/omath_logo_mega.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
.github/images/logos/omath_logo_nano.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
.github/images/showcase/apex.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
.github/images/showcase/cod_bo2.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
.github/images/showcase/cs2.jpeg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 KiB

BIN
.github/images/yt_previews/img.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
.github/psd/omath.psd vendored Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.26)
project(omath VERSION 3.2.1 LANGUAGES CXX)
project(omath VERSION 3.5.0 LANGUAGES CXX)
include(CMakePackageConfigHelpers)
@@ -13,9 +13,19 @@ option(OMATH_IMGUI_INTEGRATION "Omath will define method to convert omath types
option(OMATH_BUILD_EXAMPLES "Build example projects with you can learn & play" OFF)
option(OMATH_STATIC_MSVC_RUNTIME_LIBRARY "Force Omath to link static runtime" OFF)
option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build to improve general performance" ON)
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" ON)
option(OMATH_USE_UNITY_BUILD "Will enable unity build to speed up compilation" OFF)
option(OMATH_ENABLE_LEGACY "Will enable legacy classes that MUST be used ONLY for backward compatibility" OFF)
message(STATUS "[${PROJECT_NAME}]: Building on ${CMAKE_HOST_SYSTEM_NAME}")
message(STATUS "[${PROJECT_NAME}]: Warnings as errors ${OMATH_THREAT_WARNING_AS_ERROR}")
message(STATUS "[${PROJECT_NAME}]: Build unit tests ${OMATH_BUILD_TESTS}")
message(STATUS "[${PROJECT_NAME}]: As dynamic library ${OMATH_BUILD_AS_SHARED_LIBRARY}")
message(STATUS "[${PROJECT_NAME}]: Static C++ runtime ${OMATH_STATIC_MSVC_RUNTIME_LIBRARY}")
message(STATUS "[${PROJECT_NAME}]: CMake unity build ${OMATH_USE_UNITY_BUILD}")
message(STATUS "[${PROJECT_NAME}]: Example projects ${OMATH_BUILD_EXAMPLES}")
message(STATUS "[${PROJECT_NAME}]: AVX2 feature status ${OMATH_USE_AVX2}")
message(STATUS "[${PROJECT_NAME}]: ImGUI integration feature status ${OMATH_IMGUI_INTEGRATION}")
message(STATUS "[${PROJECT_NAME}]: Legacy features support ${OMATH_ENABLE_LEGACY}")
file(GLOB_RECURSE OMATH_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
file(GLOB_RECURSE OMATH_HEADERS CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
@@ -27,10 +37,10 @@ else ()
add_library(${PROJECT_NAME} STATIC ${OMATH_SOURCES} ${OMATH_HEADERS})
endif ()
message(STATUS "[OMATH]: Building on ${CMAKE_HOST_SYSTEM_NAME}")
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_VERSION="${PROJECT_VERSION}")
if (OMATH_IMGUI_INTEGRATION)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_IMGUI_INTEGRATION)
@@ -90,6 +100,7 @@ target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
if (OMATH_BUILD_TESTS)
add_subdirectory(extlibs)
add_subdirectory(tests)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS)
endif ()
if (OMATH_BUILD_EXAMPLES)

View File

@@ -2,10 +2,10 @@
Thanks to everyone who made this possible, including:
- Saikari aka luadebug for VCPKG port.
- Saikari aka luadebug for VCPKG port and awesome new initial logo design.
And a big hand to everyone else who has contributed over the past!
THANKS! <3
-- Orange++ <orange-cpp@yandex.ru>
-- Orange++ <orange_github@proton.me>

15
LICENSE
View File

@@ -1,4 +1,4 @@
Copyright (C) 2024-2025 Orange++ <orange-cpp@yandex.ru>
Copyright (C) 2024-2025 Orange++ <orange_github@proton.me>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -14,4 +14,15 @@ freely, subject to the following restrictions:
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
3. This notice may not be removed or altered from any source distribution.
4. If you are an employee, contractor, volunteer, representative,
or have any other affiliation (past, present, or future)
with any of the following entities:
* "Yandex" LLC
* "Rutube" LLC
Or if you represent or are associated with any legal, organizational, or
professional entity providing services to or on behalf of the aforementioned entities:
You are expressly forbidden from accessing, using, modifying, distributing, or
interacting with the Software and its source code in any form. You must immediately
delete or destroy any physical or digital copies of the Software and/or
its source code, including any derivative works, tools, or information obtained from the Software.

View File

@@ -1,8 +1,8 @@
<div align = center>
![banner](https://github.com/orange-cpp/omath/blob/main/.github/images/banner.png?raw=true)
![banner](.github/images/logos/omath_logo_macro.png)
![GitHub License](https://img.shields.io/github/license/orange-cpp/omath)
![Static Badge](https://img.shields.io/badge/license-libomath-orange)
![GitHub contributors](https://img.shields.io/github/contributors/orange-cpp/omath)
![GitHub top language](https://img.shields.io/github/languages/top/orange-cpp/omath)
[![CodeFactor](https://www.codefactor.io/repository/github/orange-cpp/omath/badge)](https://www.codefactor.io/repository/github/orange-cpp/omath)
@@ -12,9 +12,24 @@
[![discord badge](https://dcbadge.limes.pink/api/server/https://discord.gg/eDgdaWbqwZ?style=flat)](https://discord.gg/eDgdaWbqwZ)
[![telegram badge](https://img.shields.io/badge/Telegram-2CA5E0?style=flat-squeare&logo=telegram&logoColor=white)](https://t.me/orangennotes)
OMath is a 100% independent, constexpr template blazingly fast math library that doesn't have legacy C++ code.
It provides the latest features, is highly customizable, has all for cheat development, DirectX/OpenGL/Vulkan support, premade support for different game engines, much more constexpr stuff than in other libraries and more...
<br>
<br>
---
**[<kbd><br>Install<br></kbd>][INSTALL]**
**[<kbd><br>Examples<br></kbd>][EXAMPLES]**
**[<kbd><br>Contribute<br></kbd>][CONTRIBUTING]**
---
<br>
</div>
Oranges's Math Library (omath) is a comprehensive, open-source library aimed at providing efficient, reliable, and versatile mathematical functions and algorithms. Developed primarily in C++, this library is designed to cater to a wide range of mathematical operations essential in scientific computing, engineering, and academic research.
<div align = center>
<a href="https://www.star-history.com/#orange-cpp/omath&Date">
@@ -36,6 +51,29 @@ Oranges's Math Library (omath) is a comprehensive, open-source library aimed at
- **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!
# Gallery
<br>
[![Youtube Video](.github/images/yt_previews/img.png)](https://youtu.be/lM_NJ1yCunw?si=-Qf5yzDcWbaxAXGQ)
<br>
![APEX Preview]
<br>
![BO2 Preview]
<br>
![CS2 Preview]
<br>
<br>
## Supported Render Pipelines
| ENGINE | SUPPORT |
|----------|---------|
@@ -53,9 +91,6 @@ Oranges's Math Library (omath) is a comprehensive, open-source library aimed at
| Linux | ✅YES |
| Darwin (MacOS) | ✅YES |
## ⏬ Installation
Please read our [installation guide](https://github.com/orange-cpp/omath/blob/main/INSTALL.md). If this link doesn't work check out INSTALL.md file.
## ❔ Usage
ESP example
```c++
@@ -77,26 +112,16 @@ for (auto ent: apex_sdk::EntityList::GetAllEntities())
// esp rendering...
}
```
## Showcase
<details>
<summary>OMATH for making cheats (click to open)</summary>
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)
Or for InfinityWard Engine based games. Like Call of Duty Black Ops 2!
![banner](https://i.imgur.com/F8dmdoo.png)
Or create simple trigger bot with embeded traceline from omath::collision::LineTrace
![banner](https://i.imgur.com/fxMjRKo.jpeg)
Or even advanced projectile aimbot
[Watch Video](https://youtu.be/lM_NJ1yCunw?si=5E87OrQMeypxSJ3E)
</details>
## 🫵🏻 Contributing
Contributions to `omath` are welcome! Please read `CONTRIBUTING.md` for details on our code of conduct and the process for submitting pull requests.
## 📜 License
This project is licensed under the ZLIB - see the `LICENSE` file for details.
## 💘 Acknowledgments
- [All contributors](https://github.com/orange-cpp/omath/graphs/contributors)
<!----------------------------------{ Images }--------------------------------->
[APEX Preview]: .github/images/showcase/apex.png
[BO2 Preview]: .github/images/showcase/cod_bo2.png
[CS2 Preview]: .github/images/showcase/cs2.jpeg
<!----------------------------------{ Buttons }--------------------------------->
[INSTALL]: INSTALL.md
[CONTRIBUTING]: CONTRIBUTING.md
[EXAMPLES]: examples

View File

@@ -2,4 +2,4 @@
## Reporting a Vulnerability
Please report security issues to `orange-cpp@yandex.ru`
Please report security issues to `orange_github@proton.me`

View File

@@ -3,10 +3,9 @@
//
#pragma once
#include <array>
#include "omath/linear_algebra/vector3.hpp"
#include "omath/triangle.hpp"
#include "omath/vector3.hpp"
#include <array>
namespace omath::primitives
{

View File

@@ -0,0 +1,16 @@
//
// Created by Vlad on 8/28/2025.
//
#pragma once
#include "omath/linear_algebra/vector3.hpp"
#include "omath/triangle.hpp"
#include <array>
namespace omath::primitives
{
[[nodiscard]]
std::array<Triangle<Vector3<float>>, 2> create_plane(const Vector3<float>& vertex_a,
const Vector3<float>& vertex_b,
const Vector3<float>& direction, float size) noexcept;
}

View File

@@ -5,6 +5,7 @@
#pragma once
#include "omath/angles.hpp"
#include <algorithm>
#include <format>
#include <utility>
namespace omath
@@ -122,13 +123,13 @@ namespace omath
}
[[nodiscard]]
constexpr Angle& operator+(const Angle& other) noexcept
constexpr Angle operator+(const Angle& other) noexcept
{
if constexpr (flags == AngleFlags::Normalized)
return {angles::wrap_angle(m_angle + other.m_angle, min, max)};
return Angle{angles::wrap_angle(m_angle + other.m_angle, min, max)};
else if constexpr (flags == AngleFlags::Clamped)
return {std::clamp(m_angle + other.m_angle, min, max)};
return Angle{std::clamp(m_angle + other.m_angle, min, max)};
else
static_assert(false);
@@ -137,7 +138,7 @@ namespace omath
}
[[nodiscard]]
constexpr Angle& operator-(const Angle& other) noexcept
constexpr Angle operator-(const Angle& other) noexcept
{
return operator+(-other);
}
@@ -149,3 +150,22 @@ namespace omath
}
};
} // namespace omath
template<class T, T MinV, T MaxV, omath::AngleFlags F, class CharT>
struct std::formatter<omath::Angle<T, MinV, MaxV, F>, CharT>
{
using AngleT = omath::Angle<T, MinV, MaxV, F>;
[[nodiscard]]
static constexpr auto parse(std::basic_format_parse_context<CharT>& ctx)
-> std::basic_format_parse_context<CharT>::iterator
{
return ctx.begin();
}
template<class FormatContext>
auto format(const AngleT& deg, FormatContext& ctx) const
{
if constexpr (std::is_same_v<typename FormatContext::char_type, char>)
return std::format_to(ctx.out(), "{}deg", deg.as_degrees());
return std::format_to(ctx.out(), L"{}deg", deg.as_degrees());
}
};

View File

@@ -3,8 +3,8 @@
//
#pragma once
#include "omath/linear_algebra/vector3.hpp"
#include "omath/triangle.hpp"
#include "omath/vector3.hpp"
namespace omath::collision
{

View File

@@ -4,8 +4,7 @@
#pragma once
#include "omath/vector3.hpp"
#include "omath/vector4.hpp"
#include "linear_algebra/vector4.hpp"
#include <cstdint>
namespace omath
@@ -167,3 +166,21 @@ namespace omath
#endif
};
} // namespace omath
template<>
struct std::formatter<omath::Color> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Color& col, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[r:{}, g:{}, b:{}, a:{}]",
static_cast<int>(col.x * 255.f),
static_cast<int>(col.y * 255.f),
static_cast<int>(col.z * 255.f),
static_cast<int>(col.w * 255.f));
}
};

View File

@@ -3,9 +3,9 @@
//
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::iw_engine

View File

@@ -3,9 +3,9 @@
//
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::opengl_engine

View File

@@ -3,9 +3,9 @@
//
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::source_engine

View File

@@ -4,9 +4,9 @@
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::unity_engine

View File

@@ -4,9 +4,9 @@
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <omath/view_angles.hpp>
namespace omath::unreal_engine

View File

@@ -2,7 +2,7 @@
// Created by vlad on 9/29/2024.
//
#pragma once
#include "omath/vector3.hpp"
#include "vector3.hpp"
#include <algorithm>
#include <array>
#include <iomanip>
@@ -11,13 +11,6 @@
#include <stdexcept>
#include <utility>
#ifdef near
#undef near
#endif
#ifdef far
#undef far
#endif
namespace omath
{
@@ -88,7 +81,7 @@ namespace omath
}
[[nodiscard]]
constexpr Type& operator[](const size_t row, const size_t col) const
constexpr const Type& operator[](const size_t row, const size_t col) const
{
return at(row, col);
}
@@ -479,4 +472,49 @@ namespace omath
{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> mat_ortho_left_handed(const Type left, const Type right,
const Type bottom, const Type top,
const Type near, const Type far) noexcept
{
return
{
{ static_cast<Type>(2) / (right - left), 0.f, 0.f, -(right + left) / (right - left)},
{ 0.f, static_cast<Type>(2) / (top - bottom), 0.f, -(top + bottom) / (top - bottom)},
{ 0.f, 0.f, static_cast<Type>(2) / (far - near), -(far + near) / (far - near) },
{ 0.f, 0.f, 0.f, 1.f }
};
}
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
[[nodiscard]]
Mat<4, 4, Type, St> mat_ortho_right_handed(const Type left, const Type right,
const Type bottom, const Type top,
const Type near, const Type far) noexcept
{
return
{
{ static_cast<Type>(2) / (right - left), 0.f, 0.f, -(right + left) / (right - left)},
{ 0.f, static_cast<Type>(2) / (top - bottom), 0.f, -(top + bottom) / (top - bottom)},
{ 0.f, 0.f, -static_cast<Type>(2) / (far - near), -(far + near) / (far - near) },
{ 0.f, 0.f, 0.f, 1.f }
};
}
} // namespace omath
template<size_t Rows, size_t Columns, class Type, omath::MatStoreType StoreType>
struct std::formatter<omath::Mat<Rows, Columns, Type, StoreType>> // NOLINT(*-dcl58-cpp)
{
using MatType = omath::Mat<Rows, Columns, Type, StoreType>;
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const MatType& mat, std::format_context& ctx)
{
return std::format_to(ctx.out(), "{}", mat.to_string());
}
};

View File

@@ -4,6 +4,7 @@
#pragma once
#include <cmath>
#include <format>
#include <tuple>
#ifdef OMATH_IMGUI_INTEGRATION
@@ -218,7 +219,6 @@ namespace omath
{
return std::make_tuple(x, y);
}
#ifdef OMATH_IMGUI_INTEGRATION
[[nodiscard]]
ImVec2 to_im_vec2() const noexcept
@@ -233,3 +233,18 @@ namespace omath
#endif
};
} // namespace omath
template<class Type>
struct std::formatter<omath::Vector2<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector2<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y);
}
};

View File

@@ -5,7 +5,7 @@
#pragma once
#include "omath/angle.hpp"
#include "omath/vector2.hpp"
#include "omath/linear_algebra/vector2.hpp"
#include <cstdint>
#include <expected>
#include <functional>
@@ -159,9 +159,9 @@ namespace omath
return Vector2<Type>::length();
}
[[nodiscard]] Type distance_to(const Vector3& vOther) const noexcept
[[nodiscard]] Type distance_to(const Vector3& v_other) const noexcept
{
return (*this - vOther).length();
return (*this - v_other).length();
}
#endif
@@ -279,21 +279,33 @@ namespace omath
}
};
} // namespace omath
// ReSharper disable once CppRedundantNamespaceDefinition
namespace std
template<> struct std::hash<omath::Vector3<float>>
{
template<> struct hash<omath::Vector3<float>>
std::size_t operator()(const omath::Vector3<float>& vec) const noexcept
{
std::size_t operator()(const omath::Vector3<float>& vec) const noexcept
{
std::size_t hash = 0;
constexpr std::hash<float> hasher;
std::size_t hash = 0;
constexpr std::hash<float> hasher;
hash ^= hasher(vec.x) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.z) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.x) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
hash ^= hasher(vec.z) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
return hash;
}
};
} // namespace std
return hash;
}
};
template<class Type>
struct std::formatter<omath::Vector3<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector3<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}, {}]", vec.x, vec.y, vec.z);
}
};

View File

@@ -4,7 +4,7 @@
#pragma once
#include <algorithm>
#include <omath/vector3.hpp>
#include "omath/linear_algebra/vector3.hpp"
namespace omath
{
@@ -201,3 +201,18 @@ namespace omath
#endif
};
} // namespace omath
template<class Type>
struct std::formatter<omath::Vector4<Type>> // NOLINT(*-dcl58-cpp)
{
[[nodiscard]]
static constexpr auto parse(std::format_parse_context& ctx)
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Vector4<Type>& vec, std::format_context& ctx)
{
return std::format_to(ctx.out(), "[{}, {}, {}, {}]", vec.x, vec.y, vec.z, vec.w);
}
};

View File

@@ -1,112 +0,0 @@
#pragma once
#ifdef OMATH_ENABLE_LEGACY
#include "omath/vector3.hpp"
#include <initializer_list>
#include <memory>
#include <string>
namespace omath
{
class Matrix final
{
public:
Matrix();
Matrix(size_t rows, size_t columns);
Matrix(const std::initializer_list<std::initializer_list<float>>& rows);
[[nodiscard]]
static Matrix to_screen_matrix(float screen_width, float screen_height);
[[nodiscard]]
static Matrix translation_matrix(const Vector3<float>& diff);
[[nodiscard]]
static Matrix orientation_matrix(const Vector3<float>& forward, const Vector3<float>& right,
const Vector3<float>& up);
[[nodiscard]]
static Matrix projection_matrix(float field_of_view, float aspect_ratio, float near, float far);
Matrix(const Matrix& other);
Matrix(size_t rows, size_t columns, const float* raw_data);
Matrix(Matrix&& other) noexcept;
[[nodiscard]]
size_t row_count() const noexcept;
[[nodiscard]]
float& operator[](size_t row, size_t column);
[[nodiscard]]
size_t columns_count() const noexcept;
[[nodiscard]]
std::pair<size_t, size_t> size() const noexcept;
[[nodiscard]]
float& at(size_t row, size_t col);
[[nodiscard]]
float sum();
void set_data_from_raw(const float* raw_matrix);
[[nodiscard]]
Matrix transpose() const;
void set(float val);
[[nodiscard]]
const float& at(size_t row, size_t col) const;
Matrix operator*(const Matrix& other) const;
Matrix& operator*=(const Matrix& other);
Matrix operator*(float f) const;
Matrix& operator*=(float f);
Matrix& operator/=(float f);
void clear();
[[nodiscard]]
Matrix strip(size_t row, size_t column) const;
[[nodiscard]]
float minor(size_t i, size_t j) const;
[[nodiscard]]
float alg_complement(size_t i, size_t j) const;
[[nodiscard]]
float determinant() const;
[[nodiscard]]
const float* raw() const;
Matrix& operator=(const Matrix& other);
Matrix& operator=(Matrix&& other) noexcept;
Matrix operator/(float f) const;
[[nodiscard]]
std::string to_string() const;
~Matrix();
private:
size_t m_rows;
size_t m_columns;
std::unique_ptr<float[]> m_data;
};
} // namespace omath
#endif

83
include/omath/omath.hpp Normal file
View File

@@ -0,0 +1,83 @@
//
// omath.hpp - Main header file that includes all omath library components
// Created for the omath library
//
#pragma once
// Basic math utilities
#include "omath/angles.hpp"
#include "omath/angle.hpp"
// Vector classes (in dependency order)
#include "omath/linear_algebra/vector2.hpp"
#include "omath/linear_algebra/vector4.hpp"
#include "omath/linear_algebra/vector3.hpp"
// Matrix classes
#include "omath/linear_algebra/mat.hpp"
// Color functionality
#include "omath/color.hpp"
// Geometric primitives
#include "omath/triangle.hpp"
#include "omath/view_angles.hpp"
// 3D primitives
#include "omath/3d_primitives/box.hpp"
// Collision detection
#include "omath/collision/line_tracer.hpp"
// Pathfinding algorithms
#include "omath/pathfinding/a_star.hpp"
#include "omath/pathfinding/navigation_mesh.hpp"
// Projectile prediction
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/projectile_prediction/proj_pred_engine.hpp"
#include "omath/projectile_prediction/proj_pred_engine_legacy.hpp"
#include "omath/projectile_prediction/proj_pred_engine_avx2.hpp"
// Projection functionality
#include "omath/projection/error_codes.hpp"
#include "omath/projection/camera.hpp"
// Engine-specific implementations
// IW Engine
#include "omath/engines/iw_engine/constants.hpp"
#include "omath/engines/iw_engine/formulas.hpp"
#include "omath/engines/iw_engine/camera.hpp"
#include "omath/engines/iw_engine/traits/camera_trait.hpp"
#include "omath/engines/iw_engine/traits/pred_engine_trait.hpp"
// OpenGL Engine
#include "omath/engines/opengl_engine/constants.hpp"
#include "omath/engines/opengl_engine/formulas.hpp"
#include "omath/engines/opengl_engine/camera.hpp"
#include "omath/engines/opengl_engine/traits/camera_trait.hpp"
#include "omath/engines/opengl_engine/traits/pred_engine_trait.hpp"
// Source Engine
#include "omath/engines/source_engine/constants.hpp"
#include "omath/engines/source_engine/formulas.hpp"
#include "omath/engines/source_engine/camera.hpp"
#include "omath/engines/source_engine/traits/camera_trait.hpp"
#include "omath/engines/source_engine/traits/pred_engine_trait.hpp"
// Unity Engine
#include "omath/engines/unity_engine/constants.hpp"
#include "omath/engines/unity_engine/formulas.hpp"
#include "omath/engines/unity_engine/camera.hpp"
#include "omath/engines/unity_engine/traits/camera_trait.hpp"
#include "omath/engines/unity_engine/traits/pred_engine_trait.hpp"
// Unreal Engine
#include "omath/engines/unreal_engine/constants.hpp"
#include "omath/engines/unreal_engine/formulas.hpp"
#include "omath/engines/unreal_engine/camera.hpp"
#include "omath/engines/unreal_engine/traits/camera_trait.hpp"
#include "omath/engines/unreal_engine/traits/pred_engine_trait.hpp"

View File

@@ -3,8 +3,8 @@
//
#pragma once
#include "omath/linear_algebra/vector3.hpp"
#include "omath/pathfinding/navigation_mesh.hpp"
#include "omath/vector3.hpp"
#include <vector>
namespace omath::pathfinding

View File

@@ -4,7 +4,7 @@
#pragma once
#include "omath/vector3.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <expected>
#include <string>
#include <vector>

View File

@@ -2,9 +2,9 @@
// Created by Vlad on 2/23/2025.
//
#pragma once
#include "omath/linear_algebra/vector3.hpp"
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/vector3.hpp"
namespace omath::projectile_prediction
{

View File

@@ -4,11 +4,11 @@
#pragma once
#include "omath/linear_algebra/vector3.hpp"
#include "omath/engines/source_engine/traits/pred_engine_trait.hpp"
#include "omath/projectile_prediction/proj_pred_engine.hpp"
#include "omath/projectile_prediction/projectile.hpp"
#include "omath/projectile_prediction/target.hpp"
#include "omath/vector3.hpp"
#include <optional>
namespace omath::projectile_prediction
@@ -20,11 +20,11 @@ namespace omath::projectile_prediction
Vector3<float> v3, // by-value for calc_viewpoint_from_angles
float pitch, float yaw, float time, float gravity, std::optional<float> maybe_pitch) {
// Presence + return types
{ T::predict_projectile_position(projectile, pitch, yaw, time, gravity) } -> std::same_as<Vec3>;
{ T::predict_target_position(target, time, gravity) } -> std::same_as<Vec3>;
{ T::predict_projectile_position(projectile, pitch, yaw, time, gravity) } -> std::same_as<Vector3<float>>;
{ T::predict_target_position(target, time, gravity) } -> std::same_as<Vector3<float>>;
{ T::calc_vector_2d_distance(vec_a) } -> std::same_as<float>;
{ T::get_vector_height_coordinate(vec_b) } -> std::same_as<float>;
{ T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as<Vec3>;
{ T::calc_viewpoint_from_angles(projectile, v3, maybe_pitch) } -> std::same_as<Vector3<float>>;
{ T::calc_direct_pitch_angle(vec_a, vec_b) } -> std::same_as<float>;
{ T::calc_direct_yaw_angle(vec_a, vec_b) } -> std::same_as<float>;

View File

@@ -3,7 +3,7 @@
//
#pragma once
#include "omath/vector3.hpp"
#include "omath/linear_algebra/vector3.hpp"
namespace omath::projectile_prediction
{

View File

@@ -3,7 +3,7 @@
//
#pragma once
#include "omath/vector3.hpp"
#include "omath/linear_algebra/vector3.hpp"
namespace omath::projectile_prediction
{

View File

@@ -4,13 +4,18 @@
#pragma once
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include "omath/projection/error_codes.hpp"
#include <expected>
#include <omath/angle.hpp>
#include <omath/mat.hpp>
#include <omath/vector3.hpp>
#include <type_traits>
#ifdef OMATH_BUILD_TESTS
// ReSharper disable once CppInconsistentNaming
class UnitTestProjection_Projection_Test;
#endif
namespace omath::projection
{
class ViewPort final
@@ -45,6 +50,9 @@ namespace omath::projection
requires CameraEngineConcept<TraitClass, Mat4X4Type, ViewAnglesType>
class Camera final
{
#ifdef OMATH_BUILD_TESTS
friend UnitTestProjection_Projection_Test;
#endif
public:
~Camera() = default;
Camera(const Vector3<float>& position, const ViewAnglesType& view_angles, const ViewPort& view_port,
@@ -164,6 +172,38 @@ namespace omath::projection
return Vector3<float>{projected.at(0, 0), projected.at(1, 0), projected.at(2, 0)};
}
[[nodiscard]]
std::expected<Vector3<float>, Error> view_port_to_screen(const Vector3<float>& ndc) const noexcept
{
const auto inv_view_proj = get_view_projection_matrix().inverted();
if (!inv_view_proj)
return std::unexpected(Error::INV_VIEW_PROJ_MAT_DET_EQ_ZERO);
auto inverted_projection =
inv_view_proj.value() * mat_column_from_vector<float, Mat4X4Type::get_store_ordering()>(ndc);
if (!inverted_projection.at(3, 0))
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
inverted_projection /= inverted_projection.at(3, 0);
return Vector3<float>{inverted_projection.at(0, 0), inverted_projection.at(1, 0),
inverted_projection.at(2, 0)};
}
[[nodiscard]]
std::expected<Vector3<float>, Error> screen_to_world(const Vector3<float>& screen_pos) const noexcept
{
return view_port_to_screen(screen_to_ndc(screen_pos));
}
[[nodiscard]]
std::expected<Vector3<float>, Error> screen_to_world(const Vector2<float>& screen_pos) const noexcept
{
const auto& [x, y] = screen_pos;
return screen_to_world({x, y, 1.f});
}
protected:
ViewPort m_view_port{};
@@ -186,19 +226,25 @@ namespace omath::projection
[[nodiscard]] Vector3<float> ndc_to_screen_position(const Vector3<float>& ndc) const noexcept
{
/*
^
| y
1 |
|
|
-1 ---------0--------- 1 --> x
|
|
-1 |
v
*/
/*
^
| y
1 |
|
|
-1 ---------0--------- 1 --> x
|
|
-1 |
v
*/
return {(ndc.x + 1.f) / 2.f * m_view_port.m_width, (1.f - ndc.y) / 2.f * m_view_port.m_height, ndc.z};
}
[[nodiscard]] Vector3<float> screen_to_ndc(const Vector3<float>& screen_pos) const noexcept
{
return {screen_pos.x / m_view_port.m_width * 2.f - 1.f, 1.f - screen_pos.y / m_view_port.m_height * 2.f,
screen_pos.z};
}
};
} // namespace omath::projection

View File

@@ -10,5 +10,6 @@ namespace omath::projection
enum class Error : uint16_t
{
WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS,
INV_VIEW_PROJ_MAT_DET_EQ_ZERO,
};
}

View File

@@ -2,7 +2,7 @@
// Created by Orange on 11/13/2024.
//
#pragma once
#include "omath/vector3.hpp"
#include "linear_algebra/vector3.hpp"
namespace omath
{

View File

@@ -0,0 +1,19 @@
//
// Created by Vlad on 8/28/2025.
//
#include "omath/3d_primitives/plane.hpp"
namespace omath::primitives
{
std::array<Triangle<Vector3<float>>, 2> create_plane(const Vector3<float>& vertex_a,
const Vector3<float>& vertex_b,
const Vector3<float>& direction, const float size) noexcept
{
const auto second_vertex_a = vertex_a + direction * size;
return std::array
{
Triangle{second_vertex_a, vertex_a, vertex_b},
Triangle{second_vertex_a, vertex_b + direction * size, vertex_b}
};
}
} // namespace omath::primitives

View File

@@ -50,12 +50,10 @@ namespace omath::collision
const auto t_hit = side_b.dot(q) * inv_det;
if (ray.infinite_length)
{
if (t_hit <= k_epsilon)
return ray.end;
}
else if (t_hit <= k_epsilon || t_hit > 1.0f - k_epsilon)
if (ray.infinite_length && t_hit <= k_epsilon)
return ray.end;
if (t_hit <= k_epsilon || t_hit > 1.0f - k_epsilon)
return ray.end;
return ray.start + ray_dir * t_hit;

View File

@@ -1,364 +0,0 @@
#ifdef OMATH_ENABLE_LEGACY
#include "omath/matrix.hpp"
#include "omath/angles.hpp"
#include "omath/vector3.hpp"
#include <complex>
#include <format>
#include <stdexcept>
#include <utility>
namespace omath
{
Matrix::Matrix(const size_t rows, const size_t columns)
{
if (rows == 0 and columns == 0)
throw std::runtime_error("Matrix cannot be 0x0");
m_rows = rows;
m_columns = columns;
m_data = std::make_unique<float[]>(m_rows * m_columns);
set(0.f);
}
Matrix::Matrix(const std::initializer_list<std::initializer_list<float>>& rows)
{
m_rows = rows.size();
m_columns = rows.begin()->size();
for (const auto& row: rows)
if (row.size() != m_columns)
throw std::invalid_argument("All rows must have the same number of columns.");
m_data = std::make_unique<float[]>(m_rows * m_columns);
size_t i = 0;
for (const auto& row: rows)
{
size_t j = 0;
for (const auto& value: row)
at(i, j++) = value;
++i;
}
}
Matrix::Matrix(const Matrix& other)
{
m_rows = other.m_rows;
m_columns = other.m_columns;
m_data = std::make_unique<float[]>(m_rows * m_columns);
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = other.at(i, j);
}
Matrix::Matrix(const size_t rows, const size_t columns, const float* raw_data)
{
m_rows = rows;
m_columns = columns;
m_data = std::make_unique<float[]>(m_rows * m_columns);
for (size_t i = 0; i < rows * columns; ++i)
at(i / rows, i % columns) = raw_data[i];
}
size_t Matrix::row_count() const noexcept
{
return m_rows;
}
float& Matrix::operator[](const size_t row, const size_t column)
{
return at(row, column);
}
Matrix::Matrix(Matrix&& other) noexcept
{
m_rows = other.m_rows;
m_columns = other.m_columns;
m_data = std::move(other.m_data);
other.m_rows = 0;
other.m_columns = 0;
other.m_data = nullptr;
}
size_t Matrix::columns_count() const noexcept
{
return m_columns;
}
std::pair<size_t, size_t> Matrix::size() const noexcept
{
return {row_count(), columns_count()};
}
float& Matrix::at(const size_t row, const size_t col)
{
return const_cast<float&>(std::as_const(*this).at(row, col));
}
float Matrix::sum()
{
float sum = 0;
for (size_t i = 0; i < row_count(); i++)
for (size_t j = 0; j < columns_count(); j++)
sum += at(i, j);
return sum;
}
const float& Matrix::at(const size_t row, const size_t col) const
{
return m_data[row * m_columns + col];
}
Matrix Matrix::operator*(const Matrix& other) const
{
if (m_columns != other.m_rows)
throw std::runtime_error("n != m");
auto out_mat = Matrix(m_rows, other.m_columns);
for (size_t d = 0; d < m_rows; ++d)
for (size_t i = 0; i < other.m_columns; ++i)
for (size_t j = 0; j < other.m_rows; ++j)
out_mat.at(d, i) += at(d, j) * other.at(j, i);
return out_mat;
}
Matrix& Matrix::operator*=(const Matrix& other)
{
*this = *this * other;
return *this;
}
Matrix Matrix::operator*(const float f) const
{
auto out = *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
out.at(i, j) *= f;
return out;
}
Matrix& Matrix::operator*=(const float f)
{
for (size_t i = 0; i < row_count(); i++)
for (size_t j = 0; j < columns_count(); j++)
at(i, j) *= f;
return *this;
}
void Matrix::clear()
{
set(0.f);
}
Matrix& Matrix::operator=(const Matrix& other)
{
if (this == &other)
return *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = other.at(i, j);
return *this;
}
Matrix& Matrix::operator=(Matrix&& other) noexcept
{
if (this == &other)
return *this;
m_rows = other.m_rows;
m_columns = other.m_columns;
m_data = std::move(other.m_data);
other.m_rows = 0;
other.m_columns = 0;
return *this;
}
Matrix& Matrix::operator/=(const float f)
{
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) /= f;
return *this;
}
Matrix Matrix::operator/(const float f) const
{
auto out = *this;
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
out.at(i, j) /= f;
return out;
}
std::string Matrix::to_string() const
{
std::string str;
for (size_t i = 0; i < m_rows; i++)
{
for (size_t j = 0; j < m_columns; ++j)
{
str += std::format("{:.1f}", at(i, j));
if (j == m_columns - 1)
str += '\n';
else
str += ' ';
}
}
return str;
}
float Matrix::determinant() const // NOLINT(*-no-recursion)
{
if (m_rows + m_columns == 2)
return at(0, 0);
if (m_rows == 2 and m_columns == 2)
return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0);
float det = 0;
for (size_t i = 0; i < m_columns; i++)
det += alg_complement(0, i) * at(0, i);
return det;
}
float Matrix::alg_complement(const size_t i, const size_t j) const // NOLINT(*-no-recursion)
{
const auto tmp = minor(i, j);
return ((i + j + 2) % 2 == 0) ? tmp : -tmp;
}
Matrix Matrix::transpose() const
{
Matrix transposed = {m_columns, m_rows};
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
transposed.at(j, i) = at(i, j);
return transposed;
}
Matrix::~Matrix() = default;
void Matrix::set(const float val)
{
for (size_t i = 0; i < m_rows; ++i)
for (size_t j = 0; j < m_columns; ++j)
at(i, j) = val;
}
Matrix Matrix::strip(const size_t row, const size_t column) const
{
Matrix stripped = {m_rows - 1, m_columns - 1};
size_t strip_row_index = 0;
for (size_t i = 0; i < m_rows; i++)
{
if (i == row)
continue;
size_t strip_column_index = 0;
for (size_t j = 0; j < m_columns; ++j)
{
if (j == column)
continue;
stripped.at(strip_row_index, strip_column_index) = at(i, j);
strip_column_index++;
}
strip_row_index++;
}
return stripped;
}
float Matrix::minor(const size_t i, const size_t j) const // NOLINT(*-no-recursion)
{
return strip(i, j).determinant();
}
Matrix Matrix::to_screen_matrix(const float screen_width, const float screen_height)
{
return {
{screen_width / 2.f, 0.f, 0.f, 0.f},
{0.f, -screen_height / 2.f, 0.f, 0.f},
{0.f, 0.f, 1.f, 0.f},
{screen_width / 2.f, screen_height / 2.f, 0.f, 1.f},
};
}
Matrix Matrix::translation_matrix(const Vector3<float>& diff)
{
return {
{1.f, 0.f, 0.f, 0.f},
{0.f, 1.f, 0.f, 0.f},
{0.f, 0.f, 1.f, 0.f},
{diff.x, diff.y, diff.z, 1.f},
};
}
Matrix Matrix::orientation_matrix(const Vector3<float>& forward, const Vector3<float>& right,
const Vector3<float>& up)
{
return {
{right.x, up.x, forward.x, 0.f},
{right.y, up.y, forward.y, 0.f},
{right.z, up.z, forward.z, 0.f},
{0.f, 0.f, 0.f, 1.f},
};
}
Matrix Matrix::projection_matrix(const float field_of_view, const float aspect_ratio, const float near,
const float far)
{
const float fov_half_tan = std::tan(angles::degrees_to_radians(field_of_view) / 2.f);
return {{1.f / (aspect_ratio * fov_half_tan), 0.f, 0.f, 0.f},
{0.f, 1.f / fov_half_tan, 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}};
}
const float* Matrix::raw() const
{
return m_data.get();
}
void Matrix::set_data_from_raw(const float* raw_matrix)
{
for (size_t i = 0; i < m_columns * m_rows; ++i)
at(i / m_rows, i % m_columns) = raw_matrix[i];
}
Matrix::Matrix()
{
m_columns = 0;
m_rows = 0;
m_data = nullptr;
}
} // namespace omath
#endif

View File

@@ -1,7 +1,4 @@
//
// Created by Vlad on 8/25/2025.
//
//
// Created by Orange on 11/27/2024.
//
#include <gtest/gtest.h>

View File

@@ -1,3 +1,192 @@
//
// Created by Orange on 11/30/2024.
//
#include <cmath>
#include <gtest/gtest.h>
#include <numbers>
#include <omath/angle.hpp>
using namespace omath;
namespace
{
// Handy aliases (defaults: Type=float, [0,360], Normalized)
using Deg = Angle<float, float(0), float(360), AngleFlags::Normalized>;
using Pitch = Angle<float, float(-90), float(90), AngleFlags::Clamped>;
using Turn = Angle<float, float(-180), float(180), AngleFlags::Normalized>;
constexpr float kEps = 1e-5f;
} // namespace
// ---------- Construction / factories ----------
TEST(UnitTestAngle, DefaultConstructor_IsZeroDegrees)
{
Deg a; // default ctor
EXPECT_FLOAT_EQ(*a, 0.0f);
EXPECT_FLOAT_EQ(a.as_degrees(), 0.0f);
}
TEST(UnitTestAngle, FromDegrees_Normalized_WrapsAboveMax)
{
const Deg a = Deg::from_degrees(370.0f);
EXPECT_FLOAT_EQ(a.as_degrees(), 10.0f);
}
TEST(UnitTestAngle, FromDegrees_Normalized_WrapsBelowMin)
{
const Deg a = Deg::from_degrees(-10.0f);
EXPECT_FLOAT_EQ(a.as_degrees(), 350.0f);
}
TEST(UnitTestAngle, FromDegrees_Clamped_ClampsToRange)
{
const Pitch hi = Pitch::from_degrees(100.0f);
const Pitch lo = Pitch::from_degrees(-120.0f);
EXPECT_FLOAT_EQ(hi.as_degrees(), 90.0f);
EXPECT_FLOAT_EQ(lo.as_degrees(), -90.0f);
}
TEST(UnitTestAngle, FromRadians_And_AsRadians)
{
const Deg a = Deg::from_radians(std::numbers::pi_v<float>);
EXPECT_FLOAT_EQ(a.as_degrees(), 180.0f);
const Deg b = Deg::from_degrees(180.0f);
EXPECT_NEAR(b.as_radians(), std::numbers::pi_v<float>, 1e-6f);
}
// ---------- Unary minus & deref ----------
TEST(UnitTestAngle, UnaryMinus_Normalized)
{
const Deg a = Deg::from_degrees(30.0f);
const Deg b = -a; // wraps to 330 in [0,360)
EXPECT_FLOAT_EQ(b.as_degrees(), 330.0f);
}
TEST(UnitTestAngle, DereferenceReturnsDegrees)
{
const Deg a = Deg::from_degrees(42.0f);
EXPECT_FLOAT_EQ(*a, 42.0f);
}
// ---------- Trigonometric helpers ----------
TEST(UnitTestAngle, SinCosTanCot_BasicCases)
{
const Deg a0 = Deg::from_degrees(0.0f);
EXPECT_NEAR(a0.sin(), 0.0f, kEps);
EXPECT_NEAR(a0.cos(), 1.0f, kEps);
// cot(0) -> cos/sin -> div by 0: allow inf or nan
const float cot0 = a0.cot();
EXPECT_TRUE(std::isinf(cot0) || std::isnan(cot0));
const Deg a45 = Deg::from_degrees(45.0f);
EXPECT_NEAR(a45.tan(), 1.0f, 1e-4f);
EXPECT_NEAR(a45.cot(), 1.0f, 1e-4f);
const Deg a90 = Deg::from_degrees(90.0f);
EXPECT_NEAR(a90.sin(), 1.0f, 1e-4f);
EXPECT_NEAR(a90.cos(), 0.0f, 1e-4f);
}
TEST(UnitTestAngle, Atan_IsAtanOfRadians)
{
// atan(as_radians). For 0° -> atan(0)=0.
const Deg a0 = Deg::from_degrees(0.0f);
EXPECT_NEAR(a0.atan(), 0.0f, kEps);
const Deg a45 = Deg::from_degrees(45.0f);
// atan(pi/4) ≈ 0.665773...
EXPECT_NEAR(a45.atan(), 0.66577375f, 1e-6f);
}
// ---------- Compound arithmetic ----------
TEST(UnitTestAngle, PlusEquals_Normalized_Wraps)
{
Deg a = Deg::from_degrees(350.0f);
a += Deg::from_degrees(20.0f); // 370 -> 10
EXPECT_FLOAT_EQ(a.as_degrees(), 10.0f);
}
TEST(UnitTestAngle, MinusEquals_Normalized_Wraps)
{
Deg a = Deg::from_degrees(10.0f);
a -= Deg::from_degrees(30.0f); // -20 -> 340
EXPECT_FLOAT_EQ(a.as_degrees(), 340.0f);
}
TEST(UnitTestAngle, PlusEquals_Clamped_Clamps)
{
Pitch p = Pitch::from_degrees(80.0f);
p += Pitch::from_degrees(30.0f); // 110 -> clamp to 90
EXPECT_FLOAT_EQ(p.as_degrees(), 90.0f);
}
TEST(UnitTestAngle, MinusEquals_Clamped_Clamps)
{
Pitch p = Pitch::from_degrees(-70.0f);
p -= Pitch::from_degrees(40.0f); // -110 -> clamp to -90
EXPECT_FLOAT_EQ(p.as_degrees(), -90.0f);
}
// ---------- Alternative ranges ----------
TEST(UnitTestAngle, NormalizedRange_Neg180To180)
{
const Turn a = Turn::from_degrees(190.0f); // -> -170
const Turn b = Turn::from_degrees(-190.0f); // -> 170
EXPECT_FLOAT_EQ(a.as_degrees(), -170.0f);
EXPECT_FLOAT_EQ(b.as_degrees(), 170.0f);
}
// ---------- Comparisons (via <=>) ----------
TEST(UnitTestAngle, Comparisons_WorkWithPartialOrdering)
{
const Deg a = Deg::from_degrees(10.0f);
const Deg b = Deg::from_degrees(20.0f);
const Deg c = Deg::from_degrees(10.0f);
EXPECT_TRUE(a < b);
EXPECT_TRUE(b > a);
EXPECT_TRUE(a <= c);
EXPECT_TRUE(c >= a);
}
// ---------- std::format formatter ----------
TEST(UnitTestAngle, Formatter_PrintsDegreesWithSuffix)
{
const Deg a = Deg::from_degrees(15.0f);
EXPECT_EQ(std::format("{}", a), "15deg");
const Deg b = Deg::from_degrees(10.5f);
EXPECT_EQ(std::format("{}", b), "10.5deg");
const Turn t = Turn::from_degrees(-170.0f);
EXPECT_EQ(std::format("{}", t), "-170deg");
}
TEST(UnitTestAngle, BinaryPlus_ReturnsWrappedSum)
{
Angle<> a = Deg::from_degrees(350.0f);
const Deg b = Deg::from_degrees(20.0f);
const Deg c = a + b; // expect 10°
EXPECT_FLOAT_EQ(c.as_degrees(), 10.0f);
}
TEST(UnitTestAngle, BinaryMinus_ReturnsWrappedDiff)
{
Angle<> a = Deg::from_degrees(10.0f);
const Deg b = Deg::from_degrees(30.0f);
const Deg c = a - b; // expect 340°
EXPECT_FLOAT_EQ(c.as_degrees(), 340.0f);
}

View File

@@ -2,10 +2,10 @@
// Revised unittest suite for LineTracer (segmentbased MöllerTrumbore)
// Pure ASCII: avoids nonstandard characters that MSVC rejects.
//
#include "gtest/gtest.h"
#include "omath/linear_algebra/vector3.hpp"
#include "omath/collision/line_tracer.hpp"
#include "omath/triangle.hpp"
#include "omath/vector3.hpp"
#include "gtest/gtest.h"
#include <cmath>
using namespace omath;

View File

@@ -1,7 +1,7 @@
// UnitTestMat.cpp
#include "omath/linear_algebra/mat.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <gtest/gtest.h>
#include "omath/mat.hpp"
#include "omath/vector3.hpp"
using namespace omath;
@@ -125,7 +125,7 @@ TEST_F(UnitTestMat, Clear)
TEST_F(UnitTestMat, ToString)
{
const std::string str = m2.to_string();
const std::string str = std::format("{}", m2);
EXPECT_FALSE(str.empty());
EXPECT_EQ(str, "[[ 1.000, 2.000]\n [ 3.000, 4.000]]");
}

View File

@@ -1,184 +0,0 @@
//
// Created by vlad on 5/18/2024.
//
#ifdef OMATH_ENABLE_LEGACY
#include <gtest/gtest.h>
#include <omath/matrix.hpp>
#include "omath/vector3.hpp"
using namespace omath;
class UnitTestMatrix : public ::testing::Test
{
protected:
Matrix m1;
Matrix m2;
void SetUp() override
{
m1 = Matrix(2, 2);
m2 = Matrix{{1.0f, 2.0f}, {3.0f, 4.0f}};
}
};
// Test constructors
TEST_F(UnitTestMatrix, Constructor_Size)
{
const Matrix m(3, 3);
EXPECT_EQ(m.row_count(), 3);
EXPECT_EQ(m.columns_count(), 3);
}
TEST_F(UnitTestMatrix, Operator_SquareBrackets)
{
EXPECT_EQ((m2[0, 0]), 1.0f);
EXPECT_EQ((m2[0, 1]), 2.0f);
EXPECT_EQ((m2[1, 0]), 3.0f);
EXPECT_EQ((m2[1, 1]), 4.0f);
}
TEST_F(UnitTestMatrix, Constructor_InitializerList)
{
Matrix m{{1.0f, 2.0f}, {3.0f, 4.0f}};
EXPECT_EQ(m.row_count(), 2);
EXPECT_EQ(m.columns_count(), 2);
EXPECT_FLOAT_EQ(m.at(0, 0), 1.0f);
EXPECT_FLOAT_EQ(m.at(1, 1), 4.0f);
}
TEST_F(UnitTestMatrix, Constructor_Copy)
{
Matrix m3 = m2;
EXPECT_EQ(m3.row_count(), m2.row_count());
EXPECT_EQ(m3.columns_count(), m2.columns_count());
EXPECT_FLOAT_EQ(m3.at(0, 0), m2.at(0, 0));
}
TEST_F(UnitTestMatrix, Constructor_Move)
{
Matrix m3 = std::move(m2);
EXPECT_EQ(m3.row_count(), 2);
EXPECT_EQ(m3.columns_count(), 2);
EXPECT_FLOAT_EQ(m3.at(0, 0), 1.0f);
EXPECT_EQ(m2.row_count(), 0); // m2 should be empty after the move
EXPECT_EQ(m2.columns_count(), 0);
}
// Test matrix operations
TEST_F(UnitTestMatrix, Operator_Multiplication_Matrix)
{
Matrix m3 = m2 * m2;
EXPECT_EQ(m3.row_count(), 2);
EXPECT_EQ(m3.columns_count(), 2);
EXPECT_FLOAT_EQ(m3.at(0, 0), 7.0f);
EXPECT_FLOAT_EQ(m3.at(1, 1), 22.0f);
}
TEST_F(UnitTestMatrix, Operator_Multiplication_Scalar)
{
Matrix m3 = m2 * 2.0f;
EXPECT_FLOAT_EQ(m3.at(0, 0), 2.0f);
EXPECT_FLOAT_EQ(m3.at(1, 1), 8.0f);
}
TEST_F(UnitTestMatrix, Operator_Division_Scalar)
{
Matrix m3 = m2 / 2.0f;
EXPECT_FLOAT_EQ(m3.at(0, 0), 0.5f);
EXPECT_FLOAT_EQ(m3.at(1, 1), 2.0f);
}
// Test matrix functions
TEST_F(UnitTestMatrix, Transpose)
{
Matrix m3 = m2.transpose();
EXPECT_FLOAT_EQ(m3.at(0, 1), 3.0f);
EXPECT_FLOAT_EQ(m3.at(1, 0), 2.0f);
}
TEST_F(UnitTestMatrix, Determinant)
{
const float det = m2.determinant();
EXPECT_FLOAT_EQ(det, -2.0f);
}
TEST_F(UnitTestMatrix, Minor)
{
const float minor = m2.minor(0, 0);
EXPECT_FLOAT_EQ(minor, 4.0f);
}
TEST_F(UnitTestMatrix, AlgComplement)
{
const float algComp = m2.alg_complement(0, 0);
EXPECT_FLOAT_EQ(algComp, 4.0f);
}
TEST_F(UnitTestMatrix, Strip)
{
Matrix m3 = m2.strip(0, 0);
EXPECT_EQ(m3.row_count(), 1);
EXPECT_EQ(m3.columns_count(), 1);
EXPECT_FLOAT_EQ(m3.at(0, 0), 4.0f);
}
TEST_F(UnitTestMatrix, ProjectionMatrix)
{
const Matrix proj = Matrix::projection_matrix(45.0f, 1.33f, 0.1f, 100.0f);
EXPECT_EQ(proj.row_count(), 4);
EXPECT_EQ(proj.columns_count(), 4);
// Further checks on projection matrix elements could be added
}
// Test other member functions
TEST_F(UnitTestMatrix, Set)
{
m1.set(3.0f);
EXPECT_FLOAT_EQ(m1.at(0, 0), 3.0f);
EXPECT_FLOAT_EQ(m1.at(1, 1), 3.0f);
}
TEST_F(UnitTestMatrix, Sum)
{
const float sum = m2.sum();
EXPECT_FLOAT_EQ(sum, 10.0f);
}
TEST_F(UnitTestMatrix, Clear)
{
m2.clear();
EXPECT_FLOAT_EQ(m2.at(0, 0), 0.0f);
EXPECT_FLOAT_EQ(m2.at(1, 1), 0.0f);
}
TEST_F(UnitTestMatrix, ToString)
{
const std::string str = m2.to_string();
EXPECT_FALSE(str.empty());
}
// Test assignment operators
TEST_F(UnitTestMatrix, AssignmentOperator_Copy)
{
Matrix m3(2, 2);
m3 = m2;
EXPECT_EQ(m3.row_count(), m2.row_count());
EXPECT_EQ(m3.columns_count(), m2.columns_count());
EXPECT_FLOAT_EQ(m3.at(0, 0), m2.at(0, 0));
}
TEST_F(UnitTestMatrix, AssignmentOperator_Move)
{
Matrix m3(2, 2);
m3 = std::move(m2);
EXPECT_EQ(m3.row_count(), 2);
EXPECT_EQ(m3.columns_count(), 2);
EXPECT_FLOAT_EQ(m3.at(0, 0), 1.0f);
EXPECT_EQ(m2.row_count(), 0); // m2 should be empty after the move
EXPECT_EQ(m2.columns_count(), 0);
}
#endif

View File

@@ -13,8 +13,12 @@ TEST(UnitTestProjection, Projection)
const auto cam = omath::source_engine::Camera({0, 0, 0}, omath::source_engine::ViewAngles{}, {1920.f, 1080.f}, fov,
0.01f, 1000.f);
const auto projected = cam.world_to_screen({1000, 0, 50});
const auto projected = cam.world_to_screen({1000.f, 0, 50.f});
const auto result = cam.screen_to_world(projected.value());
const auto result2 = cam.world_to_screen(result.value());
EXPECT_EQ(static_cast<omath::Vector2<float>>(projected.value()),
static_cast<omath::Vector2<float>>(result2.value()));
EXPECT_NEAR(projected->x, 960.f, 0.001f);
EXPECT_NEAR(projected->y, 504.f, 0.001f);
EXPECT_NEAR(projected->z, 1.f, 0.001f);

View File

@@ -1,11 +1,10 @@
//
// Created by Orange on 1/6/2025.
//
#include "omath/triangle.hpp"
#include "omath/linear_algebra/vector3.hpp"
#include <cmath> // For std::sqrt, std::isinf, std::isnan
#include <gtest/gtest.h>
#include <omath/vector3.hpp>
#include "omath/triangle.hpp"
using namespace omath;

View File

@@ -2,10 +2,10 @@
// Created by Vlad on 02.09.2024.
//
#include <omath/linear_algebra/vector2.hpp>
#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;

View File

@@ -2,11 +2,11 @@
// Created by Vlad on 01.09.2024.
//
#include <omath/linear_algebra/vector3.hpp>
#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;

View File

@@ -5,9 +5,9 @@
// Vector4Test.cpp
//
#include <omath/linear_algebra/vector4.hpp>
#include <gtest/gtest.h>
#include <limits> // For std::numeric_limits
#include <omath/vector4.hpp>
using namespace omath;