From 931937d010ede8eb4dafb4517eb6c9b4801379cf Mon Sep 17 00:00:00 2001 From: Orange Date: Mon, 23 Dec 2024 17:53:47 +0300 Subject: [PATCH] added open gl stuff --- CMakeLists.txt | 5 +- include/omath/engines/OpenGL/Camera.hpp | 19 +++++ include/omath/engines/OpenGL/Constants.hpp | 25 ++++++ include/omath/engines/OpenGL/Formulas.hpp | 54 +++++++++++++ include/omath/engines/Source/Camera.hpp | 2 +- .../Source/{Constants.h => Constants.hpp} | 0 include/omath/engines/Source/Formulas.hpp | 2 +- include/omath/projection/Camera.hpp | 5 +- source/engines/CMakeLists.txt | 3 +- source/engines/OpenGL/CMakeLists.txt | 1 + source/engines/OpenGL/Camera.cpp | 35 ++++++++ source/engines/Source/Camera.cpp | 5 +- tests/engines/UnitTestOpenGL.cpp | 80 +++++++++++++------ tests/engines/UnitTestSourceEngine.cpp | 2 +- 14 files changed, 206 insertions(+), 32 deletions(-) create mode 100644 include/omath/engines/OpenGL/Camera.hpp create mode 100644 include/omath/engines/OpenGL/Constants.hpp create mode 100644 include/omath/engines/OpenGL/Formulas.hpp rename include/omath/engines/Source/{Constants.h => Constants.hpp} (100%) create mode 100644 source/engines/OpenGL/CMakeLists.txt create mode 100644 source/engines/OpenGL/Camera.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9af2110..08132d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,10 @@ option(OMATH_BUILD_AS_SHARED_LIBRARY "Build Omath as .so or .dll" OFF) if (OMATH_BUILD_AS_SHARED_LIBRARY) add_library(omath SHARED source/Vector3.cpp) else() - add_library(omath STATIC source/Vector3.cpp) + add_library(omath STATIC source/Vector3.cpp + include/omath/engines/OpenGL/Constants.hpp + include/omath/engines/OpenGL/Formulas.hpp + include/omath/engines/OpenGL/Camera.hpp) endif() target_compile_definitions(omath PUBLIC OMATH_EXPORT) diff --git a/include/omath/engines/OpenGL/Camera.hpp b/include/omath/engines/OpenGL/Camera.hpp new file mode 100644 index 0000000..0ad9729 --- /dev/null +++ b/include/omath/engines/OpenGL/Camera.hpp @@ -0,0 +1,19 @@ +// +// Created by Orange on 12/23/2024. +// +#pragma once +#include "Constants.hpp" +#include "omath/projection/Camera.hpp" + +namespace omath::opengl +{ + class Camera final : public projection::Camera + { + public: + 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 CalcViewMatrix() const override; + [[nodiscard]] Mat4x4 CalcProjectionMatrix() const override; + }; +} \ No newline at end of file diff --git a/include/omath/engines/OpenGL/Constants.hpp b/include/omath/engines/OpenGL/Constants.hpp new file mode 100644 index 0000000..a8912a2 --- /dev/null +++ b/include/omath/engines/OpenGL/Constants.hpp @@ -0,0 +1,25 @@ +// +// Created by Orange on 12/23/2024. +// +#pragma once + +#include +#include +#include +#include + +namespace omath::opengl +{ + constexpr Vector3 kAbsUp = {0, 1, 0}; + constexpr Vector3 kAbsRight = {1, 0, 0}; + constexpr Vector3 kAbsForward = {0, 0, -1}; + + using Mat4x4 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>; + using Mat3x3 = Mat<4, 4, float, MatStoreType::COLUMN_MAJOR>; + using Mat1x3 = Mat<1, 3, float, MatStoreType::COLUMN_MAJOR>; + using PitchAngle = Angle; + using YawAngle = Angle; + using RollAngle = Angle; + + using ViewAngles = omath::ViewAngles; +} \ 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..8e6b2ed --- /dev/null +++ b/include/omath/engines/OpenGL/Formulas.hpp @@ -0,0 +1,54 @@ +// +// Created by Orange on 12/23/2024. +// +#pragma once +#include "Constants.hpp" + + +namespace omath::opengl +{ + [[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) + { + const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2.f); + + 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}, + + }; + } +} \ No newline at end of file diff --git a/include/omath/engines/Source/Camera.hpp b/include/omath/engines/Source/Camera.hpp index 53641f2..739aa86 100644 --- a/include/omath/engines/Source/Camera.hpp +++ b/include/omath/engines/Source/Camera.hpp @@ -2,7 +2,7 @@ // Created by Orange on 12/4/2024. // #pragma once -#include "Constants.h" +#include "Constants.hpp" #include "omath/projection/Camera.hpp" namespace omath::source diff --git a/include/omath/engines/Source/Constants.h b/include/omath/engines/Source/Constants.hpp similarity index 100% rename from include/omath/engines/Source/Constants.h rename to include/omath/engines/Source/Constants.hpp diff --git a/include/omath/engines/Source/Formulas.hpp b/include/omath/engines/Source/Formulas.hpp index 3c8a6d7..0b8ff03 100644 --- a/include/omath/engines/Source/Formulas.hpp +++ b/include/omath/engines/Source/Formulas.hpp @@ -2,7 +2,7 @@ // Created by Orange on 12/4/2024. // #pragma once -#include "Constants.h" +#include "Constants.hpp" namespace omath::source { diff --git a/include/omath/projection/Camera.hpp b/include/omath/projection/Camera.hpp index 381aee6..95f4eb0 100644 --- a/include/omath/projection/Camera.hpp +++ b/include/omath/projection/Camera.hpp @@ -126,7 +126,10 @@ namespace omath::projection 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)}; + const auto screenPositionX = (projected.At(0,0)+1.f) / 2.f * m_viewPort.m_width; + const auto screenPositionY = (-projected.At(1,0)+1) / 2.f * m_viewPort.m_height; + + return Vector3{screenPositionX, screenPositionY, projected.At(2,0)}; } protected: diff --git a/source/engines/CMakeLists.txt b/source/engines/CMakeLists.txt index f01db76..2d2a3c9 100644 --- a/source/engines/CMakeLists.txt +++ b/source/engines/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(Source) \ No newline at end of file +add_subdirectory(Source) +add_subdirectory(OpenGL) \ No newline at end of file diff --git a/source/engines/OpenGL/CMakeLists.txt b/source/engines/OpenGL/CMakeLists.txt new file mode 100644 index 0000000..0abf868 --- /dev/null +++ b/source/engines/OpenGL/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(omath PRIVATE Camera.cpp) \ No newline at end of file diff --git a/source/engines/OpenGL/Camera.cpp b/source/engines/OpenGL/Camera.cpp new file mode 100644 index 0000000..9ad5a47 --- /dev/null +++ b/source/engines/OpenGL/Camera.cpp @@ -0,0 +1,35 @@ +// +// Created by Orange on 12/23/2024. +// +#include "omath/engines/OpenGL/Camera.hpp" +#include "omath/engines/OpenGL/Formulas.hpp" + + +namespace omath::opengl +{ + + Camera::Camera(const Vector3& position, const ViewAngles& viewAngles, const projection::ViewPort& viewPort, + const Angle& fov, const float near, const float far) : + projection::Camera(position, viewAngles, viewPort, fov, near, far) + { + } + void Camera::LookAt([[maybe_unused]] 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::CalcViewMatrix() const + { + return opengl::CalcViewMatrix(m_viewAngles, m_origin); + } + Mat4x4 Camera::CalcProjectionMatrix() const + { + return CalcPerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, + m_farPlaneDistance); + } +} // namespace omath::opengl diff --git a/source/engines/Source/Camera.cpp b/source/engines/Source/Camera.cpp index 370e2bd..444e208 100644 --- a/source/engines/Source/Camera.cpp +++ b/source/engines/Source/Camera.cpp @@ -26,11 +26,12 @@ namespace omath::source Mat4x4 Camera::CalcViewMatrix() const { - return source::CalcViewMatrix(m_viewAngles, m_origin); + return source::CalcViewMatrix(m_viewAngles, m_origin); } Mat4x4 Camera::CalcProjectionMatrix() const { - return CalcPerspectiveProjectionMatrix(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 46f5afc..461d9d2 100644 --- a/tests/engines/UnitTestOpenGL.cpp +++ b/tests/engines/UnitTestOpenGL.cpp @@ -1,37 +1,69 @@ // // Created by Orange on 11/23/2024. // -#include #include -#include -#include - -// #include - -// #include "glm/ext/matrix_clip_space.hpp" -// #include "glm/ext/matrix_transform.hpp" +#include +#include +#include -TEST(UnitTestOpenGL, Projection) +TEST(UnitTestOpenGL, ForwardVector) { + const auto forward = omath::opengl::ForwardVector({}); - /*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); + EXPECT_EQ(forward, omath::opengl::kAbsForward); +} + +TEST(UnitTestOpenGL, RightVector) +{ + const auto right = omath::opengl::RightVector({}); + + EXPECT_EQ(right, omath::opengl::kAbsRight); +} + +TEST(UnitTestOpenGL, UpVector) +{ + const auto up = omath::opengl::UpVector({}); + EXPECT_EQ(up, omath::opengl::kAbsUp); +} + +TEST(UnitTestOpenGL, ProjectTargetMovedFromCamera) +{ + constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); + auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); - 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 = + for (float distance = -10.f; distance > -1000.f; distance -= 0.01f) { - {0}, - {0}, - {-0.2f}, - {1} - }; + const auto projected = cam.WorldToScreen({0, 0, distance}); - //auto ndc_omath = proj_omath * cords_omath; - // ndc_omath /= ndc_omath.At(3, 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); + } +} + +TEST(UnitTestOpenGL, CameraSetAndGetFov) +{ + constexpr auto fov = omath::projection::FieldOfView::FromDegrees(90.f); + auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, fov, 0.01f, 1000.f); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 90.f); + cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f)); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f); +} + +TEST(UnitTestOpenGL, CameraSetAndGetOrigin) +{ + auto cam = omath::opengl::Camera({0, 0, 0}, {}, {1920.f, 1080.f}, {}, 0.01f, 1000.f); + + EXPECT_EQ(cam.GetOrigin(), omath::Vector3{}); + cam.SetFieldOfView(omath::projection::FieldOfView::FromDegrees(50.f)); + + EXPECT_EQ(cam.GetFieldOfView().AsDegrees(), 50.f); } \ No newline at end of file diff --git a/tests/engines/UnitTestSourceEngine.cpp b/tests/engines/UnitTestSourceEngine.cpp index 2313ae3..cb73a44 100644 --- a/tests/engines/UnitTestSourceEngine.cpp +++ b/tests/engines/UnitTestSourceEngine.cpp @@ -3,7 +3,7 @@ // #include #include -#include +#include #include