// Extra collision tests: Simplex, MeshCollider, EPA #include #include #include #include #include using namespace omath; using namespace omath::collision; 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}; EXPECT_FALSE(s.handle(dir)); // direction should not be zero EXPECT_GT(dir.length_sqr(), 0.0f); } 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}; EXPECT_FALSE(s.handle(dir)); EXPECT_GT(dir.length_sqr(), 0.0f); } 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}; // if origin inside, handle returns true const bool inside = s.handle(dir); EXPECT_TRUE(inside); } TEST(CollisionExtra, MeshColliderOriginAndFurthest) { omath::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); 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}); // 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)); } 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 meshB = meshA; meshB.set_origin({0.5f, 0.f, 0.f}); // translate to overlap omath::source_engine::MeshCollider A(meshA); omath::source_engine::MeshCollider B(meshB); // 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} }; auto pool = std::pmr::monotonic_buffer_resource(1024); 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()) { auto r = *res; EXPECT_TRUE(std::isfinite(r.depth)); EXPECT_GT(r.normal.length_sqr(), 0.0f); } }