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