commit 7c533861a7bead27607f9348e1f30eb68058a6a7 Author: Orange Date: Thu Nov 23 05:03:54 2023 +0300 initial commit diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..d6370b7 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,148 @@ +# 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-not-null-terminated-result, +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' \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a572362 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/uml.iml b/.idea/uml.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/uml.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8a7d9c4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.26) +project(uml) + +add_library(uml source/Vector3.cpp) +add_subdirectory(source) + +target_include_directories(uml PUBLIC include) \ No newline at end of file diff --git a/include/uml/ProjectilePredictor.h b/include/uml/ProjectilePredictor.h new file mode 100644 index 0000000..b13e0e8 --- /dev/null +++ b/include/uml/ProjectilePredictor.h @@ -0,0 +1,36 @@ +// +// Created by vlad on 11/6/23. +// + +#pragma once +#include + +namespace uml +{ + class Vector3; +} + +namespace uml::prediction +{ + class ProjectilePredictor + { + public: + [[nodiscard]] + static std::optional CalculateViewAngles(const Vector3& origin, + const Vector3& target, + const Vector3& targetVelocity, + float gravity, + float bulletSpeed, + float bulletGravity, + bool inAir); + + private: + [[nodiscard]] + static std::optional CalculateAimPitch(const Vector3& origin, + const Vector3& target, + float bulletSpeed, + float bulletGravity); + [[nodiscard]] static float ProjectileTravelTime(float distance, float angle, float speed); + }; + +}; diff --git a/include/uml/Vector3.h b/include/uml/Vector3.h new file mode 100644 index 0000000..1fee6da --- /dev/null +++ b/include/uml/Vector3.h @@ -0,0 +1,55 @@ +// +// Created by vlad on 10/28/23. +// + +#pragma once + +namespace uml +{ + class Vector3 final + { + public: + float x = 0.f; + float y = 0.f; + float z = 0.f; + Vector3(const float x, const float y, const float z) + { + this->x = x; + this->y = y; + this->z = z; + } + Vector3() = default; + + bool operator==(const Vector3& src) const; + bool operator!=(const Vector3& src) const; + + Vector3& operator+=(const Vector3& v); + Vector3& operator-=(const Vector3& v); + Vector3& operator*=(float fl); + Vector3& operator*=(const Vector3& v); + Vector3& operator/=(const Vector3& v); + Vector3& operator+=(float fl); + Vector3& operator/=(float fl); + Vector3& operator-=(float fl); + + [[nodiscard]] float DistTo(const Vector3& vOther) const; + Vector3& Abs(); + [[nodiscard]] float DistToSqr(const Vector3& vOther) const; + [[nodiscard]] float Dot(const Vector3& vOther) const; + [[nodiscard]] float Length() const; + [[nodiscard]] float LengthSqr() const; + [[nodiscard]] float Length2D() const; + + Vector3 operator-() const; + Vector3 operator+(const Vector3& v) const; + Vector3 operator-(const Vector3& v) const; + Vector3 operator*(float fl) const; + Vector3 operator*(const Vector3& v) const; + Vector3 operator/(float fl) const; + Vector3 operator/(const Vector3& v) const; + [[nodiscard]] Vector3 Transform(const Vector3& angles, float length) const; + [[nodiscard]] float Sum() const; + [[nodiscard]] float Sum2D() const; + [[nodiscard]] Vector3 ViewAngleTo(const Vector3& other) const; + }; +} diff --git a/include/uml/angles.h b/include/uml/angles.h new file mode 100644 index 0000000..6726896 --- /dev/null +++ b/include/uml/angles.h @@ -0,0 +1,11 @@ +// +// Created by vlad on 11/6/23. +// + +#pragma once + +namespace uml::angles +{ + [[nodiscard]] float RadToDeg(float rads); + [[nodiscard]] float DegToRad(float degrees); +} \ No newline at end of file diff --git a/include/uml/matrix.h b/include/uml/matrix.h new file mode 100644 index 0000000..ebf8dba --- /dev/null +++ b/include/uml/matrix.h @@ -0,0 +1,73 @@ +#pragma once +#include +#include + +namespace uml +{ + class Vector3; + + class matrix + { + public: + matrix(size_t rows, size_t columns); + + explicit matrix(const std::vector> &rows); + + [[nodiscard]] static matrix to_screen_matrix(float screenWidth, float screenHeight); + + matrix(const matrix &other); + + matrix(size_t rows, size_t columns, float *pRaw); + + matrix(matrix &&other) noexcept; + + [[nodiscard]] size_t get_rows_count() const noexcept; + + [[nodiscard]] size_t get_columns_count() const noexcept; + + [[nodiscard]] std::pair get_size() const noexcept; + + float &at(size_t iRow, size_t iCol); + + float get_sum(); + + matrix transpose(); + + void set(float val); + + [[nodiscard]] const float &at(size_t iRow, size_t iCol) const; + + matrix operator*(const matrix &other) const; + + matrix operator*(float f) const; + + matrix operator*(const Vector3 &vec3) const; + + matrix &operator*=(float f); + + matrix &operator/=(float f); + + void clear(); + + [[nodiscard]] matrix strip(size_t row, size_t column) const; + + [[nodiscard]] float minor(size_t i, size_t j) const; + + [[nodiscard]] float alg_complement(size_t i, size_t j) const; + + [[nodiscard]] float det() const; + + matrix &operator=(const matrix &other); + + matrix &operator=(matrix &&other) noexcept; + + matrix operator/(float f) const; + + ~matrix(); + + private: + size_t m_rows = 0; + size_t m_columns = 0; + std::unique_ptr m_pData = nullptr; + }; +} \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000..810521a --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources(uml PRIVATE + Vector3.cpp + matrix.cpp + angles.cpp + ProjectilePredictor.cpp) \ No newline at end of file diff --git a/source/ProjectilePredictor.cpp b/source/ProjectilePredictor.cpp new file mode 100644 index 0000000..b0c8bc5 --- /dev/null +++ b/source/ProjectilePredictor.cpp @@ -0,0 +1,74 @@ +// +// Created by vlad on 11/6/23. +// + +#include "uml/ProjectilePredictor.h" +#include "uml/Vector3.h" +#include "uml/angles.h" + +#include + +namespace uml::prediction +{ + + std::optional + ProjectilePredictor::CalculateViewAngles(const Vector3 &origin, + const Vector3 &target, + const Vector3 &targetVelocity, + float gravity, + float bulletSpeed, + float bulletGravity, + bool inAir) + { + constexpr float maxTime = 3.0f; + constexpr float timeStep = 0.01f; + + for (float time = 0.0f; time <= maxTime; time += timeStep) + { + auto predPos = target + targetVelocity * time; + + if (inAir) + predPos -= Vector3(0, 0, gravity * (time * time) * 0.5); + + const auto angle = CalculateAimPitch(origin, predPos, bulletSpeed, bulletGravity); + + if (!angle.has_value()) + return std::nullopt; + + const auto timeToHit = ProjectileTravelTime((predPos - origin).Length2D(), *angle, bulletSpeed); + + if (timeToHit > time) + continue; + + + auto viewAngles = origin.ViewAngleTo(predPos); + viewAngles.x = angle.value(); + + return viewAngles; + } + return std::nullopt; + } + + std::optional + ProjectilePredictor::CalculateAimPitch(const Vector3 &origin, const Vector3 &target, + float bulletSpeed, float bulletGravity) + { + const auto delta = target - origin; + + const auto distance = delta.Length2D(); + + + float root = powf(bulletSpeed, 4) - bulletGravity * (bulletGravity * distance * distance + 2.0f * delta.z * powf(bulletSpeed, 2)); + if (root < 0.0f) { + return std::nullopt; + } + root = sqrt(root); + float angle = atanf((powf(bulletSpeed, 2) - root) / (bulletGravity * distance)) * 180.f / (float)M_PI; + return -angle; + } + + float ProjectilePredictor::ProjectileTravelTime(float distance, float angle, float speed) + { + return std::abs(distance / (std::cos(angles::DegToRad(angle)) * speed)); + } +} \ No newline at end of file diff --git a/source/Vector3.cpp b/source/Vector3.cpp new file mode 100644 index 0000000..eca4c01 --- /dev/null +++ b/source/Vector3.cpp @@ -0,0 +1,215 @@ +// +// Created by vlad on 10/28/23. +// + + +#include +#include +#include + + +namespace uml +{ + bool Vector3::operator==(const Vector3 &src) const + { + return (src.x == x) and (src.y == y) and (src.z == z); + } + + bool Vector3::operator!=(const Vector3 &src) const + { + return (src.x != x) or (src.y != y) or (src.z != z); + } + + Vector3 &Vector3::operator+=(const Vector3 &v) + { + x += v.x; + y += v.y; + z += v.z; + + return *this; + } + + Vector3 &Vector3::operator-=(const Vector3 &v) + { + x -= v.x; + y -= v.y; + z -= v.z; + + return *this; + } + + Vector3 &Vector3::operator*=(const float fl) + { + x *= fl; + y *= fl; + z *= fl; + + return *this; + } + + Vector3 &Vector3::operator*=(const Vector3 &v) + { + x *= v.x; + y *= v.y; + z *= v.z; + + return *this; + } + + Vector3 &Vector3::operator/=(const Vector3 &v) + { + x /= v.x; + y /= v.y; + z /= v.z; + + return *this; + } + + Vector3 &Vector3::operator+=(const float fl) + { + x += fl; + y += fl; + z += fl; + + return *this; + } + + Vector3 &Vector3::operator/=(const float fl) + { + x /= fl; + y /= fl; + z /= fl; + + return *this; + } + + Vector3 &Vector3::operator-=(const float fl) + { + x -= fl; + y -= fl; + z -= fl; + + return *this; + } + + float Vector3::DistTo(const Vector3 &vOther) const + { + Vector3 delta; + + delta.x = x - vOther.x; + delta.y = y - vOther.y; + delta.z = z - vOther.z; + + return delta.Length(); + } + + Vector3 &Vector3::Abs() + { + x = fabsf(x); + y = fabsf(y); + z = fabsf(z); + + return *this; + } + + float Vector3::DistToSqr(const Vector3 &vOther) const + { + Vector3 delta; + + delta.x = x - vOther.x; + delta.y = y - vOther.y; + delta.z = z - vOther.z; + + return delta.LengthSqr(); + } + + float Vector3::Dot(const Vector3 &vOther) const + { + return (x * vOther.x + y * vOther.y + z * vOther.z); + } + + float Vector3::Length() const + { + return sqrt(x * x + y * y + z * z); + } + + float Vector3::LengthSqr(void) const + { + return (x * x + y * y + z * z); + } + + float Vector3::Length2D() const + { + return sqrt(x * x + y * y); + + } + + Vector3 Vector3::operator-(void) const + { + return {-x, -y, -z}; + } + + Vector3 Vector3::operator+(const Vector3 &v) const + { + return {x + v.x, y + v.y, z + v.z}; + } + + Vector3 Vector3::operator-(const Vector3 &v) const + { + return {x - v.x, y - v.y, z - v.z}; + } + + Vector3 Vector3::operator*(float fl) const + { + return {x * fl, y * fl, z * fl}; + } + + Vector3 Vector3::operator*(const Vector3 &v) const + { + return {x * v.x, y * v.y, z * v.z}; + } + + Vector3 Vector3::operator/(const float fl) const + { + return {x / fl, y / fl, z / fl}; + } + + Vector3 Vector3::operator/(const Vector3 &v) const + { + return {x / v.x, y / v.y, z / v.z}; + } + + Vector3 Vector3::Transform(const Vector3 &angles, const float length) const + { + Vector3 transformed; + transformed.x += cosf(angles.y * static_cast(M_PI / 180.f)) * length; + transformed.y += sinf(angles.y * static_cast(M_PI / 180.f)) * length; + transformed.z += tanf(angles.x * static_cast(M_PI / 180.f)) * length; + + return transformed; + } + + float Vector3::Sum() const + { + return x + y + z; + } + + float Vector3::Sum2D() const + { + return x + y; + } + + Vector3 Vector3::ViewAngleTo(const Vector3 &other) const + { + const float distance = DistTo(other); + const auto delta = other - *this; + + // Make x negative since -89 is top and 89 is bottom + return + { + -angles::RadToDeg(asinf(delta.z / distance)), + angles::RadToDeg(atan2f(delta.y, delta.x)), + 0.f + }; + } +} \ No newline at end of file diff --git a/source/angles.cpp b/source/angles.cpp new file mode 100644 index 0000000..9d9a361 --- /dev/null +++ b/source/angles.cpp @@ -0,0 +1,18 @@ +// +// Created by vlad on 11/6/23. +// +#include "uml/angles.h" +#include + +namespace uml::angles +{ + float RadToDeg(float rads) + { + return rads * 180.f / static_cast(M_PI); + } + + float DegToRad(float degrees) + { + return degrees * static_cast(M_PI) / 180.f; + } +} diff --git a/source/matrix.cpp b/source/matrix.cpp new file mode 100644 index 0000000..944390b --- /dev/null +++ b/source/matrix.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2022. + * Created by Alpatov Softworks with love in Russia. + */ + +#include "uml/matrix.h" +#include "uml/Vector3.h" +#include +#include +#include + + +namespace uml +{ + matrix::matrix(const size_t rows, const size_t columns) + { + if (rows == 0 and columns == 0) + throw std::runtime_error("Matrix cannot be 0x0"); + + m_rows = rows; + m_columns = columns; + + m_pData = std::make_unique(m_rows * m_columns); + + set(0.f); + } + + matrix::matrix(const std::vector> &rows) + { + m_rows = rows.size(); + m_columns = rows[0].size(); + + + m_pData = std::make_unique(m_rows * m_columns); + + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + at(i,j) = rows[i][j]; + } + + matrix::matrix(const matrix &other) + { + m_rows = other.m_rows; + m_columns = other.m_columns; + + m_pData = std::make_unique(m_rows * m_columns); + + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + at(i, j) = other.at(i, j); + } + + matrix::matrix(const size_t rows, const size_t columns, float *pRaw) + { + m_rows = rows; + m_columns = columns; + + + m_pData = std::make_unique(m_rows * m_columns); + + for (size_t i = 0; i < rows*columns; ++i) + at(i / rows, i % columns) = pRaw[i]; + + } + + size_t matrix::get_rows_count() const noexcept + { + return m_rows; + } + + matrix::matrix(matrix &&other) noexcept + { + m_rows = other.m_rows; + m_columns = other.m_columns; + m_pData = std::move(other.m_pData); + + } + + size_t matrix::get_columns_count() const noexcept + { + return m_columns; + } + + std::pair matrix::get_size() const noexcept + { + return {get_rows_count(), get_columns_count()}; + } + + float &matrix::at(const size_t iRow, const size_t iCol) + { + return const_cast(std::as_const(*this).at(iRow, iCol)); + } + + float matrix::get_sum() + { + float sum = 0; + + for (size_t i = 0; i < get_rows_count(); i++) + for (size_t j = 0; j < get_columns_count(); j++) + sum += at(i, j); + + return sum; + } + + const float &matrix::at(const size_t iRow, const size_t iCol) const + { + return m_pData[iRow * m_columns + iCol]; + } + + matrix matrix::operator*(const matrix &other) const + { + if (m_columns != other.m_rows) + throw std::runtime_error("n != m"); + + auto outMat = matrix(m_rows, other.m_columns); + + for (size_t d = 0; d < m_rows; ++d) + for (size_t i = 0; i < other.m_columns; ++i) + for (size_t j = 0; j < other.m_rows; ++j) + outMat.at(d, i) += at(d, j) * other.at(j, i); + + + return outMat; + } + + matrix matrix::operator*(const float f) const + { + auto out = *this; + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + out.at(i, j) *= f; + + return out; + } + + matrix &matrix::operator*=(const float f) + { + for (size_t i = 0; i < get_rows_count(); i++) + for (size_t j = 0; j < get_columns_count(); j++) + at(i, j) *= f; + return *this; + } + + void matrix::clear() + { + set(0.f); + } + + matrix matrix::operator*(const Vector3 &vec3) const + { + auto vecmatrix = matrix(m_rows, 1); + vecmatrix.set(1.f); + vecmatrix.at(0, 0) = vec3.x; + vecmatrix.at(1, 0) = vec3.y; + vecmatrix.at(2, 0) = vec3.z; + + return *this * vecmatrix; + + } + + + matrix &matrix::operator=(const matrix &other) + { + if (this == &other) + return *this; + + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + at(i, j) = other.at(i, j); + + return *this; + + } + + matrix &matrix::operator=(matrix &&other) noexcept + { + if (this == &other) + return *this; + + m_rows = other.m_rows; + m_columns = other.m_columns; + m_pData = std::move(other.m_pData); + + return *this; + + } + + matrix &matrix::operator/=(const float f) + { + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + at(i, j) /= f; + + return *this; + } + + matrix matrix::operator/(const float f) const + { + auto out = *this; + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + out.at(i, j) /= f; + + return out; + } + + float matrix::det() const + { + if (m_rows + m_columns == 2) + return at(0, 0); + + if (m_rows == 2 and m_columns == 2) + return at(0, 0) * at(1, 1) - at(0, 1) * at(1, 0); + + float fDet = 0; + for (size_t i = 0; i < m_columns; i++) + fDet += alg_complement(0, i) * at(0, i); + + return fDet; + } + + float matrix::alg_complement(const size_t i, const size_t j) const + { + const auto tmp = minor(i, j); + return ((i + j + 2) % 2 == 0) ? tmp : -tmp; + } + + matrix matrix::transpose() + { + matrix transposed = {m_columns, m_rows}; + + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + transposed.at(j, i) = at(i, j); + + return transposed; + } + + matrix::~matrix() = default; + + void matrix::set(const float val) + { + for (size_t i = 0; i < m_rows; ++i) + for (size_t j = 0; j < m_columns; ++j) + at(i, j) = val; + } + + matrix matrix::strip(const size_t row, const size_t column) const + { + matrix stripped = {m_rows - 1, m_columns - 1}; + size_t iStripRowIndex = 0; + + for (size_t i = 0; i < m_rows; i++) + { + if (i == row) + continue; + + size_t iStripColumnIndex = 0; + for (size_t j = 0; j < m_columns; ++j) + { + if (j == column) + continue; + + stripped.at(iStripRowIndex, iStripColumnIndex) = at(i, j); + iStripColumnIndex++; + } + + iStripRowIndex++; + } + + return stripped; + } + + float matrix::minor(const size_t i, const size_t j) const + { + return strip(i, j).det(); + } + + matrix matrix::to_screen_matrix(float screenWidth, float screenHeight) + { + return matrix({ + {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}, + }); + } +} \ No newline at end of file