From 0afa20b4e5d763213c03cc3a89f75a3c325cafa9 Mon Sep 17 00:00:00 2001 From: Orange Date: Wed, 4 Dec 2024 04:58:29 +0300 Subject: [PATCH] refactored camera --- include/omath/Angle.hpp | 2 +- include/omath/Mat.hpp | 50 +++++++- include/omath/engines/Source/Camera.hpp | 22 ++++ include/omath/engines/Source/Constants.h | 24 ++++ include/omath/engines/Source/Formulas.hpp | 98 ++++++++++++++++ include/omath/engines/opengl.hpp | 44 ++++--- include/omath/engines/source.hpp | 135 ---------------------- include/omath/projection/Camera.hpp | 33 ++---- source/CMakeLists.txt | 3 +- source/engines/CMakeLists.txt | 1 + source/engines/Source/CMakeLists.txt | 1 + source/engines/Source/Camera.cpp | 31 +++++ source/prediction/Projectile.cpp | 4 +- tests/engines/UnitTestOpenGL.cpp | 1 - tests/engines/UnitTestSourceEngine.cpp | 3 +- tests/general/UnitTestProjection.cpp | 4 +- 16 files changed, 262 insertions(+), 194 deletions(-) create mode 100644 include/omath/engines/Source/Camera.hpp create mode 100644 include/omath/engines/Source/Constants.h create mode 100644 include/omath/engines/Source/Formulas.hpp delete mode 100644 include/omath/engines/source.hpp create mode 100644 source/engines/CMakeLists.txt create mode 100644 source/engines/Source/CMakeLists.txt create mode 100644 source/engines/Source/Camera.cpp diff --git a/include/omath/Angle.hpp b/include/omath/Angle.hpp index 9b5c64f..7d50e93 100644 --- a/include/omath/Angle.hpp +++ b/include/omath/Angle.hpp @@ -16,7 +16,7 @@ namespace omath Clamped = 1, }; - template + template requires std::is_arithmetic_v class Angle { diff --git a/include/omath/Mat.hpp b/include/omath/Mat.hpp index a3f1807..3059dd3 100644 --- a/include/omath/Mat.hpp +++ b/include/omath/Mat.hpp @@ -320,23 +320,23 @@ namespace omath std::array m_data; }; - template + template [[nodiscard]] - constexpr static Mat<1, 4, T, St> MatRowFromVector(const Vector3& vector) noexcept + constexpr static Mat<1, 4, Type, St> MatRowFromVector(const Vector3& vector) noexcept { return {{vector.x, vector.y, vector.z, 1}}; } - template + template [[nodiscard]] - constexpr static Mat<4, 1, T, St> MatColumnFromVector(const Vector3& vector) noexcept + constexpr static Mat<4, 1, Type, St> MatColumnFromVector(const Vector3& vector) noexcept { return {{vector.x}, {vector.y}, {vector.z}, {1}}; } - template + template [[nodiscard]] - constexpr Mat<4, 4, T, St> MatTranslation(const Vector3& diff) noexcept + constexpr Mat<4, 4, Type, St> MatTranslation(const Vector3& diff) noexcept { return { @@ -346,4 +346,42 @@ namespace omath {0, 0, 0, 1}, }; } + + template + [[nodiscard]] + constexpr Mat<3, 3, Type, St> RotationMatrixAxisX(const Angle& roll) noexcept + { + return + { + {1, 0, 0}, + {0, 0, roll.Cos(), -roll.Sin()}, + {0, 0, roll.Sin(), roll.Cos()}, + }; + } + + template + [[nodiscard]] + constexpr Mat<3, 3, Type, St> RotationMatrixAxisY(const Angle& pitch) noexcept + { + return + { + {pitch.Cos(), 0, pitch.Sin()}, + {0 , 1, 0}, + {-pitch.Sin(), 0, pitch.Cos()}, + }; + } + + template + [[nodiscard]] + constexpr Mat<3, 3, Type, St> RotationMatrixAxisZ(const Angle& Yaw) noexcept + { + return + { + {Yaw.Cos(), -Yaw.Sin(), 0}, + {Yaw.Sin(), Yaw.Cos(), 0}, + {0, 0, 1}, + }; + } + + } // namespace omath diff --git a/include/omath/engines/Source/Camera.hpp b/include/omath/engines/Source/Camera.hpp new file mode 100644 index 0000000..7e73c98 --- /dev/null +++ b/include/omath/engines/Source/Camera.hpp @@ -0,0 +1,22 @@ +// +// Created by Orange on 12/4/2024. +// +#pragma once +#include "Constants.h" +#include "omath/projection/Camera.hpp" + +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) + { + } + void LookAt(const Vector3& target) override; + [[nodiscard]] Mat4x4 GetViewMatrix() const override; + [[nodiscard]] Mat4x4 GetProjectionMatrix() const override; + }; +} \ No newline at end of file diff --git a/include/omath/engines/Source/Constants.h b/include/omath/engines/Source/Constants.h new file mode 100644 index 0000000..f77b195 --- /dev/null +++ b/include/omath/engines/Source/Constants.h @@ -0,0 +1,24 @@ +// +// Created by Orange on 12/4/2024. +// +#pragma once + +#include +#include +#include +#include +namespace omath::source +{ + constexpr Vector3 kAbsUp = {0, 0, 1}; + constexpr Vector3 kAbsRight = {0, -1, 0}; + constexpr Vector3 kAbsForward = {1, 0, 0}; + + using Mat4x4 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>; + using Mat3x3 = Mat<4, 4, float, MatStoreType::ROW_MAJOR>; + + using PitchAngle = Angle; + using YawAngle = Angle; + using RollAngle = Angle; + + using ViewAngles = omath::ViewAngles; +} // namespace omath::source diff --git a/include/omath/engines/Source/Formulas.hpp b/include/omath/engines/Source/Formulas.hpp new file mode 100644 index 0000000..39e16c3 --- /dev/null +++ b/include/omath/engines/Source/Formulas.hpp @@ -0,0 +1,98 @@ +// +// Created by Orange on 12/4/2024. +// +#pragma once +#include "Constants.h" + + +namespace omath::source +{ + [[nodiscard]] + inline Vector3 ForwardVector(const ViewAngles& angles) + { + const auto cosPitch = angles.pitch.Cos(); + const auto sinPitch = angles.pitch.Sin(); + + const auto cosYaw = angles.yaw.Cos(); + const auto sinYaw = angles.yaw.Sin(); + + + return {cosPitch * cosYaw, cosPitch * sinYaw, -sinPitch}; + } + + [[nodiscard]] + inline Vector3 RightVector(const ViewAngles& angles) + { + const auto cosPitch = angles.pitch.Cos(); + const auto sinPitch = angles.pitch.Sin(); + + const auto cosYaw = angles.yaw.Cos(); + const auto sinYaw = angles.yaw.Sin(); + + const auto cosRoll = angles.roll.Cos(); + const auto sinRoll = angles.roll.Sin(); + + + return + { + -1 * sinRoll * sinPitch * cosYaw + -1 * cosRoll * -sinYaw, + -1 * sinRoll * sinPitch * sinYaw + -1 * cosRoll * cosYaw, + -1 * sinRoll * cosPitch + }; + } + + [[nodiscard]] + inline Vector3 UpVector(const ViewAngles& angles) + { + const auto cosPitch = angles.pitch.Cos(); + const auto sinPitch = angles.pitch.Sin(); + + const auto cosYaw = angles.yaw.Cos(); + const auto sinYaw = angles.yaw.Sin(); + + const auto cosRoll = angles.roll.Cos(); + const auto sinRoll = angles.roll.Sin(); + + + return + { + cosRoll * sinPitch * cosYaw + - sinRoll * -sinYaw, + cosRoll * sinPitch * sinYaw + - sinRoll * cosYaw, + cosRoll * cosPitch, + }; + } + + [[nodiscard]] + constexpr Mat4x4 ViewMatrixFromVecs(const Vector3& forward, const Vector3& right, const Vector3& up, + const Vector3& camera_pos) + { + 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); + } + + + [[nodiscard]] + inline Mat4x4 PerspectiveProjectionMatrix(const float fieldOfView, const float aspectRatio, const float near, const float far) + { + 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}, + }; + } +} // namespace omath::source diff --git a/include/omath/engines/opengl.hpp b/include/omath/engines/opengl.hpp index 78d7821..68edf9d 100644 --- a/include/omath/engines/opengl.hpp +++ b/include/omath/engines/opengl.hpp @@ -2,9 +2,10 @@ // Created by Orange on 11/23/2024. // #pragma once -#include "omath/Vector3.hpp" -#include "omath/Mat.hpp" + #include "omath/Angle.hpp" +#include "omath/Mat.hpp" +#include "omath/Vector3.hpp" namespace omath::opengl { @@ -14,34 +15,31 @@ namespace omath::opengl template - requires std::is_floating_point_v || std::is_integral_v - [[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> ViewMatrix(const Vector3& forward, - const Vector3& right, - const Vector3& up, - const Vector3& cam_origin) + requires std::is_arithmetic_v + [[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> ViewMatrix(const Vector3& forward, const Vector3& right, + const Vector3& up, const Vector3& cam_origin) { - return + return Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> { - {right.x, up.x, -forward.x, 0}, - {right.y, up.y, -forward.y, 0}, - {right.z, up.z, -forward.z, 0}, - {-cam_origin.x, -cam_origin.y, -cam_origin.z, 1}, - }; + {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(-cam_origin); } template - requires std::is_floating_point_v || std::is_integral_v - [[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> PerspectiveProjectionMatrix( - const float fieldOfView, const Type& aspectRatio, const Type& near, const Type& far) + requires std::is_arithmetic_v + [[nodiscard]] Mat<4, 4, Type, MatStoreType::COLUMN_MAJOR> + PerspectiveProjectionMatrix(const float fieldOfView, const Type& aspectRatio, const Type& near, const Type& far) { const float fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2); - return - { - {static_cast(1) / (aspectRatio * fovHalfTan), 0, 0, 0}, - {0, static_cast(1) / (fovHalfTan), 0, 0}, - {0, 0, -(far + near) / (far - near), -(static_cast(2) * far * near) / (far - near)}, - {0, 0, -1, 0}, + return { + {static_cast(1) / (aspectRatio * fovHalfTan), 0, 0, 0}, + {0, static_cast(1) / (fovHalfTan), 0, 0}, + {0, 0, -(far + near) / (far - near), -(static_cast(2) * far * near) / (far - near)}, + {0, 0, -1, 0}, }; } -} +} // namespace omath::opengl diff --git a/include/omath/engines/source.hpp b/include/omath/engines/source.hpp deleted file mode 100644 index cabbaea..0000000 --- a/include/omath/engines/source.hpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Created by Orange on 11/24/2024. -// -#pragma once -#include "omath/Mat.hpp" -#include "omath/Vector3.hpp" - -#include -#include -#include - -namespace omath::source -{ - constexpr Vector3 kAbsUp = {0, 0, 1}; - constexpr Vector3 kAbsRight = {0, -1, 0}; - constexpr Vector3 kAbsForward = {1, 0, 0}; - - using PitchAngle = Angle; - using YawAngle = Angle; - using RollAngle = Angle; - - using ViewAngles = omath::ViewAngles; - - - inline Vector3 ForwardVector(const ViewAngles& angles); - inline Vector3 RightVector(const ViewAngles& angles); - inline Vector3 UpVector(const ViewAngles& angles); - - - template - requires std::is_floating_point_v || std::is_integral_v - [[nodiscard]] constexpr Mat<4, 4, Type, MatStoreType::ROW_MAJOR> ViewMatrixFromVecs(const Vector3& forward, const Vector3& right, - const Vector3& up, const Vector3& camera_pos) - { - return Mat<4, 4, Type, MatStoreType::ROW_MAJOR>{ - {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) ; - } - - - template - requires std::is_floating_point_v || std::is_integral_v - [[nodiscard]] Mat<4, 4, Type, MatStoreType::ROW_MAJOR> ViewMatrix(const ViewAngles& angles, const Vector3& cam_origin) - { - return ViewMatrixFromVecs(ForwardVector(angles), RightVector(angles), UpVector(angles), cam_origin); - } - - template - requires std::is_arithmetic_v && std::is_signed_v - [[nodiscard]] Mat<4, 4, Type, MatStoreType::ROW_MAJOR> - PerspectiveProjectionMatrix(const Type& fieldOfView, const Type& aspectRatio, const Type& near, const Type& far) - { - constexpr auto kMultiplyFactor = Type(0.75); - - const Type fovHalfTan = std::tan(angles::DegreesToRadians(fieldOfView) / 2) * kMultiplyFactor; - - return { - {-static_cast(1) / (aspectRatio * fovHalfTan), 0, 0, 0}, - {0, -static_cast(1) / (fovHalfTan), 0, 0}, - {0, 0, (far + near) / (far - near), -(static_cast(2) * far * near) / (far - near)}, - {0, 0, 1, 0}, - }; - } - // Copied from - // https://github.com/ValveSoftware/source-sdk-2013/blob/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/mathlib/mathlib_base.cpp#L919 - [[nodiscard]] - inline Vector3 ForwardVector(const ViewAngles& angles) - { - const auto cosPitch = angles.pitch.Cos(); - const auto sinPitch = angles.pitch.Sin(); - - const auto cosYaw = angles.yaw.Cos(); - const auto sinYaw = angles.yaw.Sin(); - - - return {cosPitch * cosYaw, cosPitch * sinYaw, -sinPitch}; - } - - [[nodiscard]] - inline Vector3 RightVector(const ViewAngles& angles) - { - const auto cosPitch = angles.pitch.Cos(); - const auto sinPitch = angles.pitch.Sin(); - - const auto cosYaw = angles.yaw.Cos(); - const auto sinYaw = angles.yaw.Sin(); - - const auto cosRoll = angles.roll.Cos(); - const auto sinRoll = angles.roll.Sin(); - - - return - { - -1 * sinRoll * sinPitch * cosYaw + -1 * cosRoll * -sinYaw, - -1 * sinRoll * sinPitch * sinYaw + -1 * cosRoll * cosYaw, - -1 * sinRoll * cosPitch - }; - } - - [[nodiscard]] - inline Vector3 UpVector(const ViewAngles& angles) - { - const auto cosPitch = angles.pitch.Cos(); - const auto sinPitch = angles.pitch.Sin(); - - const auto cosYaw = angles.yaw.Cos(); - const auto sinYaw = angles.yaw.Sin(); - - const auto cosRoll = angles.roll.Cos(); - const auto sinRoll = angles.roll.Sin(); - - - return - { - cosRoll * sinPitch * cosYaw + - sinRoll * -sinYaw, - cosRoll * sinPitch * sinYaw + - sinRoll * cosYaw, - cosRoll * cosPitch, - }; - } - using Camera = omath::projection::Camera), decltype(PerspectiveProjectionMatrix)>; - - - // Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort, - // const Angle& fov, const float near, const float far, - // const std::function& viewMatFunc, const std::function& projFunc) - - inline Camera CreateCamera(const Vector3& position, const auto& viewAngles, const projection::ViewPort& viewPort, - const Angle& fov, const float near, const float far) - { - return Camera(position, viewAngles, viewPort, fov, near, far, ViewMatrix, PerspectiveProjectionMatrix); - } -} // namespace omath::source diff --git a/include/omath/projection/Camera.hpp b/include/omath/projection/Camera.hpp index ba87ba6..c94da1f 100644 --- a/include/omath/projection/Camera.hpp +++ b/include/omath/projection/Camera.hpp @@ -26,42 +26,33 @@ namespace omath::projection } }; - template - requires std::is_same_v, - std::invoke_result_t> + template class Camera { public: + virtual ~Camera() = default; Camera(const Vector3& position, const ViewAnglesType& viewAngles, const ViewPort& viewPort, - const Angle& fov, const float near, const float far, - const std::function& viewMatFunc, const std::function& projFunc) : + const Angle& 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), CreateViewMatrix(viewMatFunc), CreateProjectionMatrix(projFunc) + m_viewAngles(viewAngles), m_origin(position) { } - void LookAt(const Vector3& target); + virtual void LookAt(const Vector3& target) = 0; - [[nodiscard]] auto GetViewMatrix() const - { - return CreateViewMatrix(m_viewAngles, m_origin); - } + [[nodiscard]] virtual Mat4x4Type GetViewMatrix() const = 0; - [[nodiscard]] auto GetProjectionMatrix() const - { - return CreateProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); - } + [[nodiscard]] virtual Mat4x4Type GetProjectionMatrix() const = 0; - [[nodiscard]] auto GetViewProjectionMatrix() const + [[nodiscard]] Mat4x4Type GetViewProjectionMatrix() const { return GetProjectionMatrix() * GetViewMatrix(); } [[nodiscard]] std::expected WorldToScreen(const Vector3& worldPosition) const { - using mat = std::invoke_result_t; - auto projected = GetViewProjectionMatrix() * MatColumnFromVector(worldPosition); + auto projected = GetViewProjectionMatrix() * MatColumnFromVector(worldPosition); if (projected.At(3, 0) == 0.0f) return std::unexpected(Error::WORLD_POSITION_IS_OUT_OF_SCREEN_BOUNDS); @@ -74,20 +65,18 @@ namespace omath::projection return Vector3{++projected.At(0,0) / 2 * m_viewPort.m_width , ++projected.At(1,0) / 2 * m_viewPort.m_height, projected.At(2,0)}; } + protected: ViewPort m_viewPort{}; Angle m_fieldOfView; float m_farPlaneDistance; float m_nearPlaneDistance; - private: ViewAnglesType m_viewAngles; Vector3 m_origin; - std::function CreateViewMatrix; - std::function CreateProjectionMatrix; - + private: template [[nodiscard]] diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index ab4e824..0e0ea74 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -10,4 +10,5 @@ target_sources(omath PRIVATE add_subdirectory(prediction) add_subdirectory(pathfinding) add_subdirectory(projection) -add_subdirectory(collision) \ No newline at end of file +add_subdirectory(collision) +add_subdirectory(engines) \ No newline at end of file diff --git a/source/engines/CMakeLists.txt b/source/engines/CMakeLists.txt new file mode 100644 index 0000000..f01db76 --- /dev/null +++ b/source/engines/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Source) \ No newline at end of file diff --git a/source/engines/Source/CMakeLists.txt b/source/engines/Source/CMakeLists.txt new file mode 100644 index 0000000..0abf868 --- /dev/null +++ b/source/engines/Source/CMakeLists.txt @@ -0,0 +1 @@ +target_sources(omath PRIVATE Camera.cpp) \ No newline at end of file diff --git a/source/engines/Source/Camera.cpp b/source/engines/Source/Camera.cpp new file mode 100644 index 0000000..285d930 --- /dev/null +++ b/source/engines/Source/Camera.cpp @@ -0,0 +1,31 @@ +// +// Created by Orange on 12/4/2024. +// +#include "omath/engines/Source/Camera.hpp" +#include "omath/engines/Source/Formulas.hpp" + + +namespace omath::source +{ + + void Camera::LookAt(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::GetViewMatrix() const + { + return ViewMatrix(m_viewAngles, m_origin); + } + + Mat4x4 Camera::GetProjectionMatrix() const + { + return PerspectiveProjectionMatrix(m_fieldOfView.AsDegrees(), m_viewPort.AspectRatio(), m_nearPlaneDistance, m_farPlaneDistance); + } +} // namespace omath::source diff --git a/source/prediction/Projectile.cpp b/source/prediction/Projectile.cpp index 3ceb951..3c58d29 100644 --- a/source/prediction/Projectile.cpp +++ b/source/prediction/Projectile.cpp @@ -4,13 +4,13 @@ #include "omath/prediction/Projectile.hpp" #include -#include +#include namespace omath::prediction { Vector3 Projectile::PredictPosition(const float pitch, const float yaw, const float time, const float gravity) const { - auto currentPos = m_origin + omath::source::ForwardVector({source::PitchAngle::FromDegrees(pitch), source::YawAngle::FromDegrees(yaw), source::RollAngle::FromDegrees(0)}) * m_launchSpeed * time; + auto currentPos = m_origin + omath::source::ForwardVector({source::PitchAngle::FromDegrees(-pitch), source::YawAngle::FromDegrees(yaw), source::RollAngle::FromDegrees(0)}) * m_launchSpeed * time; currentPos.z -= (gravity * m_gravityScale) * std::pow(time, 2.f) * 0.5f; return currentPos; diff --git a/tests/engines/UnitTestOpenGL.cpp b/tests/engines/UnitTestOpenGL.cpp index cbe252b..1ea9459 100644 --- a/tests/engines/UnitTestOpenGL.cpp +++ b/tests/engines/UnitTestOpenGL.cpp @@ -6,7 +6,6 @@ #include #include #include -#include // #include // #include "glm/ext/matrix_clip_space.hpp" diff --git a/tests/engines/UnitTestSourceEngine.cpp b/tests/engines/UnitTestSourceEngine.cpp index 9c1861f..28a5805 100644 --- a/tests/engines/UnitTestSourceEngine.cpp +++ b/tests/engines/UnitTestSourceEngine.cpp @@ -2,7 +2,8 @@ // Created by Orange on 11/23/2024. // #include -#include +#include +#include diff --git a/tests/general/UnitTestProjection.cpp b/tests/general/UnitTestProjection.cpp index fc0ced4..70fce84 100644 --- a/tests/general/UnitTestProjection.cpp +++ b/tests/general/UnitTestProjection.cpp @@ -4,14 +4,14 @@ #include #include #include -#include +#include #include #include TEST(UnitTestProjection, Projection) { auto x = omath::Angle::FromDegrees(90.f); - auto cam = omath::source::CreateCamera({-10, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.1f, 1000.f); + auto cam = omath::source::Camera({-10, 0, 0}, omath::source::ViewAngles{}, {1920.f, 1080.f}, x, 0.1f, 1000.f); const auto projected = cam.WorldToScreen({10, 0, 0}); std::print("{} {} {}", projected->x, projected->y, projected->z);