def material_from_json(m: Any) -> Any: if m['name'] == 'Lambert': return Lambert(color=Vec3(*m['args'])) elif m['name'] == 'Metal': return Metal(color=Vec3(*m['args'])) else: raise RuntimeError('Unknown material type: ' + m.name)
def test_ray_intersection_min(): scene = [Sphere(1, Translation(0, 0, -5), Lambert(Vec3(0, 0, 0)))] ray = Ray(Point3(0, 0, 0), Vec3(0, 0, -1)) hits = list(map(lambda s: s.hit(ray), scene)) min_hit = min(hits, key=lambda h: h.t) assert min_hit is not None
def test_ray_intersection(): s = Sphere(1, Translation(0, 0, 0), Lambert(Vec3(0, 0, 0))) ray = Ray(Point3(0, 0, 3), Vec3(0, 0, -1)) i = s.hit(ray) assert i is not None assert i.t == 2 assert i.point == Point3(0, 0, 1) assert i.normal == Vec3(0, 0, 1) assert isinstance(i.material, Lambert)
def __matmul__(self, other): if isinstance(other, Vec3): return Vec3(vec=self.matrix @ other.vec) if isinstance(other, Point3): return Point3(vec=self.matrix @ other.vec) if isinstance(other, Ray): return Ray(Point3(vec=self.matrix @ other.origin.vec), Vec3(vec=self.matrix @ other.direction.vec))
def test_ray_intersection_metal_scatter(): s = Sphere(1, Translation(0, 0, 0), Metal(Vec3(0, 0, 0))) ray = Ray(Point3(0, 0, 3), Vec3(0, 0, -1)) i = s.hit(ray) assert i is not None assert i.t == 2 assert i.point == Point3(0, 0, 1) assert i.normal == Vec3(0, 0, 1) assert isinstance(i.material, Metal) reflected = i.material.scatter(ray, i) assert reflected is not None r, a = reflected assert r.direction == Vec3(0, 0, 1)
def __init__(self, width, height): ascpect_ratio = width / height viewport_height = 2.0 viewport_width = ascpect_ratio * viewport_height focal_length = 1.0 self.__origin = Point3(0,0,0) self.__horizontal = Vec3(viewport_width, 0, 0) self.__vertical = Vec3(0, viewport_height, 0) self.__lower_left_corner = self.__origin - self.__horizontal/2 - self.__vertical/2 - Vec3(0,0,focal_length)
def hit(self, ray): r = self.world_to_object @ ray t = self.__hit_internal(r.direction.vec[:3], r.origin.vec[:3], self.radius) if t is not None: intersection_point = r.point_at(t) return Intersection(self.object_to_world @ intersection_point, Vec3(vec=intersection_point.vec).normalize(), t, self.material) return None
def render(self, nproc, chunksize): print(f'width = {self.width}') print(f'height = {self.height}') print(f'samples = {self.samples}') images = {} if nproc != 0: images = sorted(process_map(self._render_lines, list(_chunks(self.height, chunksize)), max_workers=nproc), key=lambda i: i[0]) else: images = list(self._render_lines((0, list(range(self.height))))) img = np.concatenate([i[1] for i in images], axis=1) for i in range(img.shape[0]): for j in range(img.shape[1]): self.film.set_pixel( i, j, Vec3(x=img[i, j, 0], y=img[i, j, 1], z=img[i, j, 2]))
def test_creation_elementwise(): v = Vec3(1, 2, 3) assert v.x == 1 assert v.y == 2 assert v.z == 3 assert v.vec[-1] == 0
def test_creation_from_vec(): v = Vec3(vec=[1, 2, 3, 0]) assert v.x == 1 assert v.y == 2 assert v.z == 3 assert v.vec[-1] == 0
def test_ray_intersection_no_min(): scene = [Sphere(1, Translation(0, 0, 5), Lambert(Vec3(0, 0, 0)))] ray = Ray(Point3(0, 0, 0), Vec3(0, 0, -1)) hits = list(filter(None, map(lambda s: s.hit(ray), scene))) assert len(hits) == 0
def test_translate_ray(): r = Ray(Point3(0, 0, 0), Vec3(0, 0, -1)) m = Translation(1, 2, 3) t = m @ r assert np.array_equal(t.origin.vec, np.array([1.0, 2.0, 3.0, 1.0])) assert np.array_equal(t.direction.vec, np.array([0.0, 0.0, -1.0, 0.0]))
def __rsub__(self, other): if isinstance(other, Point3): return Vec3(vec=self.vec - other.vec) if isinstance(other, Vec3): return Point3(vec=self.vec - other.vec) return NotImplemented
def random_unit_vector(): a = uniform(0, 2 * pi) z = uniform(-1, 1) r = sqrt(1 - z * z) return Vec3(r * cos(a), r * sin(a), z)
def test_translate_ray_2(): r = Ray(Point3(0, 0, 0), Vec3(0, 0, -1)) m = Translation(0, 0, -10) t = m @ r assert np.array_equal(t.origin.vec, np.array([0.0, 0.0, -10.0, 1.0]))
def test_point_vec_addition(): assert isinstance(Point3(0, 0, 0) + Vec3(0, 0, 0), Point3) assert isinstance(Vec3(0, 0, 0) + Point3(0, 0, 0), Point3)
def test_ray_intersection_miss(): s = Sphere(1, Translation(0, 0, 0), None) ray = Ray(Point3(0, 0, 3), Vec3(0, 1, 0)) assert s.hit(ray) is None
def test_translate_vector(): v = Vec3(1, 1, 1) m = Translation(1, 2, 3) t = m @ v assert np.array_equal(t.vec, np.array([1.0, 1.0, 1.0, 0.0]))