From db57dfd5f98f4e6b76000ef7968f38e1242adc03 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 10:28:07 +0300 Subject: [PATCH 01/15] added camera --- include/omath/matrix.h | 2 + include/omath/projection/Camera.h | 38 ++++++++++++++++ source/CMakeLists.txt | 3 +- source/Vector3.cpp | 33 ++++++++++++-- source/matrix.cpp | 6 +++ source/projection/CMakeLists.txt | 1 + source/projection/Camera.cpp | 74 +++++++++++++++++++++++++++++++ tests/UnitTestAstar.cpp | 2 +- 8 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 include/omath/projection/Camera.h create mode 100644 source/projection/CMakeLists.txt create mode 100644 source/projection/Camera.cpp diff --git a/include/omath/matrix.h b/include/omath/matrix.h index 79655cc..9610377 100644 --- a/include/omath/matrix.h +++ b/include/omath/matrix.h @@ -51,6 +51,8 @@ namespace omath Matrix operator*(const Matrix &other) const; + Matrix& operator*=(const Matrix &other); + Matrix operator*(float f) const; Matrix operator*(const Vector3 &vec3) const; diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h new file mode 100644 index 0000000..8f25902 --- /dev/null +++ b/include/omath/projection/Camera.h @@ -0,0 +1,38 @@ +// +// Created by Vlad on 27.08.2024. +// + +#pragma once + +#include +#include +#include +#include + + +namespace omath::projection +{ + class Camera + { + public: + void SetViewAngles(const Vector3& viewAngles); + [[nodiscard]] const Vector3& GetViewAngles() const; + + [[nodiscard]] Matrix GetViewMatrix() const; + [[nodiscard]] Matrix GetProjectionMatrix() const; + [[nodiscard]] Matrix GetTranslationMatrix() const; + [[nodiscard]] Matrix GetOrientationMatrix() const; + + [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const; + + Vector3 m_viewPort; + float m_fieldOfView; + + float m_farPlaneDistance; + float m_nearPlaneDistance; + + private: + Vector3 m_viewAngles; + Vector3 m_origin; + }; +} diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 499567c..c35e3a5 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -5,4 +5,5 @@ target_sources(omath PRIVATE Vector4.cpp) add_subdirectory(prediction) -add_subdirectory(pathfinding) \ No newline at end of file +add_subdirectory(pathfinding) +add_subdirectory(projection) \ No newline at end of file diff --git a/source/Vector3.cpp b/source/Vector3.cpp index e0a68f1..35466f2 100644 --- a/source/Vector3.cpp +++ b/source/Vector3.cpp @@ -219,7 +219,12 @@ namespace omath const auto sinYaw = std::sin(angles::DegreesToRadians(yaw)); - return {cosPitch*cosYaw, cosPitch*sinYaw, sinPitch}; + return + { + cosPitch*cosYaw, + cosPitch*sinYaw, + sinPitch + }; } Vector3 Vector3::RightVector(const float pitch, const float yaw, const float roll) @@ -230,13 +235,33 @@ namespace omath const auto cosYaw = std::cos(angles::DegreesToRadians(yaw)); const auto sinYaw = std::sin(angles::DegreesToRadians(yaw)); - const auto cosRoll = std::cos(angles::DegreesToRadians(yaw)); - const auto sinRoll = std::sin(angles::DegreesToRadians(yaw)); + const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); + const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); return {-sinRoll*sinPitch*cosYaw + -cosRoll*-sinYaw, -sinRoll*sinPitch*sinYaw + -cosRoll*cosYaw, - sinRoll*cosPitch}; + -sinRoll*cosPitch}; + } + + Vector3 Vector3::UpVector(float pitch, float yaw, float roll) + { + 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)); + + const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); + const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); + + + return + { + cosRoll*sinPitch*cosYaw+-sinRoll*-sinYaw, + cosRoll*sinPitch*cosYaw+-sinRoll*-sinYaw, + cosRoll*cosPitch, + }; } Vector3 Vector3::Cross(const Vector3 &v) const diff --git a/source/matrix.cpp b/source/matrix.cpp index 7ca9309..40d9a8f 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -120,6 +120,12 @@ namespace omath return outMat; } + Matrix & Matrix::operator*=(const Matrix &other) + { + *this = *this * other; + return *this; + } + Matrix Matrix::operator*(const float f) const { auto out = *this; diff --git a/source/projection/CMakeLists.txt b/source/projection/CMakeLists.txt new file mode 100644 index 0000000..0abf868 --- /dev/null +++ b/source/projection/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(omath PRIVATE Camera.cpp) \ No newline at end of file diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp new file mode 100644 index 0000000..984c414 --- /dev/null +++ b/source/projection/Camera.cpp @@ -0,0 +1,74 @@ +// +// Created by Vlad on 27.08.2024. +// +#include "omath/projection/Camera.h" +#include "omath/angles.h" + + +namespace omath::projection +{ + Matrix Camera::GetViewMatrix() const + { + return GetOrientationMatrix() * GetTranslationMatrix(); + } + + Matrix Camera::GetProjectionMatrix() const + { + const auto aspectRatio = m_viewPort.x / m_viewPort.y; + const auto verticalFov = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + + + return Matrix( + { + {1.f / (aspectRatio * verticalFov), 0.f, 0.f, 0.f}, + {0.f, 1.f / verticalFov, 0.f, 0.f}, + {0.f, 0.f, m_farPlaneDistance / (m_farPlaneDistance-m_nearPlaneDistance), -m_farPlaneDistance*m_nearPlaneDistance / (m_farPlaneDistance-m_nearPlaneDistance)}, + {0.f, 0.f, 1.f, 0.f} + }); + } + + Matrix Camera::GetTranslationMatrix() const + { + return Matrix( + { + {1.f, 0.f, 0.f, m_origin.x}, + {0.f, 1.f, 0.f, m_origin.y}, + {0.f, 0.f, 1.f, m_origin.z}, + {0.f, 0.f, 0.f, 1.f}, + }); + } + + Matrix Camera::GetOrientationMatrix() 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 Matrix( + { + {right.x, up.y, right.z, 0.f}, + {up.x, up.y, up.y, 0.f}, + {forward.x, forward.y, forward.z, 0.f}, + {0.f, 0.f, 0.f, 1.f}, + }); + } + + std::expected Camera::WorldToScreen(const Vector3 &worldPosition) const + { + const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); + + const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(); + + auto projected = posVecAsMatrix * viewProjectionMatrix; + + if (projected.At(0, 3) <= 0.f) + return std::unexpected("Projection point is out of camera field of view"); + + projected /= projected.At(0, 3); + + projected *= Matrix::ToScreenMatrix(m_viewPort.x, m_viewPort.y); + + return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)}; + } +} diff --git a/tests/UnitTestAstar.cpp b/tests/UnitTestAstar.cpp index 91780e8..f16cd8e 100644 --- a/tests/UnitTestAstar.cpp +++ b/tests/UnitTestAstar.cpp @@ -13,5 +13,5 @@ TEST(UnitTestAstar, FindingRightPath) mesh.m_verTextMap[{0.f, 1.f, 0.f}] = {{0.f, 2.f, 0.f}}; mesh.m_verTextMap[{0.f, 2.f, 0.f}] = {{0.f, 3.f, 0.f}}; mesh.m_verTextMap[{0.f, 3.f, 0.f}] = {}; - omath::pathfinding::Astar::FindPath({}, {0.f, 3.f, 0.f}, mesh); + std::ignore = omath::pathfinding::Astar::FindPath({}, {0.f, 3.f, 0.f}, mesh); } \ No newline at end of file From 13188615ed86b71bce15130648c48b06a55c4cf0 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 10:56:56 +0300 Subject: [PATCH 02/15] added unit test --- include/omath/projection/Camera.h | 1 + source/Vector3.cpp | 21 +++++++++++---------- source/projection/Camera.cpp | 11 +++++++++++ tests/CMakeLists.txt | 2 +- tests/UnitTestProjection.cpp | 15 +++++++++++++++ 5 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 tests/UnitTestProjection.cpp diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index 8f25902..f86c8b6 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -15,6 +15,7 @@ namespace omath::projection class Camera { public: + Camera(const Vector3& position, const Vector3& viewAngles, const Vector3& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); [[nodiscard]] const Vector3& GetViewAngles() const; diff --git a/source/Vector3.cpp b/source/Vector3.cpp index 35466f2..39d5757 100644 --- a/source/Vector3.cpp +++ b/source/Vector3.cpp @@ -238,10 +238,12 @@ namespace omath const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); - - return {-sinRoll*sinPitch*cosYaw + -cosRoll*-sinYaw, - -sinRoll*sinPitch*sinYaw + -cosRoll*cosYaw, - -sinRoll*cosPitch}; + // Right vector calculation + return { + cosYaw * cosRoll - sinYaw * sinPitch * sinRoll, // X component + sinRoll * cosPitch, // Y component + sinYaw * cosRoll + cosYaw * sinPitch * sinRoll // Z component + }; } Vector3 Vector3::UpVector(float pitch, float yaw, float roll) @@ -255,12 +257,11 @@ namespace omath const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); - - return - { - cosRoll*sinPitch*cosYaw+-sinRoll*-sinYaw, - cosRoll*sinPitch*cosYaw+-sinRoll*-sinYaw, - cosRoll*cosPitch, + // Up vector calculation + return { + -sinRoll * cosYaw + cosRoll * sinPitch * sinYaw, // X component + cosRoll * cosPitch, // Y component + -sinRoll * sinYaw - cosRoll * sinPitch * cosYaw // Z component }; } diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 984c414..dac1ffe 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -7,6 +7,17 @@ namespace omath::projection { + Camera::Camera(const Vector3 &position, const Vector3 &viewAngles, const Vector3 &viewPort, const float fov, const float near, + const float far) + { + m_origin = position; + m_viewAngles = viewAngles; + m_viewPort = viewPort; + m_fieldOfView = fov; + m_nearPlaneDistance = near; + m_farPlaneDistance = far; + } + Matrix Camera::GetViewMatrix() const { return GetOrientationMatrix() * GetTranslationMatrix(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9781a8b..f47be28 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/out/${CMAKE_BUILD_TYPE}" file(GLOB TEST_SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) include(GoogleTest) -add_executable(unit-tests UnitTestPrediction.cpp UnitTestMatrix.cpp UnitTestAstar.cpp) +add_executable(unit-tests UnitTestPrediction.cpp UnitTestMatrix.cpp UnitTestAstar.cpp UnitTestProjection.cpp) target_link_libraries(unit-tests PRIVATE gtest gtest_main omath) diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp new file mode 100644 index 0000000..df7eaeb --- /dev/null +++ b/tests/UnitTestProjection.cpp @@ -0,0 +1,15 @@ +// +// Created by Vlad on 27.08.2024. +// +#include +#include +#include +#include + +TEST(UnitTestProjection, IsPointOnScreen) +{ + const omath::projection::Camera camera({}, {90, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 120, 10, 100); + + const auto proj = camera.WorldToScreen({0,0,15}); + EXPECT_TRUE(proj.has_value()); +} \ No newline at end of file From 15186785eb6e903a75ac987d25a3315e73c246a0 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 14:50:54 +0300 Subject: [PATCH 03/15] fixed direction vectors --- include/omath/{matrix.h => Matrix.h} | 0 source/Vector3.cpp | 26 +++++--------------------- source/matrix.cpp | 3 ++- source/projection/Camera.cpp | 3 +++ 4 files changed, 10 insertions(+), 22 deletions(-) rename include/omath/{matrix.h => Matrix.h} (100%) diff --git a/include/omath/matrix.h b/include/omath/Matrix.h similarity index 100% rename from include/omath/matrix.h rename to include/omath/Matrix.h diff --git a/source/Vector3.cpp b/source/Vector3.cpp index 39d5757..40664cd 100644 --- a/source/Vector3.cpp +++ b/source/Vector3.cpp @@ -238,31 +238,15 @@ namespace omath const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); - // Right vector calculation - return { - cosYaw * cosRoll - sinYaw * sinPitch * sinRoll, // X component - sinRoll * cosPitch, // Y component - sinYaw * cosRoll + cosYaw * sinPitch * sinRoll // Z component - }; + + return {-sinRoll*sinPitch*cosYaw + -cosRoll*-sinYaw, + -sinRoll*sinPitch*sinYaw + -cosRoll*cosYaw, + sinRoll*cosPitch}; } Vector3 Vector3::UpVector(float pitch, float yaw, float roll) { - 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)); - - const auto cosRoll = std::cos(angles::DegreesToRadians(roll)); - const auto sinRoll = std::sin(angles::DegreesToRadians(roll)); - - // Up vector calculation - return { - -sinRoll * cosYaw + cosRoll * sinPitch * sinYaw, // X component - cosRoll * cosPitch, // Y component - -sinRoll * sinYaw - cosRoll * sinPitch * cosYaw // Z component - }; + return RightVector(pitch, yaw, roll).Cross(ForwardVector(pitch, yaw)); } Vector3 Vector3::Cross(const Vector3 &v) const diff --git a/source/matrix.cpp b/source/matrix.cpp index 40d9a8f..7ef65e4 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -1,10 +1,11 @@ -#include "omath/matrix.h" +#include "omath/Matrix.h" #include #include "omath/Vector3.h" #include #include #include +#include namespace omath diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index dac1ffe..6a32d38 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -2,6 +2,9 @@ // Created by Vlad on 27.08.2024. // #include "omath/projection/Camera.h" + +#include + #include "omath/angles.h" From 8359524cdb2395352b04062cf7d5a1872b3be51f Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 14:57:56 +0300 Subject: [PATCH 04/15] fixed unit test --- tests/UnitTestMatrix.cpp | 2 +- tests/UnitTestProjection.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UnitTestMatrix.cpp b/tests/UnitTestMatrix.cpp index dceb264..a86692f 100644 --- a/tests/UnitTestMatrix.cpp +++ b/tests/UnitTestMatrix.cpp @@ -2,7 +2,7 @@ // Created by vlad on 5/18/2024. // #include -#include +#include #include diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index df7eaeb..c232da9 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -2,7 +2,7 @@ // Created by Vlad on 27.08.2024. // #include -#include +#include #include #include From 8fc9a5495877daedbc1ac87ce53db657f89fc88c Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 13:12:35 +0300 Subject: [PATCH 05/15] patched up matrixes --- source/projection/Camera.cpp | 37 +++++++++++++++++++++--------------- tests/UnitTestProjection.cpp | 4 ++-- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 6a32d38..9fd7851 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -28,26 +28,33 @@ namespace omath::projection Matrix Camera::GetProjectionMatrix() const { - const auto aspectRatio = m_viewPort.x / m_viewPort.y; - const auto verticalFov = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const float fRight = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const float fLeft = -fRight; + const float vFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); + + const float fTop = std::tan(vFov / 2.f); + const float fBottom = -fTop; + + const auto m_fFar = m_farPlaneDistance; + const auto m_fNear = m_nearPlaneDistance; + + return Matrix({ + {2.f / (fRight - fLeft), 0.f, 0.f, 0.f}, + {0.f, 0.f, 2.f / (fTop - fBottom), 0.f}, + {0.f, (m_fFar + m_fNear) / (m_fFar - m_fNear), 0.f, 1.f}, + {0.f, -2.f * m_fNear * m_fFar / (m_fFar - m_fNear), 0.f, 0.f}, + }); - return Matrix( - { - {1.f / (aspectRatio * verticalFov), 0.f, 0.f, 0.f}, - {0.f, 1.f / verticalFov, 0.f, 0.f}, - {0.f, 0.f, m_farPlaneDistance / (m_farPlaneDistance-m_nearPlaneDistance), -m_farPlaneDistance*m_nearPlaneDistance / (m_farPlaneDistance-m_nearPlaneDistance)}, - {0.f, 0.f, 1.f, 0.f} - }); } Matrix Camera::GetTranslationMatrix() const { return Matrix( { - {1.f, 0.f, 0.f, m_origin.x}, - {0.f, 1.f, 0.f, m_origin.y}, - {0.f, 0.f, 1.f, m_origin.z}, + {1.f, 0.f, 0.f, -m_origin.x}, + {0.f, 1.f, 0.f, -m_origin.y}, + {0.f, 0.f, 1.f, -m_origin.z}, {0.f, 0.f, 0.f, 1.f}, }); } @@ -61,9 +68,9 @@ namespace omath::projection return Matrix( { - {right.x, up.y, right.z, 0.f}, - {up.x, up.y, up.y, 0.f}, - {forward.x, forward.y, forward.z, 0.f}, + {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}, }); } diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index c232da9..67f27b3 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -8,8 +8,8 @@ TEST(UnitTestProjection, IsPointOnScreen) { - const omath::projection::Camera camera({}, {90, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 120, 10, 100); + const omath::projection::Camera camera({}, {90, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 120, 10, 100); - const auto proj = camera.WorldToScreen({0,0,15}); + const auto proj = camera.WorldToScreen({0, 0, 20}); EXPECT_TRUE(proj.has_value()); } \ No newline at end of file From e5dbb78b1586e8ebb53bebc0a819549b0a891e81 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 17:35:17 +0300 Subject: [PATCH 06/15] patch --- source/projection/Camera.cpp | 20 ++++++++++---------- tests/UnitTestProjection.cpp | 7 +++++-- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 9fd7851..34217d4 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -23,7 +23,7 @@ namespace omath::projection Matrix Camera::GetViewMatrix() const { - return GetOrientationMatrix() * GetTranslationMatrix(); + return GetTranslationMatrix() * GetOrientationMatrix(); } Matrix Camera::GetProjectionMatrix() const @@ -40,10 +40,10 @@ namespace omath::projection const auto m_fNear = m_nearPlaneDistance; return Matrix({ - {2.f / (fRight - fLeft), 0.f, 0.f, 0.f}, - {0.f, 0.f, 2.f / (fTop - fBottom), 0.f}, - {0.f, (m_fFar + m_fNear) / (m_fFar - m_fNear), 0.f, 1.f}, - {0.f, -2.f * m_fNear * m_fFar / (m_fFar - m_fNear), 0.f, 0.f}, + {2.f / (fRight - fLeft), 0.f, 0.f, 0.f}, + {0.f, 2.f / (fTop - fBottom), 0.f, 0.f}, + {0.f, 0.f, (m_fFar + m_fNear) / (m_fFar - m_fNear), 1.f}, + {0.f, 0.f, -2.f * m_fNear * m_fFar / (m_fFar - m_fNear), 0.f}, }); } @@ -52,10 +52,10 @@ namespace omath::projection { return Matrix( { - {1.f, 0.f, 0.f, -m_origin.x}, - {0.f, 1.f, 0.f, -m_origin.y}, - {0.f, 0.f, 1.f, -m_origin.z}, - {0.f, 0.f, 0.f, 1.f}, + {1.f, 0.f, 0.f, 0.f}, + {0.f, 1.f, 0.f, 1.f}, + {0.f, 0.f, 1.f, 0.f}, + {-m_origin.x, -m_origin.y, -m_origin.z, 1.f}, }); } @@ -90,6 +90,6 @@ namespace omath::projection projected *= Matrix::ToScreenMatrix(m_viewPort.x, m_viewPort.y); - return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)}; + return Vector3{projected.At(0, 0), projected.At(0, 2), projected.At(0, 1)}; } } diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index 67f27b3..bb727a3 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -1,6 +1,7 @@ // // Created by Vlad on 27.08.2024. // +#include #include #include #include @@ -8,8 +9,10 @@ TEST(UnitTestProjection, IsPointOnScreen) { - const omath::projection::Camera camera({}, {90, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 120, 10, 100); + const omath::projection::Camera camera({0, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); - const auto proj = camera.WorldToScreen({0, 0, 20}); + const auto proj = camera.WorldToScreen({5, 0, 0}); + if (proj) + std::print("{} {} {}", proj->x, proj->z, proj->y); EXPECT_TRUE(proj.has_value()); } \ No newline at end of file From 6356d06e34ea5719939990b3ea9335fcd4edf1a6 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 21:47:08 +0300 Subject: [PATCH 07/15] patch --- source/matrix.cpp | 1 - source/projection/Camera.cpp | 29 ++++++++++++++--------------- tests/UnitTestProjection.cpp | 6 +++--- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/source/matrix.cpp b/source/matrix.cpp index 7ef65e4..c6e0d69 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace omath diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 34217d4..fd93ec1 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -31,21 +31,20 @@ namespace omath::projection const float fRight = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); const float fLeft = -fRight; - const float vFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); + const float verticalFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); - const float fTop = std::tan(vFov / 2.f); - const float fBottom = -fTop; + const float top = std::tan(verticalFov / 2.f); + const float botton = -top; - const auto m_fFar = m_farPlaneDistance; - const auto m_fNear = m_nearPlaneDistance; + const auto far = m_farPlaneDistance; + const auto near = m_nearPlaneDistance; return Matrix({ - {2.f / (fRight - fLeft), 0.f, 0.f, 0.f}, - {0.f, 2.f / (fTop - fBottom), 0.f, 0.f}, - {0.f, 0.f, (m_fFar + m_fNear) / (m_fFar - m_fNear), 1.f}, - {0.f, 0.f, -2.f * m_fNear * m_fFar / (m_fFar - m_fNear), 0.f}, + {1.555f / (fRight - fLeft), 0.f, 0.f, 0.f}, + {0.f, 1.15f / (top - botton), 0.f, 0.f}, + {0.f, 0.f, (far + near) / (far - near), 1.f}, + {0.f, 0.f, -near * far / (far - near), 0.f}, }); - } Matrix Camera::GetTranslationMatrix() const @@ -68,10 +67,10 @@ namespace omath::projection return Matrix( { - {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}, + {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}, }); } @@ -90,6 +89,6 @@ namespace omath::projection projected *= Matrix::ToScreenMatrix(m_viewPort.x, m_viewPort.y); - return Vector3{projected.At(0, 0), projected.At(0, 2), projected.At(0, 1)}; + return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)}; } } diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index bb727a3..a989c9e 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -9,10 +9,10 @@ TEST(UnitTestProjection, IsPointOnScreen) { - const omath::projection::Camera camera({0, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); + const omath::projection::Camera camera({5, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); - const auto proj = camera.WorldToScreen({5, 0, 0}); + const auto proj = camera.WorldToScreen({10, 0, 0}); if (proj) - std::print("{} {} {}", proj->x, proj->z, proj->y); + std::print("{} {} {}", proj->x, proj->y, proj->z); EXPECT_TRUE(proj.has_value()); } \ No newline at end of file From 927d56fef37e4da64490ef8ad942de558a2fb822 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 23:03:33 +0300 Subject: [PATCH 08/15] added debug methods --- include/omath/projection/Camera.h | 5 ++++- source/projection/Camera.cpp | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index f86c8b6..7b2f864 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -18,9 +18,12 @@ namespace omath::projection Camera(const Vector3& position, const Vector3& viewAngles, const Vector3& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); [[nodiscard]] const Vector3& GetViewAngles() const; + static float& GetFloat1(); + + static float& GetFloat2(); [[nodiscard]] Matrix GetViewMatrix() const; - [[nodiscard]] Matrix GetProjectionMatrix() const; + [[nodiscard]] Matrix GetProjectionMatrix(float scaleX, float scaleY) const; [[nodiscard]] Matrix GetTranslationMatrix() const; [[nodiscard]] Matrix GetOrientationMatrix() const; diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index fd93ec1..7d6b2ac 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -21,12 +21,22 @@ namespace omath::projection m_farPlaneDistance = far; } + float & Camera::GetFloat1() { + static float m_float1 = 1.52550f; + return m_float1; + } + + float & Camera::GetFloat2() { + static float m_float2 = 1.14500f; + return m_float2; + } + Matrix Camera::GetViewMatrix() const { return GetTranslationMatrix() * GetOrientationMatrix(); } - Matrix Camera::GetProjectionMatrix() const + Matrix Camera::GetProjectionMatrix(const float scaleX, const float scaleY) const { const float fRight = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); const float fLeft = -fRight; @@ -40,8 +50,8 @@ namespace omath::projection const auto near = m_nearPlaneDistance; return Matrix({ - {1.555f / (fRight - fLeft), 0.f, 0.f, 0.f}, - {0.f, 1.15f / (top - botton), 0.f, 0.f}, + {scaleX / (fRight - fLeft), 0.f, 0.f, 0.f}, + {0.f, scaleY / (top - botton), 0.f, 0.f}, {0.f, 0.f, (far + near) / (far - near), 1.f}, {0.f, 0.f, -near * far / (far - near), 0.f}, }); @@ -78,7 +88,7 @@ namespace omath::projection { const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); - const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(); + const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(GetFloat1(), GetFloat2()); auto projected = posVecAsMatrix * viewProjectionMatrix; From dbc5c86cc4ef7dd1ace7f3ee59b083f027c32544 Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 20:53:34 +0300 Subject: [PATCH 09/15] fixed typo --- source/projection/Camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 7d6b2ac..f8d490b 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -62,7 +62,7 @@ namespace omath::projection return Matrix( { {1.f, 0.f, 0.f, 0.f}, - {0.f, 1.f, 0.f, 1.f}, + {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {-m_origin.x, -m_origin.y, -m_origin.z, 1.f}, }); From 3b897e27a8e3facadbb1226c67bb99affc537e7e Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 21:01:16 +0300 Subject: [PATCH 10/15] fixed naming --- source/projection/Camera.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index f8d490b..47540a0 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -38,20 +38,20 @@ namespace omath::projection Matrix Camera::GetProjectionMatrix(const float scaleX, const float scaleY) const { - const float fRight = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); - const float fLeft = -fRight; + const float right = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const float left = -right; const float verticalFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); const float top = std::tan(verticalFov / 2.f); - const float botton = -top; + const float bottom = -top; const auto far = m_farPlaneDistance; const auto near = m_nearPlaneDistance; return Matrix({ - {scaleX / (fRight - fLeft), 0.f, 0.f, 0.f}, - {0.f, scaleY / (top - botton), 0.f, 0.f}, + {scaleX / (right - left), 0.f, 0.f, 0.f}, + {0.f, scaleY / (top - bottom), 0.f, 0.f}, {0.f, 0.f, (far + near) / (far - near), 1.f}, {0.f, 0.f, -near * far / (far - near), 0.f}, }); From 8a67b7edbe96cc85a27eb8482068c3f400b15e8c Mon Sep 17 00:00:00 2001 From: Orange Date: Tue, 27 Aug 2024 21:41:21 +0300 Subject: [PATCH 11/15] maybe improved matrix --- include/omath/projection/Camera.h | 2 +- source/projection/Camera.cpp | 24 ++++++++++-------------- tests/UnitTestProjection.cpp | 6 +++--- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index 7b2f864..c96dd16 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -23,7 +23,7 @@ namespace omath::projection static float& GetFloat2(); [[nodiscard]] Matrix GetViewMatrix() const; - [[nodiscard]] Matrix GetProjectionMatrix(float scaleX, float scaleY) const; + [[nodiscard]] Matrix GetProjectionMatrix() const; [[nodiscard]] Matrix GetTranslationMatrix() const; [[nodiscard]] Matrix GetOrientationMatrix() const; diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 47540a0..fe88929 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -2,9 +2,7 @@ // Created by Vlad on 27.08.2024. // #include "omath/projection/Camera.h" - #include - #include "omath/angles.h" @@ -36,24 +34,22 @@ namespace omath::projection return GetTranslationMatrix() * GetOrientationMatrix(); } - Matrix Camera::GetProjectionMatrix(const float scaleX, const float scaleY) const + Matrix Camera::GetProjectionMatrix() const { - const float right = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const float right = m_nearPlaneDistance * std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); const float left = -right; - const float verticalFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); - - const float top = std::tan(verticalFov / 2.f); + const float top = right * (m_viewPort.y / m_viewPort.x); const float bottom = -top; - const auto far = m_farPlaneDistance; - const auto near = m_nearPlaneDistance; + const float near = m_nearPlaneDistance; + const float far = m_farPlaneDistance; return Matrix({ - {scaleX / (right - left), 0.f, 0.f, 0.f}, - {0.f, scaleY / (top - bottom), 0.f, 0.f}, - {0.f, 0.f, (far + near) / (far - near), 1.f}, - {0.f, 0.f, -near * far / (far - near), 0.f}, + {2 * near / (right - left), 0.f, (right + left) / (right - left), 0.f}, + {0.f, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0.f}, + {0.f, 0.f, (far + near) / (far - near), 2 * near * far / (far - near)}, + {0.f, 0.f, -1.f, 0.f}, }); } @@ -88,7 +84,7 @@ namespace omath::projection { const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); - const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(GetFloat1(), GetFloat2()); + const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(); auto projected = posVecAsMatrix * viewProjectionMatrix; diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index a989c9e..dcd5d4c 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -9,10 +9,10 @@ TEST(UnitTestProjection, IsPointOnScreen) { - const omath::projection::Camera camera({5, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); + const omath::projection::Camera camera({0, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); - const auto proj = camera.WorldToScreen({10, 0, 0}); + const auto proj = camera.WorldToScreen({100, 0, 15}); if (proj) - std::print("{} {} {}", proj->x, proj->y, proj->z); + std::print("{} {}", proj->x, proj->y); EXPECT_TRUE(proj.has_value()); } \ No newline at end of file From 74372a9f38dba696853770cbb1036e0732bc02cc Mon Sep 17 00:00:00 2001 From: Orange Date: Wed, 28 Aug 2024 01:26:27 +0300 Subject: [PATCH 12/15] patch --- source/projection/Camera.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index fe88929..ee11876 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -2,7 +2,9 @@ // Created by Vlad on 27.08.2024. // #include "omath/projection/Camera.h" + #include + #include "omath/angles.h" @@ -36,20 +38,23 @@ namespace omath::projection Matrix Camera::GetProjectionMatrix() const { - const float right = m_nearPlaneDistance * std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const float right = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); const float left = -right; - const float top = right * (m_viewPort.y / m_viewPort.x); + const float verticalFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); + + const float top = std::tan(verticalFov / 2.f); const float bottom = -top; - const float near = m_nearPlaneDistance; - const float far = m_farPlaneDistance; + const auto far = m_farPlaneDistance; + const auto near = m_nearPlaneDistance; - return Matrix({ - {2 * near / (right - left), 0.f, (right + left) / (right - left), 0.f}, - {0.f, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0.f}, - {0.f, 0.f, (far + near) / (far - near), 2 * near * far / (far - near)}, - {0.f, 0.f, -1.f, 0.f}, + return Matrix( + { + {GetFloat1() * 2.f * near / (right - left), 0.f, (right + left) / (right - left), 0.f}, + {0.f, GetFloat1() * 2.f * near / (top - bottom), (top + bottom) / (top - bottom), 0.f}, + {0.f, 0.f, (far + near) / (far - near), 2.f * near * far / (far - near)}, + {0.f, 0.f, 1.f, 0.f}, }); } From f447752c6fd4cdbaa433e611bbde170a0d160d3a Mon Sep 17 00:00:00 2001 From: Orange Date: Wed, 28 Aug 2024 17:50:22 +0300 Subject: [PATCH 13/15] changed world to screen --- source/projection/Camera.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index ee11876..e7ae0f9 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -38,23 +38,18 @@ namespace omath::projection Matrix Camera::GetProjectionMatrix() const { - const float right = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); - const float left = -right; - - const float verticalFov = angles::DegreesToRadians(m_fieldOfView) * (m_viewPort.y / m_viewPort.x); - - const float top = std::tan(verticalFov / 2.f); - const float bottom = -top; + const float fovHalfTan = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); + const auto aspectRatio = m_viewPort.x / m_viewPort.y; const auto far = m_farPlaneDistance; const auto near = m_nearPlaneDistance; return Matrix( { - {GetFloat1() * 2.f * near / (right - left), 0.f, (right + left) / (right - left), 0.f}, - {0.f, GetFloat1() * 2.f * near / (top - bottom), (top + bottom) / (top - bottom), 0.f}, + {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}, + {0.f, 0.f, -1.f, 0.f}, }); } From 67713f52bdc07e724a860691290d29def4d33083 Mon Sep 17 00:00:00 2001 From: Orange Date: Fri, 30 Aug 2024 02:42:58 +0300 Subject: [PATCH 14/15] extracted some methods --- include/omath/Matrix.h | 15 ++++-- include/omath/projection/Camera.h | 13 +++++- source/matrix.cpp | 77 +++++++++++++++++++++++++------ source/projection/Camera.cpp | 60 +++++------------------- tests/UnitTestProjection.cpp | 2 +- 5 files changed, 98 insertions(+), 69 deletions(-) diff --git a/include/omath/Matrix.h b/include/omath/Matrix.h index 9610377..1cb2633 100644 --- a/include/omath/Matrix.h +++ b/include/omath/Matrix.h @@ -2,7 +2,7 @@ #include #include #include - +#include namespace omath { @@ -13,11 +13,20 @@ namespace omath public: Matrix(size_t rows, size_t columns); - explicit Matrix(const std::vector> &rows); + Matrix(const std::initializer_list>& rows); [[nodiscard]] static Matrix ToScreenMatrix(float screenWidth, float screenHeight); + [[nodiscard]] + static Matrix TranslationMatrix(const Vector3& diff); + + [[nodiscard]] + static Matrix OrientationMatrix(const Vector3& forward, const Vector3& right, const Vector3& up); + + [[nodiscard]] + static Matrix ProjectionMatrix(float fielOfView, float aspectRatio,float near, float far); + Matrix(const Matrix &other); Matrix(size_t rows, size_t columns, const float *pRaw); @@ -42,7 +51,7 @@ namespace omath void SetDataFromRaw(const float* pRawMatrix); [[nodiscard]] - Matrix Transpose(); + Matrix Transpose() const; void Set(float val); diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index c96dd16..d389077 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -12,10 +12,19 @@ namespace omath::projection { + class ViewPort final + { + public: + float m_width; + float m_height; + + [[nodiscard]] float AspectRatio() const {return m_width / m_height;} + }; + class Camera { public: - Camera(const Vector3& position, const Vector3& viewAngles, const Vector3& viewPort, float fov, float near, float far); + Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); [[nodiscard]] const Vector3& GetViewAngles() const; static float& GetFloat1(); @@ -29,7 +38,7 @@ namespace omath::projection [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const; - Vector3 m_viewPort; + ViewPort m_viewPort{}; float m_fieldOfView; float m_farPlaneDistance; diff --git a/source/matrix.cpp b/source/matrix.cpp index c6e0d69..cd98ee3 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -1,10 +1,13 @@ #include "omath/Matrix.h" +#include "omath/Vector3.h" +#include "omath/angles.h" + #include -#include "omath/Vector3.h" #include #include #include +#include namespace omath @@ -22,17 +25,26 @@ namespace omath Set(0.f); } - Matrix::Matrix(const std::vector> &rows) + Matrix::Matrix(const std::initializer_list>& rows) { m_rows = rows.size(); - m_columns = rows[0].size(); + m_columns = rows.begin()->size(); + for (const auto& row : rows) + if (row.size() != m_columns) + throw std::invalid_argument("All rows must have the same number of columns."); + m_data = std::make_unique(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]; + size_t i = 0; + for (const auto& row : rows) + { + size_t j = 0; + for (const auto& value : row) + At(i, j++) = value; + ++i; + } } Matrix::Matrix(const Matrix &other) @@ -247,7 +259,7 @@ namespace omath return ((i + j + 2) % 2 == 0) ? tmp : -tmp; } - Matrix Matrix::Transpose() + Matrix Matrix::Transpose() const { Matrix transposed = {m_columns, m_rows}; @@ -298,14 +310,51 @@ namespace omath return Strip(i, j).Determinant(); } - Matrix Matrix::ToScreenMatrix(float screenWidth, float screenHeight) + Matrix Matrix::ToScreenMatrix(const float screenWidth, const 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}, - }); + 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}, + }; + } + + 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 fielOfView, const float aspectRatio, const float near, + const float far) + { + const float fovHalfTan = std::tan(angles::DegreesToRadians(fielOfView) / 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} + }; } const float * Matrix::Raw() const diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index e7ae0f9..63e5578 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -10,8 +10,8 @@ namespace omath::projection { - Camera::Camera(const Vector3 &position, const Vector3 &viewAngles, const Vector3 &viewPort, const float fov, const float near, - const float far) + Camera::Camera(const Vector3 &position, const Vector3 &viewAngles, const ViewPort &viewPort, + const float fov, const float near, const float far) { m_origin = position; m_viewAngles = viewAngles; @@ -21,79 +21,41 @@ namespace omath::projection m_farPlaneDistance = far; } - float & Camera::GetFloat1() { - static float m_float1 = 1.52550f; + float& Camera::GetFloat1() { + static float m_float1 = 0.36689f; return m_float1; } - float & Camera::GetFloat2() { + float& Camera::GetFloat2() { static float m_float2 = 1.14500f; return m_float2; } Matrix Camera::GetViewMatrix() const - { - return GetTranslationMatrix() * GetOrientationMatrix(); - } - - Matrix Camera::GetProjectionMatrix() const - { - const float fovHalfTan = std::tan(angles::DegreesToRadians(m_fieldOfView) / 2.f); - const auto aspectRatio = m_viewPort.x / m_viewPort.y; - - const auto far = m_farPlaneDistance; - const auto near = m_nearPlaneDistance; - - return Matrix( - { - {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}, - }); - } - - Matrix Camera::GetTranslationMatrix() const - { - return Matrix( - { - {1.f, 0.f, 0.f, 0.f}, - {0.f, 1.f, 0.f, 0.f}, - {0.f, 0.f, 1.f, 0.f}, - {-m_origin.x, -m_origin.y, -m_origin.z, 1.f}, - }); - } - - Matrix Camera::GetOrientationMatrix() 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 Matrix( - { - {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 Matrix::TranslationMatrix(-m_origin) * Matrix::OrientationMatrix(forward, right, up); } std::expected Camera::WorldToScreen(const Vector3 &worldPosition) const { const auto posVecAsMatrix = Matrix({{worldPosition.x, worldPosition.y, worldPosition.z, 1.f}}); - const auto viewProjectionMatrix = GetViewMatrix() * GetProjectionMatrix(); - auto projected = posVecAsMatrix * viewProjectionMatrix; + const auto projectionMatrix = Matrix::ProjectionMatrix(m_fieldOfView, m_viewPort.AspectRatio(), + m_nearPlaneDistance, m_farPlaneDistance); + + auto projected = posVecAsMatrix * (GetViewMatrix() * projectionMatrix); if (projected.At(0, 3) <= 0.f) return std::unexpected("Projection point is out of camera field of view"); projected /= projected.At(0, 3); - projected *= Matrix::ToScreenMatrix(m_viewPort.x, m_viewPort.y); + projected *= Matrix::ToScreenMatrix(m_viewPort.m_width, m_viewPort.m_height); return Vector3{projected.At(0, 0), projected.At(0, 1), projected.At(0, 2)}; } diff --git a/tests/UnitTestProjection.cpp b/tests/UnitTestProjection.cpp index dcd5d4c..2d92930 100644 --- a/tests/UnitTestProjection.cpp +++ b/tests/UnitTestProjection.cpp @@ -9,7 +9,7 @@ TEST(UnitTestProjection, IsPointOnScreen) { - const omath::projection::Camera camera({0, 0, 0}, {0, 0.f, 0.f} , {1920.f, 1080.f, 0.f}, 110, 0.1, 500); + const omath::projection::Camera camera({0.f, 0.f, 0.f}, {0, 0.f, 0.f} , {1920.f, 1080.f}, 110.f, 0.1f, 500.f); const auto proj = camera.WorldToScreen({100, 0, 15}); if (proj) From a5dbf040d34a5bd1250d4dc3443009a95cbd3027 Mon Sep 17 00:00:00 2001 From: Orange Date: Fri, 30 Aug 2024 02:56:22 +0300 Subject: [PATCH 15/15] removed debug methods --- include/omath/projection/Camera.h | 5 +---- source/projection/Camera.cpp | 10 ---------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/include/omath/projection/Camera.h b/include/omath/projection/Camera.h index d389077..4bbd069 100644 --- a/include/omath/projection/Camera.h +++ b/include/omath/projection/Camera.h @@ -26,11 +26,8 @@ namespace omath::projection public: Camera(const Vector3& position, const Vector3& viewAngles, const ViewPort& viewPort, float fov, float near, float far); void SetViewAngles(const Vector3& viewAngles); + [[nodiscard]] const Vector3& GetViewAngles() const; - static float& GetFloat1(); - - static float& GetFloat2(); - [[nodiscard]] Matrix GetViewMatrix() const; [[nodiscard]] Matrix GetProjectionMatrix() const; [[nodiscard]] Matrix GetTranslationMatrix() const; diff --git a/source/projection/Camera.cpp b/source/projection/Camera.cpp index 63e5578..49bb12c 100644 --- a/source/projection/Camera.cpp +++ b/source/projection/Camera.cpp @@ -21,16 +21,6 @@ namespace omath::projection m_farPlaneDistance = far; } - float& Camera::GetFloat1() { - static float m_float1 = 0.36689f; - return m_float1; - } - - float& Camera::GetFloat2() { - static float m_float2 = 1.14500f; - return m_float2; - } - Matrix Camera::GetViewMatrix() const { const auto forward = Vector3::ForwardVector(m_viewAngles.x, m_viewAngles.y);