mirror of
https://github.com/orange-cpp/omath.git
synced 2026-02-13 07:03:25 +00:00
Merge pull request #15 from orange-cpp/u/orange-cpp/misc
Global improvement
This commit is contained in:
62
.clang-format
Normal file
62
.clang-format
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Generated from CLion C/C++ Code Style settings
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BraceWrapping:
|
||||||
|
AfterCaseLabel: true
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: true
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
AfterExternBlock: true
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
BeforeLambdaBody: true
|
||||||
|
BeforeWhile: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBraces: Custom
|
||||||
|
BreakConstructorInitializers: AfterColon
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
ColumnLimit: 120
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ContinuationIndentWidth: 8
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^".*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 4
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: All
|
||||||
|
PointerAlignment: Left
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
TabWidth: 4
|
||||||
|
...
|
||||||
147
.clang-tidy
Normal file
147
.clang-tidy
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# Generated from CLion Inspection settings
|
||||||
|
---
|
||||||
|
Checks: '-*,
|
||||||
|
bugprone-argument-comment,
|
||||||
|
bugprone-assert-side-effect,
|
||||||
|
bugprone-bad-signal-to-kill-thread,
|
||||||
|
bugprone-branch-clone,
|
||||||
|
bugprone-copy-constructor-init,
|
||||||
|
bugprone-dangling-handle,
|
||||||
|
bugprone-dynamic-static-initializers,
|
||||||
|
bugprone-fold-init-type,
|
||||||
|
bugprone-forward-declaration-namespace,
|
||||||
|
bugprone-forwarding-reference-overload,
|
||||||
|
bugprone-inaccurate-erase,
|
||||||
|
bugprone-incorrect-roundings,
|
||||||
|
bugprone-integer-division,
|
||||||
|
bugprone-lambda-function-name,
|
||||||
|
bugprone-macro-parentheses,
|
||||||
|
bugprone-macro-repeated-side-effects,
|
||||||
|
bugprone-misplaced-operator-in-strlen-in-alloc,
|
||||||
|
bugprone-misplaced-pointer-arithmetic-in-alloc,
|
||||||
|
bugprone-misplaced-widening-cast,
|
||||||
|
bugprone-move-forwarding-reference,
|
||||||
|
bugprone-multiple-statement-macro,
|
||||||
|
bugprone-no-escape,
|
||||||
|
bugprone-parent-virtual-call,
|
||||||
|
bugprone-posix-return,
|
||||||
|
bugprone-reserved-identifier,
|
||||||
|
bugprone-sizeof-container,
|
||||||
|
bugprone-sizeof-expression,
|
||||||
|
bugprone-spuriously-wake-up-functions,
|
||||||
|
bugprone-string-constructor,
|
||||||
|
bugprone-string-integer-assignment,
|
||||||
|
bugprone-string-literal-with-embedded-nul,
|
||||||
|
bugprone-suspicious-enum-usage,
|
||||||
|
bugprone-suspicious-include,
|
||||||
|
bugprone-suspicious-memset-usage,
|
||||||
|
bugprone-suspicious-missing-comma,
|
||||||
|
bugprone-suspicious-semicolon,
|
||||||
|
bugprone-suspicious-string-compare,
|
||||||
|
bugprone-suspicious-memory-comparison,
|
||||||
|
bugprone-suspicious-realloc-usage,
|
||||||
|
bugprone-swapped-arguments,
|
||||||
|
bugprone-terminating-continue,
|
||||||
|
bugprone-throw-keyword-missing,
|
||||||
|
bugprone-too-small-loop-variable,
|
||||||
|
bugprone-undefined-memory-manipulation,
|
||||||
|
bugprone-undelegated-constructor,
|
||||||
|
bugprone-unhandled-self-assignment,
|
||||||
|
bugprone-unused-raii,
|
||||||
|
bugprone-unused-return-value,
|
||||||
|
bugprone-use-after-move,
|
||||||
|
bugprone-virtual-near-miss,
|
||||||
|
cert-dcl21-cpp,
|
||||||
|
cert-dcl58-cpp,
|
||||||
|
cert-err34-c,
|
||||||
|
cert-err52-cpp,
|
||||||
|
cert-err60-cpp,
|
||||||
|
cert-flp30-c,
|
||||||
|
cert-msc50-cpp,
|
||||||
|
cert-msc51-cpp,
|
||||||
|
cert-str34-c,
|
||||||
|
cppcoreguidelines-interfaces-global-init,
|
||||||
|
cppcoreguidelines-narrowing-conversions,
|
||||||
|
cppcoreguidelines-pro-type-member-init,
|
||||||
|
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||||
|
cppcoreguidelines-slicing,
|
||||||
|
google-default-arguments,
|
||||||
|
google-explicit-constructor,
|
||||||
|
google-runtime-operator,
|
||||||
|
hicpp-exception-baseclass,
|
||||||
|
hicpp-multiway-paths-covered,
|
||||||
|
misc-misplaced-const,
|
||||||
|
misc-new-delete-overloads,
|
||||||
|
misc-no-recursion,
|
||||||
|
misc-non-copyable-objects,
|
||||||
|
misc-throw-by-value-catch-by-reference,
|
||||||
|
misc-unconventional-assign-operator,
|
||||||
|
misc-uniqueptr-reset-release,
|
||||||
|
modernize-avoid-bind,
|
||||||
|
modernize-concat-nested-namespaces,
|
||||||
|
modernize-deprecated-headers,
|
||||||
|
modernize-deprecated-ios-base-aliases,
|
||||||
|
modernize-loop-convert,
|
||||||
|
modernize-make-shared,
|
||||||
|
modernize-make-unique,
|
||||||
|
modernize-pass-by-value,
|
||||||
|
modernize-raw-string-literal,
|
||||||
|
modernize-redundant-void-arg,
|
||||||
|
modernize-replace-auto-ptr,
|
||||||
|
modernize-replace-disallow-copy-and-assign-macro,
|
||||||
|
modernize-replace-random-shuffle,
|
||||||
|
modernize-return-braced-init-list,
|
||||||
|
modernize-shrink-to-fit,
|
||||||
|
modernize-unary-static-assert,
|
||||||
|
modernize-use-auto,
|
||||||
|
modernize-use-bool-literals,
|
||||||
|
modernize-use-emplace,
|
||||||
|
modernize-use-equals-default,
|
||||||
|
modernize-use-equals-delete,
|
||||||
|
modernize-use-nodiscard,
|
||||||
|
modernize-use-noexcept,
|
||||||
|
modernize-use-nullptr,
|
||||||
|
modernize-use-override,
|
||||||
|
modernize-use-transparent-functors,
|
||||||
|
modernize-use-uncaught-exceptions,
|
||||||
|
mpi-buffer-deref,
|
||||||
|
mpi-type-mismatch,
|
||||||
|
openmp-use-default-none,
|
||||||
|
performance-faster-string-find,
|
||||||
|
performance-for-range-copy,
|
||||||
|
performance-implicit-conversion-in-loop,
|
||||||
|
performance-inefficient-algorithm,
|
||||||
|
performance-inefficient-string-concatenation,
|
||||||
|
performance-inefficient-vector-operation,
|
||||||
|
performance-move-const-arg,
|
||||||
|
performance-move-constructor-init,
|
||||||
|
performance-no-automatic-move,
|
||||||
|
performance-noexcept-move-constructor,
|
||||||
|
performance-trivially-destructible,
|
||||||
|
performance-type-promotion-in-math-fn,
|
||||||
|
performance-unnecessary-copy-initialization,
|
||||||
|
performance-unnecessary-value-param,
|
||||||
|
portability-simd-intrinsics,
|
||||||
|
readability-avoid-const-params-in-decls,
|
||||||
|
readability-const-return-type,
|
||||||
|
readability-container-size-empty,
|
||||||
|
readability-convert-member-functions-to-static,
|
||||||
|
readability-delete-null-pointer,
|
||||||
|
readability-deleted-default,
|
||||||
|
readability-inconsistent-declaration-parameter-name,
|
||||||
|
readability-make-member-function-const,
|
||||||
|
readability-misleading-indentation,
|
||||||
|
readability-misplaced-array-index,
|
||||||
|
readability-non-const-parameter,
|
||||||
|
readability-redundant-control-flow,
|
||||||
|
readability-redundant-declaration,
|
||||||
|
readability-redundant-function-ptr-dereference,
|
||||||
|
readability-redundant-smartptr-get,
|
||||||
|
readability-redundant-string-cstr,
|
||||||
|
readability-redundant-string-init,
|
||||||
|
readability-simplify-subscript-expr,
|
||||||
|
readability-static-accessed-through-instance,
|
||||||
|
readability-static-definition-in-anonymous-namespace,
|
||||||
|
readability-string-compare,
|
||||||
|
readability-uniqueptr-delete-release,
|
||||||
|
readability-use-anyofallof'
|
||||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,6 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/extlibs/glm" vcs="Git" />
|
||||||
<mapping directory="$PROJECT_DIR$/extlibs/googletest" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/extlibs/googletest" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -6,6 +6,9 @@ project(omath VERSION 1.0.0)
|
|||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 26)
|
set(CMAKE_CXX_STANDARD 26)
|
||||||
|
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
option(OMATH_BUILD_TESTS "Build unit tests" ON)
|
option(OMATH_BUILD_TESTS "Build unit tests" ON)
|
||||||
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
|
option(OMATH_THREAT_WARNING_AS_ERROR "Set highest level of warnings and force compiler to treat them as errors" ON)
|
||||||
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
|
option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF)
|
||||||
@@ -23,10 +26,10 @@ if(OMATH_BUILD_TESTS)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 AND OMATH_THREAT_WARNING_AS_ERROR)
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND OMATH_THREAT_WARNING_AS_ERROR)
|
||||||
target_compile_options(omath PRIVATE /W4 /WX)
|
target_compile_options(omath PRIVATE /W4 /WX)
|
||||||
elseif(UNIX AND OMATH_THREAT_WARNING_AS_ERROR)
|
elseif(OMATH_THREAT_WARNING_AS_ERROR)
|
||||||
target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(omath
|
target_include_directories(omath
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
## Goal
|
## 🎯 Goal
|
||||||
|
|
||||||
My goal is to provide a space where it is safe for everyone to contribute to,
|
My goal is to provide a space where it is safe for everyone to contribute to,
|
||||||
and get support for, open-source software in a respectful and cooperative
|
and get support for, open-source software in a respectful and cooperative
|
||||||
@@ -10,7 +10,7 @@ surrounding community a place for everyone.
|
|||||||
As members, contributors, and everyone else who may participate in the
|
As members, contributors, and everyone else who may participate in the
|
||||||
development, I strive to keep the entire experience civil.
|
development, I strive to keep the entire experience civil.
|
||||||
|
|
||||||
## Standards
|
## 📜 Standards
|
||||||
|
|
||||||
Our community standards exist in order to make sure everyone feels comfortable
|
Our community standards exist in order to make sure everyone feels comfortable
|
||||||
contributing to the project(s) together.
|
contributing to the project(s) together.
|
||||||
@@ -27,14 +27,14 @@ Examples of breaking each rule respectively include:
|
|||||||
- Posting distasteful imagery, trolling, or posting things unrelated to the topic at hand.
|
- Posting distasteful imagery, trolling, or posting things unrelated to the topic at hand.
|
||||||
- Treating someone as worse because of their lack of understanding of an issue.
|
- Treating someone as worse because of their lack of understanding of an issue.
|
||||||
|
|
||||||
## Enforcement
|
## ⚡ Enforcement
|
||||||
|
|
||||||
Enforcement of this CoC is done by Orange++ and/or other core contributors.
|
Enforcement of this CoC is done by Orange++ and/or other core contributors.
|
||||||
|
|
||||||
I, as the core developer, will strive my best to keep this community civil and
|
I, as the core developer, will strive my best to keep this community civil and
|
||||||
following the standards outlined above.
|
following the standards outlined above.
|
||||||
|
|
||||||
### Reporting incidents
|
### 🚩 Reporting incidents
|
||||||
|
|
||||||
If you believe an incident of breaking these standards has occurred, but nobody has
|
If you believe an incident of breaking these standards has occurred, but nobody has
|
||||||
taken appropriate action, you can privately contact the people responsible for dealing
|
taken appropriate action, you can privately contact the people responsible for dealing
|
||||||
@@ -47,10 +47,11 @@ with such incidents in multiple ways:
|
|||||||
- `@orange_cpp`
|
- `@orange_cpp`
|
||||||
|
|
||||||
***Telegram***
|
***Telegram***
|
||||||
- `@orange-cpp`
|
- `@orange_cpp`
|
||||||
|
|
||||||
I guarantee your privacy and will not share those reports with anyone.
|
I guarantee your privacy and will not share those reports with anyone.
|
||||||
|
|
||||||
## Enforcement Strategy
|
## ⚖️ Enforcement Strategy
|
||||||
|
|
||||||
Depending on the severity of the infraction, any action from the list below may be applied.
|
Depending on the severity of the infraction, any action from the list below may be applied.
|
||||||
Please keep in mind cases are reviewed on a per-case basis and members are the ultimate
|
Please keep in mind cases are reviewed on a per-case basis and members are the ultimate
|
||||||
@@ -63,27 +64,27 @@ to be taken is still up to the member.
|
|||||||
For example, if the matter at hand regards a representative of a marginalized group or minority,
|
For example, if the matter at hand regards a representative of a marginalized group or minority,
|
||||||
the member might ask for a first-hand opinion from another representative of such group.
|
the member might ask for a first-hand opinion from another representative of such group.
|
||||||
|
|
||||||
### Correction/Edit
|
### ✏️ Correction/Edit
|
||||||
|
|
||||||
If your message is found to be misleading or poorly worded, a member might
|
If your message is found to be misleading or poorly worded, a member might
|
||||||
edit your message.
|
edit your message.
|
||||||
|
|
||||||
### Warning/Deletion
|
### ⚠️ Warning/Deletion
|
||||||
|
|
||||||
If your message is found inappropriate, a member might give you a public or private warning,
|
If your message is found inappropriate, a member might give you a public or private warning,
|
||||||
and/or delete your message.
|
and/or delete your message.
|
||||||
|
|
||||||
### Mute
|
### 🔇 Mute
|
||||||
|
|
||||||
If your message is disruptive, or you have been repeatedly violating the standards,
|
If your message is disruptive, or you have been repeatedly violating the standards,
|
||||||
a member might mute (or temporarily ban) you.
|
a member might mute (or temporarily ban) you.
|
||||||
|
|
||||||
### Ban
|
### ⛔ Ban
|
||||||
|
|
||||||
If your message is hateful, very disruptive, or other, less serious infractions are repeated
|
If your message is hateful, very disruptive, or other, less serious infractions are repeated
|
||||||
ignoring previous punishments, a member might ban you permanently.
|
ignoring previous punishments, a member might ban you permanently.
|
||||||
|
|
||||||
## Scope
|
## 🔎 Scope
|
||||||
|
|
||||||
This CoC shall apply to all projects ran under the Orange++ lead and all _official_ communities
|
This CoC shall apply to all projects ran under the Orange++ lead and all _official_ communities
|
||||||
outside of GitHub.
|
outside of GitHub.
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Please report security issues to `orange-cpp@yandex.com`
|
Please report security issues to `orange-cpp@yandex.ru`
|
||||||
154
include/omath/Angle.hpp
Normal file
154
include/omath/Angle.hpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "omath/Angles.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
namespace omath
|
||||||
|
{
|
||||||
|
enum class AngleFlags
|
||||||
|
{
|
||||||
|
Normalized = 0,
|
||||||
|
Clamped = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Type = float, Type min = Type(0), Type max = Type(360), AngleFlags flags = AngleFlags::Normalized>
|
||||||
|
requires std::is_arithmetic_v<Type>
|
||||||
|
class Angle
|
||||||
|
{
|
||||||
|
Type m_angle;
|
||||||
|
constexpr Angle(const Type& degrees)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
m_angle = angles::WrapAngle(degrees, min, max);
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
m_angle = std::clamp(degrees, min, max);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert(false);
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static Angle FromDegrees(const Type& degrees)
|
||||||
|
{
|
||||||
|
return {degrees};
|
||||||
|
}
|
||||||
|
constexpr Angle() : m_angle(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr static Angle FromRadians(const Type& degrees)
|
||||||
|
{
|
||||||
|
return {angles::RadiansToDegrees<Type>(degrees)};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr const Type& operator*() const
|
||||||
|
{
|
||||||
|
return m_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Type AsDegrees() const
|
||||||
|
{
|
||||||
|
return m_angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Type AsRadians() const
|
||||||
|
{
|
||||||
|
return angles::DegreesToRadians(m_angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Sin() const
|
||||||
|
{
|
||||||
|
return std::sin(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Cos() const
|
||||||
|
{
|
||||||
|
return std::cos(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Tan() const
|
||||||
|
{
|
||||||
|
return std::tan(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Atan() const
|
||||||
|
{
|
||||||
|
return std::atan(AsRadians());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
Type Cot() const
|
||||||
|
{
|
||||||
|
return Cos() / Sin();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator+=(const Angle& other)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
m_angle = angles::WrapAngle(m_angle + other.m_angle, min, max);
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
m_angle = std::clamp(m_angle + other.m_angle, min, max);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static_assert(false);
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr std::partial_ordering operator<=>(const Angle& other) const = default;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator-=(const Angle& other)
|
||||||
|
{
|
||||||
|
return operator+=(-other);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator+(const Angle& other)
|
||||||
|
{
|
||||||
|
if constexpr (flags == AngleFlags::Normalized)
|
||||||
|
return {angles::WrapAngle(m_angle + other.m_angle, min, max)};
|
||||||
|
|
||||||
|
else if constexpr (flags == AngleFlags::Clamped)
|
||||||
|
return {std::clamp(m_angle + other.m_angle, min, max)};
|
||||||
|
|
||||||
|
else
|
||||||
|
static_assert(false);
|
||||||
|
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle& operator-(const Angle& other)
|
||||||
|
{
|
||||||
|
return operator+(-other);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr Angle operator-() const
|
||||||
|
{
|
||||||
|
return {-m_angle};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -4,15 +4,61 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
namespace omath::angles
|
namespace omath::angles
|
||||||
{
|
{
|
||||||
[[nodiscard]] constexpr float RadiansToDegrees(const float radiands)
|
template<class Type>
|
||||||
|
requires std::is_floating_point_v<Type>
|
||||||
|
[[nodiscard]] constexpr Type RadiansToDegrees(const Type& radians)
|
||||||
{
|
{
|
||||||
return radiands * (180.f / std::numbers::pi_v<float>);
|
return radians * (Type(180) / std::numbers::pi_v<Type>);
|
||||||
}
|
}
|
||||||
[[nodiscard]] constexpr float DegreesToRadians(const float degrees)
|
|
||||||
|
template<class Type>
|
||||||
|
requires std::is_floating_point_v<Type>
|
||||||
|
[[nodiscard]] constexpr Type DegreesToRadians(const Type& degrees)
|
||||||
{
|
{
|
||||||
return degrees * (std::numbers::pi_v<float> / 180.f);
|
return degrees * (std::numbers::pi_v<Type> / Type(180));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class type>
|
||||||
|
requires std::is_floating_point_v<type>
|
||||||
|
[[nodiscard]] type HorizontalFovToVertical(const type& horFov, const type& aspect)
|
||||||
|
{
|
||||||
|
const auto fovRad = DegreesToRadians(horFov);
|
||||||
|
|
||||||
|
const auto vertFov = type(2) * std::atan(std::tan(fovRad / type(2)) / aspect);
|
||||||
|
|
||||||
|
return RadiansToDegrees(vertFov);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
requires std::is_floating_point_v<Type>
|
||||||
|
[[nodiscard]] Type VerticalFovToHorizontal(const Type& vertFov, const Type& aspect)
|
||||||
|
{
|
||||||
|
const auto fovRad = DegreesToRadians(vertFov);
|
||||||
|
|
||||||
|
const auto horFov = Type(2) * std::atan(std::tan(fovRad / Type(2)) * aspect);
|
||||||
|
|
||||||
|
return RadiansToDegrees(horFov);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
requires std::is_arithmetic_v<Type>
|
||||||
|
[[nodiscard]] Type WrapAngle(const Type& angle, const Type& min, const Type& max)
|
||||||
|
{
|
||||||
|
if (angle <= max && angle >= min)
|
||||||
|
return angle;
|
||||||
|
|
||||||
|
const Type range = max - min;
|
||||||
|
|
||||||
|
Type wrappedAngle = std::fmod(angle - min, range);
|
||||||
|
|
||||||
|
if (wrappedAngle < 0)
|
||||||
|
wrappedAngle += range;
|
||||||
|
|
||||||
|
return wrappedAngle + min;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,9 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "Vector3.hpp"
|
#include "Vector3.hpp"
|
||||||
#include <stdexcept>
|
|
||||||
#include "Angles.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace omath
|
namespace omath
|
||||||
@@ -25,7 +24,7 @@ namespace omath
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<size_t Rows = 0, size_t Columns = 0, class Type = float, MatStoreType StoreType = MatStoreType::ROW_MAJOR>
|
template<size_t Rows = 0, size_t Columns = 0, class Type = float, MatStoreType StoreType = MatStoreType::ROW_MAJOR>
|
||||||
requires (std::is_floating_point_v<Type> || std::is_integral_v<Type>)
|
requires std::is_arithmetic_v<Type>
|
||||||
class Mat final
|
class Mat final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -33,7 +32,10 @@ namespace omath
|
|||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
constexpr static MatStoreType GetStoreOrdering()
|
||||||
|
{
|
||||||
|
return StoreType;
|
||||||
|
}
|
||||||
constexpr Mat(const std::initializer_list<std::initializer_list<Type>>& rows)
|
constexpr Mat(const std::initializer_list<std::initializer_list<Type>>& rows)
|
||||||
{
|
{
|
||||||
if (rows.size() != Rows)
|
if (rows.size() != Rows)
|
||||||
@@ -59,24 +61,24 @@ namespace omath
|
|||||||
std::copy_n(rawData, Rows * Columns, m_data.begin());
|
std::copy_n(rawData, Rows * Columns, m_data.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat(const Mat &other) noexcept
|
constexpr Mat(const Mat& other) noexcept
|
||||||
{
|
{
|
||||||
m_data = other.m_data;
|
m_data = other.m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat(Mat &&other) noexcept
|
constexpr Mat(Mat&& other) noexcept
|
||||||
{
|
{
|
||||||
m_data = std::move(other.m_data);
|
m_data = std::move(other.m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static consteval size_t RowCount() noexcept
|
static constexpr size_t RowCount() noexcept
|
||||||
{
|
{
|
||||||
return Rows;
|
return Rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static consteval size_t ColumnsCount() noexcept
|
static constexpr size_t ColumnsCount() noexcept
|
||||||
{
|
{
|
||||||
return Columns;
|
return Columns;
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,7 @@ namespace omath
|
|||||||
return {Rows, Columns};
|
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)
|
if (rowIndex >= Rows || columnIndex >= Columns)
|
||||||
throw std::out_of_range("Index out of range");
|
throw std::out_of_range("Index out of range");
|
||||||
@@ -105,9 +107,9 @@ namespace omath
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr Type &At(const size_t rowIndex, const size_t columnIndex)
|
[[nodiscard]] constexpr Type& At(const size_t rowIndex, const size_t columnIndex)
|
||||||
{
|
{
|
||||||
return const_cast<Type &>(std::as_const(*this).At(rowIndex, columnIndex));
|
return const_cast<Type&>(std::as_const(*this).At(rowIndex, columnIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -126,16 +128,17 @@ namespace omath
|
|||||||
Set(0);
|
Set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void Set(const Type &value) noexcept
|
constexpr void Set(const Type& value) noexcept
|
||||||
{
|
{
|
||||||
std::ranges::fill(m_data, value);
|
std::ranges::fill(m_data, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operator overloading for multiplication with another Mat
|
// Operator overloading for multiplication with another Mat
|
||||||
template<size_t OtherColumns>
|
template<size_t OtherColumns>
|
||||||
constexpr Mat<Rows, OtherColumns> operator*(const Mat<Columns, OtherColumns> &other) const
|
constexpr Mat<Rows, OtherColumns, Type, StoreType>
|
||||||
|
operator*(const Mat<Columns, OtherColumns, Type, StoreType>& other) const
|
||||||
{
|
{
|
||||||
Mat<Rows, OtherColumns> result;
|
Mat<Rows, OtherColumns, Type, StoreType> result;
|
||||||
|
|
||||||
for (size_t i = 0; i < Rows; ++i)
|
for (size_t i = 0; i < Rows; ++i)
|
||||||
for (size_t j = 0; j < OtherColumns; ++j)
|
for (size_t j = 0; j < OtherColumns; ++j)
|
||||||
@@ -148,7 +151,7 @@ namespace omath
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat &operator*=(const Type &f) noexcept
|
constexpr Mat& operator*=(const Type& f) noexcept
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < Rows; ++i)
|
for (size_t i = 0; i < Rows; ++i)
|
||||||
for (size_t j = 0; j < Columns; ++j)
|
for (size_t j = 0; j < Columns; ++j)
|
||||||
@@ -157,19 +160,20 @@ namespace omath
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t OtherColumns>
|
template<size_t OtherColumns>
|
||||||
constexpr Mat<Rows, OtherColumns> operator*=(const Mat<Columns, OtherColumns> &other)
|
constexpr Mat<Rows, OtherColumns, Type, StoreType>
|
||||||
|
operator*=(const Mat<Columns, OtherColumns, Type, StoreType>& other)
|
||||||
{
|
{
|
||||||
return *this = *this * other;
|
return *this = *this * other;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat operator*(const Type &f) const noexcept
|
constexpr Mat operator*(const Type& f) const noexcept
|
||||||
{
|
{
|
||||||
Mat result(*this);
|
Mat result(*this);
|
||||||
result *= f;
|
result *= f;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat &operator/=(const Type &f) noexcept
|
constexpr Mat& operator/=(const Type& f) noexcept
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < Rows; ++i)
|
for (size_t i = 0; i < Rows; ++i)
|
||||||
for (size_t j = 0; j < Columns; ++j)
|
for (size_t j = 0; j < Columns; ++j)
|
||||||
@@ -177,14 +181,14 @@ namespace omath
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat operator/(const Type &f) const noexcept
|
constexpr Mat operator/(const Type& f) const noexcept
|
||||||
{
|
{
|
||||||
Mat result(*this);
|
Mat result(*this);
|
||||||
result /= f;
|
result /= f;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat &operator=(const Mat &other) noexcept
|
constexpr Mat& operator=(const Mat& other) noexcept
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -194,7 +198,7 @@ namespace omath
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Mat &operator=(Mat &&other) noexcept
|
constexpr Mat& operator=(Mat&& other) noexcept
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -207,9 +211,9 @@ namespace omath
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr Mat<Columns, Rows> Transposed() const noexcept
|
constexpr Mat<Columns, Rows, Type, StoreType> Transposed() const noexcept
|
||||||
{
|
{
|
||||||
Mat<Columns, Rows> transposed;
|
Mat<Columns, Rows, Type, StoreType> transposed;
|
||||||
for (size_t i = 0; i < Rows; ++i)
|
for (size_t i = 0; i < Rows; ++i)
|
||||||
for (size_t j = 0; j < Columns; ++j)
|
for (size_t j = 0; j < Columns; ++j)
|
||||||
transposed.At(j, i) = At(i, j);
|
transposed.At(j, i) = At(i, j);
|
||||||
@@ -240,9 +244,9 @@ namespace omath
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr Mat<Rows - 1, Columns - 1> Minor(const size_t row, const size_t column) const
|
constexpr Mat<Rows - 1, Columns - 1, Type, StoreType> Minor(const size_t row, const size_t column) const
|
||||||
{
|
{
|
||||||
Mat<Rows - 1, Columns - 1> result;
|
Mat<Rows - 1, Columns - 1, Type, StoreType> result;
|
||||||
for (size_t i = 0, m = 0; i < Rows; ++i)
|
for (size_t i = 0, m = 0; i < Rows; ++i)
|
||||||
{
|
{
|
||||||
if (i == row)
|
if (i == row)
|
||||||
@@ -260,15 +264,15 @@ namespace omath
|
|||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr const std::array<Type, Rows*Columns>& RawArray() const
|
constexpr const std::array<Type, Rows * Columns>& RawArray() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr std::array<Type, Rows*Columns>& RawArray()
|
constexpr std::array<Type, Rows * Columns>& RawArray()
|
||||||
{
|
{
|
||||||
return const_cast<std::array<Type, Rows*Columns>>(std::as_const(*this).RawArray());
|
return const_cast<std::array<Type, Rows * Columns>>(std::as_const(*this).RawArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
@@ -288,12 +292,23 @@ namespace omath
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator==(const Mat& mat) const
|
||||||
|
{
|
||||||
|
return m_data == mat.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool operator!=(const Mat& mat) const
|
||||||
|
{
|
||||||
|
return !operator==(mat);
|
||||||
|
}
|
||||||
|
|
||||||
// Static methods that return fixed-size matrices
|
// Static methods that return fixed-size matrices
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr static Mat<4, 4> ToScreenMat(const Type &screenWidth, const Type &screenHeight) noexcept
|
constexpr static Mat<4, 4> ToScreenMat(const Type& screenWidth, const Type& screenHeight) noexcept
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
|
return {
|
||||||
{screenWidth / 2, 0, 0, 0},
|
{screenWidth / 2, 0, 0, 0},
|
||||||
{0, -screenHeight / 2, 0, 0},
|
{0, -screenHeight / 2, 0, 0},
|
||||||
{0, 0, 1, 0},
|
{0, 0, 1, 0},
|
||||||
@@ -301,68 +316,95 @@ namespace omath
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
private:
|
||||||
constexpr static Mat<4, 4> TranslationMat(const Vector3 &diff) noexcept
|
std::array<Type, Rows * Columns> m_data;
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{1, 0, 0, 0},
|
|
||||||
{0, 1, 0, 0},
|
|
||||||
{0, 0, 1, 0},
|
|
||||||
{diff.x, diff.y, diff.z, 1},
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr static Mat<4, 4> OrientationMat(const Vector3 &forward, const Vector3 &right,
|
constexpr static Mat<1, 4, Type, St> MatRowFromVector(const Vector3& vector) noexcept
|
||||||
const Vector3 &up) noexcept
|
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{right.x, up.x, forward.x, 0},
|
|
||||||
{right.y, up.y, forward.y, 0},
|
|
||||||
{right.z, up.z, forward.z, 0},
|
|
||||||
{0, 0, 0, 1},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr static Mat<4, 4> ProjectionMat(const Type &fieldOfView, const Type &aspectRatio,
|
|
||||||
const Type &near, const Type &far, const Type &lensZoom) noexcept
|
|
||||||
{
|
|
||||||
const Type &fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2);
|
|
||||||
const Type &frustumHeight = far - near;
|
|
||||||
|
|
||||||
return
|
|
||||||
{
|
|
||||||
{-1 / (aspectRatio * fovHalfTan) * lensZoom, 0, 0, 0},
|
|
||||||
{0, -1 / fovHalfTan * lensZoom, 0, 0},
|
|
||||||
{0, 0, -far / frustumHeight, -1},
|
|
||||||
{0, 0, near * far / frustumHeight, 0}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr static Mat<4, 1> MatRowFromVector(const Vector3 &vector) noexcept
|
|
||||||
{
|
{
|
||||||
return {{vector.x, vector.y, vector.z, 1}};
|
return {{vector.x, vector.y, vector.z, 1}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr static Mat<1, 4> MatColumnFromVector(const Vector3 &vector) noexcept
|
constexpr static Mat<4, 1, Type, St> MatColumnFromVector(const Vector3& 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
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
{
|
{
|
||||||
{
|
{1, 0, 0, diff.x},
|
||||||
{vector.x},
|
{0, 1, 0, diff.y},
|
||||||
{vector.y},
|
{0, 0, 1, diff.z},
|
||||||
{vector.z},
|
{0, 0, 0, 1},
|
||||||
{1}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||||
std::array<Type, Rows * Columns> m_data;
|
[[nodiscard]]
|
||||||
|
Mat<4, 4, Type, St> MatRotationAxisX(const Angle& angle) noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
{1, 0, 0, 0},
|
||||||
|
{0, angle.Cos(), -angle.Sin(), 0},
|
||||||
|
{0, angle.Sin(), angle.Cos(), 0},
|
||||||
|
{0, 0, 0, 1}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat<4, 4, Type, St> MatRotationAxisY(const Angle& angle) noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
{angle.Cos(), 0, angle.Sin(), 0},
|
||||||
|
{0 , 1, 0, 0},
|
||||||
|
{-angle.Sin(), 0, angle.Cos(), 0},
|
||||||
|
{0 , 0, 0, 1}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat<4, 4, Type, St> MatRotationAxisZ(const Angle& angle) noexcept
|
||||||
|
{
|
||||||
|
return
|
||||||
|
{
|
||||||
|
{angle.Cos(), -angle.Sin(), 0, 0},
|
||||||
|
{angle.Sin(), angle.Cos(), 0, 0},
|
||||||
|
{ 0, 0, 1, 0},
|
||||||
|
{ 0, 0, 0, 1},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return Mat<4, 4, Type, St>
|
||||||
|
{
|
||||||
|
{right.x, right.y, right.z, 0},
|
||||||
|
{up.x, up.y, up.z, 0},
|
||||||
|
{forward.x, forward.y, forward.z, 0},
|
||||||
|
{0, 0, 0, 1},
|
||||||
|
|
||||||
|
} * MatTranslation<Type, St>(-cameraOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class ViewAngles>
|
||||||
|
[[nodiscard]]
|
||||||
|
Mat<4, 4, Type, St> MatRotation(const ViewAngles& angles) noexcept
|
||||||
|
{
|
||||||
|
return MatRotationAxisZ(angles.yaw) * MatRotationAxisY(angles.pitch) * MatRotationAxisX(angles.roll);
|
||||||
|
}
|
||||||
|
} // namespace omath
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <initializer_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <initializer_list>
|
|
||||||
|
|
||||||
namespace omath
|
namespace omath
|
||||||
{
|
{
|
||||||
@@ -27,11 +27,11 @@ namespace omath
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static Matrix ProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
|
static Matrix ProjectionMatrix(float fieldOfView, float aspectRatio, float near, float far);
|
||||||
|
|
||||||
Matrix(const Matrix &other);
|
Matrix(const Matrix& other);
|
||||||
|
|
||||||
Matrix(size_t rows, size_t columns, const float *pRaw);
|
Matrix(size_t rows, size_t columns, const float* pRaw);
|
||||||
|
|
||||||
Matrix(Matrix &&other) noexcept;
|
Matrix(Matrix&& other) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
size_t RowCount() const noexcept;
|
size_t RowCount() const noexcept;
|
||||||
@@ -43,7 +43,7 @@ namespace omath
|
|||||||
std::pair<size_t, size_t> Size() const noexcept;
|
std::pair<size_t, size_t> Size() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
float &At(size_t iRow, size_t iCol);
|
float& At(size_t iRow, size_t iCol);
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
float Sum();
|
float Sum();
|
||||||
@@ -56,17 +56,17 @@ namespace omath
|
|||||||
void Set(float val);
|
void Set(float val);
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
const float &At(size_t iRow, size_t iCol) const;
|
const float& At(size_t iRow, size_t iCol) const;
|
||||||
|
|
||||||
Matrix operator*(const Matrix &other) const;
|
Matrix operator*(const Matrix& other) const;
|
||||||
|
|
||||||
Matrix& operator*=(const Matrix &other);
|
Matrix& operator*=(const Matrix& other);
|
||||||
|
|
||||||
Matrix operator*(float f) const;
|
Matrix operator*(float f) const;
|
||||||
|
|
||||||
Matrix &operator*=(float f);
|
Matrix& operator*=(float f);
|
||||||
|
|
||||||
Matrix &operator/=(float f);
|
Matrix& operator/=(float f);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
@@ -85,9 +85,9 @@ namespace omath
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
const float* Raw() const;
|
const float* Raw() const;
|
||||||
|
|
||||||
Matrix &operator=(const Matrix &other);
|
Matrix& operator=(const Matrix& other);
|
||||||
|
|
||||||
Matrix &operator=(Matrix &&other) noexcept;
|
Matrix& operator=(Matrix&& other) noexcept;
|
||||||
|
|
||||||
Matrix operator/(float f) const;
|
Matrix operator/(float f) const;
|
||||||
|
|
||||||
@@ -101,4 +101,4 @@ namespace omath
|
|||||||
size_t m_columns;
|
size_t m_columns;
|
||||||
std::unique_ptr<float[]> m_data;
|
std::unique_ptr<float[]> m_data;
|
||||||
};
|
};
|
||||||
}
|
} // namespace omath
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace omath
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
||||||
|
|
||||||
Vector3 m_vertex1;
|
Vector3 m_vertex1;
|
||||||
Vector3 m_vertex2;
|
Vector3 m_vertex2;
|
||||||
Vector3 m_vertex3;
|
Vector3 m_vertex3;
|
||||||
|
|||||||
@@ -216,10 +216,6 @@ namespace omath
|
|||||||
|
|
||||||
[[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const;
|
[[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const;
|
||||||
|
|
||||||
[[nodiscard]] static Vector3 ForwardVector(float pitch, float yaw);
|
|
||||||
[[nodiscard]] static Vector3 RightVector(float pitch, float yaw, float roll);
|
|
||||||
[[nodiscard]] static Vector3 UpVector(float pitch, float yaw, float roll);
|
|
||||||
|
|
||||||
[[nodiscard]] std::tuple<float, float, float> AsTuple() const
|
[[nodiscard]] std::tuple<float, float, float> AsTuple() const
|
||||||
{
|
{
|
||||||
return std::make_tuple(x, y, z);
|
return std::make_tuple(x, y, z);
|
||||||
|
|||||||
15
include/omath/ViewAngles.hpp
Normal file
15
include/omath/ViewAngles.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace omath
|
||||||
|
{
|
||||||
|
template<class PitchType, class YawType, class RollType>
|
||||||
|
struct ViewAngles
|
||||||
|
{
|
||||||
|
PitchType pitch;
|
||||||
|
YawType yaw;
|
||||||
|
RollType roll;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ namespace omath::collision
|
|||||||
public:
|
public:
|
||||||
LineTracer() = delete;
|
LineTracer() = delete;
|
||||||
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static bool CanTraceLine(const Ray& ray, const Triangle3d& triangle);
|
static bool CanTraceLine(const Ray& ray, const Triangle3d& triangle);
|
||||||
|
|
||||||
|
|||||||
19
include/omath/engines/Source/Camera.hpp
Normal file
19
include/omath/engines/Source/Camera.hpp
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 12/4/2024.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include "Constants.h"
|
||||||
|
#include "omath/projection/Camera.hpp"
|
||||||
|
|
||||||
|
namespace omath::source
|
||||||
|
{
|
||||||
|
class Camera final : public projection::Camera<Mat4x4, ViewAngles>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort,
|
||||||
|
const Angle<float, 0, 180, AngleFlags::Clamped>& fov, float near, float far);
|
||||||
|
void LookAt(const Vector3& target) override;
|
||||||
|
[[nodiscard]] Mat4x4 GetViewMatrix() const override;
|
||||||
|
[[nodiscard]] Mat4x4 GetProjectionMatrix() const override;
|
||||||
|
};
|
||||||
|
}
|
||||||
24
include/omath/engines/Source/Constants.h
Normal file
24
include/omath/engines/Source/Constants.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 12/4/2024.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <omath/Vector3.hpp>
|
||||||
|
#include <omath/Mat.hpp>
|
||||||
|
#include <omath/Angle.hpp>
|
||||||
|
#include <omath/ViewAngles.hpp>
|
||||||
|
namespace omath::source
|
||||||
|
{
|
||||||
|
constexpr Vector3 kAbsUp = {0, 0, 1};
|
||||||
|
constexpr Vector3 kAbsRight = {0, -1, 0};
|
||||||
|
constexpr Vector3 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>;
|
||||||
|
} // namespace omath::source
|
||||||
57
include/omath/engines/Source/Formulas.hpp
Normal file
57
include/omath/engines/Source/Formulas.hpp
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 12/4/2024.
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
#include "Constants.h"
|
||||||
|
|
||||||
|
namespace omath::source
|
||||||
|
{
|
||||||
|
[[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(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
inline 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.
|
||||||
|
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::source
|
||||||
@@ -12,6 +12,12 @@
|
|||||||
|
|
||||||
namespace omath::pathfinding
|
namespace omath::pathfinding
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum Error
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class NavigationMesh final
|
class NavigationMesh final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace omath::prediction
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr Vector3 PredictPosition(float time, float gravity) const
|
constexpr Vector3 PredictPosition(const float time, const float gravity) const
|
||||||
{
|
{
|
||||||
auto predicted = m_origin + m_velocity * time;
|
auto predicted = m_origin + m_velocity * time;
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <expected>
|
#include <expected>
|
||||||
#include <omath/Vector3.hpp>
|
|
||||||
#include <omath/Mat.hpp>
|
#include <omath/Mat.hpp>
|
||||||
#include <string_view>
|
#include <omath/Vector3.hpp>
|
||||||
#include "ErrorCodes.hpp"
|
#include "ErrorCodes.hpp"
|
||||||
|
#include <omath/Angle.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
namespace omath::projection
|
namespace omath::projection
|
||||||
@@ -19,29 +20,70 @@ namespace omath::projection
|
|||||||
float m_width;
|
float m_width;
|
||||||
float m_height;
|
float m_height;
|
||||||
|
|
||||||
[[nodiscard]] constexpr float AspectRatio() const {return m_width / m_height;}
|
[[nodiscard]] constexpr float AspectRatio() const
|
||||||
|
{
|
||||||
|
return m_width / m_height;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
using FieldOfView = const Angle<float, 0.f, 180.f, AngleFlags::Clamped>;
|
||||||
|
|
||||||
|
template<class Mat4x4Type, class ViewAnglesType>
|
||||||
class Camera
|
class Camera
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort,
|
virtual ~Camera() = default;
|
||||||
float fov, float near, float far, float lensZoom);
|
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
|
||||||
void SetViewAngles(const Vector3& viewAngles);
|
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)
|
||||||
|
{
|
||||||
|
|
||||||
[[nodiscard]] Mat<4, 4> GetViewMatrix() const;
|
}
|
||||||
|
|
||||||
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Vector3& worldPosition) const;
|
virtual void LookAt(const Vector3& target) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual Mat4x4Type GetViewMatrix() const = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual Mat4x4Type GetProjectionMatrix() const = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] Mat4x4Type GetViewProjectionMatrix()
|
||||||
|
{
|
||||||
|
return GetProjectionMatrix() * GetViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::expected<Vector3, Error> WorldToScreen(const Mat4x4Type& viewProj, const Vector3& worldPosition) const
|
||||||
|
{
|
||||||
|
auto projected = viewProj * MatColumnFromVector<float, Mat4x4Type::GetStoreOrdering()>(worldPosition);
|
||||||
|
|
||||||
|
if (projected.At(3, 0) == 0.0f)
|
||||||
|
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||||
|
|
||||||
|
projected /= projected.At(3, 0);
|
||||||
|
|
||||||
|
if (IsNdcOutOfBounds(projected))
|
||||||
|
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
||||||
|
|
||||||
|
return Vector3{(projected.At(0,0)+1) / 2 * m_viewPort.m_width , (-projected.At(1,0)+1) / 2 * m_viewPort.m_height, projected.At(2,0)};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
ViewPort m_viewPort{};
|
ViewPort m_viewPort{};
|
||||||
float m_fieldOfView;
|
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
|
||||||
|
|
||||||
float m_farPlaneDistance;
|
float m_farPlaneDistance;
|
||||||
float m_nearPlaneDistance;
|
float m_nearPlaneDistance;
|
||||||
float m_lensZoom;
|
|
||||||
|
|
||||||
|
ViewAnglesType m_viewAngles;
|
||||||
|
Vector3 m_origin;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector3 m_viewAngles;
|
template<class Type>
|
||||||
Vector3 m_origin;
|
[[nodiscard]]
|
||||||
|
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
|
||||||
|
{
|
||||||
|
return std::ranges::any_of( ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace omath::projection
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ add_subdirectory(prediction)
|
|||||||
add_subdirectory(pathfinding)
|
add_subdirectory(pathfinding)
|
||||||
add_subdirectory(projection)
|
add_subdirectory(projection)
|
||||||
add_subdirectory(collision)
|
add_subdirectory(collision)
|
||||||
|
add_subdirectory(engines)
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
#include "omath/Matrix.hpp"
|
#include "omath/Matrix.hpp"
|
||||||
#include "omath/Vector3.hpp"
|
|
||||||
#include "omath/Angles.hpp"
|
#include "omath/Angles.hpp"
|
||||||
|
#include "omath/Vector3.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#include <complex>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <utility>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <complex>
|
|
||||||
|
|
||||||
|
|
||||||
namespace omath
|
namespace omath
|
||||||
@@ -31,23 +30,23 @@ namespace omath
|
|||||||
m_columns = rows.begin()->size();
|
m_columns = rows.begin()->size();
|
||||||
|
|
||||||
|
|
||||||
for (const auto& row : rows)
|
for (const auto& row: rows)
|
||||||
if (row.size() != m_columns)
|
if (row.size() != m_columns)
|
||||||
throw std::invalid_argument("All rows must have the same number of columns.");
|
throw std::invalid_argument("All rows must have the same number of columns.");
|
||||||
|
|
||||||
m_data = std::make_unique<float[]>(m_rows * m_columns);
|
m_data = std::make_unique<float[]>(m_rows * m_columns);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (const auto& row : rows)
|
for (const auto& row: rows)
|
||||||
{
|
{
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (const auto& value : row)
|
for (const auto& value: row)
|
||||||
At(i, j++) = value;
|
At(i, j++) = value;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix::Matrix(const Matrix &other)
|
Matrix::Matrix(const Matrix& other)
|
||||||
{
|
{
|
||||||
m_rows = other.m_rows;
|
m_rows = other.m_rows;
|
||||||
m_columns = other.m_columns;
|
m_columns = other.m_columns;
|
||||||
@@ -59,7 +58,7 @@ namespace omath
|
|||||||
At(i, j) = other.At(i, j);
|
At(i, j) = other.At(i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix::Matrix(const size_t rows, const size_t columns, const float *pRaw)
|
Matrix::Matrix(const size_t rows, const size_t columns, const float* pRaw)
|
||||||
{
|
{
|
||||||
m_rows = rows;
|
m_rows = rows;
|
||||||
m_columns = columns;
|
m_columns = columns;
|
||||||
@@ -67,9 +66,8 @@ namespace omath
|
|||||||
|
|
||||||
m_data = std::make_unique<float[]>(m_rows * m_columns);
|
m_data = std::make_unique<float[]>(m_rows * m_columns);
|
||||||
|
|
||||||
for (size_t i = 0; i < rows*columns; ++i)
|
for (size_t i = 0; i < rows * columns; ++i)
|
||||||
At(i / rows, i % columns) = pRaw[i];
|
At(i / rows, i % columns) = pRaw[i];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Matrix::RowCount() const noexcept
|
size_t Matrix::RowCount() const noexcept
|
||||||
@@ -77,7 +75,7 @@ namespace omath
|
|||||||
return m_rows;
|
return m_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix::Matrix(Matrix &&other) noexcept
|
Matrix::Matrix(Matrix&& other) noexcept
|
||||||
{
|
{
|
||||||
m_rows = other.m_rows;
|
m_rows = other.m_rows;
|
||||||
m_columns = other.m_columns;
|
m_columns = other.m_columns;
|
||||||
@@ -99,7 +97,7 @@ namespace omath
|
|||||||
return {RowCount(), ColumnsCount()};
|
return {RowCount(), ColumnsCount()};
|
||||||
}
|
}
|
||||||
|
|
||||||
float &Matrix::At(const size_t iRow, const size_t iCol)
|
float& Matrix::At(const size_t iRow, const size_t iCol)
|
||||||
{
|
{
|
||||||
return const_cast<float&>(std::as_const(*this).At(iRow, iCol));
|
return const_cast<float&>(std::as_const(*this).At(iRow, iCol));
|
||||||
}
|
}
|
||||||
@@ -115,12 +113,12 @@ namespace omath
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float &Matrix::At(const size_t iRow, const size_t iCol) const
|
const float& Matrix::At(const size_t iRow, const size_t iCol) const
|
||||||
{
|
{
|
||||||
return m_data[iRow * m_columns + iCol];
|
return m_data[iRow * m_columns + iCol];
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix Matrix::operator*(const Matrix &other) const
|
Matrix Matrix::operator*(const Matrix& other) const
|
||||||
{
|
{
|
||||||
if (m_columns != other.m_rows)
|
if (m_columns != other.m_rows)
|
||||||
throw std::runtime_error("n != m");
|
throw std::runtime_error("n != m");
|
||||||
@@ -136,7 +134,7 @@ namespace omath
|
|||||||
return outMat;
|
return outMat;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix & Matrix::operator*=(const Matrix &other)
|
Matrix& Matrix::operator*=(const Matrix& other)
|
||||||
{
|
{
|
||||||
*this = *this * other;
|
*this = *this * other;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -152,7 +150,7 @@ namespace omath
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix &Matrix::operator*=(const float f)
|
Matrix& Matrix::operator*=(const float f)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < RowCount(); i++)
|
for (size_t i = 0; i < RowCount(); i++)
|
||||||
for (size_t j = 0; j < ColumnsCount(); j++)
|
for (size_t j = 0; j < ColumnsCount(); j++)
|
||||||
@@ -165,7 +163,7 @@ namespace omath
|
|||||||
Set(0.f);
|
Set(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix &Matrix::operator=(const Matrix &other)
|
Matrix& Matrix::operator=(const Matrix& other)
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -175,10 +173,9 @@ namespace omath
|
|||||||
At(i, j) = other.At(i, j);
|
At(i, j) = other.At(i, j);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix &Matrix::operator=(Matrix &&other) noexcept
|
Matrix& Matrix::operator=(Matrix&& other) noexcept
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -191,10 +188,9 @@ namespace omath
|
|||||||
other.m_columns = 0;
|
other.m_columns = 0;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix &Matrix::operator/=(const float f)
|
Matrix& Matrix::operator/=(const float f)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_rows; ++i)
|
for (size_t i = 0; i < m_rows; ++i)
|
||||||
for (size_t j = 0; j < m_columns; ++j)
|
for (size_t j = 0; j < m_columns; ++j)
|
||||||
@@ -221,9 +217,9 @@ namespace omath
|
|||||||
{
|
{
|
||||||
for (size_t j = 0; j < m_columns; ++j)
|
for (size_t j = 0; j < m_columns; ++j)
|
||||||
{
|
{
|
||||||
str += std::format("{:.1f}",At(i, j));
|
str += std::format("{:.1f}", At(i, j));
|
||||||
|
|
||||||
if (j == m_columns-1)
|
if (j == m_columns - 1)
|
||||||
str += '\n';
|
str += '\n';
|
||||||
else
|
else
|
||||||
str += ' ';
|
str += ' ';
|
||||||
@@ -306,8 +302,7 @@ namespace omath
|
|||||||
|
|
||||||
Matrix Matrix::ToScreenMatrix(const float screenWidth, const float screenHeight)
|
Matrix Matrix::ToScreenMatrix(const float screenWidth, const float screenHeight)
|
||||||
{
|
{
|
||||||
return
|
return {
|
||||||
{
|
|
||||||
{screenWidth / 2.f, 0.f, 0.f, 0.f},
|
{screenWidth / 2.f, 0.f, 0.f, 0.f},
|
||||||
{0.f, -screenHeight / 2.f, 0.f, 0.f},
|
{0.f, -screenHeight / 2.f, 0.f, 0.f},
|
||||||
{0.f, 0.f, 1.f, 0.f},
|
{0.f, 0.f, 1.f, 0.f},
|
||||||
@@ -315,10 +310,9 @@ namespace omath
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix Matrix::TranslationMatrix(const Vector3 &diff)
|
Matrix Matrix::TranslationMatrix(const Vector3& diff)
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
|
return {
|
||||||
{1.f, 0.f, 0.f, 0.f},
|
{1.f, 0.f, 0.f, 0.f},
|
||||||
{0.f, 1.f, 0.f, 0.f},
|
{0.f, 1.f, 0.f, 0.f},
|
||||||
{0.f, 0.f, 1.f, 0.f},
|
{0.f, 0.f, 1.f, 0.f},
|
||||||
@@ -326,10 +320,9 @@ namespace omath
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix Matrix::OrientationMatrix(const Vector3 &forward, const Vector3 &right, const Vector3 &up)
|
Matrix Matrix::OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up)
|
||||||
{
|
|
||||||
return
|
|
||||||
{
|
{
|
||||||
|
return {
|
||||||
{right.x, up.x, forward.x, 0.f},
|
{right.x, up.x, forward.x, 0.f},
|
||||||
{right.y, up.y, forward.y, 0.f},
|
{right.y, up.y, forward.y, 0.f},
|
||||||
{right.z, up.z, forward.z, 0.f},
|
{right.z, up.z, forward.z, 0.f},
|
||||||
@@ -337,18 +330,14 @@ namespace omath
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix Matrix::ProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
|
Matrix Matrix::ProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far)
|
||||||
const float far)
|
|
||||||
{
|
{
|
||||||
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
|
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
|
||||||
|
|
||||||
return
|
return {{1.f / (aspectRatio * fovHalfTan), 0.f, 0.f, 0.f},
|
||||||
{
|
|
||||||
{1.f / (aspectRatio*fovHalfTan), 0.f, 0.f, 0.f},
|
|
||||||
{0.f, 1.f / fovHalfTan, 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, (far + near) / (far - near), 2.f * near * far / (far - near)},
|
||||||
{0.f, 0.f, -1.f, 0.f}
|
{0.f, 0.f, -1.f, 0.f}};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float* Matrix::Raw() const
|
const float* Matrix::Raw() const
|
||||||
@@ -356,9 +345,9 @@ namespace omath
|
|||||||
return m_data.get();
|
return m_data.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix::SetDataFromRaw(const float *pRawMatrix)
|
void Matrix::SetDataFromRaw(const float* pRawMatrix)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < m_columns*m_rows; ++i)
|
for (size_t i = 0; i < m_columns * m_rows; ++i)
|
||||||
At(i / m_rows, i % m_columns) = pRawMatrix[i];
|
At(i / m_rows, i % m_columns) = pRawMatrix[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,4 +357,4 @@ namespace omath
|
|||||||
m_rows = 0;
|
m_rows = 0;
|
||||||
m_data = nullptr;
|
m_data = nullptr;
|
||||||
}
|
}
|
||||||
}
|
} // namespace omath
|
||||||
|
|||||||
@@ -20,50 +20,4 @@ namespace omath
|
|||||||
0.f
|
0.f
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 Vector3::ForwardVector(const float pitch, const float yaw)
|
|
||||||
{
|
|
||||||
const auto cosPitch = std::cos(angles::DegreesToRadians(pitch));
|
|
||||||
const auto sinPitch = std::sin(angles::DegreesToRadians(pitch));
|
|
||||||
|
|
||||||
const auto cosYaw = std::cos(angles::DegreesToRadians(yaw));
|
|
||||||
const auto sinYaw = std::sin(angles::DegreesToRadians(yaw));
|
|
||||||
|
|
||||||
|
|
||||||
return
|
|
||||||
{
|
|
||||||
cosPitch*cosYaw,
|
|
||||||
cosPitch*sinYaw,
|
|
||||||
sinPitch
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::RightVector(const float pitch, const float yaw, const float roll)
|
|
||||||
{
|
|
||||||
const auto radPitch = angles::DegreesToRadians(pitch);
|
|
||||||
const auto radYaw = angles::DegreesToRadians(yaw);
|
|
||||||
const auto radRoll = angles::DegreesToRadians(roll);
|
|
||||||
|
|
||||||
const auto cosPitch = std::cos(radPitch);
|
|
||||||
const auto sinPitch = std::sin(radPitch);
|
|
||||||
|
|
||||||
const auto cosYaw = std::cos(radYaw);
|
|
||||||
const auto sinYaw = std::sin(radYaw);
|
|
||||||
|
|
||||||
const auto cosRoll = std::cos(radRoll);
|
|
||||||
const auto sinRoll = std::sin(radRoll);
|
|
||||||
|
|
||||||
|
|
||||||
return
|
|
||||||
{
|
|
||||||
sinRoll*sinPitch*cosYaw + cosRoll*sinYaw,
|
|
||||||
sinRoll*sinPitch*sinYaw - cosRoll*cosYaw,
|
|
||||||
-sinRoll*cosPitch
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Vector3::UpVector(float pitch, float yaw, float roll)
|
|
||||||
{
|
|
||||||
return RightVector(pitch, yaw, roll).Cross(ForwardVector(pitch, yaw));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
//
|
//
|
||||||
// Created by Orange on 11/13/2024.
|
// Created by Orange on 11/13/2024.
|
||||||
//
|
//
|
||||||
#pragma once
|
|
||||||
#include "omath/collision/LineTracer.hpp"
|
#include "omath/collision/LineTracer.hpp"
|
||||||
|
|
||||||
namespace omath::collision
|
namespace omath::collision
|
||||||
|
|||||||
1
source/engines/CMakeLists.txt
Normal file
1
source/engines/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
add_subdirectory(Source)
|
||||||
1
source/engines/Source/CMakeLists.txt
Normal file
1
source/engines/Source/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
target_sources(omath PRIVATE Camera.cpp)
|
||||||
36
source/engines/Source/Camera.cpp
Normal file
36
source/engines/Source/Camera.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 12/4/2024.
|
||||||
|
//
|
||||||
|
#include "omath/engines/Source/Camera.hpp"
|
||||||
|
#include "omath/engines/Source/Formulas.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace omath::source
|
||||||
|
{
|
||||||
|
|
||||||
|
Camera::Camera(const Vector3& 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)
|
||||||
|
{
|
||||||
|
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::GetViewMatrix() const
|
||||||
|
{
|
||||||
|
return CalcViewMatrix(m_viewAngles, m_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat4x4 Camera::GetProjectionMatrix() const
|
||||||
|
{
|
||||||
|
return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance);
|
||||||
|
}
|
||||||
|
} // namespace omath::source
|
||||||
@@ -58,7 +58,7 @@ namespace omath::prediction
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
root = std::sqrt(root);
|
root = std::sqrt(root);
|
||||||
const float angle = std::atan((std::pow(projectile.m_launchSpeed, 2.f) - root) / (bulletGravity * distance2d));
|
const float angle = std::atan((launchSpeedSqr - root) / (bulletGravity * distance2d));
|
||||||
|
|
||||||
return angles::RadiansToDegrees(angle);
|
return angles::RadiansToDegrees(angle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,18 @@
|
|||||||
|
|
||||||
#include "omath/prediction/Projectile.hpp"
|
#include "omath/prediction/Projectile.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <omath/engines/Source/Formulas.hpp>
|
||||||
|
|
||||||
namespace omath::prediction
|
namespace omath::prediction
|
||||||
{
|
{
|
||||||
Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
|
Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
|
||||||
{
|
{
|
||||||
auto currentPos = m_origin + Vector3::ForwardVector(pitch, yaw) * m_launchSpeed * time;
|
auto currentPos = m_origin + source::ForwardVector({source::PitchAngle::FromDegrees(-pitch),
|
||||||
currentPos.z -= (gravity * m_gravityScale) * std::pow(time, 2.f) * 0.5f;
|
source::YawAngle::FromDegrees(yaw),
|
||||||
|
source::RollAngle::FromDegrees(0)}) *
|
||||||
|
m_launchSpeed * time;
|
||||||
|
currentPos.z -= (gravity * m_gravityScale) * (time * time) * 0.5f;
|
||||||
|
|
||||||
return currentPos;
|
return currentPos;
|
||||||
}
|
}
|
||||||
}
|
} // namespace omath::prediction
|
||||||
|
|||||||
@@ -3,56 +3,7 @@
|
|||||||
//
|
//
|
||||||
#include "omath/projection/Camera.hpp"
|
#include "omath/projection/Camera.hpp"
|
||||||
|
|
||||||
#include <complex>
|
|
||||||
|
|
||||||
#include "omath/Angles.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace omath::projection
|
namespace omath::projection
|
||||||
{
|
{
|
||||||
Camera::Camera(const Vector3 &position, const Vector3 &viewAngles, const ViewPort &viewPort,
|
|
||||||
const float fov, const float near, const float far, const float lensZoom)
|
|
||||||
{
|
|
||||||
m_origin = position;
|
|
||||||
m_viewAngles = viewAngles;
|
|
||||||
m_viewPort = viewPort;
|
|
||||||
m_fieldOfView = fov;
|
|
||||||
m_nearPlaneDistance = near;
|
|
||||||
m_farPlaneDistance = far;
|
|
||||||
m_lensZoom = lensZoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat<4, 4> Camera::GetViewMatrix() const
|
|
||||||
{
|
|
||||||
const auto forward = Vector3::ForwardVector(m_viewAngles.x, m_viewAngles.y);
|
|
||||||
const auto right = Vector3::RightVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z);
|
|
||||||
const auto up = Vector3::UpVector(m_viewAngles.x, m_viewAngles.y, m_viewAngles.z);
|
|
||||||
|
|
||||||
return Mat<>::TranslationMat(-m_origin) * Mat<>::OrientationMat(forward, right, up);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::expected<Vector3, Error> Camera::WorldToScreen(const Vector3& worldPosition) const
|
|
||||||
{
|
|
||||||
const auto posVecAsMatrix = Mat<>::MatColumnFromVector(worldPosition);
|
|
||||||
|
|
||||||
|
|
||||||
const auto projectionMatrix = Mat<>::ProjectionMat(m_fieldOfView, m_viewPort.AspectRatio(),
|
|
||||||
m_nearPlaneDistance, m_farPlaneDistance, m_lensZoom);
|
|
||||||
|
|
||||||
Mat<1, 4> projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix);
|
|
||||||
|
|
||||||
if (projected.At(0, 3) == 0.f)
|
|
||||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
|
||||||
|
|
||||||
projected /= projected.At(0, 3);
|
|
||||||
|
|
||||||
if (projected.At(0, 0) < -1.f || projected.At(0, 0) > 1.f ||
|
|
||||||
projected.At(0, 1) < -1.f || projected.At(0, 1) > 1.f ||
|
|
||||||
projected.At(0, 2) < -1.f || projected.At(0, 2) > 1.f)
|
|
||||||
return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS);
|
|
||||||
|
|
||||||
projected *= Mat<4, 4>::ToScreenMat(m_viewPort.m_width, m_viewPort.m_height);
|
|
||||||
|
|
||||||
return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,24 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}"
|
|||||||
|
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
add_executable(unit-tests
|
add_executable(unit-tests
|
||||||
UnitTestPrediction.cpp
|
general/UnitTestPrediction.cpp
|
||||||
UnitTestMatrix.cpp
|
general/UnitTestMatrix.cpp
|
||||||
UnitTestMat.cpp
|
general/UnitTestMat.cpp
|
||||||
UnitTestAstar.cpp
|
general/UnitTestAstar.cpp
|
||||||
UnitTestProjection.cpp
|
general/UnitTestProjection.cpp
|
||||||
UnitTestVector3.cpp
|
general/UnitTestVector3.cpp
|
||||||
UnitTestVector2.cpp
|
general/UnitTestVector2.cpp
|
||||||
UnitTestColor.cpp
|
general/UnitTestColor.cpp
|
||||||
UnitTestVector4.cpp
|
general/UnitTestVector4.cpp
|
||||||
UnitTestLineTrace.cpp
|
general/UnitTestLineTrace.cpp
|
||||||
|
general/UnitTestAngles.cpp
|
||||||
|
general/UnitTestViewAngles.cpp
|
||||||
|
general/UnitTestAngle.cpp
|
||||||
|
|
||||||
|
engines/UnitTestOpenGL.cpp
|
||||||
|
engines/UnitTestUnityEngine.cpp
|
||||||
|
engines/UnitTestSourceEngine.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath)
|
target_link_libraries(unit-tests PRIVATE gtest gtest_main omath)
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by Vlad on 27.08.2024.
|
|
||||||
//
|
|
||||||
#include <complex>
|
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <omath/Matrix.hpp>
|
|
||||||
#include <print>
|
|
||||||
#include <omath/projection/Camera.hpp>
|
|
||||||
|
|
||||||
TEST(UnitTestProjection, Projection)
|
|
||||||
{
|
|
||||||
const omath::projection::Camera camera({0.f, 0.f, 0.f}, {0, 0.f, 0.f} , {1920.f, 1080.f}, 110.f, 0.375f, 5000.f, 1.335f);
|
|
||||||
|
|
||||||
const auto projected = camera.WorldToScreen({5000, 0, 0});
|
|
||||||
|
|
||||||
|
|
||||||
EXPECT_TRUE(projected.has_value());
|
|
||||||
EXPECT_EQ(projected->z, 1.f);
|
|
||||||
}
|
|
||||||
37
tests/engines/UnitTestOpenGL.cpp
Normal file
37
tests/engines/UnitTestOpenGL.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/23/2024.
|
||||||
|
//
|
||||||
|
#include <complex>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <omath/Matrix.hpp>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
// #include <glm/glm.hpp>
|
||||||
|
|
||||||
|
// #include "glm/ext/matrix_clip_space.hpp"
|
||||||
|
// #include "glm/ext/matrix_transform.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
TEST(UnitTestOpenGL, Projection)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*const auto proj_glm = glm::perspective(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||||
|
// const auto proj_glm2 = glm::perspectiveLH_NO(glm::radians(90.f), 16.f / 9.f, 0.1f, 1000.f);
|
||||||
|
// const auto proj_omath = omath::Mat<4, 4, float, omath::MatStoreType::COLUMN_MAJOR>((const float*)&proj_glm);
|
||||||
|
// EXPECT_EQ(omath::opengl::PerspectiveProjectionMatrix(90, 16.f / 9.f, 0.1f, 1000.f), proj_omath);
|
||||||
|
|
||||||
|
|
||||||
|
glm::vec4 ndc_glm2 = proj_glm * glm::vec4(300.f, 0.f, -1000.f, 1.f);
|
||||||
|
ndc_glm2 /= ndc_glm2.w;
|
||||||
|
const omath::Mat<4, 1, float, omath::MatStoreType::COLUMN_MAJOR> cords_omath =
|
||||||
|
{
|
||||||
|
{0},
|
||||||
|
{0},
|
||||||
|
{-0.2f},
|
||||||
|
{1}
|
||||||
|
};
|
||||||
|
|
||||||
|
//auto ndc_omath = proj_omath * cords_omath;
|
||||||
|
// ndc_omath /= ndc_omath.At(3, 0);
|
||||||
|
*/
|
||||||
|
}
|
||||||
50
tests/engines/UnitTestSourceEngine.cpp
Normal file
50
tests/engines/UnitTestSourceEngine.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/23/2024.
|
||||||
|
//
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <omath/engines/Source/Camera.hpp>
|
||||||
|
#include <omath/engines/Source/Constants.h>
|
||||||
|
#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, PerpectiveProjectionAtCenter)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
const auto viewProjMatrix = cam.GetViewProjectionMatrix();
|
||||||
|
|
||||||
|
for (float distance = 0.02f; distance < 1000.f; distance += 0.01f)
|
||||||
|
{
|
||||||
|
const auto projected = cam.WorldToScreen(viewProjMatrix, {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);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
tests/engines/UnitTestUnityEngine.cpp
Normal file
3
tests/engines/UnitTestUnityEngine.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/27/2024.
|
||||||
|
//
|
||||||
3
tests/general/UnitTestAngle.cpp
Normal file
3
tests/general/UnitTestAngle.cpp
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
50
tests/general/UnitTestAngles.cpp
Normal file
50
tests/general/UnitTestAngles.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <omath/Angles.hpp>
|
||||||
|
#include <omath/Angle.hpp>
|
||||||
|
|
||||||
|
TEST(UnitTestAngles, RadiansToDeg)
|
||||||
|
{
|
||||||
|
constexpr float rad = 67;
|
||||||
|
|
||||||
|
EXPECT_NEAR(omath::angles::RadiansToDegrees(rad), 3838.82f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UnitTestAngles, DegreesToRadians)
|
||||||
|
{
|
||||||
|
constexpr float degree = 90;
|
||||||
|
|
||||||
|
EXPECT_NEAR(omath::angles::DegreesToRadians(degree), 1.5708f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UnitTestAngles, HorizontalFovToVerical)
|
||||||
|
{
|
||||||
|
constexpr float hFov = 90;
|
||||||
|
constexpr float aspectRation = 16.0f / 9.0f;
|
||||||
|
const auto verticalFov = omath::angles::HorizontalFovToVertical(hFov, aspectRation);
|
||||||
|
|
||||||
|
EXPECT_NEAR(verticalFov, 58.71f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(UnitTestAngles, VerticalToHorizontal)
|
||||||
|
{
|
||||||
|
constexpr float vFov = 58.71;
|
||||||
|
constexpr float aspectRation = 16.0f / 9.0f;
|
||||||
|
const auto horizontalFov = omath::angles::VerticalFovToHorizontal(vFov, aspectRation);
|
||||||
|
|
||||||
|
EXPECT_NEAR(horizontalFov, 89.99f, 0.01f);
|
||||||
|
}
|
||||||
|
TEST(UnitTestAngles, WrapAngle)
|
||||||
|
{
|
||||||
|
const float wrapped = omath::angles::WrapAngle(361.f, 0.f, 360.f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(wrapped, 1.f, 0.01f);
|
||||||
|
}
|
||||||
|
TEST(UnitTestAngles, WrapAngleNegativeRange)
|
||||||
|
{
|
||||||
|
const float wrapped = omath::angles::WrapAngle(-90.f, 0.f, 360.f);
|
||||||
|
|
||||||
|
EXPECT_NEAR(wrapped, 270.f, 0.01f);
|
||||||
|
}
|
||||||
@@ -154,35 +154,6 @@ TEST_F(UnitTestMat, StaticMethod_ToScreenMat)
|
|||||||
EXPECT_FLOAT_EQ(screenMat.At(3, 3), 1.0f);
|
EXPECT_FLOAT_EQ(screenMat.At(3, 3), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test static method: TranslationMat
|
|
||||||
TEST_F(UnitTestMat, StaticMethod_TranslationMat)
|
|
||||||
{
|
|
||||||
Vector3 diff{10.0f, 20.0f, 30.0f};
|
|
||||||
Mat<4, 4> transMat = Mat<4, 4>::TranslationMat(diff);
|
|
||||||
EXPECT_FLOAT_EQ(transMat.At(0, 0), 1.0f);
|
|
||||||
EXPECT_FLOAT_EQ(transMat.At(3, 0), diff.x);
|
|
||||||
EXPECT_FLOAT_EQ(transMat.At(3, 1), diff.y);
|
|
||||||
EXPECT_FLOAT_EQ(transMat.At(3, 2), diff.z);
|
|
||||||
EXPECT_FLOAT_EQ(transMat.At(3, 3), 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test static method: OrientationMat
|
|
||||||
TEST_F(UnitTestMat, StaticMethod_OrientationMat)
|
|
||||||
{
|
|
||||||
constexpr Vector3 forward{0.0f, 0.0f, 1.0f};
|
|
||||||
constexpr Vector3 right{1.0f, 0.0f, 0.0f};
|
|
||||||
constexpr Vector3 up{0.0f, 1.0f, 0.0f};
|
|
||||||
constexpr Mat<4, 4> orientMat = Mat<4, 4>::OrientationMat(forward, right, up);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(0, 0), right.x);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(0, 1), up.x);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(0, 2), forward.x);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(1, 0), right.y);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(1, 1), up.y);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(1, 2), forward.y);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(2, 0), right.z);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(2, 1), up.z);
|
|
||||||
EXPECT_FLOAT_EQ(orientMat.At(2, 2), forward.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test exception handling in At() method
|
// Test exception handling in At() method
|
||||||
TEST_F(UnitTestMat, Method_At_OutOfRange)
|
TEST_F(UnitTestMat, Method_At_OutOfRange)
|
||||||
@@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
TEST(UnitTestPrediction, PredictionTest)
|
TEST(UnitTestPrediction, PredictionTest)
|
||||||
{
|
{
|
||||||
const omath::prediction::Target target{.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
|
constexpr omath::prediction::Target target{
|
||||||
const omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4};
|
.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 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();
|
const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple();
|
||||||
18
tests/general/UnitTestProjection.cpp
Normal file
18
tests/general/UnitTestProjection.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// Created by Vlad on 27.08.2024.
|
||||||
|
//
|
||||||
|
#include <complex>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <omath/Matrix.hpp>
|
||||||
|
#include <omath/engines/Source/Camera.hpp>
|
||||||
|
#include <omath/projection/Camera.hpp>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
TEST(UnitTestProjection, Projection)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
const auto projected = cam.WorldToScreen(cam.GetViewProjectionMatrix(), {1000, 0, 50});
|
||||||
|
std::print("{} {} {}", projected->x, projected->y, projected->z);
|
||||||
|
}
|
||||||
4
tests/general/UnitTestViewAngles.cpp
Normal file
4
tests/general/UnitTestViewAngles.cpp
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
//
|
||||||
|
// Created by Orange on 11/30/2024.
|
||||||
|
//
|
||||||
|
#include <omath/ViewAngles.hpp>
|
||||||
Reference in New Issue
Block a user