#include #include #include "rays.h" #include "spheres.h" #include "intersections.h" #include "runner.h" #include "matrices.h" #include "transformations.h" static bool spheres_test_0(const char ** scenario) { *scenario = "A ray intersects a sphere at two points"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && float_equal(xs.i[0].t, 4.0f) && float_equal(xs.i[1].t, 6.0f); } static bool spheres_test_1(const char ** scenario) { *scenario = "A ray intersects a sphere at a tangent"; struct ray r = ray(point(0.0f, 1.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && float_equal(xs.i[0].t, 5.0f) && float_equal(xs.i[1].t, 5.0f); } static bool spheres_test_2(const char ** scenario) { *scenario = "A ray misses a sphere"; struct ray r = ray(point(0.0f, 2.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 0; } static bool spheres_test_3(const char ** scenario) { *scenario = "A ray originates in a sphere"; struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && float_equal(xs.i[0].t, -1.0f) && float_equal(xs.i[1].t, 1.0f); } static bool spheres_test_4(const char ** scenario) { *scenario = "A sphere is behind a ray"; struct ray r = ray(point(0.0f, 0.0f, 5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && float_equal(xs.i[0].t, -6.0f) && float_equal(xs.i[1].t, -4.0f); } static bool spheres_test_5(const char ** scenario) { *scenario = "Intersect sets the object on the intersection"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && xs.i[0].object == &s && xs.i[1].object == &s; } static bool spheres_test_6(const char ** scenario) { *scenario = "A sphere's default transformation"; struct sphere s = sphere(); struct mat4x4 identity = mat4x4_identity(); return mat4x4_equal(&s.transform, &identity); } static bool spheres_test_7(const char ** scenario) { *scenario = "Changing a sphere's transformation"; struct sphere s = sphere(); struct mat4x4 t = translation(2.0f, 3.0f, 4.0f); s.transform = t; return mat4x4_equal(&s.transform, &t); } static bool spheres_test_8(const char ** scenario) { *scenario = "Intersecting a scaled sphere with a ray"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); s.transform = scaling(2.0f, 2.0f, 2.0f); struct intersections2 xs = intersect(&s, r); return xs.count == 2 && float_equal(xs.i[0].t, 3.0f) && float_equal(xs.i[1].t, 7.0f); } static bool spheres_test_9(const char ** scenario) { *scenario = "Intersecting a translated sphere with a ray"; struct ray r = ray(point(0.0f, 0.0f, 5.0f), vector(0.0f, 0.0f, 1.0f)); struct sphere s = sphere(); s.transform = translation(5.0f, 0.0f, 0.0f); struct intersections2 xs = intersect(&s, r); return xs.count == 0; } static bool spheres_test_10(const char ** scenario) { *scenario = "The normal on a sphere at a point on the x axis"; struct sphere s = sphere(); struct tuple n = sphere_normal_at(&s, point(1.0f, 0.0f, 0.0f)); return tuple_equal(n, vector(1.0f, 0.0f, 0.0f)); } static bool spheres_test_11(const char ** scenario) { *scenario = "The normal on a sphere at a point on the y axis"; struct sphere s = sphere(); struct tuple n = sphere_normal_at(&s, point(0.0f, 1.0f, 0.0f)); return tuple_equal(n, vector(0.0f, 1.0f, 0.0f)); } static bool spheres_test_12(const char ** scenario) { *scenario = "The normal on a sphere at a point on the z axis"; struct sphere s = sphere(); struct tuple n = sphere_normal_at(&s, point(0.0f, 0.0f, 1.0f)); return tuple_equal(n, vector(0.0f, 0.0f, 1.0f)); } static bool spheres_test_13(const char ** scenario) { *scenario = "The normal on a sphere at a nonaxial point"; struct sphere s = sphere(); struct tuple n = sphere_normal_at(&s, point(0.5773502691896257, 0.5773502691896257, 0.5773502691896257)); return tuple_equal(n, vector(0.5773502691896257, 0.5773502691896257, 0.5773502691896257)); } static bool spheres_test_14(const char ** scenario) { *scenario = "The normal is a normalized vector"; struct sphere s = sphere(); struct tuple n = sphere_normal_at(&s, point(0.5773502691896257, 0.5773502691896257, 0.5773502691896257)); return tuple_equal(n, tuple_normalize(n)); } static bool spheres_test_15(const char ** scenario) { *scenario = "Computing the normal on a translated sphere"; struct sphere s = sphere(); s.transform = translation(0.0f, 1.0f, 0.0f); struct tuple n = sphere_normal_at(&s, point(0.0f, 1.70711f, -0.70711)); return tuple_equal(n, vector(0.0f, 0.70711f, -0.70711f)); } static bool spheres_test_16(const char ** scenario) { *scenario = "Computing the normal on a transformed sphere"; struct sphere s = sphere(); struct mat4x4 scale = scaling(1.0f, 0.5f, 1.0f); struct mat4x4 rotate = rotation_z(pi / 5.0f); struct mat4x4 m = mat4x4_mul_m(&scale, &rotate); s.transform = m; struct tuple n = sphere_normal_at(&s, point(0.0f, 0.7071067811865476, -0.7071067811865476)); return tuple_equal(n, vector(0.0f, 0.97014f, -0.24254f)); } static bool spheres_test_17(const char ** scenario) { *scenario = "A sphere has a default material"; struct sphere s = sphere(); struct material m = s.material; return material_equal(m, material()); } static bool spheres_test_18(const char ** scenario) { *scenario = "A sphere may be assigned a material"; struct sphere s = sphere(); struct material m = material(); m.ambient = 1.0f; s.material = m; return material_equal(s.material, m); } test_t spheres_tests[] = { spheres_test_0, spheres_test_1, spheres_test_2, spheres_test_3, spheres_test_4, spheres_test_5, spheres_test_6, spheres_test_7, spheres_test_8, spheres_test_9, spheres_test_10, spheres_test_11, spheres_test_12, spheres_test_13, spheres_test_14, spheres_test_15, spheres_test_16, spheres_test_17, spheres_test_18, }; RUNNER(spheres_tests);