#include #include #include "intersections_shapes.h" #include "transformations.h" #include "runner.h" static bool intersections_test_0(const char ** scenario) { *scenario = "An intersection encapsulates t and object"; struct shape s = sphere(); struct intersection i = intersection(3.5f, &s); return float_equal(i.t, 3.5f) && i.object == &s; } static bool intersections_test_1(const char ** scenario) { *scenario = "Aggregating intersections"; struct shape s = sphere(); struct intersection i1 = intersection(1.0f, &s); struct intersection i2 = intersection(2.0f, &s); struct intersections xs; intersections(&xs, 2, i1, i2); return xs.count == 2 && float_equal(xs.i[0].t, 1.0f) && float_equal(xs.i[1].t, 2.0f); } static bool intersections_test_2(const char ** scenario) { *scenario = "The hit, when all intersections have positive t"; struct shape s = sphere(); struct intersection i1 = intersection(1.0f, &s); struct intersection i2 = intersection(2.0f, &s); struct intersections xs; intersections(&xs, 2, i2, i1); struct intersection * i = hit((struct intersections *)&xs); return i != NULL && i->t == i1.t && i->object == i1.object; } static bool intersections_test_3(const char ** scenario) { *scenario = "The hit, when some intersections have negative t"; struct shape s = sphere(); struct intersection i1 = intersection(-1.0f, &s); struct intersection i2 = intersection( 1.0f, &s); struct intersections xs; intersections(&xs, 2, i2, i1); struct intersection * i = hit((struct intersections *)&xs); return i != NULL && i->t == i2.t && i->object == i2.object; } static bool intersections_test_4(const char ** scenario) { *scenario = "The hit, when all intersections have negative t"; struct shape s = sphere(); struct intersection i1 = intersection(-2.0f, &s); struct intersection i2 = intersection(-1.0f, &s); struct intersections xs; intersections(&xs, 2, i2, i1); struct intersection * i = hit((struct intersections *)&xs); return i == NULL; } static bool intersections_test_5(const char ** scenario) { *scenario = "The hit is always the lowest nonnegative intersection"; struct shape s = sphere(); struct intersection i1 = intersection( 5.0f, &s); struct intersection i2 = intersection( 7.0f, &s); struct intersection i3 = intersection(-3.0f, &s); struct intersection i4 = intersection( 2.0f, &s); struct intersections xs; intersections(&xs, 4, i1, i2, i3, i4); struct intersection * i = hit((struct intersections *)&xs); return i != NULL && i->t == i4.t && i->object == i4.object; } static bool intersections_test_6(const char ** scenario) { *scenario = "In-place ascending sort of intersections"; struct shape s1 = sphere(); s1.material.ambient = 1.0f; struct shape s2 = sphere(); s2.material.ambient = 2.0f; struct shape s3 = sphere(); s3.material.ambient = 3.0f; struct shape s4 = sphere(); s4.material.ambient = 4.0f; struct intersection i1 = intersection( 5.0f, &s1); struct intersection i2 = intersection( 7.0f, &s2); struct intersection i3 = intersection(-3.0f, &s3); struct intersection i4 = intersection( 2.0f, &s4); struct intersections xs; intersections(&xs, 4, i1, i2, i3, i4); intersections_sort(&xs); return float_equal(xs.i[0].t, -3.0f) && float_equal(xs.i[0].object->material.ambient, 3.0f) && float_equal(xs.i[1].t, 2.0f) && float_equal(xs.i[1].object->material.ambient, 4.0f) && float_equal(xs.i[2].t, 5.0f) && float_equal(xs.i[2].object->material.ambient, 1.0f) && float_equal(xs.i[3].t, 7.0f) && float_equal(xs.i[3].object->material.ambient, 2.0f); } static bool intersections_test_7(const char ** scenario) { *scenario = "Precomputing the state of an intersection"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct shape shape = sphere(); struct intersection i = intersection(4.0f, &shape); struct computations comps = prepare_computations(i, r); return float_equal(comps.t, i.t) && comps.object == &shape && tuple_equal(comps.point, point(0.0f, 0.0f, -1.0f)) && tuple_equal(comps.eyev, vector(0.0f, 0.0f, -1.0f)) && tuple_equal(comps.normalv, vector(0.0f, 0.0f, -1.0f)); } static bool intersections_test_8(const char ** scenario) { *scenario = "The hit, when an intersection occurs on the outside"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct shape shape = sphere(); struct intersection i = intersection(4.0f, &shape); struct computations comps = prepare_computations(i, r); return comps.inside == false; } static bool intersections_test_9(const char ** scenario) { *scenario = "The hit, when an intersection occurs on the inside"; struct ray r = ray(point(0.0f, 0.0f, 0.0f), vector(0.0f, 0.0f, 1.0f)); struct shape shape = sphere(); struct intersection i = intersection(1.0f, &shape); struct computations comps = prepare_computations(i, r); return tuple_equal(comps.point, point(0.0f, 0.0f, 1.0f)) && tuple_equal(comps.eyev, vector(0.0f, 0.0f, -1.0f)) && comps.inside == true && tuple_equal(comps.normalv, vector(0.0f, 0.0f, -1.0f)); } static bool intersections_test_10(const char ** scenario) { *scenario = "The hit should offset the point"; struct ray r = ray(point(0.0f, 0.0f, -5.0f), vector(0.0f, 0.0f, 1.0f)); struct shape shape = sphere(); shape.transform = translation(0.0f, 0.0f, 1.0f); struct intersection i = intersection(5.0f, &shape); struct computations comps = prepare_computations(i, r); return comps.over_point.z < -epsilon / 2.0f && comps.point.z > comps.over_point.z; } test_t intersections_tests[] = { intersections_test_0, intersections_test_1, intersections_test_2, intersections_test_3, intersections_test_4, intersections_test_5, intersections_test_6, intersections_test_7, intersections_test_8, intersections_test_9, intersections_test_10, }; RUNNER(intersections_tests);