def test_color_at_with_mutually_reflective_surfaces(self): w = World() w.light_source = PointLight(Point(0, 0, 0), Color.white()) lower = Plane() lower.material.reflective = 1 lower.transformation = translation(0, -1, 0) upper = Plane() upper.material.reflective = 1 upper.transformation = translation(0, 1, 0) w.add(lower, upper) r = Ray(Point(0, 0, 0), Vector(0, 1, 0)) # Avoid Infinite Recursion w.color_at(r) assert True
def test_chained_transformations_are_in_reverse_order(self): p = Point(1, 0, 1) a = rotation_x(math.pi / 2) b = scaling(5, 5, 5) c = translation(10, 5, 7) t = c * b * a * p assert t == Point(15, 0, 7)
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_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_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_under_point_is_offset_below_the_surface(self, glass_sphere): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = glass_sphere() shape.transformation = translation(0, 0, 1) i = Intersection(5, shape) xs = Intersections(i) comps = i.prepare_computations(r, xs) assert comps.under_point.z > EPSILON / 2 assert comps.point.z < comps.under_point.z
def test_finding_n1_and_n2_at_various_intersections( self, glass_sphere, index, n1, n2): a = glass_sphere() a.transformation = scaling(2, 2, 2) a.material.refractive_index = 1.5 b = glass_sphere() b.transformation = translation(0, 0, -0.25) b.material.refractive_index = 2.0 c = glass_sphere() c.transformation = translation(0, 0, 0.25) c.material.refractive_index = 2.5 r = Ray(Point(0, 0, -4), Vector(0, 0, 1)) xs = Intersections(Intersection(2, a), Intersection(2.75, b), Intersection(3.25, c), Intersection(4.75, b), Intersection(5.25, c), Intersection(6, a)) comps = xs[index].prepare_computations(r, xs) assert comps.n1 == n1 assert comps.n2 == n2
def test_individual_transformations_in_sequence(self): p = Point(1, 0, 1) a = rotation_x(math.pi / 2) b = scaling(5, 5, 5) c = translation(10, 5, 7) p2 = a * p assert p2 == Point(1, -1, 0) p3 = b * p2 assert p3 == Point(5, -5, 0) p4 = c * p3 assert p4 == Point(15, 0, 7)
def test_reflected_color_for_reflective_material(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.reflected_color(comps) assert color == Color(0.19033, 0.23791, 0.14274)
def test_shade_hit_with_reflective_material(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.shade_hit(comps) assert color == Color(0.87676, 0.92434, 0.82917)
def test_reflected_color_at_max_recursive_depth(self, default_world): w = default_world shape = Plane() shape.material.reflective = 0.5 shape.transformation = translation(0, -1, 0) w.add(shape) r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2)) i = Intersection(sqrt(2), shape) comps = i.prepare_computations(r) color = w.reflected_color(comps, 0) assert color == Color.black()
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)
from raytracer.patterns import * from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.scene import World from raytracer.shapes import Sphere, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material.color = Color(.1, 1, .1) floor.material.reflective = 0.9 floor.material.transparency = 1 floor.material.refractive_index = 1.333 under = Sphere() under.transformation = translation(0, -.5, 0) * scaling(.25, .25, .25) under.material.color = Color(0, .8, 0) under.material.refractive_index = 1.5 under.material.ambient = .8 above = Sphere() above.transformation = translation(1, .5, 0) * scaling(.5, .5, .5) above.material.color = Color(.2, 0, 0) above.material.diffuse = .8 above.material.ambient = .5 bottom = Plane() bottom.transformation = translation(0, -1.25, 0) bottom.material.pattern = StripePattern(Color.black(), Color(0, .2, .2)) bottom.material.diffuse = .25 bottom.material.ambient = .25
from raytracer.lights import PointLight from raytracer.materials import Material from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.scene import World from raytracer.shapes import Sphere, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material = Material() floor.material.color = Color(1, 0.9, 0.9) floor.material.specular = 0 middle = Sphere() middle.transformation = translation(-0.5, 1, 0.5) middle.material = Material() middle.material.color = Color(0.5, 0, 0) middle.material.diffuse = 0.7 middle.material.specular = 0.3 middle.material.reflective = 1 right = Sphere() right.transformation = translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5) right.material = Material() right.material.color = Color(0.2, 0.2, 0.8) right.material.diffuse = 0.7 right.material.specular = 0.3 right.material.reflective = .5 left = Sphere()
def test_translate_ray(self): r = Ray(Point(1, 2, 3), Vector(0, 1, 0)) m = translation(3, 4, 5) r2 = r.transform(m) assert r2.origin == Point(4, 6, 8) assert r2.direction == Vector(0, 1, 0)
def test_construct_ray_when_camera_is_transformed(self): c = Camera(201, 101, pi / 2) c.transformation = rotation_y(pi / 4) * translation(0, -2, 5) r = c.ray_for_pixel(100, 50) assert r.origin == Point(0, 2, -5) assert r.direction == Vector(sqrt(2) / 2, 0, -sqrt(2) / 2)
from raytracer.lights import PointLight from raytracer.patterns import * from raytracer.matrices import scaling, rotation_x, rotation_y, rotation_z, translation, view_transform from raytracer.scene import World from raytracer.shapes import Cylinder, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material.color = Color(.8, .8, .8) floor.material.reflective = .2 cylinder = Cylinder(closed=True) cylinder.maximum = 0.25 cylinder.material.color = Color(.8, 0, 0) cylinder.material.reflective = .6 cylinder.transformation = translation(0, 1, 0) world = World() world.add(floor, cylinder) world.light_source = PointLight(Point(-10, 10, -10), Color.white()) camera = Camera(160, 120, pi / 3) camera.transformation = view_transform(Point(0, 1.5, -5), Point( 0, 1, 0), Vector(0, 1, 0)) * rotation_y(-pi / 4) * rotation_x(-pi / 6) canvas = camera.render(world) write_ppm_to_file(canvas.to_ppm(), f'..{sep}..{sep}resources{sep}cylinders.ppm')
from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.patterns import * from raytracer.matrices import scaling, rotation_y, rotation_z, translation, view_transform from raytracer.scene import World from raytracer.shapes import Cube, Plane from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Plane() floor.material.color = Color(.8, .8, .8) floor.material.reflective = .2 cube = Cube() cube.material.color = Color(.8, 0, 0) cube.material.reflective = .6 cube.transformation = translation(0, 1, 0) * rotation_y(pi / 4) world = World() world.add(floor, cube) world.light_source = PointLight(Point(-10, 10, -10), Color.white()) camera = Camera(160, 120, pi / 3) camera.transformation = view_transform(Point(0, 1.5, -5), Point(0, 1, 0), Vector(0, 1, 0)) canvas = camera.render(world) write_ppm_to_file(canvas.to_ppm(), f'..{sep}..{sep}resources{sep}cubes.ppm')
def test_assign_transformation(self): pattern = test_pattern() pattern.transformation = translation(1, 2, 3) assert pattern.transformation == translation(1, 2, 3)
from raytracer.lights import PointLight from raytracer.materials import Material from raytracer.matrices import scaling, rotation_y, rotation_x, translation, view_transform from raytracer.scene import World from raytracer.shapes import Sphere from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': floor = Sphere() floor.transformation = scaling(10, 0.01, 10) floor.material = Material() floor.material.color = Color(1, 0.9, 0.9) floor.material.specular = 0 left_wall = Sphere() left_wall.transformation = translation(0, 0, 5) * \ rotation_y(-pi / 4) * rotation_x(pi / 2) * \ scaling(10, 0.01, 10) left_wall.material = floor.material right_wall = Sphere() right_wall.transformation = translation(0, 0, 5) * \ rotation_y(pi / 4) * rotation_x(pi / 2) * \ scaling(10, 0.01, 10) right_wall.material = floor.material middle = Sphere() middle.transformation = translation(-0.5, 1, 0.5) middle.material = Material() middle.material.color = Color(0.1, 1, 0.5) middle.material.diffuse = 0.7
def test_multiply_by_inverse_of_translation_matrix(self): transform = translation(5, -3, 2) inv = transform.inverse() p = Point(-3, 4, 5) assert inv * p == Point(-8, 7, 3)
def test_view_transformation_moves_the_world(self): _from = Point(0, 0, 8) to = Point(0, 0, 0) up = Vector(0, 1, 0) t = view_transform(_from, to, up) assert t == translation(0, 0, -8)
def test_translation_does_not_affect_vectors(self): transform = translation(5, -3, 2) v = Vector(-3, 4, 5) assert transform * v == v
from math import pi from os import sep from raytracer.camera import Camera from raytracer.canvas import write_ppm_to_file from raytracer.lights import PointLight from raytracer.matrices import translation, view_transform from raytracer.scene import World from raytracer.shapes import Cone from raytracer.tuples import Color, Point, Vector if __name__ == '__main__': cone = Cone(closed=False) cone.maximum = 1 cone.minimum = -1 cone.material.color = Color(.8, 0, 0) cone.transformation = translation(0, 1, 0) world = World() world.add(cone) world.light_source = PointLight(Point(-5, 5, -5), Color.white()) camera = Camera(160, 120, pi / 3) camera.transformation = view_transform(Point(0, 1.5, -5), Point(0, 1, 0), Vector(0, 1, 0)) canvas = camera.render(world) write_ppm_to_file(canvas.to_ppm(), f'..{sep}..{sep}resources{sep}cone.ppm')
def test_multiply_by_translation_matrix(self): transform = translation(5, -3, 2) p = Point(-3, 4, 5) assert transform * p == Point(2, 1, 7)