def test_pattern_with_both_object_and_pattern_transformation(self): obj = Sphere() obj.transformation = scaling(2, 2, 2) pattern = test_pattern() pattern.transformation = translation(0.5, 1, 1.5) c = pattern.pattern_at_shape(obj, Point(2.5, 3, 3.5)) assert c == Color(0.75, 0.5, 0.25)
def test_both_transform(): s = Sphere() s.set_transform(Scaling(2, 2, 2)) pattern = _TestPattern() pattern.set_pattern_transform(Translation(0.5, 1, 1.5)) c = pattern.pattern_at_shape(s, Point(2.5, 3, 3.5)) assert c == Color(0.75, 0.5, 0.25)
def test_ray_sphere_intersect(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() i = s.intersect(r) assert len(i) == 2 assert i[0].t == 4.0 assert i[1].t == 6.0
def test_sphere_behind_ray(): r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) s = Sphere() i = s.intersect(r) assert len(i) == 2 assert i[0].t == -6.0 assert i[1].t == -4.0
def test_object_intersect(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() xs = s.intersect(r) assert len(xs) == 2 assert xs[0].object == s assert xs[1].object == s
def test_ray_in_sphere(): r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) s = Sphere() i = s.intersect(r) assert len(i) == 2 assert i[0].t == -1 assert i[1].t == 1
def test_ray_tangent_intersect(): r = Ray(Point(0, 1, -5), Vector(0, 0, 1)) s = Sphere() i = s.intersect(r) assert len(i) == 2 assert i[0].t == 5.0 assert i[1].t == 5.0
def test_hit_offset(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = Sphere() shape.set_transform(Translation(0, 0, 1)) i = Intersection(5, shape) comps = i.prepare_computation(r) assert comps.over_point.z < -EPSILON / 2 assert comps.point.z > comps.over_point.z
def test_hit_should_offset_the_point(self): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = Sphere() shape.transformation = translation(0, 0, 1) i = Intersection(5, shape) comps = i.prepare_computations(r) assert comps.over_point.z < -EPSILON / 2 assert comps.point.z > comps.over_point.z
def test_transformed_group(): g = Group() g.set_transform(Scaling(2, 2, 2)) s = Sphere() s.set_transform(Translation(5, 0, 0)) g.add_child(s) r = Ray(Point(10, 0, -10), Vector(0, 0, 1)) xs = g.intersect(r) assert len(xs) == 2
def test_world_to_object(): g1 = Group() g1.set_transform(RotationY(math.pi / 2)) g2 = Group() g2.set_transform(Scaling(2, 2, 2)) g1.add_child(g2) s = Sphere() s.set_transform(Translation(5, 0, 0)) g2.add_child(s) p = s.world_to_object(Point(-2, 0, -10)) assert p == Point(0, 0, -1)
def test_child_normal(): g1 = Group() g1.set_transform(RotationY(math.pi / 2)) g2 = Group() g2.set_transform(Scaling(1, 2, 3)) g1.add_child(g2) s = Sphere() s.set_transform(Translation(5, 0, 0)) g2.add_child(s) n = s.normal_at(Point(1.7321, 1.1547, -5.5774)) assert n == Vector(0.2857, 0.4286, -0.8571)
def default_world(): w = World() w.light_source = PointLight(Point(-10, 10, -10), Color.white()) s1 = Sphere() s1.material.color = Color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2 = Sphere() s2.transformation = scaling(0.5, 0.5, 0.5) w.add(s1, s2) return w
def test_shade_hit_is_given_an_intersection_in_shadow(self): w = World() w.light_source = PointLight(Point(0, 0, -10), Color.white()) s1 = Sphere() s2 = Sphere() s2.transformation = translation(0, 0, 10) w.add(s1, s2) r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) i = Intersection(4, s2) comps = i.prepare_computations(r) c = w.shade_hit(comps) assert c == Color(0.1, 0.1, 0.1)
def test_lighting_with_pattern_applied(self): m = Material() m.pattern = StripePattern(Color.white(), Color.black()) m.ambient = 1 m.diffuse = 0 m.specular = 0 eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color.white()) c1 = m.lighting(Sphere(), light, Point(0.9, 0, 0), eyev, normalv, False) c2 = m.lighting(Sphere(), light, Point(1.1, 0, 0), eyev, normalv, False) assert c1 == Color.white() assert c2 == Color.black()
def test_shadow_shade_hit(): w = World() w.light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) s1 = Sphere() s2 = Sphere() s2.set_transform(Translation(0, 0, 10)) w.objects.extend([s1, s2]) r = Ray(Point(0, 0, 5), Vector(0, 0, 1)) i = Intersection(4, s2) comps = i.prepare_computation(r) c = w.shade_hit(comps) print(c) assert c == Color(0.1, 0.1, 0.1)
def test_normal_object_to_world(): g1 = Group() g1.set_transform(RotationY(math.pi / 2)) g2 = Group() g2.set_transform(Scaling(1, 2, 3)) g1.add_child(g2) s = Sphere() s.set_transform(Translation(5, 0, 0)) g2.add_child(s) n = s.normal_to_world( Vector(math.sqrt(3) / 3, math.sqrt(3) / 3, math.sqrt(3) / 3)) assert n == Vector(0.2857, 0.4286, -0.8571)
def test_positive_hit(): s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i1, i2) i = xs.hit() assert i == i1
def test_lighting_with_surface_in_shadow(self, background): eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) in_shadow = True result = background['m'].lighting(Sphere(), light, background['position'], eyev, normalv, in_shadow) assert result == Color(0.1, 0.1, 0.1)
def test_mixed_hit(): s = Sphere() i1 = Intersection(-1, s) i2 = Intersection(1, s) xs = Intersections(i1, i2) i = xs.hit() assert i == i2
def test_shade_hit_with_transparent_material(self, default_world): w = default_world floor = Plane() floor.transformation = translation(0, -1, 0) floor.material.transparency = 0.5 floor.material.refractive_index = 1.5 ball = Sphere() ball.material.color = Color(1, 0, 0) ball.material.ambient = 0.5 ball.transformation = translation(0, -3.5, -0.5) w.add(floor, ball) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) xs = Intersections(Intersection(sqrt(2), floor)) comps = xs[0].prepare_computations(r, xs) color = w.shade_hit(comps, 5) assert color == Color(0.93642, 0.68642, 0.68642)
def test_negative_hit(): s = Sphere() i1 = Intersection(-2, s) i2 = Intersection(-1, s) xs = Intersections(i1, i2) i = xs.hit() assert i is None
def test_aggregate_intersections(): s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i1, i2) assert len(xs) == 2 assert xs[0].t == 1 assert xs[1].t == 2
def test_hit_is_always_lowest_nonnegative_intersection(self): s = Sphere() i1 = Intersection(5, s) i2 = Intersection(7, s) i3 = Intersection(-3, s) i4 = Intersection(2, s) xs = Intersections(i1, i2, i3, i4) assert xs.hit() == i4
def shade_hit_transparent(): w = World().default() floor = Plane() floor.set_transform(Translation(0, -1, 0)) floor.material.transparency = 0.5 floor.material.refractive_index = 1.5 w.objects.append(floor) ball = Sphere() ball.material.color = Color(1, 0, 0) ball.material.ambient = 0.5 ball.set_transform(Translation(0, -3.5, -0.5)) w.objects.append(ball) r = Ray(Point(0, 0, -3), Vector(0, -math.sqrt(2) / 2, math.sqrt(2) / 2)) xs = Intersections(Intersection(math.sqrt(2), floor)) comps = xs[0].prepare_computations(r, xs) color = w.shade_hit(comps, 5) assert color == Color(0.93642, 0.68642, 0.68642)
def test_aggregate_intersections(self): s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i1, i2) assert xs.count == 2 assert xs[0].t == 1 assert xs[1].t == 2
def test_lighting_eye_offset(): # eye between light and surface, 45 offset s = Sphere() m = Material() p = Point(0, 0, 0) eyev = Vector(0, math.sqrt(2) / 2, -math.sqrt(2) / 2) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, -10), Color(1, 1, 1)) res = m.lighting(s, light, p, eyev, normalv) assert res == Color(1.0, 1.0, 1.0)
def test_lighting_eye_in_path(): # eye in reflection path s = Sphere() m = Material() p = Point(0, 0, 0) eyev = Vector(0, -math.sqrt(2) / 2, -math.sqrt(2) / 2) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 10, -10), Color(1, 1, 1)) res = m.lighting(s, light, p, eyev, normalv) assert res == Color(1.6364, 1.6364, 1.6364)
def test_lighting_eye_opposite(): # eye opposite surface, 45 offset s = Sphere() m = Material() p = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 10, -10), Color(1, 1, 1)) res = m.lighting(s, light, p, eyev, normalv) assert res == Color(0.7364, 0.7364, 0.7364)
def test_lighting_behind_surface(): # eye behind surface s = Sphere() m = Material() p = Point(0, 0, 0) eyev = Vector(0, 0, -1) normalv = Vector(0, 0, -1) light = PointLight(Point(0, 0, 10), Color(1, 1, 1)) res = m.lighting(s, light, p, eyev, normalv) assert res == Color(0.1, 0.1, 0.1)