Ejemplo n.º 1
0
class Shape:
    def __init__(self):
        self.transform = Identity()
        self.material = Material()
        self.parent = None

    def set_material(self, material: Material):
        self.material = material

    def set_transform(self, t: Matrix):
        self.transform *= t

    def __eq__(self, other):
        return (self.__class__ == other.__class__
                and self.material == other.material
                and self.parent == other.parent
                and self.transform == other.transform)

    def intersect(self, ray: Ray):
        local_ray = ray.transform(self.transform.inverse())
        return self.local_intersect(local_ray)

    def normal_at(self, world_point: Point):
        local_point = self.world_to_object(world_point)
        local_normal = self.local_normal_at(local_point)
        return self.normal_to_world(local_normal)

    def world_to_object(self, point: Point):
        if self.parent is not None:
            point = self.parent.world_to_object(point)
        return self.transform.inverse() * point

    def normal_to_world(self, normal: Vector):
        normalv = self.transform.inverse().transpose() * normal
        normalv.w = 0
        normalv = normalv.normalize()

        if self.parent is not None:
            normalv = self.parent.normal_to_world(normalv)

        return normalv

    def local_normal_at(self, local_point):
        raise TypeError("Generic Shapes cannot be evaluated")

    def local_intersect(self, ray):
        raise TypeError("Generic Shapes cannot be evaluated")

    def __str__(self):
        return f"{self.__class__}: Transform:\n{self.transform}"
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
    def __init__(self, hsize: int, vsize: int, fov: float, transform: Matrix = None):
        self.hsize = hsize
        self.vsize = vsize
        self.fov = fov
        if transform is None:
            self.transform = Identity()
        else:
            self.transform = transform

        half_view = math.tan(self.fov / 2)
        aspect = self.hsize / self.vsize
        if aspect >= 1:
            self.half_width = half_view
            self.half_height = half_view / aspect
        else:
            self.half_width = half_view * aspect
            self.half_height = half_view
        self.pixel_size = (self.half_width * 2) / self.hsize
Ejemplo n.º 4
0
def test_camera_attributes():
    hsize = 160
    vsize = 120
    fov = math.pi / 2
    c = Camera(hsize, vsize, fov)
    assert c.hsize == 160
    assert c.vsize == 120
    assert c.fov == math.pi / 2
    assert c.transform == Identity()
Ejemplo n.º 5
0
class Camera:
    def __init__(self, hsize: int, vsize: int, fov: float, transform: Matrix = None):
        self.hsize = hsize
        self.vsize = vsize
        self.fov = fov
        if transform is None:
            self.transform = Identity()
        else:
            self.transform = transform

        half_view = math.tan(self.fov / 2)
        aspect = self.hsize / self.vsize
        if aspect >= 1:
            self.half_width = half_view
            self.half_height = half_view / aspect
        else:
            self.half_width = half_view * aspect
            self.half_height = half_view
        self.pixel_size = (self.half_width * 2) / self.hsize

    def ray_for_pixel(self, px, py):
        x_offset = (px + 0.5) * self.pixel_size
        y_offset = (py + 0.5) * self.pixel_size

        world_x = self.half_width - x_offset
        world_y = self.half_height - y_offset

        pixel = self.transform.inverse() * Point(world_x, world_y, -1)
        origin = self.transform.inverse() * Point(0, 0, 0)
        direction = (pixel - origin).normalize()
        return Ray(origin, direction)

    def render(self, world: World):
        image = Canvas(self.hsize, self.vsize)
        for y in range(self.vsize):
            print(y)
            for x in range(self.hsize):
                ray = self.ray_for_pixel(x, y)
                color = world.color_at(ray)
                image.write_pixel(x, y, color)
        return image
Ejemplo n.º 6
0
class Pattern:
    def __init__(self):
        self.transform = Identity()

    def set_pattern_transform(self, t: Matrix):
        self.transform *= t

    def pattern_at_shape(self, shape, world_point: Point):
        object_point = shape.world_to_object(world_point)
        pattern_point = self.transform.inverse() * object_point
        return self.pattern_at(pattern_point)

    def pattern_at(self, point):
        raise TypeError("Generic Pattern Cannot be evaluated")
Ejemplo n.º 7
0
 def __init__(self):
     self.transform = Identity()
     self.material = Material()
     self.parent = None
Ejemplo n.º 8
0
def test_default_transform():
    pattern = _TestPattern()
    assert pattern.transform == Identity()
Ejemplo n.º 9
0
 def __init__(self):
     self.transform = Identity()
Ejemplo n.º 10
0
def test_group_creation():
    g = Group()
    assert g.transform == Identity()
    assert len(g.objects) == 0
Ejemplo n.º 11
0
def test_default_transform():
    s = _TestShape()
    assert s.transform == Identity()
Ejemplo n.º 12
0
def test_identity_transpose():
    m = Identity()
    assert m == m.transpose()
Ejemplo n.º 13
0
def test_identity_mult():
    m = Matrix([[0, 1, 2, 4], [1, 2, 4, 8], [2, 4, 8, 16], [4, 8, 16, 32]])
    i = Identity()
    assert m * i == m
Ejemplo n.º 14
0
def test_glassy_sphere():
    s = GlassSphere()
    assert s.transform == Identity()
    assert s.material.transparency == 1.0
    assert s.material.refractive_index == 1.5