def ray_for_pixel(self, px, py): xoffset = (px + 0.5) * self.Get_Pixel_Size() yoffset = (py + 0.5) * self.Get_Pixel_Size() world_x = self.Half_Width() - xoffset world_y = self.Half_Height() - yoffset pixel = self.set_transform.inverse().multiply_tuple( point(world_x, world_y, -1)) origin = self.set_transform.inverse().multiply_tuple(point(0, 0, 0)) direction = pixel - origin direction = direction.normalize() return ray(origin, direction)
def check_tuple(x, y, z, w): """ checks if the tuple is a point or a vector """ if w == 0: return vector(x, y, z) return point(x, y, z)
def normal_at(self, p): """ returns the normalized normal at that point """ object_point = self.transform_within.inverse().multiply_tuple(p) object_normal = object_point - point(0, 0, 0) world_normal = self.transform_within.inverse().transpose().multiply_tuple(object_normal) world_normal.val[3] = 0.0 return world_normal.normalize()
def default_world(): light = point_light(point(-10, 10, -10), color(1, 1, 1)) s1 = sphere() s1.material.colour = color(0.8, 1.0, 0.6) s1.material.diffuse = 0.7 s1.material.specular = 0.2 s2 = sphere() s2.transform_within = scaling(0.5, 0.5, 0.5) w = world(object=[s1, s2], light=[light]) return w
def intersect(self, ray_initial): """ The big intersect function that finds the intersection of a sphere and a ray two or zero intersections returned zero in teh case of no intersection two in the case of both a single and two unique intersections smaller first followed by larger intersection """ r = ray_initial.transform(self.transform_within.inverse()) sphere_to_ray = r.Origin() - point(0, 0, 0) a = r.Direction().dot(r.Direction()) b = 2 * r.Direction().dot(sphere_to_ray) c = sphere_to_ray.dot(sphere_to_ray) - 1 discriminant = b * b - 4 * a * c if discriminant < 0: return () t1 = (-b - sqrt(discriminant))/(2 * a) t2 = (-b + sqrt(discriminant)) / (2 * a) return [{'time': t1, 'object': self}, {'time': t2, 'object': self}]
def multiply_tuple(self, tuple): A = np.array(self.data) B = np.array(tuple.val) if A.dot(B)[3] == 0: return vector(A.dot(B)[0], A.dot(B)[1], A.dot(B)[2]) return point(A.dot(B)[0], A.dot(B)[1], A.dot(B)[2])
middle.material.diffuse = 0.7 middle.material.specular = 0.3 right = sphere() right.set_transform(translation(1.5, 0.5, -0.5) * scaling(0.5, 0.5, 0.5)) right.material.colour = color(0.5, 1, 0.1) right.material.diffuse = 0.7 right.material.specular = 0.3 left = sphere() left.set_transform(translation(-1.5, 0.33, -0.75) * scaling(0.33, 0.33, 0.33)) left.material.colour = color(1, 0.8, 0.1) left.material.diffuse = 0.7 left.material.specular = 0.3 source = point_light(point(-10, 10, -10), color(1, 1, 1)) w = world(object=[middle, left, right, floor, left_wall, right_wall]) w.set_light(source) c = camera(200, 100, pi / 3) FROM = point(0, 1.5, -5) TO = point(0, 1, 0) UP = vector(0, 1, 0) data = view_transform(FROM, TO, UP) c.Set_Transform(data) IMAGE = c.render(w) IMAGE.to_ppm(filename='pls')
check what the origin is in the ray """ return self.origin def Direction(self): """ check the direcrion of the ray """ return self.direction def position(self, time): """ returns a point at t second along the origin and direction of the ray """ final = self.origin + (self.direction * time) return final def transform(self, matrix): """ returns a second transformed ray """ return ray(matrix.multiply_tuple(self.origin), matrix.multiply_tuple(self.direction)) if __name__ == '__main__': r = ray(point(1, 2, 3), vector(0, 1, 0)) m = scaling(2, 3, 4) r2 = r.transform(m) print(r2.origin, r.origin) print(r2.direction, r.direction)
if __name__ == '__main__': # w = world() # w.set_light(point_light(point(0, 0, -10), color(1, 1, 1))) # s1 = sphere() # w.add_object(s1) # s2 = sphere(transform_within=translation(0, 0, 10)) # w.add_object(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) # print(c.red, c.green, c.blue) r = ray(point(0, 0, -5), vector(0, 0, 1)) shape = sphere() shape.transform_within = translation(0, 0, 1) i = Intersection(5, shape) comps = i.prepare_computations(r) print(comps['over_point'].val[2] < -EPSILON / 2) print(comps['point'].val[2] > comps['over_point'].val[2]) # w = default_world() # p = point(10, -10, 10) # result = w.is_shadowed(p) # print(result) # w.set_light(point_light(point(0, 0.25, 0), color(1, 1, 1))) # r = ray(point(0, 0, 0), vector(0, 0, 1)) # i = Intersection(0.5, w.items[1]) # comps = i.prepare_computations(r)