def test_inverse_of_an_x_rotation(self): p = point(0, 1, 0) half_quarter = rotation_x(pi / 4) inv = half_quarter.inverse() self.assert_tuple_equals(point(0, sqrt(2) / 2, -sqrt(2) / 2), inv * p, 1e-5)
def test_rotating_point_around_axis_z(self): p = point(0, 1, 0) half_quarter = rotation_z(pi / 4) full_quarter = rotation_z(pi / 2) self.assert_tuple_equals(point(-sqrt(2) / 2, sqrt(2) / 2, 0), half_quarter * p, 1e-5) self.assert_tuple_equals(point(-1, 0, 0), full_quarter * p, 1e-5)
def test_view_transformation_matrix_looking_in_positive_z_direction(self): from_where = point(0, 0, 0) to = point(0, 0, 1) up = vector(0, 1, 0) t = view_transform(from_where, to, up) self.assertEqual(scaling(-1, 1, -1), t)
def test_the_view_trasnformation_move_the_world(self): from_where = point(0, 0, 8) to = point(0, 0, 0) up = vector(0, 1, 0) t = view_transform(from_where, to, up) self.assert_matrix_equals(translation(0, 0, -8), t)
def test_transformation_matrix_for_the_default_orientation(self): from_where = point(0, 0, 0) to = point(0, 0, -1) up = vector(0, 1, 0) t = view_transform(from_where, to, up) self.assert_matrix_equals(identity_matrix, t)
def test_chain_transformation_must_be_applied_in_reverse_order(self): p = point(1, 0, 1) a = rotation_x(pi / 2) b = scaling(5, 5, 5) c = translation(10, 5, 7) t = c * b * a self.assertEqual(point(15, 0, 7), t * p)
def test_precomputing_state_of_intersection(self): ray = Ray(point(0, 0, -5), vector(0, 0, 1)) shape = Sphere() xs = Intersection(4, shape) xs.prepare_hit(ray) self.assertEqual(point(0, 0, -1), xs.point) self.assertEqual(vector(0, 0, -1), xs.eyev) self.assertEqual(vector(0, 0, -1), xs.normalv)
def test_shading_an_intersection_form_the_inside(self): world = default_world() world.light = PointLight(point(0, 0.25, 0), color(1, 1, 1)) ray = Ray(point(0, 0, 0), vector(0, 0, 1)) shape = world.objects[1] xs = Intersection(0.5, shape) xs.prepare_hit(ray) c = shade_hit(world, xs) self.assert_tuple_equals(color(0.90498, 0.90498, 0.90498), c, 0.001)
def test_arbitrary_view_transformation(self): from_where = point(1, 3, 2) to = point(4, -2, 8) up = vector(1, 1, 0) t = view_transform(from_where, to, up) m = Matrix4(-0.50709, 0.50709, 0.67612, -2.36643, 0.76772, 0.60609, 0.12122, -2.82843, -0.35857, 0.59761, -0.71714, 0.00000, 0.00000, 0.00000, 0.00000, 1.00000) self.assert_matrix_equals(m, t)
def test_individual_transformation_are_applied_in_sequence(self): p = point(1, 0, 1) a = rotation_x(pi / 2) b = scaling(5, 5, 5) c = translation(10, 5, 7) p2 = a * p p3 = b * p2 p4 = c * p3 self.assertEqual(point(15, 0, 7), p4)
def test_intersection_occurs_on_the_inside(self): ray = Ray(point(0, 0, 0), vector(0, 0, 1)) shape = Sphere() xs = Intersection(1, shape) xs.prepare_hit(ray) self.assertEqual(point(0, 0, 1), xs.point) self.assertEqual(vector(0, 0, -1), xs.eyev) self.assertEqual(True, xs.inside) self.assertEqual(vector(0, 0, -1), xs.normalv)
def test_rendering_world_with_camera(self): w = default_world() c = Camera(11, 11, pi / 2.0) from_where = point(0, 0, -5) to = point(0, 0, 0) up = vector(0, 1, 0) c.transform = view_transform(from_where, to, up) image = render(c, w) self.assert_tuple_equals(color(0.38066, 0.47583, 0.2855), image.pixel_at(5, 5), 0.001)
def ray_for_pixel(camera, px, py): x_offset = (px + 0.5) * camera.pixel_size y_offset = (py + 0.5) * camera.pixel_size world_x = camera.half_width - x_offset world_y = camera.half_height - y_offset pixel = camera.transform.inverse() * point(world_x, world_y, -1) origin = camera.transform.inverse() * point(0, 0, 0) direction = (pixel - origin).normalize() return Ray(origin, direction)
def test_the_color_when_ray_hits(self): world = default_world() ray = Ray(point(0, 0, -5), vector(0, 0, 1)) c = color_at(world, ray) self.assert_tuple_equals(color(0.38066, 0.47583, 0.2855), c, 0.001)
def test_computing_normal_on_translated_sphere(self): s = Sphere() s.set_transform(translation(0, 1, 0)) n = s.normal_at(point(0, 1.70711, -0.70711)) self.assert_tuple_equals(vector(0, 0.70711, -0.70711), n, 0.001)
def test_the_color_when_ray_misses(self): world = default_world() ray = Ray(point(0, 0, -5), vector(0, 1, 0)) c = color_at(world, ray) self.assertEqual(color(0, 0, 0), c)
def test_default_world(self): light = PointLight(point(-10, 10, -10), color(1, 1, 1)) s1 = Sphere() s2 = Sphere() s1.material.color = color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2.set_transform(scaling(0.5, 0.5, 0.5)) world = default_world() self.assertEqual(light.position, world.light.position) self.assertEqual(light.intensity, world.light.intensity) self.assertEqual(s1.material.color, world.objects[0].material.color) self.assertEqual(s1.material.diffuse, world.objects[0].material.diffuse) self.assertEqual(s1.material.specular, world.objects[0].material.specular) self.assertEqual(s2.material.color, world.objects[1].material.color) self.assertEqual(s2.material.diffuse, world.objects[1].material.diffuse) self.assertEqual(s2.material.specular, world.objects[1].material.specular)
def test_computing_normal_on_scaled_sphere(self): s = Sphere() s.set_transform(scaling(1, 0.5, 1)) n = s.normal_at(point(0, math.sqrt(2) / 2, -math.sqrt(2) / 2)) self.assert_tuple_equals(vector(0, 0.97014, -0.24254), n, 0.001)
def test_construct_ray_through_the_center_of_the_canvas(self): c = Camera(201, 101, pi / 2.0) r = ray_for_pixel(c, 100, 50) self.assert_tuple_equals(point(0, 0, 0), r.origin, 0.001) self.assert_tuple_equals(vector(0, 0, -1), r.direction, 0.001)
def test_ray_intersects_sphere_at_tangent(self): r = Ray(point(0, 1, -5), vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(2, len(xs)) self.assertEqual(5, xs[0].t) self.assertEqual(5, xs[1].t)
def test_construct_ray_through_corner_of_the_canvas(self): c = Camera(201, 101, pi / 2.0) r = ray_for_pixel(c, 0, 0) self.assert_tuple_equals(point(0, 0, 0), r.origin, 0.001) self.assert_tuple_equals(vector(0.66519, 0.33259, -0.66851), r.direction, 0.001)
def test_sphere_behind_ray(self): r = Ray(point(0, 0, 5), vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(2, len(xs)) self.assertEqual(-6, xs[0].t) self.assertEqual(-4, xs[1].t)
def test_intersecting_translated_sphere_with_ray(self): r = Ray(point(0, 0, -5), vector(0, 0, 1)) s = Sphere() s.set_transform(translation(5, 0, 0)) xs = s.intersect(r) self.assertEqual(0, len(xs))
def test_intersect_sets_object_on_intersection(self): r = Ray(point(0, 0, -5), vector(0, 0, 1)) s = sphere.Sphere() xs = s.intersect(r) self.assertEqual(2, len(xs)) self.assertEqual(s, xs[0].shape) self.assertEqual(s, xs[1].shape)
def test_ray_originates_inside_sphere(self): r = Ray(point(0, 0, 0), vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) self.assertEqual(2, len(xs)) self.assertEqual(-1, xs[0].t) self.assertEqual(1, xs[1].t)
def test_intersection_occurs_on_the_outside(self): ray = Ray(point(0, 0, -5), vector(0, 0, 1)) shape = Sphere() xs = Intersection(4, shape) xs.prepare_hit(ray) self.assertEqual(False, xs.inside)
def test_point_light_has_position_and_intensity(self): intensity = color(1, 1, 1) position = point(0, 0, 0) light = PointLight(position, intensity) self.assertEqual(position, light.position) self.assertEqual(intensity, light.intensity)
def test_normal_on_sphere_at_point_on_none_axial_point(self): s = Sphere() n = s.normal_at( point(math.sqrt(3) / 3, math.sqrt(3) / 3, math.sqrt(3) / 3)) self.assertEqual(n.normalize(), n)
def test_normal_is_normalized_vector(self): s = Sphere() n = s.normal_at( point(math.sqrt(3) / 3, math.sqrt(3) / 3, math.sqrt(3) / 3)) self.assertEqual(n.normalize(), n)
def test_shading_and_intersection(self): world = default_world() ray = Ray(point(0, 0, -5), vector(0, 0, 1)) shape = world.objects[0] xs = Intersection(4, shape) xs.prepare_hit(ray) c = shade_hit(world, xs) self.assert_tuple_equals(color(0.38066, 0.47583, 0.2855), c, 0.001)