def ray_for_pixel(self, pixel_x, pixel_y): xoffset = (pixel_x + 0.5) * self.pixel_size yoffset = (pixel_y + 0.5) * self.pixel_size world_x = self.half_width - xoffset world_y = self.half_height - yoffset pixel = multiply_tuple(self.__inverse_transform, point(world_x, world_y, -1)) origin = multiply_tuple(self.__inverse_transform, point(0, 0, 0)) direction = normalize(subtract(pixel, origin)) return Ray(origin, direction)
def from_yaml(cls, data): camera = cls(data['width'], data['height'], data['field-of-view']) values = data['from'] from_pos = point(values[0], values[1], values[2]) values = data['to'] to_pos = point(values[0], values[1], values[2]) values = data['up'] up_vector = vector(values[0], values[1], values[2]) camera.set_transform(view_transform(from_pos, to_pos, up_vector)) return camera
def from_yaml(cls, data): values = data['at'] position = point(values[0], values[1], values[2]) values = data['intensity'] intensity = color(values[0], values[1], values[2]) return cls(position, intensity)
def main(): p = dict(position=point(0, 1, 0), velocity=normalize(vector(1, 1, 0))) e = dict(gravity=vector(0, -0.1, 0), wind=vector(-0.01, 0, 0)) while p['position'][1] > 0.0: print( f"position {p['position'][0]}, {p['position'][1]}, {p['position'][2]}" ) p = tick(e, p)
def main(): canvas_pixels = 500 canvas = Canvas(canvas_pixels, canvas_pixels) shape = Sphere() # assign material shape.material = Material() shape.material.color = color(1, 0.2, 1) light_position = point(-10, 10, -10) light_color = color(1, 1, 1) light = PointLight(light_position, light_color) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) shape_hit = hit(xs) if shape_hit is not None: hit_point = r.position_at(shape_hit.t) normal = shape_hit.object.normal_at(hit_point) eye = negate(r.direction) px_color = lighting(shape_hit.object.material, shape_hit.object, light, hit_point, eye, normal) canvas.set_pixel(x, y, px_color) with open('render_phong_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def main(): canvas_pixels = 400 canvas = Canvas(canvas_pixels, canvas_pixels) red = color(1, 0, 0) shape = Sphere() # shrink it along the y axis #shape.set_transform(scaling(1, 0.5, 1)) # shrink it along the x axis #shape.set_transform(scaling(0.5, 1, 1)) # shrink it, and rotate it! # shape.set_transform(multiply_matrix(rotation_z(pi / 4), scaling(0.5, 1, # 1))) # shrink it, and skew it! # shape.set_transform( # multiply_matrix(shearing(1, 0, 0, 0, 0, 0), scaling(0.5, 1, 1))) ray_origin = point(0, 0, -5) wall_z = 10 wall_size = 7.0 pixel_size = wall_size / canvas_pixels half = wall_size / 2 for y in range(canvas_pixels): world_y = half - pixel_size * y for x in range(canvas_pixels): world_x = -half + pixel_size * x pos = point(world_x, world_y, wall_z) r = Ray(ray_origin, normalize(subtract(pos, ray_origin))) xs = shape.intersect(r) if hit(xs) is not None: canvas.set_pixel(x, y, red) with open('render_sphere.ppm', 'w') as out_file: out_file.write(canvas.to_ppm())
def main(): p = dict(position=point(0, 1, 0), velocity=multiply(normalize(vector(1, 1.8, 0)), 11.25)) e = dict(gravity=vector(0, -0.1, 0), wind=vector(-0.01, 0, 0)) c = Canvas(900, 550) while p['position'][1] > 0.0: print( f"position {p['position'][0]}, {p['position'][1]}, {p['position'][2]}" ) c.set_pixel(round(p['position'][0]), c.height - round(p['position'][1]), color(0.0, 1.0, 0.0)) p = tick(e, p) with open('cannon.ppm', 'w') as out_file: out_file.write(c.to_ppm())
def main(): c = Canvas(500, 500) p = point(0, 0, 1) translate = translation(250, 0, 250) scale = scaling(100, 0, 100) for h in range(12): r = rotation_y(h * pi / 6) transform = multiply_matrix(translate, multiply_matrix(scale, r)) p2 = multiply_tuple(transform, p) print(f"position ({p2[0]}, {p2[1]}, {p2[2]})") c.set_pixel(round(p2[0]), c.height - round(p2[2]), color(0.0, 1.0, 0.0)) with open('clock.ppm', 'w') as out_file: out_file.write(c.to_ppm())
def local_intersect(self, local_ray): sphere_to_ray = subtract(local_ray.origin, point(0, 0, 0)) a = dot(local_ray.direction, local_ray.direction) b = 2 * dot(local_ray.direction, sphere_to_ray) c = dot(sphere_to_ray, sphere_to_ray) - 1 discriminant = b**2 - 4 * a * c if discriminant < 0: return [] t1 = (-b - sqrt(discriminant)) / (2 * a) t2 = (-b + sqrt(discriminant)) / (2 * a) i1 = Intersection(t1, self) i2 = Intersection(t2, self) return [i1, i2]
def default(cls): world = cls() world.add_light(PointLight(point(-10, 10, -10), color(1, 1, 1))) sphere1 = Sphere() mat = Material() mat.color = color(0.8, 1.0, 0.6) mat.diffuse = 0.7 mat.specular = 0.2 sphere1.material = mat sphere2 = Sphere() sphere2.set_transform(scaling(0.5, 0.5, 0.5)) world.objects.append(sphere1) world.objects.append(sphere2) return world
def from_yaml(cls, data): values = data['corner'] corner = point(values[0], values[1], values[2]) values = data['uvec'] uvec = vector(values[0], values[1], values[2]) usteps = data['usteps'] values = data['vvec'] vvec = vector(values[0], values[1], values[2]) vsteps = data['vsteps'] values = data['intensity'] intensity = color(values[0], values[1], values[2]) light = cls(corner, uvec, usteps, vvec, vsteps, intensity) if 'jitter' in data and data['jitter']: light.jitter_by = RandomSequence() return light
def parse_obj_file(content, material=Material()): obj_file = ObjFile() current_group = obj_file.groups["default"] for line in content: parts = line.split() if len(parts) < 1: obj_file.ignored += 1 continue if parts[0] == "v": obj_file.vertices.append( point(float(parts[1]), float(parts[2]), float(parts[3]))) elif parts[0] == "vn": obj_file.normals.append( vector(float(parts[1]), float(parts[2]), float(parts[3]))) elif parts[0] == "g": current_group = Group() obj_file.groups[parts[1]] = current_group elif parts[0] == "f": vertices = [None] normals = [None] for index in range(1, len(parts)): v, vt, vn = to_ints(parts[index]) vertices.append(obj_file.vertices[v]) if vn: normals.append(obj_file.normals[vn]) triangles = fan_triangulation(vertices, normals, material) for triangle in triangles: current_group.add_child(triangle) else: obj_file.ignored += 1 return obj_file
def step_calculate_local_normal_n3_of_t_at_point(context, x, y, z): context.n3 = context.t.local_normal_at(point(x, y, z))
def step_create_triangle_t_with_points(context, x1, y1, z1, \ x2, y2, z2, \ x3, y3, z3): context.t = Triangle(point(x1, y1, z1), point(x2, y2, z2), point(x3, y3, z3))
def step_impl(context): actual = multiply_tuple(context.inv, context.p) expected = point(0, sqrt(2) / 2, -sqrt(2) / 2)
def step_impl(context, x, y, z): actual = multiply_tuple(context.transform, context.p) expected = point(x, y, z) assert_tuple(actual, expected)
def step_assert_light_positon_equals_point(context, x, y, z): assert_tuple(context.light.position, point(x, y, z))
def step_create_point_origin(context, x, y, z): context.origin = point(x, y, z)
def step_create_point_light_direct(context, px, py, pz, red, green, blue): context.light = PointLight(point(px, py, pz), color(red, green, blue))
def step_assign_world_to_object_of_point_to_p(context, x, y, z): context.p = context.s.world_to_object(point(x, y, z))
def step_assert_light_corner_equals_point(context, x, y, z): assert_tuple(context.light.corner, point(x, y, z))
def step_assert_saved_ray_origin_equals_point(context, x, y, z): assert_tuple(context.s.saved_ray.origin, point(x, y, z))
def step_assign_normal_of_tri_at_point_to_i(context): context.n = context.tri.normal_at(point(0, 0, 0), context.i)
def step_assert_p_equals_point(context, x, y, z): assert_tuple(context.p, point(x, y, z))
def step_impl(context): actual = multiply_tuple(context.half_quarter, context.p) expected = point(-sqrt(2) / 2, sqrt(2) / 2, 0) assert_tuple(actual, expected)
def step_assign_normal_of_s_at_point_to_n(context, x, y, z): context.n = context.s.normal_at(point(x, y, z))
def step_impl(context, x, y, z): actual = multiply_tuple(context.full_quarter, context.p) expected = point(x, y, z) assert_tuple(actual, expected)
def step_assign_normal_of_s_at_certain_point_to_n(context): xyz = sqrt(3) / 3 context.n = context.s.normal_at(point(xyz, xyz, xyz))
def step_assign_local_normal_at_to_n3(context, x, y, z): context.n3 = context.p.local_normal_at(point(x, y, z))
def step_assign_normal_of_s_at_another_point_to_n(context): xyz = sqrt(2) / 2 context.n = context.s.normal_at(point(0, xyz, -xyz))