#include #include #include #include #include #include #include #include using namespace XCEngine::Math; namespace { // ============================================================ // Ray Tests // ============================================================ TEST(Math_Ray, DefaultConstructor) { Ray ray; EXPECT_FLOAT_EQ(ray.origin.x, 0.0f); EXPECT_FLOAT_EQ(ray.origin.y, 0.0f); EXPECT_FLOAT_EQ(ray.origin.z, 0.0f); EXPECT_FLOAT_EQ(ray.direction.x, 0.0f); EXPECT_FLOAT_EQ(ray.direction.y, 0.0f); EXPECT_FLOAT_EQ(ray.direction.z, 0.0f); } TEST(Math_Ray, ParameterConstructor) { Vector3 origin(1, 2, 3); Vector3 direction(0, 0, 1); Ray ray(origin, direction); EXPECT_FLOAT_EQ(ray.origin.x, 1.0f); EXPECT_FLOAT_EQ(ray.origin.y, 2.0f); EXPECT_FLOAT_EQ(ray.origin.z, 3.0f); } TEST(Math_Ray, GetPoint) { Ray ray(Vector3::Zero(), Vector3::Right()); Vector3 point = ray.GetPoint(5.0f); EXPECT_FLOAT_EQ(point.x, 5.0f); EXPECT_FLOAT_EQ(point.y, 0.0f); EXPECT_FLOAT_EQ(point.z, 0.0f); } TEST(Math_Ray, IntersectsSphere_Hit) { Ray ray(Vector3(-5, 0, 0), Vector3::Right()); Sphere sphere(Vector3::Zero(), 1.0f); float t; bool hit = ray.Intersects(sphere, t); EXPECT_TRUE(hit); EXPECT_GE(t, 0.0f); } TEST(Math_Ray, IntersectsSphere_Miss) { Ray ray(Vector3(0, 5, 0), Vector3::Right()); Sphere sphere(Vector3::Zero(), 1.0f); float t; bool hit = ray.Intersects(sphere, t); EXPECT_FALSE(hit); } TEST(Math_Ray, IntersectsBox_Hit) { Ray ray(Vector3(-5, 0, 0), Vector3::Right()); Box box(Vector3::Zero(), Vector3(1, 1, 1)); float t; bool hit = ray.Intersects(box, t); EXPECT_TRUE(hit); EXPECT_GE(t, 0.0f); } TEST(Math_Ray, IntersectsBox_Miss) { Ray ray(Vector3(0, 5, 0), Vector3::Right()); Box box(Vector3(10, 0, 0), Vector3(1, 1, 1)); float t; bool hit = ray.Intersects(box, t); EXPECT_FALSE(hit); } TEST(Math_Ray, IntersectsPlane_Hit) { Ray ray(Vector3(0, 0, -5), Vector3::Forward()); Plane plane(Vector3::Forward(), 0.0f); float t; bool hit = ray.Intersects(plane, t); EXPECT_TRUE(hit); EXPECT_NEAR(t, 5.0f, 1e-3f); } TEST(Math_Ray, IntersectsPlane_Miss) { Ray ray(Vector3(0, 0, -5), Vector3::Back()); Plane plane(Vector3::Forward(), 0.0f); float t; bool hit = ray.Intersects(plane, t); EXPECT_FALSE(hit); } // ============================================================ // Sphere Tests // ============================================================ TEST(Math_Sphere, DefaultConstructor) { Sphere sphere; EXPECT_FLOAT_EQ(sphere.center.x, 0.0f); EXPECT_FLOAT_EQ(sphere.radius, 0.0f); } TEST(Math_Sphere, ParameterConstructor) { Sphere sphere(Vector3(1, 2, 3), 5.0f); EXPECT_FLOAT_EQ(sphere.center.x, 1.0f); EXPECT_FLOAT_EQ(sphere.center.y, 2.0f); EXPECT_FLOAT_EQ(sphere.center.z, 3.0f); EXPECT_FLOAT_EQ(sphere.radius, 5.0f); } TEST(Math_Sphere, Contains_Inside) { Sphere sphere(Vector3::Zero(), 2.0f); EXPECT_TRUE(sphere.Contains(Vector3(1, 0, 0))); } TEST(Math_Sphere, Contains_Outside) { Sphere sphere(Vector3::Zero(), 1.0f); EXPECT_FALSE(sphere.Contains(Vector3(5, 0, 0))); } TEST(Math_Sphere, Contains_OnSurface) { Sphere sphere(Vector3::Zero(), 1.0f); EXPECT_TRUE(sphere.Contains(Vector3(1, 0, 0))); } TEST(Math_Sphere, Intersects_Overlap) { Sphere a(Vector3::Zero(), 1.0f); Sphere b(Vector3(1.5f, 0, 0), 1.0f); EXPECT_TRUE(a.Intersects(b)); } TEST(Math_Sphere, Intersects_Separate) { Sphere a(Vector3::Zero(), 1.0f); Sphere b(Vector3(5, 0, 0), 1.0f); EXPECT_FALSE(a.Intersects(b)); } // ============================================================ // Plane Tests // ============================================================ TEST(Math_Plane, DefaultConstructor) { Plane plane; EXPECT_FLOAT_EQ(plane.normal.x, 0.0f); EXPECT_FLOAT_EQ(plane.normal.y, 1.0f); EXPECT_FLOAT_EQ(plane.normal.z, 0.0f); EXPECT_FLOAT_EQ(plane.distance, 0.0f); } TEST(Math_Plane, ParameterConstructor) { Plane plane(Vector3::Forward(), 5.0f); EXPECT_FLOAT_EQ(plane.normal.z, 1.0f); EXPECT_FLOAT_EQ(plane.distance, 5.0f); } TEST(Math_Plane, FromPoints) { Plane plane = Plane::FromPoints( Vector3(0, 0, 0), Vector3(1, 0, 0), Vector3(0, 1, 0) ); EXPECT_FLOAT_EQ(plane.normal.z, -1.0f); EXPECT_FLOAT_EQ(plane.distance, 0.0f); } TEST(Math_Plane, GetDistanceToPoint) { Plane plane(Vector3::Forward(), 0.0f); float dist = plane.GetDistanceToPoint(Vector3(0, 0, 5)); EXPECT_FLOAT_EQ(dist, 5.0f); } TEST(Math_Plane, GetClosestPoint) { Plane plane(Vector3::Forward(), 0.0f); Vector3 point = plane.GetClosestPoint(Vector3(3, 4, 5)); EXPECT_FLOAT_EQ(point.x, 3.0f); EXPECT_FLOAT_EQ(point.y, 4.0f); EXPECT_FLOAT_EQ(point.z, 0.0f); } TEST(Math_Plane, GetSide_Positive) { Plane plane(Vector3::Forward(), 0.0f); EXPECT_TRUE(plane.GetSide(Vector3(0, 0, 1))); } TEST(Math_Plane, GetSide_Negative) { Plane plane(Vector3::Forward(), 0.0f); EXPECT_FALSE(plane.GetSide(Vector3(0, 0, -1))); } TEST(Math_Plane, IntersectsSphere_Inside) { Plane plane(Vector3::Forward(), 0.0f); Sphere sphere(Vector3(0, 0, 0), 1.0f); EXPECT_TRUE(plane.Intersects(sphere)); } TEST(Math_Plane, IntersectsSphere_Outside) { Plane plane(Vector3::Forward(), 5.0f); Sphere sphere(Vector3(0, 0, 0), 1.0f); EXPECT_FALSE(plane.Intersects(sphere)); } // ============================================================ // Bounds Tests // ============================================================ TEST(Math_Bounds, DefaultConstructor) { Bounds bounds; EXPECT_FLOAT_EQ(bounds.center.x, 0.0f); EXPECT_FLOAT_EQ(bounds.extents.x, 0.0f); } TEST(Math_Bounds, ParameterConstructor) { Bounds bounds(Vector3(5, 5, 5), Vector3(10, 10, 10)); EXPECT_FLOAT_EQ(bounds.center.x, 5.0f); EXPECT_FLOAT_EQ(bounds.extents.x, 5.0f); } TEST(Math_Bounds, GetMin) { Bounds bounds(Vector3(5, 5, 5), Vector3(10, 10, 10)); Vector3 min = bounds.GetMin(); EXPECT_FLOAT_EQ(min.x, 0.0f); EXPECT_FLOAT_EQ(min.y, 0.0f); EXPECT_FLOAT_EQ(min.z, 0.0f); } TEST(Math_Bounds, GetMax) { Bounds bounds(Vector3(5, 5, 5), Vector3(10, 10, 10)); Vector3 max = bounds.GetMax(); EXPECT_FLOAT_EQ(max.x, 10.0f); EXPECT_FLOAT_EQ(max.y, 10.0f); EXPECT_FLOAT_EQ(max.z, 10.0f); } TEST(Math_Bounds, SetMinMax) { Bounds bounds; bounds.SetMinMax(Vector3(0, 0, 0), Vector3(10, 10, 10)); EXPECT_FLOAT_EQ(bounds.center.x, 5.0f); EXPECT_FLOAT_EQ(bounds.extents.x, 5.0f); } TEST(Math_Bounds, Contains_Inside) { Bounds bounds(Vector3::Zero(), Vector3(10, 10, 10)); EXPECT_TRUE(bounds.Contains(Vector3::Zero())); } TEST(Math_Bounds, Contains_Outside) { Bounds bounds(Vector3::Zero(), Vector3(2, 2, 2)); EXPECT_FALSE(bounds.Contains(Vector3(5, 5, 5))); } TEST(Math_Bounds, Contains_OnSurface) { Bounds bounds(Vector3::Zero(), Vector3(2, 2, 2)); EXPECT_TRUE(bounds.Contains(Vector3(1, 1, 1))); } TEST(Math_Bounds, Intersects_Overlap) { Bounds a(Vector3::Zero(), Vector3(2, 2, 2)); Bounds b(Vector3(1, 1, 1), Vector3(2, 2, 2)); EXPECT_TRUE(a.Intersects(b)); } TEST(Math_Bounds, Intersects_Separate) { Bounds a(Vector3::Zero(), Vector3(2, 2, 2)); Bounds b(Vector3(10, 10, 10), Vector3(2, 2, 2)); EXPECT_FALSE(a.Intersects(b)); } TEST(Math_Bounds, Encapsulate_Point) { Bounds bounds(Vector3::Zero(), Vector3(2, 2, 2)); bounds.Encapsulate(Vector3(5, 5, 5)); EXPECT_GT(bounds.GetMax().x, 5.0f); } TEST(Math_Bounds, Encapsulate_Bounds) { Bounds a(Vector3::Zero(), Vector3(2, 2, 2)); Bounds b(Vector3(5, 5, 5), Vector3(2, 2, 2)); a.Encapsulate(b); EXPECT_GT(a.GetMax().x, 5.0f); } TEST(Math_Bounds, Expand) { Bounds bounds(Vector3::Zero(), Vector3(2, 2, 2)); bounds.Expand(2.0f); EXPECT_GT(bounds.GetMax().x, 3.0f); } TEST(Math_Bounds, GetVolume) { Bounds bounds(Vector3::Zero(), Vector3(2, 4, 6)); float volume = bounds.GetVolume(); EXPECT_FLOAT_EQ(volume, 48.0f); } TEST(Math_Bounds, GetClosestPoint) { Bounds bounds(Vector3::Zero(), Vector3(2, 2, 2)); Vector3 point = bounds.GetClosestPoint(Vector3(10, 10, 10)); EXPECT_FLOAT_EQ(point.x, 1.0f); EXPECT_FLOAT_EQ(point.y, 1.0f); EXPECT_FLOAT_EQ(point.z, 1.0f); } // ============================================================ // Frustum Tests // ============================================================ TEST(Math_Frustum, Contains_Point) { Frustum frustum; Plane nearPlane; nearPlane.normal = Vector3::Forward(); nearPlane.distance = 1.0f; frustum.planes[4] = nearPlane; EXPECT_TRUE(frustum.Contains(Vector3(0, 0, 2))); } TEST(Math_Frustum, Contains_Sphere) { Frustum frustum; Plane nearPlane; nearPlane.normal = Vector3::Forward(); nearPlane.distance = 1.0f; frustum.planes[4] = nearPlane; Sphere sphere(Vector3(0, 0, 5), 1.0f); EXPECT_TRUE(frustum.Contains(sphere)); } TEST(Math_Frustum, Intersects_Sphere) { Frustum frustum; Plane nearPlane; nearPlane.normal = Vector3::Forward(); nearPlane.distance = 1.0f; frustum.planes[4] = nearPlane; Sphere sphere(Vector3(0, 0, 2), 0.5f); EXPECT_TRUE(frustum.Intersects(sphere)); } TEST(Math_Frustum, Intersects_Bounds) { Frustum frustum; Plane nearPlane; nearPlane.normal = Vector3::Forward(); nearPlane.distance = 1.0f; frustum.planes[4] = nearPlane; Bounds bounds(Vector3(0, 0, 2), Vector3(1, 1, 1)); EXPECT_TRUE(frustum.Intersects(bounds)); } } // namespace