121 lines
3.6 KiB
C++
121 lines
3.6 KiB
C++
|
|
#include <gtest/gtest.h>
|
||
|
|
#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();
|
||
|
|
}
|