Compare commits

..

43 Commits

Author SHA1 Message Date
2ec0e2f93f Update CREDITS.md to include Billy O'Neal
Added acknowledgment for Billy O'Neal's contributions.
2025-09-18 06:08:49 +03:00
9170ffb1a9 Merge pull request #74 from BillyONeal/fmodf
Don't name std::fmodf.
2025-09-18 06:04:43 +03:00
e05f9ef5a9 Removes FMA check for matrix multiplication
Removes preprocessor check for FMA instructions in matrix multiplication functions.
This simplifies the code and relies on the compiler's ability to optimize the
code based on available hardware support. The assumption is that modern
compilers will automatically utilize FMA instructions if available, and fall
back to alternative implementations if not.
2025-09-18 06:02:37 +03:00
89bb4aa625 Guards AVX2 usage with a preprocessor definition
Ensures that AVX2 intrinsics are only included when the
OMATH_USE_AVX2 preprocessor definition is set. This prevents
compilation errors when AVX2 support is not available or
explicitly disabled.
2025-09-18 05:22:22 +03:00
Billy Robert O'Neal III
9b0845593d Don't name std::fmodf.
The C standard library function fmodf is not guaranteed to be in namespace std, and in fact is not with a default Ubuntu 24.04 installation, leading to the following compile error:

```console
Change Dir: '/vcpkg/buildtrees/vcpkg-ci-orange-math/x64-linux-dbg'

Run Build Command(s): /vcpkg/downloads/tools/ninja/1.12.1-linux/ninja -v -v -j33
[1/2] /usr/bin/c++ -DOMATH_SUPRESS_SAFETY_CHECKS -DOMATH_VERSION=\"3.5.0\" -isystem /vcpkg/installed/x64-linux/include -fPIC -g -std=gnu++23 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /vcpkg/scripts/test_ports/vcpkg-ci-orange-math/project/main.cpp
FAILED: CMakeFiles/main.dir/main.cpp.o
/usr/bin/c++ -DOMATH_SUPRESS_SAFETY_CHECKS -DOMATH_VERSION=\"3.5.0\" -isystem /vcpkg/installed/x64-linux/include -fPIC -g -std=gnu++23 -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /vcpkg/scripts/test_ports/vcpkg-ci-orange-math/project/main.cpp
In file included from /vcpkg/installed/x64-linux/include/omath/omath.hpp:22,
                 from /vcpkg/scripts/test_ports/vcpkg-ci-orange-math/project/main.cpp:1:
/vcpkg/installed/x64-linux/include/omath/color.hpp: In member function ‘constexpr omath::Hsv omath::Color::to_hsv() const’:
/vcpkg/installed/x64-linux/include/omath/color.hpp:98:45: error: ‘fmodf’ is not a member of ‘std’; did you mean ‘modf’?
   98 |                 hsv_data.hue = 60.f * (std::fmodf(((green - blue) / delta), 6.f));
      |                                             ^~~~~
      |                                             modf
ninja: build stopped: subcommand failed.
```

Only the 'sufficient additional overloads' of `fmod` are guaranteed to be in `std`. Since this is clearly intended to call the (float, float) overload, explicitly cast `((green - blue) / delta)` (which is a `double`) to `float` and call the name in `std` as suggested by the diagnostic.
2025-09-17 19:15:10 -07:00
617ded2dd4 Merge pull request #73 from orange-cpp/featore/performance_tests
added performance folder
2025-09-17 20:53:11 +03:00
e882a224d2 fix 2025-09-17 20:50:30 +03:00
e04f6573c0 patch 2025-09-17 20:46:00 +03:00
791e3b2313 improved bench 2025-09-17 20:40:03 +03:00
26b56d757c fix 2025-09-17 20:25:22 +03:00
fbb77b9925 patch 2025-09-17 20:22:42 +03:00
7b671dbd90 added benchmark submodule 2025-09-17 20:14:33 +03:00
5875930f1a added benchmark 2025-09-17 19:56:50 +03:00
d773985822 added avx mutiplication 2025-09-17 19:47:29 +03:00
a2de6f8fae renamed folder 2025-09-17 18:07:28 +03:00
d71795006d added performance folder 2025-09-17 17:47:55 +03:00
561438d45c Merge pull request #72 from orange-cpp/feature/mat_refactor
Feature/mat refactor
2025-09-17 17:41:15 +03:00
874b028e86 removed unused var 2025-09-17 17:38:17 +03:00
68ec42d9ed added space 2025-09-17 17:33:05 +03:00
8aeb4667d7 decomposed mutiplication 2025-09-17 17:30:57 +03:00
565464f0cd forgot std 2025-09-17 17:23:02 +03:00
04b50d4545 Merge pull request #71 from orange-cpp/feature/mat_perf_boost
Improves matrix multiplication performance
2025-09-17 17:18:12 +03:00
e01d32fb22 Improves matrix multiplication performance
Optimizes matrix multiplication by specializing the algorithm
based on the matrix storage type (row-major or column-major).

