diff --git a/include/omath/Angle.hpp b/include/omath/Angle.hpp index b46da50..26c6ebf 100644 --- a/include/omath/Angle.hpp +++ b/include/omath/Angle.hpp @@ -144,5 +144,11 @@ namespace omath { return operator+(-other); } + + [[nodiscard]] + constexpr Angle operator-() const + { + return {-m_angle}; + } }; } diff --git a/include/omath/Mat.hpp b/include/omath/Mat.hpp index 84628da..66ade7e 100644 --- a/include/omath/Mat.hpp +++ b/include/omath/Mat.hpp @@ -349,7 +349,7 @@ namespace omath template [[nodiscard]] - Mat<4, 4, Type, St> RotationMatAxisX(const Angle& angle) noexcept + Mat<4, 4, Type, St> MatRotationAxisX(const Angle& angle) noexcept { return { @@ -362,7 +362,7 @@ namespace omath template [[nodiscard]] - Mat<4, 4, Type, St> RotationMatAxisY(const Angle& angle) noexcept + Mat<4, 4, Type, St> MatRotationAxisY(const Angle& angle) noexcept { return { @@ -375,21 +375,36 @@ namespace omath template [[nodiscard]] - Mat<4, 4, Type, St> RotationMatAxisZ(const Angle& angle) noexcept + 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}, + {angle.Sin(), angle.Cos(), 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1}, }; } + template + [[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(-cameraOrigin); + } + template [[nodiscard]] - Mat<4, 4, Type, St> RotationMat(const ViewAngles& angles) noexcept + Mat<4, 4, Type, St> MatRotation(const ViewAngles& angles) noexcept { - return RotationMatAxisZ(angles.yaw) * RotationMatAxisY(angles.pitch) * RotationMatAxisX(angles.roll); + return MatRotationAxisZ(angles.yaw) * MatRotationAxisY(angles.pitch) * MatRotationAxisX(angles.roll); } } // namespace omath diff --git a/include/omath/engines/OpenGL/Constants.hpp b/include/omath/engines/OpenGL/Constants.hpp new file mode 100644 index 0000000..aec3520 --- /dev/null +++ b/include/omath/engines/OpenGL/Constants.hpp @@ -0,0 +1,14 @@ +// +// Created by Orange on 12/4/2024. +// +#pragma once + +#include + + +namespace omath::opengl +{ + constexpr Vector3 kAbsUp = {0, 1, 0}; + constexpr Vector3 kAbsRight = {1, 0, 0}; + constexpr Vector3 kAbsForward = {0, 0, -1}; +} \ No newline at end of file diff --git a/include/omath/engines/OpenGL/Formulas.hpp b/include/omath/engines/OpenGL/Formulas.hpp new file mode 100644 index 0000000..2a50756 --- /dev/null +++ b/include/omath/engines/OpenGL/Formulas.hpp @@ -0,0 +1,4 @@ +// +// Created by Orange on 12/4/2024. +// +#pragma once \ No newline at end of file diff --git a/include/omath/engines/opengl.hpp b/include/omath/engines/OpenGL/OpenGL.hpp similarity index 100% rename from include/omath/engines/opengl.hpp rename to include/omath/engines/OpenGL/OpenGL.hpp diff --git a/include/omath/engines/Source/Camera.hpp b/include/omath/engines/Source/Camera.hpp index 7e73c98..aca13cf 100644 --- a/include/omath/engines/Source/Camera.hpp +++ b/include/omath/engines/Source/Camera.hpp @@ -10,11 +10,8 @@ namespace omath::source class Camera final : public projection::Camera { public: - Camera(const Vector3& position, const ViewAngles& viewAngles, - const projection::ViewPort& viewPort, const Angle& fov, float near, const float far) : - projection::Camera(position, viewAngles, viewPort, fov, near, far) - { - } + Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort, + const Angle& fov, float near, float far); void LookAt(const Vector3& target) override; [[nodiscard]] Mat4x4 GetViewMatrix() const override; [[nodiscard]] Mat4x4 GetProjectionMatrix() const override; diff --git a/include/omath/engines/Source/Constants.h b/include/omath/engines/Source/Constants.h index f77b195..ecf1b40 100644 --- a/include/omath/engines/Source/Constants.h +++ b/include/omath/engines/Source/Constants.h @@ -15,7 +15,7 @@ namespace omath::source 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; using YawAngle = Angle; using RollAngle = Angle; diff --git a/include/omath/engines/Source/Formulas.hpp b/include/omath/engines/Source/Formulas.hpp index 8a9c9e8..652f263 100644 --- a/include/omath/engines/Source/Formulas.hpp +++ b/include/omath/engines/Source/Formulas.hpp @@ -10,7 +10,7 @@ namespace omath::source [[nodiscard]] inline Vector3 ForwardVector(const ViewAngles& angles) { - const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsForward); + const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsForward); return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)}; } @@ -18,7 +18,7 @@ namespace omath::source [[nodiscard]] inline Vector3 RightVector(const ViewAngles& angles) { - const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsRight); + const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsRight); return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)}; } @@ -26,42 +26,33 @@ namespace omath::source [[nodiscard]] inline Vector3 UpVector(const ViewAngles& angles) { - const auto vec = RotationMat(angles) * MatColumnFromVector(kAbsUp); + const auto vec = MatRotation(angles) * MatColumnFromVector(kAbsUp); return {vec.At(0, 0), vec.At(1, 0), vec.At(2, 0)}; } - [[nodiscard]] - constexpr Mat4x4 ViewMatrixFromVecs(const Vector3& forward, const Vector3& right, const Vector3& up, - const Vector3& camera_pos) + [[nodiscard]] inline Mat4x4 CalcViewMatrix(const ViewAngles& angles, const Vector3& cam_origin) { - return Mat4x4{ - {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(-camera_pos); - } - - [[nodiscard]] inline Mat4x4 ViewMatrix(const ViewAngles& angles, const Vector3& cam_origin) - { - return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin); + return MatCameraView(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin); } [[nodiscard]] - inline Mat4x4 PerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far) + 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}, - }; + {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 diff --git a/include/omath/projection/Camera.hpp b/include/omath/projection/Camera.hpp index a6723a1..15db451 100644 --- a/include/omath/projection/Camera.hpp +++ b/include/omath/projection/Camera.hpp @@ -25,6 +25,7 @@ namespace omath::projection return m_width / m_height; } }; + using FieldOfView = const Angle; template class Camera @@ -33,7 +34,7 @@ namespace omath::projection public: virtual ~Camera() = default; Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort, - const Angle& fov, const float near, const float far) : + 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) { @@ -48,15 +49,12 @@ namespace omath::projection [[nodiscard]] Mat4x4Type GetViewProjectionMatrix() { - if (!m_viewProjectionMatrix) - m_viewProjectionMatrix = GetProjectionMatrix() * GetViewMatrix(); - - return m_viewProjectionMatrix.value(); + return GetProjectionMatrix() * GetViewMatrix(); } - [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) + [[nodiscard]] std::expected WorldToScreen(const Mat4x4Type& viewProj, const Vector3& worldPosition) const { - auto projected = GetViewProjectionMatrix() * MatColumnFromVector(worldPosition); + auto projected = viewProj * MatColumnFromVector(worldPosition); if (projected.At(3, 0) == 0.0f) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); @@ -66,7 +64,7 @@ namespace omath::projection if (IsNdcOutOfBounds(projected)) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); - return Vector3{++projected.At(0,0) / 2 * m_viewPort.m_width , ++projected.At(1,0) / 2 * m_viewPort.m_height, projected.At(2,0)}; + 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: @@ -81,7 +79,6 @@ namespace omath::projection Vector3 m_origin; private: - std::optional m_viewProjectionMatrix = std::nullopt; template [[nodiscard]] constexpr static bool IsNdcOutOfBounds(const Type& ndc) diff --git a/source/engines/Source/Camera.cpp b/source/engines/Source/Camera.cpp index 285d930..51eb507 100644 --- a/source/engines/Source/Camera.cpp +++ b/source/engines/Source/Camera.cpp @@ -8,6 +8,11 @@ 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(position, viewAngles, viewPort, fov, near, far) + { + } void Camera::LookAt(const Vector3& target) { const float distance = m_origin.DistTo(target); @@ -15,17 +20,17 @@ namespace omath::source m_viewAngles.pitch = PitchAngle::FromRadians(std::asin(delta.z / distance)); - m_viewAngles.yaw = YawAngle::FromRadians(std::atan2(delta.y, delta.x)); + m_viewAngles.yaw = -YawAngle::FromRadians(std::atan2(delta.y, delta.x)); m_viewAngles.roll = RollAngle::FromRadians(0.f); } Mat4x4 Camera::GetViewMatrix() const { - return ViewMatrix(m_viewAngles, m_origin); + return CalcViewMatrix(m_viewAngles, m_origin); } Mat4x4 Camera::GetProjectionMatrix() const { - return PerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); + return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); } } // namespace omath::source diff --git a/tests/engines/UnitTestOpenGL.cpp b/tests/engines/UnitTestOpenGL.cpp index 1ea9459..46f5afc 100644 --- a/tests/engines/UnitTestOpenGL.cpp +++ b/tests/engines/UnitTestOpenGL.cpp @@ -5,7 +5,7 @@ #include #include #include -#include + // #include // #include "glm/ext/matrix_clip_space.hpp" @@ -34,14 +34,4 @@ TEST(UnitTestOpenGL, Projection) //auto ndc_omath = proj_omath * cords_omath; // ndc_omath /= ndc_omath.At(3, 0); */ -} -TEST(UnitTestOpenGL, Projection2) -{ - const auto orient = omath::opengl::ViewMatrix(omath::opengl::kAbsForward, -omath::opengl::kAbsRight, omath::opengl::kAbsUp, {}); - - const omath::Mat<4, 1,float, omath::MatStoreType::COLUMN_MAJOR> cords_omath = - { - {0}, {0}, {-10}, {1} - }; - std::cout << (orient * cords_omath).ToString(); } \ No newline at end of file diff --git a/tests/engines/UnitTestSourceEngine.cpp b/tests/engines/UnitTestSourceEngine.cpp index 28a5805..9ec3ae5 100644 --- a/tests/engines/UnitTestSourceEngine.cpp +++ b/tests/engines/UnitTestSourceEngine.cpp @@ -2,16 +2,14 @@ // Created by Orange on 11/23/2024. // #include +#include #include #include - - - TEST(UnitTestSourceEngine, ForwardVector) { - const auto forward = omath::source::ForwardVector({}); + const auto forward = omath::source::ForwardVector({{}, {}, {}}); EXPECT_EQ(forward, omath::source::kAbsForward); } @@ -27,4 +25,26 @@ 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); + } } \ No newline at end of file diff --git a/tests/general/UnitTestProjection.cpp b/tests/general/UnitTestProjection.cpp index 70fce84..ab8b71c 100644 --- a/tests/general/UnitTestProjection.cpp +++ b/tests/general/UnitTestProjection.cpp @@ -11,8 +11,8 @@ TEST(UnitTestProjection, Projection) { auto x = omath::Angle::FromDegrees(90.f); - auto cam = omath::source::Camera({-10, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.1f, 1000.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({10, 0, 0}); + const auto projected = cam.WorldToScreen(cam.GetViewProjectionMatrix(), {1000, 0, 50}); std::print("{} {} {}", projected->x, projected->y, projected->z); } \ No newline at end of file