def run() -> None: STEPS = 180 SIZE = 600 MIDDLE = SIZE // 2 canvas = Canvas(SIZE, SIZE) color = Color(1, 0, 0) color_increment = Color(0, 0, 1.0 / STEPS) position = point(0, 1, 0) rotate = rotation_z(-2 * math.pi / STEPS) translate = translation(MIDDLE, MIDDLE, 0) scale = scaling(SIZE // 3, SIZE // 3, 1) for i in range(STEPS): canvas_position = translate * scale * position assert isinstance(canvas_position, Point) canvas.write_pixel( int(round(canvas_position.x)), SIZE - int(round(canvas_position.y)), color, ) position = rotate * position color += color_increment ppm = PPM(canvas) file_name = "clocks.ppm" ppm.save_to_file(file_name) print(f"Output stored to {file_name}")
def test_sphere_intersection_scaled(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = Sphere() s.set_transform(scaling(2, 2, 2)) x = r.intersects(s) assert len(x) == 2 assert x[0].t == 3 assert x[1].t == 7
def test_transformation_chain(): p = Point(1, 0, 1) A = rotation_x(pi / 2) B = scaling(5, 5, 5) C = translation(10, 5, 7) T = C @ B @ A assert T * p == Point(15, 0, 7)
def create_room() -> List[Sphere]: floor = Sphere() floor.transform = scaling(10, 0.01, 10) floor.material.color = Color(1, 0.9, 0.9) floor.material.specular = 0 left_wall = Sphere() left_wall.transform = (translation(0, 0, 5) * rotation_y(-math.pi / 4) * rotation_x(math.pi / 2) * scaling(10, 0.01, 10)) left_wall.material = floor.material right_wall = Sphere() right_wall.transform = (translation(0, 0, 5) * rotation_y(math.pi / 4) * rotation_x(math.pi / 2) * scaling(10, 0.01, 10)) right_wall.material = floor.material return [floor, left_wall, right_wall]
def create_objects() -> List[Sphere]: middle = Sphere() middle.transform = translation(-0.5, 1, 0.5) middle.material.color = Color(0.1, 1, 0.5) middle.material.diffuse = 0.7 middle.material.specular = 0.3 right = Sphere() right.transform = translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5) right.material.color = Color(0.5, 1, 0.1) right.material.diffuse = 0.7 right.material.specular = 0.3 left = Sphere() left.transform = translation(-1.5, 0.33, -0.75) * scaling(0.33, 0.33, 0.33) left.material.color = Color(1, 0.8, 0.1) left.material.diffuse = 0.7 left.material.specular = 0.3 return [middle, right, left]
def create_structure( structure_type: str, x: float, y: float, z: float ) -> Union[Tuple, Color, Matrix]: if structure_type == "vector": return vector(x, y, z) elif structure_type == "point": return point(x, y, z) elif structure_type == "color": return Color(x, y, z) elif structure_type == "scaling": return scaling(x, y, z) elif structure_type == "translation": return translation(x, y, z) else: raise NotImplementedError(f"structure type '{structure_type}' not recognized")
def default_world() -> World: """A default world with 2 spheres and a light""" sphere_1 = Sphere() sphere_1.material = Material() sphere_1.material.color = Color(0.8, 1.0, 0.6) sphere_1.material.diffuse = 0.7 sphere_1.material.specular = 0.2 sphere_2 = Sphere() sphere_2.transform = scaling(0.5, 0.5, 0.5) world = World() world.light = PointLight(point(-10, 10, -10), Color(1, 1, 1)) world.objects.append(sphere_1) world.objects.append(sphere_2) return world
def test_sphere_normal_at_scaled(): s = Sphere() s.set_transform(scaling(1, 0.5, 1)) n = s.normal_at(Point(0, sqrt(2) / 2, -sqrt(2) / 2)) assert n == Vector(0, 0.9701425001453319, -0.24253562503633297)
def test_scale(): r = Ray(Point(1, 2, 3), Vector(0, 1, 0)) m = scaling(2, 3, 4) r2 = r.transform(m) assert r2.origin == Point(2, 6, 12) assert r2.direction == Vector(0, 3, 0)
def test_reflection(): t = scaling(-1, 1, 1) p = Point(2, 3, 4) assert t * p == Point(-2, 3, 4)
def test_scaling_inverse(): t = scaling(2, 3, 4) inv = t.inv v = Vector(-4, 6, 8) assert inv * v == Vector(-2, 2, 2)
def test_scaling_vector(): t = scaling(2, 3, 4) p = Vector(-4, 6, 8) assert t * p == Vector(-8, 18, 32)
def test_scaling_point(): t = scaling(2, 3, 4) p = Point(-4, 6, 8) assert t * p == Point(-8, 18, 32)
from math import pi from src.canvas import Canvas from src.color import Color from src.primitives import Sphere from src.ray import Ray from src.transformations import scaling, rotation_z from src.tupl import Point s = Sphere() t = rotation_z(pi / 4) @ scaling(0.5, 1, 1) s.set_transform(t) r_origin = Point(0, 0, -5) wall_z = 10 wall_size = 7 N = 100 c = Canvas(N, N) pixel_size = wall_size / N half = wall_size / 2 red = Color(255, 0, 0) for y in range(c.height): world_y = half - pixel_size * y for x in range(c.width): world_x = -half + pixel_size * x position = Point(world_x, world_y, wall_z) r = Ray(r_origin, (position - r_origin).normalize()) X = r.intersects(s) if X.hit is not None: c.write_pixel(x, y, red)
def assign_scaling(context, var, x, y, z): context.variables[var] = scaling(x, y, z)