This change significantly improves performance by leveraging
memory access patterns specific to each storage order.
2025-09-17 17:12:41 +03:00
a3a023a664 Add acknowledgment for AmbushedRaccoon's contribution 2025-09-16 16:58:00 +03:00
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
19 changed files with 426 additions and 71 deletions

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

5
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "extlibs/googletest"]
path = extlibs/googletest
url = https://github.com/google/googletest.git
url = https://github.com/google/googletest.git
[submodule "extlibs/benchmark"]
path = extlibs/benchmark
url = https://github.com/google/benchmark.git

1
.idea/vcs.xml generated
View File

@@ -2,6 +2,7 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/extlibs/benchmark" vcs="Git" />
<mapping directory="$PROJECT_DIR$/extlibs/googletest" vcs="Git" />
</component>
</project>

View File

@@ -6,6 +6,7 @@ include(CMakePackageConfigHelpers)
option(OMATH_BUILD_TESTS "Build unit tests" ${PROJECT_IS_TOP_LEVEL})
option(OMATH_BUILD_BENCHMARK "Build benchmarks" ${PROJECT_IS_TOP_LEVEL})
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
option(OMATH_USE_AVX2 "Omath will use AVX2 to boost performance" ON)
@@ -16,9 +17,10 @@ option(OMATH_SUPRESS_SAFETY_CHECKS "Supress some safety checks in release build
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}]: Building on ${CMAKE_HOST_SYSTEM_NAME}, compiler ${CMAKE_CXX_COMPILER_ID}")
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}]: Build benchmark ${OMATH_BUILD_BENCHMARK}")
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}")
@@ -90,16 +92,23 @@ if (OMATH_STATIC_MSVC_RUNTIME_LIBRARY)
)
endif ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE -mavx2 -mfma)
if (OMATH_USE_AVX2 AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${PROJECT_NAME} PUBLIC -mavx2 -mavx -mfma)
endif ()
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
if (OMATH_BUILD_TESTS OR OMATH_BUILD_BENCHMARK)
add_subdirectory(extlibs)
endif ()
if (OMATH_BUILD_TESTS)
add_subdirectory(extlibs)
add_subdirectory(tests)
target_compile_definitions(${PROJECT_NAME} PUBLIC OMATH_BUILD_TESTS)
endif ()
if (OMATH_BUILD_BENCHMARK)
add_subdirectory(benchmark)
endif ()
if (OMATH_BUILD_EXAMPLES)

View File

@@ -3,6 +3,8 @@
Thanks to everyone who made this possible, including:
- Saikari aka luadebug for VCPKG port and awesome new initial logo design.
- AmbushedRaccoon for telegram post about omath to boost repository activity.
- Billy O'Neal aka BillyONeal for fixing compilation issues due to C math library compatibility.
And a big hand to everyone else who has contributed over the past!

View File

