diff --git a/tests/engines/unit_test_traits_engines.cpp b/tests/engines/unit_test_traits_engines.cpp index 8a82a8b..f891a3e 100644 --- a/tests/engines/unit_test_traits_engines.cpp +++ b/tests/engines/unit_test_traits_engines.cpp @@ -38,14 +38,14 @@ static void expect_matrix_near(const MatT& a, const MatT& b, float eps = 1e-5f) // Generic tests for PredEngineTrait behaviour across engines TEST(TraitTests, Frostbite_Pred_And_Mesh_And_Camera) { - namespace E = omath::frostbite_engine; + namespace e = omath::frostbite_engine; projectile_prediction::Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; - const auto pos = E::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); EXPECT_NEAR(pos.x, 0.f, 1e-4f); EXPECT_NEAR(pos.z, 10.f, 1e-4f); EXPECT_NEAR(pos.y, -9.81f * 0.5f, 1e-4f); @@ -54,57 +54,57 @@ TEST(TraitTests, Frostbite_Pred_And_Mesh_And_Camera) t.m_origin = {0.f, 5.f, 0.f}; t.m_velocity = {2.f, 0.f, 0.f}; t.m_is_airborne = true; - const auto pred = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred.x, 4.f, 1e-6f); EXPECT_NEAR(pred.y, 5.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); // Also test non-airborne path (no gravity applied) t.m_is_airborne = false; - const auto pred_ground = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred_ground = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred_ground.x, 4.f, 1e-6f); EXPECT_NEAR(pred_ground.y, 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); std::optional pitch = 45.f; - auto vp = E::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); EXPECT_NEAR(vp.y, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); // Direct angles Vector3 origin{0.f, 0.f, 0.f}; Vector3 view_to{0.f, 1.f, 1.f}; - const auto pitch_calc = E::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); + const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dir = (view_to - origin).normalized(); EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.y)), 1e-3f); - const auto yaw_calc = E::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); + const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(dir.x, dir.z)), 1e-3f); // MeshTrait simply forwards to rotation_matrix; ensure it compiles and returns something - E::ViewAngles va; - const auto m1 = E::MeshTrait::rotation_matrix(va); - const auto m2 = E::rotation_matrix(va); + e::ViewAngles va; + const auto m1 = e::MeshTrait::rotation_matrix(va); + const auto m2 = e::rotation_matrix(va); expect_matrix_near(m1, m2); // CameraTrait look at should be callable - const auto angles = E::CameraTrait::calc_look_at_angle({0, 0, 0}, {0, 1, 1}); + const auto angles = e::CameraTrait::calc_look_at_angle({0, 0, 0}, {0, 1, 1}); (void)angles; - const auto proj = E::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); - const auto expected = E::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); + const auto proj = e::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); + const auto expected = e::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); expect_matrix_near(proj, expected); } TEST(TraitTests, IW_Pred_And_Mesh_And_Camera) { - namespace E = omath::iw_engine; + namespace e = omath::iw_engine; projectile_prediction::Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; - const auto pos = E::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); EXPECT_NEAR(pos.x, 10.f, 1e-4f); EXPECT_NEAR(pos.z, -9.81f * 0.5f, 1e-4f); @@ -112,50 +112,50 @@ TEST(TraitTests, IW_Pred_And_Mesh_And_Camera) t.m_origin = {0.f, 0.f, 5.f}; t.m_velocity = {0.f, 0.f, 2.f}; t.m_is_airborne = true; - const auto pred = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); // predicted = origin + velocity * t -> z = 5 + 2*2 = 9; then gravity applied EXPECT_NEAR(pred.z, 9.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::calc_vector_2d_distance({3.f, 4.f, 0.f}), 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 3.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 4.f, 0.f}), 5.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 3.f, 1e-6f); std::optional pitch = 45.f; - auto vp = E::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); EXPECT_NEAR(vp.z, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); Vector3 origin{0.f, 0.f, 0.f}; Vector3 view_to{1.f, 1.f, 1.f}; - const auto pitch_calc = E::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); + const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dist = origin.distance_to(view_to); EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin((view_to.z - origin.z) / dist)), 1e-3f); - const auto yaw_calc = E::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); + const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); const auto delta = view_to - origin; EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(delta.y, delta.x)), 1e-3f); - E::ViewAngles va; - expect_matrix_near(E::MeshTrait::rotation_matrix(va), E::rotation_matrix(va)); + e::ViewAngles va; + expect_matrix_near(e::MeshTrait::rotation_matrix(va), e::rotation_matrix(va)); - const auto proj = E::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(45.f), {1920.f, 1080.f}, 0.1f, 1000.f); - const auto expected = E::calc_perspective_projection_matrix(45.f, 1920.f / 1080.f, 0.1f, 1000.f); + const auto proj = e::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(45.f), {1920.f, 1080.f}, 0.1f, 1000.f); + const auto expected = e::calc_perspective_projection_matrix(45.f, 1920.f / 1080.f, 0.1f, 1000.f); expect_matrix_near(proj, expected); // non-airborne t.m_is_airborne = false; - const auto pred_ground_iw = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred_ground_iw = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred_ground_iw.z, 9.f, 1e-6f); } TEST(TraitTests, OpenGL_Pred_And_Mesh_And_Camera) { - namespace E = omath::opengl_engine; + namespace e = omath::opengl_engine; projectile_prediction::Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; - const auto pos = E::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); EXPECT_NEAR(pos.z, -10.f, 1e-4f); EXPECT_NEAR(pos.y, -9.81f * 0.5f, 1e-4f); @@ -163,49 +163,49 @@ TEST(TraitTests, OpenGL_Pred_And_Mesh_And_Camera) t.m_origin = {0.f, 5.f, 0.f}; t.m_velocity = {2.f, 0.f, 0.f}; t.m_is_airborne = true; - const auto pred = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred.x, 4.f, 1e-6f); EXPECT_NEAR(pred.y, 5.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); std::optional pitch = 45.f; - auto vp = E::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); EXPECT_NEAR(vp.y, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); Vector3 origin{0.f, 0.f, 0.f}; Vector3 view_to{0.f, 1.f, 1.f}; - const auto pitch_calc = E::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); + const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dir = (view_to - origin).normalized(); EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.y)), 1e-3f); - const auto yaw_calc = E::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); + const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(-std::atan2(dir.x, -dir.z)), 1e-3f); - E::ViewAngles va; - expect_matrix_near(E::MeshTrait::rotation_matrix(va), E::rotation_matrix(va)); + e::ViewAngles va; + expect_matrix_near(e::MeshTrait::rotation_matrix(va), e::rotation_matrix(va)); - const auto proj = E::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); - const auto expected = E::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); + const auto proj = e::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); + const auto expected = e::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); expect_matrix_near(proj, expected); // non-airborne t.m_is_airborne = false; - const auto pred_ground_gl = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred_ground_gl = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred_ground_gl.x, 4.f, 1e-6f); } TEST(TraitTests, Unity_Pred_And_Mesh_And_Camera) { - namespace E = omath::unity_engine; + namespace e = omath::unity_engine; projectile_prediction::Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; - const auto pos = E::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); EXPECT_NEAR(pos.z, 10.f, 1e-4f); EXPECT_NEAR(pos.y, -9.81f * 0.5f, 1e-4f); @@ -213,49 +213,49 @@ TEST(TraitTests, Unity_Pred_And_Mesh_And_Camera) t.m_origin = {0.f, 5.f, 0.f}; t.m_velocity = {2.f, 0.f, 0.f}; t.m_is_airborne = true; - const auto pred = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred.x, 4.f, 1e-6f); EXPECT_NEAR(pred.y, 5.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); std::optional pitch = 45.f; - auto vp = E::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); EXPECT_NEAR(vp.y, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); Vector3 origin{0.f, 0.f, 0.f}; Vector3 view_to{0.f, 1.f, 1.f}; - const auto pitch_calc = E::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); + const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dir = (view_to - origin).normalized(); EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.y)), 1e-3f); - const auto yaw_calc = E::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); + const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(dir.x, dir.z)), 1e-3f); - E::ViewAngles va; - expect_matrix_near(E::MeshTrait::rotation_matrix(va), E::rotation_matrix(va)); + e::ViewAngles va; + expect_matrix_near(e::MeshTrait::rotation_matrix(va), e::rotation_matrix(va)); - const auto proj = E::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); - const auto expected = E::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); + const auto proj = e::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); + const auto expected = e::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); expect_matrix_near(proj, expected); // non-airborne t.m_is_airborne = false; - const auto pred_ground_unity = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred_ground_unity = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred_ground_unity.x, 4.f, 1e-6f); } TEST(TraitTests, Unreal_Pred_And_Mesh_And_Camera) { - namespace E = omath::unreal_engine; + namespace e = omath::unreal_engine; projectile_prediction::Projectile p; p.m_origin = {0.f, 0.f, 0.f}; p.m_launch_speed = 10.f; p.m_gravity_scale = 1.f; - const auto pos = E::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); + const auto pos = e::PredEngineTrait::predict_projectile_position(p, 0.f, 0.f, 1.f, 9.81f); EXPECT_NEAR(pos.x, 10.f, 1e-4f); EXPECT_NEAR(pos.y, -9.81f * 0.5f, 1e-4f); @@ -263,35 +263,35 @@ TEST(TraitTests, Unreal_Pred_And_Mesh_And_Camera) t.m_origin = {0.f, 5.f, 0.f}; t.m_velocity = {2.f, 0.f, 0.f}; t.m_is_airborne = true; - const auto pred = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred.x, 4.f, 1e-6f); EXPECT_NEAR(pred.y, 5.f - 9.81f * (2.f * 2.f) * 0.5f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); - EXPECT_NEAR(E::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::calc_vector_2d_distance({3.f, 0.f, 4.f}), 5.f, 1e-6f); + EXPECT_NEAR(e::PredEngineTrait::get_vector_height_coordinate({1.f, 2.5f, 3.f}), 2.5f, 1e-6f); std::optional pitch = 45.f; - auto vp = E::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); + auto vp = e::PredEngineTrait::calc_viewpoint_from_angles(p, {10.f, 0.f, 0.f}, pitch); EXPECT_NEAR(vp.z, 0.f + 10.f * std::tan(angles::degrees_to_radians(45.f)), 1e-6f); Vector3 origin{0.f, 0.f, 0.f}; Vector3 view_to{1.f, 1.f, 1.f}; - const auto pitch_calc = E::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); + const auto pitch_calc = e::PredEngineTrait::calc_direct_pitch_angle(origin, view_to); const auto dir = (view_to - origin).normalized(); EXPECT_NEAR(pitch_calc, angles::radians_to_degrees(std::asin(dir.z)), 1e-3f); - const auto yaw_calc = E::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); + const auto yaw_calc = e::PredEngineTrait::calc_direct_yaw_angle(origin, view_to); EXPECT_NEAR(yaw_calc, angles::radians_to_degrees(std::atan2(dir.y, dir.x)), 1e-3f); - E::ViewAngles va; - expect_matrix_near(E::MeshTrait::rotation_matrix(va), E::rotation_matrix(va)); + e::ViewAngles va; + expect_matrix_near(e::MeshTrait::rotation_matrix(va), e::rotation_matrix(va)); - const auto proj = E::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); - const auto expected = E::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); + const auto proj = e::CameraTrait::calc_projection_matrix(projection::FieldOfView::from_degrees(60.f), {1280.f, 720.f}, 0.1f, 1000.f); + const auto expected = e::calc_perspective_projection_matrix(60.f, 1280.f / 720.f, 0.1f, 1000.f); expect_matrix_near(proj, expected); // non-airborne t.m_is_airborne = false; - const auto pred_ground_unreal = E::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); + const auto pred_ground_unreal = e::PredEngineTrait::predict_target_position(t, 2.f, 9.81f); EXPECT_NEAR(pred_ground_unreal.x, 4.f, 1e-6f); } diff --git a/tests/general/unit_test_collision_extra.cpp b/tests/general/unit_test_collision_extra.cpp index 94b49e6..0db0ead 100644 --- a/tests/general/unit_test_collision_extra.cpp +++ b/tests/general/unit_test_collision_extra.cpp @@ -1,8 +1,8 @@ // Extra collision tests: Simplex, MeshCollider, EPA #include -#include -#include #include +#include +#include #include using namespace omath; @@ -12,7 +12,7 @@ TEST(SimplexTest, HandleEmptySimplex) { Simplex> simplex; Vector3 direction{1, 0, 0}; - + EXPECT_EQ(simplex.size(), 0); EXPECT_FALSE(simplex.handle(direction)); } @@ -21,21 +21,21 @@ TEST(SimplexTest, HandleLineCollinearWithXAxis) { using Vec3 = Vector3; Simplex simplex; - + simplex.push_front(Vec3{1, 0, 0}); simplex.push_front(Vec3{-1, 0, 0}); - + Vec3 direction{}; std::ignore = simplex.handle(direction); - + EXPECT_NEAR(direction.x, 0.f, 1e-6f); } TEST(CollisionExtra, SimplexLineHandle) { Simplex> s; - s = { Vector3{1.f,0.f,0.f}, Vector3{2.f,0.f,0.f} }; - Vector3 dir{0,0,0}; + s = {Vector3{1.f, 0.f, 0.f}, Vector3{2.f, 0.f, 0.f}}; + Vector3 dir{0, 0, 0}; EXPECT_FALSE(s.handle(dir)); // direction should not be zero EXPECT_GT(dir.length_sqr(), 0.0f); @@ -44,8 +44,8 @@ TEST(CollisionExtra, SimplexLineHandle) TEST(CollisionExtra, SimplexTriangleHandle) { Simplex> s; - s = { Vector3{1.f,0.f,0.f}, Vector3{0.f,1.f,0.f}, Vector3{0.f,0.f,1.f} }; - Vector3 dir{0,0,0}; + s = {Vector3{1.f, 0.f, 0.f}, Vector3{0.f, 1.f, 0.f}, Vector3{0.f, 0.f, 1.f}}; + Vector3 dir{0, 0, 0}; EXPECT_FALSE(s.handle(dir)); EXPECT_GT(dir.length_sqr(), 0.0f); } @@ -54,8 +54,9 @@ TEST(CollisionExtra, SimplexTetrahedronInside) { Simplex> s; // tetra that surrounds origin roughly - s = { Vector3{1.f,0.f,0.f}, Vector3{0.f,1.f,0.f}, Vector3{0.f,0.f,1.f}, Vector3{-1.f,-1.f,-1.f} }; - Vector3 dir{0,0,0}; + s = {Vector3{1.f, 0.f, 0.f}, Vector3{0.f, 1.f, 0.f}, Vector3{0.f, 0.f, 1.f}, + Vector3{-1.f, -1.f, -1.f}}; + Vector3 dir{0, 0, 0}; // if origin inside, handle returns true const bool inside = s.handle(dir); EXPECT_TRUE(inside); @@ -63,44 +64,38 @@ TEST(CollisionExtra, SimplexTetrahedronInside) TEST(CollisionExtra, MeshColliderOriginAndFurthest) { - omath::source_engine::Mesh mesh = { - std::vector>{ - { { 1.f, 1.f, 1.f }, {}, {} }, - { {-1.f, -1.f, -1.f }, {}, {} } - }, - {} - }; + source_engine::Mesh mesh = { + std::vector>{{{1.f, 1.f, 1.f}, {}, {}}, {{-1.f, -1.f, -1.f}, {}, {}}}, {}}; mesh.set_origin({0, 2, 0}); - omath::source_engine::MeshCollider collider(mesh); + source_engine::MeshCollider collider(mesh); - EXPECT_EQ(collider.get_origin(), omath::Vector3(0,2,0)); - collider.set_origin({1,2,3}); - EXPECT_EQ(collider.get_origin(), omath::Vector3(1,2,3)); + EXPECT_EQ(collider.get_origin(), omath::Vector3(0, 2, 0)); + collider.set_origin({1, 2, 3}); + EXPECT_EQ(collider.get_origin(), omath::Vector3(1, 2, 3)); - const auto v = collider.find_abs_furthest_vertex_position({1.f,0.f,0.f}); + const auto v = collider.find_abs_furthest_vertex_position({1.f, 0.f, 0.f}); // the original vertex at (1,1,1) translated by origin (1,2,3) becomes (2,3,4) - EXPECT_EQ(v, omath::Vector3(2.f,3.f,4.f)); + EXPECT_EQ(v, omath::Vector3(2.f, 3.f, 4.f)); } TEST(CollisionExtra, EPAConvergesOnSimpleCase) { // Build two simple colliders using simple meshes that overlap - omath::source_engine::Mesh meshA = { - std::vector>{{ {0.f,0.f,0.f}, {}, {} }, { {1.f,0.f,0.f}, {}, {} } }, - {} - }; - omath::source_engine::Mesh mesh_b = meshA; + source_engine::Mesh meshA = { + std::vector>{{{0.f, 0.f, 0.f}, {}, {}}, {{1.f, 0.f, 0.f}, {}, {}}}, {}}; + source_engine::Mesh mesh_b = meshA; mesh_b.set_origin({0.5f, 0.f, 0.f}); // translate to overlap - omath::source_engine::MeshCollider a(meshA); - omath::source_engine::MeshCollider b(mesh_b); + source_engine::MeshCollider a(meshA); + source_engine::MeshCollider b(mesh_b); // Create a simplex that approximately contains the origin in Minkowski space - Simplex> simplex; - simplex = { omath::Vector3{0.5f,0.f,0.f}, omath::Vector3{-0.5f,0.f,0.f}, omath::Vector3{0.f,0.5f,0.f}, omath::Vector3{0.f,-0.5f,0.f} }; + Simplex> simplex; + simplex = {omath::Vector3{0.5f, 0.f, 0.f}, omath::Vector3{-0.5f, 0.f, 0.f}, + omath::Vector3{0.f, 0.5f, 0.f}, omath::Vector3{0.f, -0.5f, 0.f}}; auto pool = std::pmr::monotonic_buffer_resource(1024); - auto res = Epa::solve(a, b, simplex, {}, pool); + auto res = Epa::solve(a, b, simplex, {}, pool); // EPA may or may not converge depending on numerics; ensure it returns optionally // but if it does, fields should be finite if (res.has_value()) diff --git a/tests/general/unit_test_epa.cpp b/tests/general/unit_test_epa.cpp index 43e6b01..0c4dbb3 100644 --- a/tests/general/unit_test_epa.cpp +++ b/tests/general/unit_test_epa.cpp @@ -9,7 +9,7 @@ using Mesh = omath::source_engine::Mesh; using Collider = omath::source_engine::MeshCollider; -using GJK = omath::collision::GjkAlgorithm; +using Gjk = omath::collision::GjkAlgorithm; using EPA = omath::collision::Epa; TEST(UnitTestEpa, TestCollisionTrue) @@ -37,15 +37,15 @@ TEST(UnitTestEpa, TestCollisionTrue) Collider A(a), B(b); // GJK - auto gjk = GJK::is_collide_with_simplex_info(A, B); - ASSERT_TRUE(gjk.hit) << "GJK should report collision"; + auto [hit, simplex] = Gjk::is_collide_with_simplex_info(A, B); + ASSERT_TRUE(hit) << "GJK should report collision"; // EPA EPA::Params params; auto pool = std::make_shared(1024); params.max_iterations = 64; params.tolerance = 1e-4f; - auto epa = EPA::solve(A, B, gjk.simplex, params, *pool); + auto epa = EPA::solve(A, B, simplex, params, *pool); ASSERT_TRUE(epa.has_value()) << "EPA should converge"; // Normal is unit @@ -70,8 +70,8 @@ TEST(UnitTestEpa, TestCollisionTrue) Collider B_plus(b_plus), B_minus(b_minus); - const bool sep_plus = !GJK::is_collide_with_simplex_info(A, B_plus).hit; - const bool sep_minus = !GJK::is_collide_with_simplex_info(A, B_minus).hit; + const bool sep_plus = !Gjk::is_collide_with_simplex_info(A, B_plus).hit; + const bool sep_minus = !Gjk::is_collide_with_simplex_info(A, B_minus).hit; // Exactly one direction should separate EXPECT_NE(sep_plus, sep_minus) << "Exactly one of ±penetration must separate"; @@ -81,12 +81,12 @@ TEST(UnitTestEpa, TestCollisionTrue) Mesh b_resolved = b; b_resolved.set_origin(b_resolved.get_origin() + resolve); - EXPECT_FALSE(GJK::is_collide(A, Collider(b_resolved))) << "Resolved position should be non-colliding"; + EXPECT_FALSE(Gjk::is_collide(A, Collider(b_resolved))) << "Resolved position should be non-colliding"; // Moving the other way should still collide Mesh b_wrong = b; b_wrong.set_origin(b_wrong.get_origin() - resolve); - EXPECT_TRUE(GJK::is_collide(A, Collider(b_wrong))); + EXPECT_TRUE(Gjk::is_collide(A, Collider(b_wrong))); } TEST(UnitTestEpa, TestCollisionTrue2) { @@ -112,7 +112,7 @@ TEST(UnitTestEpa, TestCollisionTrue2) Collider A(a), B(b); // --- GJK must detect collision and provide simplex --- - auto gjk = GJK::is_collide_with_simplex_info(A, B); + auto gjk = Gjk::is_collide_with_simplex_info(A, B); ASSERT_TRUE(gjk.hit) << "GJK should report collision for overlapping cubes"; // --- EPA penetration --- EPA::Params params; @@ -139,11 +139,11 @@ TEST(UnitTestEpa, TestCollisionTrue2) // Apply once: B + pen must separate; the opposite must still collide Mesh b_resolved = b; b_resolved.set_origin(b_resolved.get_origin() + pen * margin); - EXPECT_FALSE(GJK::is_collide(A, Collider(b_resolved))) << "Applying penetration should separate"; + EXPECT_FALSE(Gjk::is_collide(A, Collider(b_resolved))) << "Applying penetration should separate"; Mesh b_wrong = b; b_wrong.set_origin(b_wrong.get_origin() - pen * margin); - EXPECT_TRUE(GJK::is_collide(A, Collider(b_wrong))) << "Opposite direction should still intersect"; + EXPECT_TRUE(Gjk::is_collide(A, Collider(b_wrong))) << "Opposite direction should still intersect"; // Some book-keeping sanity EXPECT_GT(epa->iterations, 0); diff --git a/tests/general/unit_test_epa_internal.cpp b/tests/general/unit_test_epa_internal.cpp index f31416c..e3c0c1b 100644 --- a/tests/general/unit_test_epa_internal.cpp +++ b/tests/general/unit_test_epa_internal.cpp @@ -32,10 +32,8 @@ TEST(EpaInternal, SolveHandlesSmallPolytope) params.max_iterations = 16; params.tolerance = 1e-6f; - const auto result = EpaDummy::solve(a, b, s, params); - // Should either return a valid result or gracefully return nullopt - if (result) + if (const auto result = EpaDummy::solve(a, b, s, params)) { EXPECT_TRUE(std::isfinite(result->depth)); EXPECT_TRUE(std::isfinite(result->normal.x)); diff --git a/tests/general/unit_test_epa_more.cpp b/tests/general/unit_test_epa_more.cpp index 086987d..ac4a799 100644 --- a/tests/general/unit_test_epa_more.cpp +++ b/tests/general/unit_test_epa_more.cpp @@ -10,7 +10,8 @@ struct DegenerateCollider { using VectorType = Vector3f; // returns furthest point along dir - VectorType find_abs_furthest_vertex_position(const VectorType& dir) const noexcept + [[nodiscard]] + static VectorType find_abs_furthest_vertex_position(const VectorType& dir) noexcept { // Always return points on a small circle in XY plane so some faces become degenerate if (dir.x > 0.5f) return {0.01f, 0.f, 0.f}; diff --git a/tests/general/unit_test_line_tracer_extra.cpp b/tests/general/unit_test_line_tracer_extra.cpp index 51214dd..6eb184c 100644 --- a/tests/general/unit_test_line_tracer_extra.cpp +++ b/tests/general/unit_test_line_tracer_extra.cpp @@ -29,9 +29,8 @@ TEST(LineTracerExtra, HitOnEdge) { constexpr Triangle> tri({0,0,0},{1,0,0},{0,1,0}); constexpr Ray ray{ {0.0f,0.0f,1.f}, {0.0f,0.0f,0.f}, false }; - const auto hit = LineTracer::get_ray_hit_point(ray, tri); // hitting exact vertex/edge may be considered miss; ensure function handles without crash - if (hit != ray.end) + if (const auto hit = LineTracer::get_ray_hit_point(ray, tri); hit != ray.end) { EXPECT_NEAR(hit.x, 0.0f, 1e-6f); EXPECT_NEAR(hit.y, 0.0f, 1e-6f);