diff --git a/include/omath/linear_algebra/vector2.hpp b/include/omath/linear_algebra/vector2.hpp index 2ee3750..51d3079 100644 --- a/include/omath/linear_algebra/vector2.hpp +++ b/include/omath/linear_algebra/vector2.hpp @@ -220,6 +220,12 @@ namespace omath { return std::make_tuple(x, y); } + + [[nodiscard]] + constexpr std::array as_array() const noexcept + { + return {x, y}; + } #ifdef OMATH_IMGUI_INTEGRATION [[nodiscard]] constexpr ImVec2 to_im_vec2() const noexcept diff --git a/include/omath/linear_algebra/vector3.hpp b/include/omath/linear_algebra/vector3.hpp index ab481f2..2845ff7 100644 --- a/include/omath/linear_algebra/vector3.hpp +++ b/include/omath/linear_algebra/vector3.hpp @@ -4,8 +4,8 @@ #pragma once -#include "omath/trigonometry/angle.hpp" #include "omath/linear_algebra/vector2.hpp" +#include "omath/trigonometry/angle.hpp" #include #include #include @@ -233,7 +233,8 @@ namespace omath return Angle::from_radians(std::acos(dot(other) / bottom)); } - [[nodiscard]] bool is_perpendicular(const Vector3& other, Type epsilon = static_cast(0.0001)) const noexcept + [[nodiscard]] bool is_perpendicular(const Vector3& other, + Type epsilon = static_cast(0.0001)) const noexcept { if (const auto angle = angle_between(other)) return std::abs(angle->as_degrees() - static_cast(90)) <= epsilon; @@ -274,6 +275,12 @@ namespace omath { return length() >= other.length(); } + + [[nodiscard]] + constexpr std::array as_array() const noexcept + { + return {this->x, this->y, z}; + } }; } // namespace omath diff --git a/include/omath/linear_algebra/vector4.hpp b/include/omath/linear_algebra/vector4.hpp index f045df9..14e2067 100644 --- a/include/omath/linear_algebra/vector4.hpp +++ b/include/omath/linear_algebra/vector4.hpp @@ -3,8 +3,8 @@ // #pragma once -#include #include "omath/linear_algebra/vector3.hpp" +#include namespace omath { @@ -183,6 +183,12 @@ namespace omath return length() >= other.length(); } + [[nodiscard]] + constexpr std::array as_array() const noexcept + { + return {this->x, this->y, this->z, w}; + } + #ifdef OMATH_IMGUI_INTEGRATION [[nodiscard]] constexpr ImVec4 to_im_vec4() const noexcept @@ -200,7 +206,7 @@ namespace omath return {static_cast(other.x), static_cast(other.y), static_cast(other.z)}; } #endif -}; + }; } // namespace omath template<> struct std::hash> diff --git a/source/engines/cry_engine/camera_trait.cpp b/source/engines/cry_engine/camera_trait.cpp index 63c1e01..ac912f8 100644 --- a/source/engines/cry_engine/camera_trait.cpp +++ b/source/engines/cry_engine/camera_trait.cpp @@ -10,8 +10,8 @@ namespace omath::cry_engine { const auto direction = (look_at - cam_origin).normalized(); - return {PitchAngle::from_radians(-std::asin(direction.z)), - YawAngle::from_radians(std::atan2(direction.y, direction.x)), RollAngle::from_radians(0.f)}; + return {PitchAngle::from_radians(std::asin(direction.z)), + YawAngle::from_radians(-std::atan2(direction.x, direction.y)), RollAngle::from_radians(0.f)}; } Mat4X4 CameraTrait::calc_view_matrix(const ViewAngles& angles, const Vector3& cam_origin) noexcept { diff --git a/source/engines/cry_engine/formulas.cpp b/source/engines/cry_engine/formulas.cpp index 14ad049..605b3d0 100644 --- a/source/engines/cry_engine/formulas.cpp +++ b/source/engines/cry_engine/formulas.cpp @@ -30,8 +30,8 @@ namespace omath::cry_engine } Mat4X4 rotation_matrix(const ViewAngles& angles) noexcept { - return mat_rotation_axis_z(angles.roll) - * mat_rotation_axis_y(angles.yaw) + return mat_rotation_axis_z(angles.yaw) + * mat_rotation_axis_y(angles.roll) * mat_rotation_axis_x(angles.pitch); } Mat4X4 calc_perspective_projection_matrix(const float field_of_view, const float aspect_ratio, const float near, diff --git a/tests/engines/unit_test_cry_engine.cpp b/tests/engines/unit_test_cry_engine.cpp new file mode 100644 index 0000000..9c446cd --- /dev/null +++ b/tests/engines/unit_test_cry_engine.cpp @@ -0,0 +1,66 @@ +// +// Created by Vladislav on 19.02.2026. +// +#include +#include +#include +#include +#include +#include + +using namespace omath; +TEST(unit_test_cry_engine, look_at_forward) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, cry_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), cry_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_cry_engine, look_at_right) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, cry_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), cry_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_cry_engine, look_at_up) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, cry_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), cry_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_cry_engine, look_at_back) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, -cry_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-cry_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_cry_engine, look_at_left) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, -cry_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-cry_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_cry_engine, look_at_down) +{ + const auto angles = cry_engine::CameraTrait::calc_look_at_angle({}, -cry_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = cry_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-cry_engine::k_abs_up).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} \ No newline at end of file diff --git a/tests/engines/unit_test_frostbite_engine.cpp b/tests/engines/unit_test_frostbite_engine.cpp index 7f6a6f3..5a2ee16 100644 --- a/tests/engines/unit_test_frostbite_engine.cpp +++ b/tests/engines/unit_test_frostbite_engine.cpp @@ -7,6 +7,7 @@ #include #include #include +#include TEST(unit_test_frostbite_engine, UnitsToCentimeters_BasicValues) { @@ -352,4 +353,55 @@ TEST(unit_test_frostbite_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); -} \ No newline at end of file +} +TEST(unit_test_frostbite_engine, look_at_right) +{ + const auto angles = omath::frostbite_engine::CameraTrait::calc_look_at_angle({}, omath::frostbite_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::frostbite_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), omath::frostbite_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_frostbite_engine, look_at_up) +{ + const auto angles = omath::frostbite_engine::CameraTrait::calc_look_at_angle({}, omath::frostbite_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::frostbite_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), omath::frostbite_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_frostbite_engine, look_at_back) +{ + const auto angles = omath::frostbite_engine::CameraTrait::calc_look_at_angle({}, -omath::frostbite_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::frostbite_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::frostbite_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_frostbite_engine, look_at_left) +{ + const auto angles = omath::frostbite_engine::CameraTrait::calc_look_at_angle({}, -omath::frostbite_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::frostbite_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::frostbite_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_frostbite_engine, look_at_down) +{ + const auto angles = omath::frostbite_engine::CameraTrait::calc_look_at_angle({}, -omath::frostbite_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::frostbite_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::frostbite_engine::k_abs_up).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} diff --git a/tests/engines/unit_test_iw_engine.cpp b/tests/engines/unit_test_iw_engine.cpp index ed27457..44f2d38 100644 --- a/tests/engines/unit_test_iw_engine.cpp +++ b/tests/engines/unit_test_iw_engine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include TEST(unit_test_iw_engine, ForwardVector) { @@ -223,4 +224,60 @@ TEST(unit_test_iw_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); +} +TEST(unit_test_iw_engine, look_at_forward) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, omath::iw_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::iw_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_iw_engine, look_at_right) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, omath::iw_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::iw_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_iw_engine, look_at_up) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, omath::iw_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::iw_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_iw_engine, look_at_back) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, -omath::iw_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::iw_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_iw_engine, look_at_left) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, -omath::iw_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::iw_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_iw_engine, look_at_down) +{ + const auto angles = omath::iw_engine::CameraTrait::calc_look_at_angle({}, -omath::iw_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::iw_engine::forward_vector(angles); + EXPECT_NEAR(dir_vector.z, -0.99984f, 0.0001f); + EXPECT_NEAR(dir_vector.x,- 0.017f, 0.01f); + EXPECT_NEAR(dir_vector.y, 0.f, 0.001f); } \ No newline at end of file diff --git a/tests/engines/unit_test_open_gl.cpp b/tests/engines/unit_test_open_gl.cpp index eb8a8f9..f784e34 100644 --- a/tests/engines/unit_test_open_gl.cpp +++ b/tests/engines/unit_test_open_gl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include TEST(unit_test_opengl, UnitsToCentimeters_BasicValues) { @@ -337,4 +338,60 @@ TEST(unit_test_opengl_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); +} + +TEST(unit_test_opengl_engine, look_at_forward) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, omath::opengl_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::opengl_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_opengl_engine, look_at_right) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, omath::opengl_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::opengl_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_opengl_engine, look_at_up) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, omath::opengl_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::opengl_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_opengl_engine, look_at_back) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, -omath::opengl_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::opengl_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_opengl_engine, look_at_left) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, -omath::opengl_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::opengl_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_opengl_engine, look_at_down) +{ + const auto angles = omath::opengl_engine::CameraTrait::calc_look_at_angle({}, -omath::opengl_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::opengl_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::opengl_engine::k_abs_up).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); } \ No newline at end of file diff --git a/tests/engines/unit_test_source_engine.cpp b/tests/engines/unit_test_source_engine.cpp index 4e3510f..f311185 100644 --- a/tests/engines/unit_test_source_engine.cpp +++ b/tests/engines/unit_test_source_engine.cpp @@ -6,6 +6,7 @@ #include #include #include +#include TEST(unit_test_source_engine_units, HammerUnitsToCentimeters_BasicValues) { @@ -365,4 +366,60 @@ TEST(unit_test_source_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); +} +TEST(unit_test_source_engine, look_at_forward) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, omath::source_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::source_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_source_engine, look_at_right) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, omath::source_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::source_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_source_engine, look_at_up) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, omath::source_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::source_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_source_engine, look_at_back) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, -omath::source_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::source_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_source_engine, look_at_left) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, -omath::source_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::source_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_source_engine, look_at_down) +{ + const auto angles = omath::source_engine::CameraTrait::calc_look_at_angle({}, -omath::source_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::source_engine::forward_vector(angles); + EXPECT_NEAR(dir_vector.z, -0.99984f, 0.0001f); + EXPECT_NEAR(dir_vector.x,- 0.017f, 0.01f); + EXPECT_NEAR(dir_vector.y, 0.f, 0.001f); } \ No newline at end of file diff --git a/tests/engines/unit_test_unity_engine.cpp b/tests/engines/unit_test_unity_engine.cpp index ac57765..6621349 100644 --- a/tests/engines/unit_test_unity_engine.cpp +++ b/tests/engines/unit_test_unity_engine.cpp @@ -7,6 +7,7 @@ #include #include #include +#include TEST(unit_test_unity_engine, UnitsToCentimeters_BasicValues) { @@ -207,7 +208,8 @@ TEST(unit_test_unity_engine, Project) constexpr auto fov = omath::projection::FieldOfView::from_degrees(60.f); const auto cam = omath::unity_engine::Camera({0, 0, 0}, {}, {1280.f, 720.f}, fov, 0.03f, 1000.f); - const auto proj = cam.world_to_screen({10.f, 3, 10.f}); + const auto proj = + cam.world_to_screen({10.f, 3, 10.f}); EXPECT_NEAR(proj->x, 1263.538, 0.001f); EXPECT_NEAR(proj->y, 547.061f, 0.001f); @@ -353,4 +355,65 @@ TEST(unit_test_unity_engine, loook_at_random_z_axis) failed_points++; } EXPECT_LE(failed_points, 100); -} \ No newline at end of file +} +TEST(unit_test_unity_engine, look_at_forward) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, omath::unity_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), omath::unity_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unity_engine, look_at_right) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, omath::unity_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), omath::unity_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unity_engine, look_at_up) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, omath::unity_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), omath::unity_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_unity_engine, look_at_back) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, -omath::unity_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::unity_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unity_engine, look_at_left) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, -omath::unity_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::unity_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unity_engine, look_at_down) +{ + const auto angles = omath::unity_engine::CameraTrait::calc_look_at_angle({}, -omath::unity_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unity_engine::forward_vector(angles); + for (const auto& [result, etalon] : + std::views::zip(dir_vector.as_array(), (-omath::unity_engine::k_abs_up).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} diff --git a/tests/engines/unit_test_unreal_engine.cpp b/tests/engines/unit_test_unreal_engine.cpp index 0a4441a..e2679c8 100644 --- a/tests/engines/unit_test_unreal_engine.cpp +++ b/tests/engines/unit_test_unreal_engine.cpp @@ -7,6 +7,7 @@ #include #include #include +#include TEST(unit_test_unreal_engine, ForwardVector) { @@ -361,4 +362,59 @@ TEST(unit_test_unreal_engine, ConstexprConversions) static_assert(cm == 100000.0, "units_to_centimeters constexpr failed"); static_assert(m == 1000.0, "units_to_meters constexpr failed"); static_assert(km == 1.0, "units_to_kilometers constexpr failed"); +} +TEST(unit_test_unreal_engine, look_at_forward) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, omath::unreal_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::unreal_engine::k_abs_forward.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unreal_engine, look_at_right) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, omath::unreal_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::unreal_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unreal_engine, look_at_up) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, omath::unreal_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), omath::unreal_engine::k_abs_right.as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} + +TEST(unit_test_unreal_engine, look_at_back) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, -omath::unreal_engine::k_abs_forward); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::unreal_engine::k_abs_forward).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unreal_engine, look_at_left) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, -omath::unreal_engine::k_abs_right); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::unreal_engine::k_abs_right).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); +} +TEST(unit_test_unreal_engine, look_at_down) +{ + const auto angles = omath::unreal_engine::CameraTrait::calc_look_at_angle({}, -omath::unreal_engine::k_abs_up); + + // ReSharper disable once CppTooWideScopeInitStatement + const auto dir_vector = omath::unreal_engine::forward_vector(angles); + for (const auto& [result, etalon] : std::views::zip(dir_vector.as_array(), (-omath::unreal_engine::k_abs_up).as_array())) + EXPECT_NEAR(result, etalon, 0.0001f); } \ No newline at end of file