@@ -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](.github/images/showcase/apex.png)
Or for InfinityWard Engine based games. Like Call of Duty Black Ops 2!
![banner](.github/images/showcase/cod_bo2.png)
Or create simple trigger bot with embeded traceline from omath::collision::LineTrace
![banner](.github/images/showcase/cs2.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

15
benchmark/CMakeLists.txt Normal file
View File

@@ -0,0 +1,15 @@
project(omath_benchmark)
file(GLOB_RECURSE OMATH_BENCHMARK_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_executable(${PROJECT_NAME} ${OMATH_BENCHMARK_SOURCES})
set_target_properties(${PROJECT_NAME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
CXX_STANDARD 23
CXX_STANDARD_REQUIRED ON)
target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark omath)

View File

@@ -0,0 +1,66 @@
//
// Created by Vlad on 9/17/2025.
//
#include <benchmark/benchmark.h>
#include <omath/omath.hpp>
#include <chrono>
using namespace omath;
void mat_float_multiplication_col_major(benchmark::State& state)
{
using MatType = Mat<128, 128, float, MatStoreType::COLUMN_MAJOR>;
MatType a;
MatType b;
a.set(3.f);
b.set(7.f);
for (auto _ : state)
std::ignore = a * b;
}
void mat_float_multiplication_row_major(benchmark::State& state)
{
using MatType = Mat<128, 128, float, MatStoreType::ROW_MAJOR>;
MatType a;
MatType b;
a.set(3.f);
b.set(7.f);
for (auto _ : state)
std::ignore = a * b;
}
void mat_double_multiplication_row_major(benchmark::State& state)
{
using MatType = Mat<128, 128, double, MatStoreType::ROW_MAJOR>;
MatType a;
MatType b;
a.set(3.f);
b.set(7.f);
for (auto _ : state)
std::ignore = a * b;
}
void mat_double_multiplication_col_major(benchmark::State& state)
{
using MatType = Mat<128, 128, double, MatStoreType::COLUMN_MAJOR>;
MatType a;
MatType b;
a.set(3.f);
b.set(7.f);
for (auto _ : state)
std::ignore = a * b;
}
BENCHMARK(mat_float_multiplication_col_major)->Iterations(5000);
BENCHMARK(mat_float_multiplication_row_major)->Iterations(5000);
BENCHMARK(mat_double_multiplication_col_major)->Iterations(5000);
BENCHMARK(mat_double_multiplication_row_major)->Iterations(5000);

5
benchmark/main.cpp Normal file
View File

@@ -0,0 +1,5 @@
//
// Created by Vlad on 9/17/2025.
//
#include <benchmark/benchmark.h>
BENCHMARK_MAIN();

View File

@@ -1 +1,2 @@
add_subdirectory(googletest)
add_subdirectory(googletest)
add_subdirectory(benchmark)

1
extlibs/benchmark Submodule

Submodule extlibs/benchmark added at 2948b6a2e6

View File

@@ -5,8 +5,8 @@
#pragma once
#include "omath/angles.hpp"
#include <algorithm>
#include <utility>
#include <format>
#include <utility>
namespace omath
{
@@ -150,17 +150,22 @@ namespace omath
}
};
} // namespace omath
template<class Type, Type min, Type max, omath::AngleFlags flags>
struct std::formatter<omath::Angle<Type, min, max, flags>> // NOLINT(*-dcl58-cpp)
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::format_parse_context& ctx)
static constexpr auto parse(std::basic_format_parse_context<CharT>& ctx)
-> std::basic_format_parse_context<CharT>::iterator
{
return ctx.begin();
}
[[nodiscard]]
static auto format(const omath::Angle<Type, min, max, flags>& deg, std::format_context& ctx)
template<class FormatContext>
auto format(const AngleT& deg, FormatContext& ctx) const
{
return std::format_to(ctx.out(), "{}deg", deg.as_degrees());
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

@@ -95,7 +95,7 @@ namespace omath
hsv_data.hue = 0.f;
else if (max == red)
hsv_data.hue = 60.f * (std::fmodf(((green - blue) / delta), 6.f));
hsv_data.hue = 60.f * (std::fmod(static_cast<float>((green - blue) / delta), 6.f));
else if (max == green)
hsv_data.hue = 60.f * (((blue - red) / delta) + 2.f);
else if (max == blue)

View File

@@ -11,6 +11,9 @@
#include <stdexcept>
#include <utility>
#ifdef OMATH_USE_AVX2
#include <immintrin.h>
#endif
namespace omath
{
@@ -155,17 +158,18 @@ namespace omath
constexpr Mat<Rows, OtherColumns, Type, StoreType>
operator*(const Mat<Columns, OtherColumns, Type, StoreType>& other) const
{
Mat<Rows, OtherColumns, Type, StoreType> result;
for (size_t i = 0; i < Rows; ++i)
for (size_t j = 0; j < OtherColumns; ++j)
{
Type sum = 0;
for (size_t k = 0; k < Columns; ++k)
sum += at(i, k) * other.at(k, j);
result.at(i, j) = sum;
}
return result;
#ifdef OMATH_USE_AVX2
if constexpr (StoreType == MatStoreType::ROW_MAJOR)
return avx_multiply_row_major(other);
if constexpr (StoreType == MatStoreType::COLUMN_MAJOR)
return avx_multiply_col_major(other);
#else
if constexpr (StoreType == MatStoreType::ROW_MAJOR)
return cache_friendly_multiply_row_major(other);
if constexpr (StoreType == MatStoreType::COLUMN_MAJOR)
return cache_friendly_multiply_col_major(other);
#endif
std::unreachable();
}
constexpr Mat& operator*=(const Type& f) noexcept
@@ -367,6 +371,176 @@ namespace omath
private:
std::array<Type, Rows * Columns> m_data;
template<size_t OtherColumns> [[nodiscard]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR>
cache_friendly_multiply_row_major(const Mat<Columns, OtherColumns, Type, MatStoreType::ROW_MAJOR>& other) const
{
Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR> result;
for (std::size_t i = 0; i < Rows; ++i)
for (std::size_t k = 0; k < Columns; ++k)
{
const Type aik = at(i, k);
for (std::size_t j = 0; j < OtherColumns; ++j)
result.at(i, j) += aik * other.at(k, j);
}
return result;
}
template<size_t OtherColumns> [[nodiscard]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR> cache_friendly_multiply_col_major(
const Mat<Columns, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>& other) const
{
Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR> result;
for (std::size_t j = 0; j < OtherColumns; ++j)
for (std::size_t k = 0; k < Columns; ++k)
{
const Type bkj = other.at(k, j);
for (std::size_t i = 0; i < Rows; ++i)
result.at(i, j) += at(i, k) * bkj;
}
return result;
}
#ifdef OMATH_USE_AVX2
template<size_t OtherColumns> [[nodiscard]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>
avx_multiply_col_major(const Mat<Columns, OtherColumns, Type, MatStoreType::COLUMN_MAJOR>& other) const
{
Mat<Rows, OtherColumns, Type, MatStoreType::COLUMN_MAJOR> result;
const Type* this_mat_data = this->raw_array().data();
const Type* other_mat_data = other.raw_array().data();
Type* result_mat_data = result.raw_array().data();
if constexpr (std::is_same_v<Type, float>)
{
// ReSharper disable once CppTooWideScopeInitStatement
constexpr std::size_t vector_size = 8;
for (std::size_t j = 0; j < OtherColumns; ++j)
{
auto* c_col = reinterpret_cast<float*>(result_mat_data + j * Rows);
for (std::size_t k = 0; k < Columns; ++k)
{
const float bkj = reinterpret_cast<const float*>(other_mat_data)[k + j * Columns];
__m256 bkjv = _mm256_set1_ps(bkj);
const auto* a_col_k = reinterpret_cast<const float*>(this_mat_data + k * Rows);
std::size_t i = 0;
for (; i + vector_size <= Rows; i += vector_size)
{
__m256 cvec = _mm256_loadu_ps(c_col + i);
__m256 avec = _mm256_loadu_ps(a_col_k + i);
cvec = _mm256_fmadd_ps(avec, bkjv, cvec);
_mm256_storeu_ps(c_col + i, cvec);
}
for (; i < Rows; ++i)
c_col[i] += a_col_k[i] * bkj;
}
}
}
else if (std::is_same_v<Type, double>)
{ // double
// ReSharper disable once CppTooWideScopeInitStatement
constexpr std::size_t vector_size = 4;
for (std::size_t j = 0; j < OtherColumns; ++j)
{
auto* c_col = reinterpret_cast<double*>(result_mat_data + j * Rows);
for (std::size_t k = 0; k < Columns; ++k)
{
const double bkj = reinterpret_cast<const double*>(other_mat_data)[k + j * Columns];
__m256d bkjv = _mm256_set1_pd(bkj);
const auto* a_col_k = reinterpret_cast<const double*>(this_mat_data + k * Rows);
std::size_t i = 0;
for (; i + vector_size <= Rows; i += vector_size)
{
__m256d cvec = _mm256_loadu_pd(c_col + i);
__m256d avec = _mm256_loadu_pd(a_col_k + i);
cvec = _mm256_fmadd_pd(avec, bkjv, cvec);
_mm256_storeu_pd(c_col + i, cvec);
}
for (; i < Rows; ++i)
c_col[i] += a_col_k[i] * bkj;
}
}
}
else
std::unreachable();
return result;
}
template<size_t OtherColumns> [[nodiscard]]
constexpr Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR>
avx_multiply_row_major(const Mat<Columns, OtherColumns, Type, MatStoreType::ROW_MAJOR>& other) const
{
Mat<Rows, OtherColumns, Type, MatStoreType::ROW_MAJOR> result;
const Type* this_mat_data = this->raw_array().data();
const Type* other_mat_data = other.raw_array().data();
Type* result_mat_data = result.raw_array().data();
if constexpr (std::is_same_v<Type, float>)
{
// ReSharper disable once CppTooWideScopeInitStatement
constexpr std::size_t vector_size = 8;
for (std::size_t i = 0; i < Rows; ++i)
{
Type* c_row = result_mat_data + i * OtherColumns;
for (std::size_t k = 0; k < Columns; ++k)
{
const auto aik = static_cast<float>(this_mat_data[i * Columns + k]);
__m256 aikv = _mm256_set1_ps(aik);
const auto* b_row = reinterpret_cast<const float*>(other_mat_data + k * OtherColumns);
std::size_t j = 0;
for (; j + vector_size <= OtherColumns; j += vector_size)
{
__m256 cvec = _mm256_loadu_ps(c_row + j);
__m256 bvec = _mm256_loadu_ps(b_row + j);
cvec = _mm256_fmadd_ps(bvec, aikv, cvec);
_mm256_storeu_ps(c_row + j, cvec);
}
for (; j < OtherColumns; ++j)
c_row[j] += aik * b_row[j];
}
}
}
else if (std::is_same_v<Type, double>)
{ // double
// ReSharper disable once CppTooWideScopeInitStatement
constexpr std::size_t vector_size = 4;
for (std::size_t i = 0; i < Rows; ++i)
{
Type* c_row = result_mat_data + i * OtherColumns;
for (std::size_t k = 0; k < Columns; ++k)
{
const auto aik = static_cast<double>(this_mat_data[i * Columns + k]);
__m256d aikv = _mm256_set1_pd(aik);
const auto* b_row = reinterpret_cast<const double*>(other_mat_data + k * OtherColumns);
std::size_t j = 0;
for (; j + vector_size <= OtherColumns; j += vector_size)
{
__m256d cvec = _mm256_loadu_pd(c_row + j);
__m256d bvec = _mm256_loadu_pd(b_row + j);
cvec = _mm256_fmadd_pd(bvec, aikv, cvec);
_mm256_storeu_pd(c_row + j, cvec);
}
for (; j < OtherColumns; ++j)
c_row[j] += aik * b_row[j];
}
}
}
else
std::unreachable();
return result;
}
#endif
};
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR> [[nodiscard]]

View File

@@ -15,7 +15,6 @@
#include "omath/linear_algebra/vector3.hpp"
// Matrix classes
#include "linear_algebra/matrix.hpp"
#include "omath/linear_algebra/mat.hpp"
// Color functionality
@@ -81,4 +80,4 @@
#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"
#include "omath/engines/unreal_engine/traits/pred_engine_trait.hpp"

View File

@@ -4,13 +4,18 @@
#pragma once
#include "omath/projection/error_codes.hpp"
#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 <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

@@ -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

@@ -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);