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'
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "extlibs/googletest"]
|
||||
path = extlibs/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
url = https://github.com/google/googletest.git
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,6 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/extlibs/glm" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/extlibs/googletest" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -6,6 +6,9 @@ project(omath VERSION 1.0.0)
|
||||
|
||||
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_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)
|
||||
@@ -23,10 +26,10 @@ if(OMATH_BUILD_TESTS)
|
||||
add_subdirectory(tests)
|
||||
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)
|
||||
elseif(UNIX AND OMATH_THREAT_WARNING_AS_ERROR)
|
||||
target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic)
|
||||
elseif(OMATH_THREAT_WARNING_AS_ERROR)
|
||||
target_compile_options(omath PRIVATE -Wall -Wextra -Wpedantic -Werror)
|
||||
endif()
|
||||
|
||||
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,
|
||||
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
|
||||
development, I strive to keep the entire experience civil.
|
||||
|
||||
## Standards
|
||||
## 📜 Standards
|
||||
|
||||
Our community standards exist in order to make sure everyone feels comfortable
|
||||
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.
|
||||
- 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.
|
||||
|
||||
I, as the core developer, will strive my best to keep this community civil and
|
||||
following the standards outlined above.
|
||||
|
||||
### Reporting incidents
|
||||
### 🚩 Reporting incidents
|
||||
|
||||
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
|
||||
@@ -47,10 +47,11 @@ with such incidents in multiple ways:
|
||||
- `@orange_cpp`
|
||||
|
||||
***Telegram***
|
||||
- `@orange-cpp`
|
||||
- `@orange_cpp`
|
||||
|
||||
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.
|
||||
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,
|
||||
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
|
||||
edit your message.
|
||||
|
||||
### Warning/Deletion
|
||||
### ⚠️ Warning/Deletion
|
||||
|
||||
If your message is found inappropriate, a member might give you a public or private warning,
|
||||
and/or delete your message.
|
||||
|
||||
### Mute
|
||||
### 🔇 Mute
|
||||
|
||||
If your message is disruptive, or you have been repeatedly violating the standards,
|
||||
a member might mute (or temporarily ban) you.
|
||||
|
||||
### Ban
|
||||
### ⛔ Ban
|
||||
|
||||
If your message is hateful, very disruptive, or other, less serious infractions are repeated
|
||||
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
|
||||
outside of GitHub.
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
## 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
|
||||
#include <numbers>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
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 <array>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include "Vector3.hpp"
|
||||
#include <stdexcept>
|
||||
#include "Angles.hpp"
|
||||
|
||||
|
||||
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>
|
||||
requires (std::is_floating_point_v<Type> || std::is_integral_v<Type>)
|
||||
requires std::is_arithmetic_v<Type>
|
||||
class Mat final
|
||||
{
|
||||
public:
|
||||
@@ -33,7 +32,10 @@ namespace omath
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
constexpr static MatStoreType GetStoreOrdering()
|
||||
{
|
||||
return StoreType;
|
||||
}
|
||||
constexpr Mat(const std::initializer_list<std::initializer_list<Type>>& rows)
|
||||
{
|
||||
if (rows.size() != Rows)
|
||||
@@ -44,7 +46,7 @@ namespace omath
|
||||
{
|
||||
if (rowIt->size() != Columns)
|
||||
throw std::invalid_argument(
|
||||
"All rows must have the same number of columns as template parameter Columns");
|
||||
"All rows must have the same number of columns as template parameter Columns");
|
||||
|
||||
auto colIt = rowIt->begin();
|
||||
for (size_t j = 0; j < Columns; ++j, ++colIt)
|
||||
@@ -59,24 +61,24 @@ namespace omath
|
||||
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;
|
||||
}
|
||||
|
||||
constexpr Mat(Mat &&other) noexcept
|
||||
constexpr Mat(Mat&& other) noexcept
|
||||
{
|
||||
m_data = std::move(other.m_data);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static consteval size_t RowCount() noexcept
|
||||
static constexpr size_t RowCount() noexcept
|
||||
{
|
||||
return Rows;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static consteval size_t ColumnsCount() noexcept
|
||||
static constexpr size_t ColumnsCount() noexcept
|
||||
{
|
||||
return Columns;
|
||||
}
|
||||
@@ -87,7 +89,7 @@ namespace omath
|
||||
return {Rows, Columns};
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr const Type &At(const size_t rowIndex, const size_t columnIndex) const
|
||||
[[nodiscard]] constexpr const Type& At(const size_t rowIndex, const size_t columnIndex) const
|
||||
{
|
||||
if (rowIndex >= Rows || columnIndex >= Columns)
|
||||
throw std::out_of_range("Index out of range");
|
||||
@@ -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]]
|
||||
@@ -126,16 +128,17 @@ namespace omath
|
||||
Set(0);
|
||||
}
|
||||
|
||||
constexpr void Set(const Type &value) noexcept
|
||||
constexpr void Set(const Type& value) noexcept
|
||||
{
|
||||
std::ranges::fill(m_data, value);
|
||||
}
|
||||
|
||||
// Operator overloading for multiplication with another Mat
|
||||
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 j = 0; j < OtherColumns; ++j)
|
||||
@@ -148,7 +151,7 @@ namespace omath
|
||||
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 j = 0; j < Columns; ++j)
|
||||
@@ -157,19 +160,20 @@ namespace omath
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
constexpr Mat operator*(const Type &f) const noexcept
|
||||
constexpr Mat operator*(const Type& f) const noexcept
|
||||
{
|
||||
Mat result(*this);
|
||||
result *= f;
|
||||
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 j = 0; j < Columns; ++j)
|
||||
@@ -177,14 +181,14 @@ namespace omath
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Mat operator/(const Type &f) const noexcept
|
||||
constexpr Mat operator/(const Type& f) const noexcept
|
||||
{
|
||||
Mat result(*this);
|
||||
result /= f;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr Mat &operator=(const Mat &other) noexcept
|
||||
constexpr Mat& operator=(const Mat& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
@@ -194,7 +198,7 @@ namespace omath
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Mat &operator=(Mat &&other) noexcept
|
||||
constexpr Mat& operator=(Mat&& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
@@ -207,9 +211,9 @@ namespace omath
|
||||
}
|
||||
|
||||
[[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 j = 0; j < Columns; ++j)
|
||||
transposed.At(j, i) = At(i, j);
|
||||
@@ -240,9 +244,9 @@ namespace omath
|
||||
}
|
||||
|
||||
[[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)
|
||||
{
|
||||
if (i == row)
|
||||
@@ -260,15 +264,15 @@ namespace omath
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const std::array<Type, Rows*Columns>& RawArray() const
|
||||
constexpr const std::array<Type, Rows * Columns>& RawArray() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
[[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]]
|
||||
@@ -288,81 +292,119 @@ namespace omath
|
||||
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
|
||||
[[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
|
||||
{
|
||||
{screenWidth / 2, 0, 0, 0},
|
||||
{0, -screenHeight / 2, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{screenWidth / 2, screenHeight / 2, 0, 1},
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 4> TranslationMat(const Vector3 &diff) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{diff.x, diff.y, diff.z, 1},
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 4> OrientationMat(const Vector3 &forward, const Vector3 &right,
|
||||
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}};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<1, 4> MatColumnFromVector(const Vector3 &vector) noexcept
|
||||
{
|
||||
return
|
||||
{
|
||||
{
|
||||
{vector.x},
|
||||
{vector.y},
|
||||
{vector.z},
|
||||
{1}
|
||||
}
|
||||
return {
|
||||
{screenWidth / 2, 0, 0, 0},
|
||||
{0, -screenHeight / 2, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{screenWidth / 2, screenHeight / 2, 0, 1},
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<Type, Rows * Columns> m_data;
|
||||
};
|
||||
}
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<1, 4, Type, St> MatRowFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
return {{vector.x, vector.y, vector.z, 1}};
|
||||
}
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR>
|
||||
[[nodiscard]]
|
||||
constexpr static Mat<4, 1, Type, St> MatColumnFromVector(const Vector3& vector) noexcept
|
||||
{
|
||||
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
|
||||
{
|
||||
{1, 0, 0, diff.x},
|
||||
{0, 1, 0, diff.y},
|
||||
{0, 0, 1, diff.z},
|
||||
{0, 0, 0, 1},
|
||||
};
|
||||
}
|
||||
|
||||
template<class Type = float, MatStoreType St = MatStoreType::ROW_MAJOR, class Angle>
|
||||
[[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
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <initializer_list>
|
||||
|
||||
namespace omath
|
||||
{
|
||||
@@ -27,11 +27,11 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
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]]
|
||||
size_t RowCount() const noexcept;
|
||||
@@ -43,7 +43,7 @@ namespace omath
|
||||
std::pair<size_t, size_t> Size() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
float &At(size_t iRow, size_t iCol);
|
||||
float& At(size_t iRow, size_t iCol);
|
||||
|
||||
[[nodiscard]]
|
||||
float Sum();
|
||||
@@ -56,17 +56,17 @@ namespace omath
|
||||
void Set(float val);
|
||||
|
||||
[[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);
|
||||
Matrix& operator*=(float f);
|
||||
|
||||
Matrix &operator/=(float f);
|
||||
Matrix& operator/=(float f);
|
||||
|
||||
void Clear();
|
||||
|
||||
@@ -85,9 +85,9 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
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;
|
||||
|
||||
@@ -101,4 +101,4 @@ namespace omath
|
||||
size_t m_columns;
|
||||
std::unique_ptr<float[]> m_data;
|
||||
};
|
||||
}
|
||||
} // namespace omath
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace omath
|
||||
{
|
||||
public:
|
||||
Triangle3d(const Vector3& vertex1, const Vector3& vertex2, const Vector3& vertex3);
|
||||
|
||||
Vector3 m_vertex1;
|
||||
Vector3 m_vertex2;
|
||||
Vector3 m_vertex3;
|
||||
@@ -29,4 +30,4 @@ namespace omath
|
||||
[[nodiscard]]
|
||||
Vector3 SideBVector() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,10 +216,6 @@ namespace omath
|
||||
|
||||
[[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
|
||||
{
|
||||
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:
|
||||
LineTracer() = delete;
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
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
|
||||
{
|
||||
|
||||
enum Error
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class NavigationMesh final
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace omath::prediction
|
||||
public:
|
||||
|
||||
[[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;
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <expected>
|
||||
#include <omath/Vector3.hpp>
|
||||
#include <omath/Mat.hpp>
|
||||
#include <string_view>
|
||||
#include <omath/Vector3.hpp>
|
||||
#include "ErrorCodes.hpp"
|
||||
#include <omath/Angle.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace omath::projection
|
||||
@@ -19,29 +20,70 @@ namespace omath::projection
|
||||
float m_width;
|
||||
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
|
||||
{
|
||||
|
||||
public:
|
||||
Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort,
|
||||
float fov, float near, float far, float lensZoom);
|
||||
void SetViewAngles(const Vector3& viewAngles);
|
||||
virtual ~Camera() = default;
|
||||
Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort,
|
||||
const FieldOfView& fov, const float near, const float far) :
|
||||
m_viewPort(viewPort), m_fieldOfView(fov), m_farPlaneDistance(far), m_nearPlaneDistance(near),
|
||||
m_viewAngles(viewAngles), m_origin(position)
|
||||
{
|
||||
|
||||
[[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{};
|
||||
float m_fieldOfView;
|
||||
Angle<float, 0.f, 180.f, AngleFlags::Clamped> m_fieldOfView;
|
||||
|
||||
float m_farPlaneDistance;
|
||||
float m_nearPlaneDistance;
|
||||
float m_lensZoom;
|
||||
|
||||
|
||||
ViewAnglesType m_viewAngles;
|
||||
Vector3 m_origin;
|
||||
|
||||
private:
|
||||
Vector3 m_viewAngles;
|
||||
Vector3 m_origin;
|
||||
template<class Type>
|
||||
[[nodiscard]]
|
||||
constexpr static bool IsNdcOutOfBounds(const Type& ndc)
|
||||
{
|
||||
return std::ranges::any_of( ndc.RawArray(), [](const auto& val) { return val < -1 || val > 1; });
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace omath::projection
|
||||
|
||||
@@ -10,4 +10,5 @@ target_sources(omath PRIVATE
|
||||
add_subdirectory(prediction)
|
||||
add_subdirectory(pathfinding)
|
||||
add_subdirectory(projection)
|
||||
add_subdirectory(collision)
|
||||
add_subdirectory(collision)
|
||||
add_subdirectory(engines)
|
||||
@@ -1,13 +1,12 @@
|
||||
#include "omath/Matrix.hpp"
|
||||
#include "omath/Vector3.hpp"
|
||||
#include "omath/Angles.hpp"
|
||||
#include "omath/Vector3.hpp"
|
||||
|
||||
|
||||
#include <complex>
|
||||
#include <format>
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <complex>
|
||||
|
||||
|
||||
namespace omath
|
||||
@@ -31,23 +30,23 @@ namespace omath
|
||||
m_columns = rows.begin()->size();
|
||||
|
||||
|
||||
for (const auto& row : rows)
|
||||
for (const auto& row: rows)
|
||||
if (row.size() != m_columns)
|
||||
throw std::invalid_argument("All rows must have the same number of columns.");
|
||||
|
||||
m_data = std::make_unique<float[]>(m_rows * m_columns);
|
||||
|
||||
size_t i = 0;
|
||||
for (const auto& row : rows)
|
||||
for (const auto& row: rows)
|
||||
{
|
||||
size_t j = 0;
|
||||
for (const auto& value : row)
|
||||
for (const auto& value: row)
|
||||
At(i, j++) = value;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Matrix &other)
|
||||
Matrix::Matrix(const Matrix& other)
|
||||
{
|
||||
m_rows = other.m_rows;
|
||||
m_columns = other.m_columns;
|
||||
@@ -59,7 +58,7 @@ namespace omath
|
||||
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_columns = columns;
|
||||
@@ -67,9 +66,8 @@ namespace omath
|
||||
|
||||
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];
|
||||
|
||||
}
|
||||
|
||||
size_t Matrix::RowCount() const noexcept
|
||||
@@ -77,7 +75,7 @@ namespace omath
|
||||
return m_rows;
|
||||
}
|
||||
|
||||
Matrix::Matrix(Matrix &&other) noexcept
|
||||
Matrix::Matrix(Matrix&& other) noexcept
|
||||
{
|
||||
m_rows = other.m_rows;
|
||||
m_columns = other.m_columns;
|
||||
@@ -99,7 +97,7 @@ namespace omath
|
||||
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));
|
||||
}
|
||||
@@ -115,12 +113,12 @@ namespace omath
|
||||
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];
|
||||
}
|
||||
|
||||
Matrix Matrix::operator*(const Matrix &other) const
|
||||
Matrix Matrix::operator*(const Matrix& other) const
|
||||
{
|
||||
if (m_columns != other.m_rows)
|
||||
throw std::runtime_error("n != m");
|
||||
@@ -136,7 +134,7 @@ namespace omath
|
||||
return outMat;
|
||||
}
|
||||
|
||||
Matrix & Matrix::operator*=(const Matrix &other)
|
||||
Matrix& Matrix::operator*=(const Matrix& other)
|
||||
{
|
||||
*this = *this * other;
|
||||
return *this;
|
||||
@@ -152,7 +150,7 @@ namespace omath
|
||||
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 j = 0; j < ColumnsCount(); j++)
|
||||
@@ -164,8 +162,8 @@ namespace omath
|
||||
{
|
||||
Set(0.f);
|
||||
}
|
||||
|
||||
Matrix &Matrix::operator=(const Matrix &other)
|
||||
|
||||
Matrix& Matrix::operator=(const Matrix& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
@@ -175,10 +173,9 @@ namespace omath
|
||||
At(i, j) = other.At(i, j);
|
||||
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
Matrix &Matrix::operator=(Matrix &&other) noexcept
|
||||
Matrix& Matrix::operator=(Matrix&& other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
@@ -191,10 +188,9 @@ namespace omath
|
||||
other.m_columns = 0;
|
||||
|
||||
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 j = 0; j < m_columns; ++j)
|
||||
@@ -221,9 +217,9 @@ namespace omath
|
||||
{
|
||||
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';
|
||||
else
|
||||
str += ' ';
|
||||
@@ -306,49 +302,42 @@ namespace omath
|
||||
|
||||
Matrix Matrix::ToScreenMatrix(const float screenWidth, const float screenHeight)
|
||||
{
|
||||
return
|
||||
{
|
||||
{screenWidth / 2.f, 0.f, 0.f, 0.f},
|
||||
{0.f, -screenHeight / 2.f, 0.f, 0.f},
|
||||
{0.f, 0.f, 1.f, 0.f},
|
||||
{screenWidth / 2.f, screenHeight / 2.f, 0.f, 1.f},
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::TranslationMatrix(const Vector3 &diff)
|
||||
{
|
||||
return
|
||||
{
|
||||
{1.f, 0.f, 0.f, 0.f},
|
||||
{0.f, 1.f, 0.f, 0.f},
|
||||
{0.f, 0.f, 1.f, 0.f},
|
||||
{diff.x, diff.y, diff.z, 1.f},
|
||||
return {
|
||||
{screenWidth / 2.f, 0.f, 0.f, 0.f},
|
||||
{0.f, -screenHeight / 2.f, 0.f, 0.f},
|
||||
{0.f, 0.f, 1.f, 0.f},
|
||||
{screenWidth / 2.f, screenHeight / 2.f, 0.f, 1.f},
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::OrientationMatrix(const Vector3 &forward, const Vector3 &right, const Vector3 &up)
|
||||
Matrix Matrix::TranslationMatrix(const Vector3& diff)
|
||||
{
|
||||
return
|
||||
{
|
||||
{right.x, up.x, forward.x, 0.f},
|
||||
{right.y, up.y, forward.y, 0.f},
|
||||
{right.z, up.z, forward.z, 0.f},
|
||||
{0.f, 0.f, 0.f, 1.f},
|
||||
return {
|
||||
{1.f, 0.f, 0.f, 0.f},
|
||||
{0.f, 1.f, 0.f, 0.f},
|
||||
{0.f, 0.f, 1.f, 0.f},
|
||||
{diff.x, diff.y, diff.z, 1.f},
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::ProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near,
|
||||
const float far)
|
||||
Matrix Matrix::OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up)
|
||||
{
|
||||
return {
|
||||
{right.x, up.x, forward.x, 0.f},
|
||||
{right.y, up.y, forward.y, 0.f},
|
||||
{right.z, up.z, forward.z, 0.f},
|
||||
{0.f, 0.f, 0.f, 1.f},
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::ProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far)
|
||||
{
|
||||
const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f);
|
||||
|
||||
return
|
||||
{
|
||||
{1.f / (aspectRatio*fovHalfTan), 0.f, 0.f, 0.f},
|
||||
{0.f, 1.f / fovHalfTan, 0.f, 0.f},
|
||||
{0.f, 0.f, (far + near) / (far - near), 2.f * near * far / (far - near)},
|
||||
{0.f, 0.f, -1.f, 0.f}
|
||||
};
|
||||
return {{1.f / (aspectRatio * fovHalfTan), 0.f, 0.f, 0.f},
|
||||
{0.f, 1.f / fovHalfTan, 0.f, 0.f},
|
||||
{0.f, 0.f, (far + near) / (far - near), 2.f * near * far / (far - near)},
|
||||
{0.f, 0.f, -1.f, 0.f}};
|
||||
}
|
||||
|
||||
const float* Matrix::Raw() const
|
||||
@@ -356,9 +345,9 @@ namespace omath
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -368,4 +357,4 @@ namespace omath
|
||||
m_rows = 0;
|
||||
m_data = nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace omath
|
||||
|
||||
@@ -20,50 +20,4 @@ namespace omath
|
||||
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.
|
||||
//
|
||||
#pragma once
|
||||
#include "omath/collision/LineTracer.hpp"
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -4,15 +4,18 @@
|
||||
|
||||
#include "omath/prediction/Projectile.hpp"
|
||||
#include <cmath>
|
||||
|
||||
#include <omath/engines/Source/Formulas.hpp>
|
||||
|
||||
namespace omath::prediction
|
||||
{
|
||||
Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const
|
||||
{
|
||||
auto currentPos = m_origin + Vector3::ForwardVector(pitch, yaw) * m_launchSpeed * time;
|
||||
currentPos.z -= (gravity * m_gravityScale) * std::pow(time, 2.f) * 0.5f;
|
||||
auto currentPos = m_origin + source::ForwardVector({source::PitchAngle::FromDegrees(-pitch),
|
||||
source::YawAngle::FromDegrees(yaw),
|
||||
source::RollAngle::FromDegrees(0)}) *
|
||||
m_launchSpeed * time;
|
||||
currentPos.z -= (gravity * m_gravityScale) * (time * time) * 0.5f;
|
||||
|
||||
return currentPos;
|
||||
}
|
||||
}
|
||||
} // namespace omath::prediction
|
||||
|
||||
@@ -3,56 +3,7 @@
|
||||
//
|
||||
#include "omath/projection/Camera.hpp"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "omath/Angles.hpp"
|
||||
|
||||
|
||||
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)
|
||||
add_executable(unit-tests
|
||||
UnitTestPrediction.cpp
|
||||
UnitTestMatrix.cpp
|
||||
UnitTestMat.cpp
|
||||
UnitTestAstar.cpp
|
||||
UnitTestProjection.cpp
|
||||
UnitTestVector3.cpp
|
||||
UnitTestVector2.cpp
|
||||
UnitTestColor.cpp
|
||||
UnitTestVector4.cpp
|
||||
UnitTestLineTrace.cpp
|
||||
general/UnitTestPrediction.cpp
|
||||
general/UnitTestMatrix.cpp
|
||||
general/UnitTestMat.cpp
|
||||
general/UnitTestAstar.cpp
|
||||
general/UnitTestProjection.cpp
|
||||
general/UnitTestVector3.cpp
|
||||
general/UnitTestVector2.cpp
|
||||
general/UnitTestColor.cpp
|
||||
general/UnitTestVector4.cpp
|
||||
general/UnitTestLineTrace.cpp
|
||||
general/UnitTestAngles.cpp
|
||||
general/UnitTestViewAngles.cpp
|
||||
general/UnitTestAngle.cpp
|
||||
|
||||
engines/UnitTestOpenGL.cpp
|
||||
engines/UnitTestUnityEngine.cpp
|
||||
engines/UnitTestSourceEngine.cpp
|
||||
|
||||
)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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_F(UnitTestMat, Method_At_OutOfRange)
|
||||
@@ -3,8 +3,9 @@
|
||||
|
||||
TEST(UnitTestPrediction, PredictionTest)
|
||||
{
|
||||
const omath::prediction::Target target{.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
|
||||
const omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4};
|
||||
constexpr omath::prediction::Target target{
|
||||
.m_origin = {100, 0, 90}, .m_velocity = {0, 0, 0}, .m_isAirborne = false};
|
||||
constexpr omath::prediction::Projectile proj = {.m_origin = {3,2,1}, .m_launchSpeed = 5000, .m_gravityScale= 0.4};
|
||||
const auto viewPoint = omath::prediction::Engine(400, 1.f / 1000.f, 50, 5.f).MaybeCalculateAimPoint(proj, target);
|
||||
|
||||
const auto [pitch, yaw, _] = proj.m_origin.ViewAngleTo(viewPoint.value()).AsTuple();
|
||||
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