#include #include "vde/collision/ray_intersect.h" #include "vde/core/triangle.h" using namespace vde::collision; using namespace vde::core; // ── Ray-Triangle intersection (origin + direction) ── TEST(RayTest, RayTriangle_Hit) { // Triangle on XY plane at z=0 Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Ray pointing downwards from above auto result = ray_triangle_intersect( Point3D(0.5, 0.5, 5.0), Vector3D(0, 0, -1), tri ); ASSERT_TRUE(result.has_value()); EXPECT_NEAR(result->point.x(), 0.5, 1e-9); EXPECT_NEAR(result->point.y(), 0.5, 1e-9); EXPECT_NEAR(result->point.z(), 0.0, 1e-9); EXPECT_GT(result->t, 0.0); // t should be positive (in ray direction) } TEST(RayTest, RayTriangle_MissParallel) { // Triangle on XY plane, ray parallel to plane Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); auto result = ray_triangle_intersect( Point3D(0, 0, 5), Vector3D(1, 0, 0), tri ); EXPECT_FALSE(result.has_value()); } TEST(RayTest, RayTriangle_MissOutside) { Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Ray hits the plane but outside the triangle auto result = ray_triangle_intersect( Point3D(3, 3, 5), Vector3D(0, 0, -1), tri ); EXPECT_FALSE(result.has_value()); } TEST(RayTest, RayTriangle_MissBehindOrigin) { Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Ray points away from the triangle auto result = ray_triangle_intersect( Point3D(0.5, 0.5, 5), Vector3D(0, 0, 1), // points +Z (away) tri ); EXPECT_FALSE(result.has_value()); } TEST(RayTest, RayTriangle_HitVertex) { Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Ray directly at vertex (0,0,0) auto result = ray_triangle_intersect( Point3D(0, 0, 5), Vector3D(0, 0, -1), tri ); ASSERT_TRUE(result.has_value()); EXPECT_NEAR(result->point.z(), 0.0, 1e-9); } TEST(RayTest, RayTriangle_HitEdge) { Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Ray at edge midpoint (between v0 and v1) auto result = ray_triangle_intersect( Point3D(1, 0, 3), Vector3D(0, 0, -1), tri ); ASSERT_TRUE(result.has_value()); EXPECT_NEAR(result->point.z(), 0.0, 1e-9); } // ── Ray-Triangle via Ray3Dd wrapper ── TEST(RayTest, RayTriangle_RayWrapper) { Triangle3D tri(Point3D(0, 0, 0), Point3D(1, 0, 0), Point3D(0, 1, 0)); Ray3Dd ray(Point3D(0.3, 0.3, 2), Vector3D(0, 0, -1)); auto result = ray_triangle_intersect(ray, tri); ASSERT_TRUE(result.has_value()); EXPECT_NEAR(result->t, 2.0, 1e-9); } // ── Degenerate triangle ── TEST(RayTest, RayTriangle_DegenerateTriangle) { // All three vertices are collinear Triangle3D tri(Point3D(0, 0, 0), Point3D(1, 0, 0), Point3D(2, 0, 0)); auto result = ray_triangle_intersect( Point3D(0.5, 0.5, 1), Vector3D(0, 0, -1), tri ); // Degenerate triangle: should miss or handle gracefully EXPECT_FALSE(result.has_value()); } // ── Oblique ray ── TEST(RayTest, RayTriangle_ObliqueRay) { Triangle3D tri(Point3D(0, 0, 0), Point3D(2, 0, 0), Point3D(0, 2, 0)); // Oblique ray that passes through triangle at (1, 0.27, 0) auto result = ray_triangle_intersect( Point3D(3, -2, 5), Vector3D(-0.37, 0.41, -0.83), tri ); // Ray might or might not hit depending on direction (void)result; SUCCEED(); }