def test_ray_translation(): r = Ray(Point(1, 2, 3), Vector(0, 1, 0)) m = Translation(3, 4, 5) r2 = r.transform(m) print(r2.origin) assert r2.origin == Point(4, 6, 8) assert r2.direction == Vector(0, 1, 0)
def test_scaled_shape_intersection(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = _TestShape() s.set_transform(Scaling(2, 2, 2)) _ = s.intersect(r) assert s.saved_ray.origin == Point(0, 0, -2.5) assert s.saved_ray.direction == Vector(0, 0, 0.5)
def test_translated_shape_intersection(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = _TestShape() s.set_transform(Translation(5, 0, 0)) _ = s.intersect(r) assert s.saved_ray.origin == Point(-5, 0, -5) assert s.saved_ray.direction == Vector(0, 0, 1)
def test_constant_normal(): p = Plane() n1 = p.local_normal_at(Point(0, 0, 0)) n2 = p.local_normal_at(Point(10, 0, -10)) n3 = p.local_normal_at(Point(-5, 0, 150)) assert n1 == Vector(0, 1, 0) assert n2 == Vector(0, 1, 0) assert n3 == Vector(0, 1, 0)
def local_normal_at(self, point: Point): maxc = max(abs(point.x), abs(point.y), abs(point.z)) if maxc == abs(point.x): return Vector(point.x, 0, 0) elif maxc == abs(point.y): return Vector(0, point.y, 0) else: return Vector(0, 0, point.z)
def local_normal_at(self, point: Point): dist = point.x**2 + point.z**2 if dist < 1 and point.y >= self.maximum - EPSILON: return Vector(0, 1, 0) elif dist < 1 and point.y <= self.minimum + EPSILON: return Vector(0, -1, 0) else: return Vector(point.x, 0, point.z)
def test_lighting_eye_between(): # eye between light and 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(1.9, 1.9, 1.9)
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_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_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_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)
def test_surface_shadow(): 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)) in_shadow = True result = m.lighting(s, light, p, eyev, normalv, in_shadow) assert result == Color(0.1, 0.1, 0.1)
def test_precompute_state(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) shape = Sphere() i = Intersection(4, shape) comps = i.prepare_computation(r) assert comps.t == i.t assert comps.object == i.object assert comps.point == Point(0, 0, -1) assert comps.eyev == Vector(0, 0, -1) assert comps.normalv == Vector(0, 0, -1)
def test_inside_hit(): r = Ray(Point(0, 0, 0), Vector(0, 0, 1)) shape = Sphere() i = Intersection(1, shape) comps = i.prepare_computation(r) assert comps.point == Point(0, 0, 1) assert comps.eyev == Vector(0, 0, -1) assert comps.inside == True assert comps.normalv == Vector(0, 0, -1)
def test_triangle_creation(): p1 = Point(0, 1, 0) p2 = Point(-1, 0, 0) p3 = Point(1, 0, 0) t = Triangle(p1, p2, p3) assert t.p1 == p1 assert t.p2 == p2 assert t.p3 == p3 assert t.e1 == Vector(-1, -1, 0) assert t.e2 == Vector(1, -1, 0) assert t.normal == Vector(0, 0, -1)
def local_normal_at(self, point: Point): dist = point.x**2 + point.z**2 y = math.sqrt(dist) if point.y > 0: y = -y if dist < 1 and point.y >= self.maximum - EPSILON: return Vector(0, 1, 0) elif dist < 1 and point.y <= self.minimum + EPSILON: return Vector(0, -1, 0) else: return Vector(point.x, y, point.z)
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_lighting_pattern(): s = Sphere() m = Material() m.pattern = StripePattern(Color(1, 1, 1), Color(0, 0, 0)) 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(1, 1, 1)) c1 = m.lighting(s, light, Point(0.9, 0, 0), eyev, normalv, False) c2 = m.lighting(s, light, Point(1.1, 0, 0), eyev, normalv, False) assert c1 == Color(1, 1, 1) assert c2 == Color(0, 0, 0)
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_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_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_ray_from_below(): p = Plane() r = Ray(Point(0, -1, 0), Vector(0, 1, 0)) xs = p.local_intersect(r) assert len(xs) == 1 assert xs[0].t == 1 assert xs[0].object == p
def test_positive_z_orientation_matrix(): f = Point(0, 0, 0) to = Point(0, 0, 1) up = Vector(0, 1, 0) t = ViewTransform(f, to, up) print(t) assert t == Scaling(-1, 1, -1)
def test_default_orientation_matrix(): f = Point(0, 0, 0) to = Point(0, 0, -1) up = Vector(0, 1, 0) t = ViewTransform(f, to, up) print(t) assert t == Identity()
def test_camera_transform_ray(): c = Camera(201, 101, math.pi / 2) c.transform = RotationY(math.pi / 4) * Translation(0, -2, 5) r = c.ray_for_pixel(100, 50) assert r.origin == Point(0, 2, -5) print(r.direction) assert r.direction == Vector(math.sqrt(2) / 2, 0, -math.sqrt(2) / 2)
def test_cone_parallel_ray(): s = Cone() direction = Vector(0, 1, 1).normalize() r = Ray(Point(0, 0, -1), direction) xs = s.local_intersect(r) assert len(xs) == 1 assert equal(xs[0].t, 0.35355)
def test_schlick_perpendicular(): s = GlassSphere() r = Ray(Point(0, 0, 0), Vector(0, 1, 0)) xs = Intersections(Intersection(-1, s), Intersection(1, s)) comps = xs[1].prepare_computation(r, xs) reflectance = comps.schlick() assert equal(reflectance, 0.04)
def test_schlick_small_angle(): s = GlassSphere() r = Ray(Point(0, 0.99, -2), Vector(0, 0, 1)) xs = Intersections(Intersection(1.8589, s)) comps = xs[0].prepare_computation(r, xs) reflectance = comps.schlick() assert equal(reflectance, 0.48873)
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