예제 #1
0
def test_assigning_a_transformation():
    # Given
    s = MockShape()
    # When
    s.transform = translation(2, 3, 4)
    # Then
    assert s.transform == translation(2, 3, 4)
def test_assigning_a_transformation():
    # Given
    pattern = MockPattern()
    # When
    pattern.transform = translation(1, 2, 3)
    # Then
    assert pattern.transform == translation(1, 2, 3)
예제 #3
0
def test_finding_n1_and_n2_at_various_intersections():
    # Given
    A = glass_sphere()
    A.transform = scaling(2, 2, 2)
    A.material.refractive_index = 1.5

    B = glass_sphere()
    B.transform = translation(0, 0, -0.25)
    B.material.refractive_index = 2.0

    C = glass_sphere()
    C.transform = translation(0, 0, 0.25)
    C.material.refractive_index = 2.5

    r = Ray(Point(0, 0, -4), Vector(0, 0, 1))
    xs = Intersections(Intersection(2, A), Intersection(2.75, B),
                       Intersection(3.25, C), Intersection(4.75, B),
                       Intersection(5.25, C), Intersection(6, A))
    EXAMPLES = [
        {
            'n1': 1.0,
            'n2': 1.5
        },  # index: 0
        {
            'n1': 1.5,
            'n2': 2.0
        },  # index: 1
        {
            'n1': 2.0,
            'n2': 2.5
        },  # index: 2
        {
            'n1': 2.5,
            'n2': 2.5
        },  # index: 3
        {
            'n1': 2.5,
            'n2': 1.5
        },  # index: 4
        {
            'n1': 1.5,
            'n2': 1.0
        },  # index: 5
    ]
    for index in range(len(EXAMPLES)):
        # When
        comps = xs[index].prepare_computations(r, xs=xs)
        # Then
        assert comps.n1 == EXAMPLES[index]['n1']
        assert comps.n2 == EXAMPLES[index]['n2']
def test_multiplying_by_the_inverse_of_a_translation_matrix():
    # Given
    transform = translation(5, -3, 2)
    inv = transform.inverse()
    p = Point(-3, 4, 5)
    # Then
    assert inv * p == Point(-8, 7, 3)
def test_computing_the_normal_on_a_translated_sphere():
    # Given
    s = Sphere()
    s.transform = translation(0, 1, 0)
    # When
    n = s.normal_at(Point(0, 1.70711, -0.70711))
    # Then
    assert n == Vector(0, 0.70711, -0.70711)
def test_constructing_a_ray_when_the_camera_is_transformed():
    # Given
    c = Camera(201, 101, pi / 2)
    # When
    c.transform = rotation_y(pi / 4) * translation(0, -2, 5)
    r = c.ray_for_pixel(100, 50)
    # Then
    assert r.origin == Point(0, 2, -5)
    assert r.direction == Vector(sqrt(2) / 2, 0, -sqrt(2) / 2)
def test_the_view_transformation_moves_the_world():
    # Given
    f = Point(0, 0, 8)
    to = Point(0, 0, 0)
    up = Vector(0, 1, 0)
    # When
    t = view_transform(f, to, up)
    # Then
    assert t == translation(0, 0, -8)
예제 #8
0
def test_translating_a_ray():
    # Given
    r = Ray(Point(1, 2, 3), Vector(0, 1, 0))
    m = translation(3, 4, 5)
    # When
    r2 = r.transform(m)
    # Then
    assert r2.origin == Point(4, 6, 8)
    assert r2.direction == Vector(0, 1, 0)
def test__color_at__with_mutually_reflective_surfaces():
    # Given
    w = World()
    w.light = PointLight(Point(0, 0, 0), Color(1, 1, 1))
    lower = Plane()
    lower.material.reflective = 1
    lower.transform = translation(0, -1, 0)
    w.objects.append(lower)
    upper = Plane()
    upper.material.reflective = 1
    upper.transform = translation(0, 1, 0)
    w.objects.append(upper)
    r = Ray(Point(0, 0, 0), Vector(0, 1, 0))
    # Then
    try:
        w.color_at(r)
    except RecursionError:
        pytest.fail("Unexpected RecursionError ...")
def test_intersecting_a_translated_sphere_with_a_ray():
    # Given
    r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
    s = Sphere()
    # When
    s.transform = translation(5, 0, 0)
    xs = s.intersect(r)
    # Then
    assert len(xs) == 0
def test_chained_transformations_must_be_applied_in_reverse_order():
    # Given
    p = Point(1, 0, 1)
    A = rotation_x(pi / 2)
    B = scaling(5, 5, 5)
    C = translation(10, 5, 7)
    # When
    T = C * B * A
    # Then
    assert T * p == Point(15, 0, 7)
예제 #12
0
def test_intersecting_a_translated_shape_with_a_ray():
    # Given
    r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
    s = MockShape()
    # When
    s.transform = translation(5, 0, 0)
    _ = s.intersect(r)
    # Then
    assert s.saved_ray.origin == Point(-5, 0, -5)
    assert s.saved_ray.direction == Vector(0, 0, 1)
def test_a_pattern_with_both_an_object_and_a_pattern_transformation():
    # Given
    shape = Sphere()
    shape.transform = scaling(2, 2, 2)
    pattern = MockPattern()
    pattern.transform = translation(0.5, 1, 1.5)
    # When
    c = pattern.pattern_at_shape(shape, Point(2.5, 3, 3.5))
    # Then
    assert c == Color(0.75, 0.5, 0.25)
def test_intersecting_a_ray_with_a_nonempty_group():
    # Given
    g = Group()
    s1 = Sphere()
    s2 = Sphere()
    s2.transform = translation(0, 0, -3)
    s3 = Sphere()
    s3.transform = translation(5, 0, 0)
    g.add_child(s1)
    g.add_child(s2)
    g.add_child(s3)
    # When
    r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
    xs = g.local_intersect(r)
    # Then
    assert len(xs) == 4
    assert xs[0].object == s2
    assert xs[1].object == s2
    assert xs[2].object == s1
    assert xs[3].object == s1
예제 #15
0
def test_the_hit_should_offset_the_point():
    # Given
    r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
    shape = Sphere()
    shape.transform = translation(0, 0, 1)
    i = Intersection(5, shape)
    # When
    comps = i.prepare_computations(r)
    # Then
    assert comps.over_point.z < -EPSILON / 2
    assert comps.point.z > comps.over_point.z
예제 #16
0
def test_the_under_point_is_offset_below_the_surface():
    # Given
    r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
    shape = glass_sphere()
    shape.transform = translation(0, 0, 1)
    i = Intersection(5, shape)
    xs = Intersections(i)
    # When
    comps = i.prepare_computations(r, xs)
    # Then
    assert comps.under_point.z > EPSILON / 2
    assert comps.point.z < comps.under_point.z
def test_intersecting_a_transformed_group():
    # Given
    g = Group()
    g.transform = scaling(2, 2, 2)
    s = Sphere()
    s.transform = translation(5, 0, 0)
    g.add_child(s)
    # When
    r = Ray(Point(10, 0, -10), Vector(0, 0, 1))
    xs = g.intersect(r)
    # Then
    assert len(xs) == 2
예제 #18
0
def test_finding_the_normal_on_a_child_object():
    # Given
    g1 = Group()
    g1.transform = rotation_y(pi / 2)
    g2 = Group()
    g2.transform = scaling(1, 2, 3)
    g1.add_child(g2)
    s = Sphere()
    s.transform = translation(5, 0, 0)
    g2.add_child(s)
    # When
    n = s.normal_at(Point(1.7321, 1.1547, -5.5774))
    # Then
    assert n == Vector(0.2857, 0.42854, -0.85716)
예제 #19
0
def test_converting_a_point_from_world_to_object_space():
    # Given
    g1 = Group()
    g1.transform = rotation_y(pi / 2)
    g2 = Group()
    g2.transform = scaling(2, 2, 2)
    g1.add_child(g2)
    s = Sphere()
    s.transform = translation(5, 0, 0)
    g2.add_child(s)
    # When
    p = s.world_to_object(Point(-2, 0, -10))
    # Then
    assert p == Point(0, 0, -1)
def test__shade_hit__with_a_reflective_material():
    # Given
    w = default_world()
    shape = Plane()
    shape.material.reflective = 0.5
    shape.transform = translation(0, -1, 0)
    w.objects.append(shape)
    r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2))
    i = Intersection(sqrt(2), shape)
    # When
    comps = i.prepare_computations(r)
    color = w.shade_hit(comps)
    # Then
    assert color == Color(0.87675, 0.92434, 0.82918)
def test__shade_hit__with_a_transparent_material():
    # Given
    w = default_world()

    floor = Plane()
    floor.transform = translation(0, -1, 0)
    floor.material.transparency = 0.5
    floor.material.refractive_index = 1.5
    w.objects.append(floor)

    ball = Sphere()
    ball.material.color = Color(1, 0, 0)
    ball.material.ambient = 0.5
    ball.transform = translation(0, -3.5, -0.5)
    w.objects.append(ball)

    r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2))
    xs = Intersections(Intersection(sqrt(2), floor))
    # When
    comps = xs[0].prepare_computations(r, xs)
    color = w.shade_hit(comps, 5)
    # Then
    assert color == Color(0.93642, 0.68642, 0.68642)
def test_the_reflected_color_at_the_maximum_recursive_depth():
    # Given
    w = default_world()
    shape = Plane()
    shape.material.reflective = 0.5
    shape.transform = translation(0, -1, 0)
    w.objects.append(shape)
    r = Ray(Point(0, 0, -3), Vector(0, -sqrt(2) / 2, sqrt(2) / 2))
    i = Intersection(sqrt(2), shape)
    # When
    comps = i.prepare_computations(r)
    color = w.reflected_color(comps, 0)
    # Then
    assert color == Color(0, 0, 0)
예제 #23
0
def test_converting_a_normal_from_object_to_world_space():
    # Given
    g1 = Group()
    g1.transform = rotation_y(pi / 2)
    g2 = Group()
    g2.transform = scaling(1, 2, 3)
    g1.add_child(g2)
    s = Sphere()
    s.transform = translation(5, 0, 0)
    g2.add_child(s)
    # When
    n = s.normal_to_world(Vector(sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3))
    # Then
    assert n == Vector(0.28571, 0.42857, -0.85714)
def test__shade_hit__is_given_an_intersection_in_shadow():
    # Given
    w = World()
    w.light = PointLight(Point(0, 0, -10), Color(1, 1, 1))
    s1 = Sphere()
    w.objects.append(s1)
    s2 = Sphere()
    s2.transform = translation(0, 0, 10)
    w.objects.append(s2)
    r = Ray(Point(0, 0, 5), Vector(0, 0, 1))
    i = Intersection(4, s2)
    # When
    comps = i.prepare_computations(r)
    c = w.shade_hit(comps)
    # Then
    assert c == Color(0.1, 0.1, 0.1)
def test_individual_transformations_are_applied_in_sequence():
    # Given
    p = Point(1, 0, 1)
    A = rotation_x(pi / 2)
    B = scaling(5, 5, 5)
    C = translation(10, 5, 7)

    # apply rotation first
    # When
    p2 = A * p
    # Then
    assert p2 == Point(1, -1, 0)

    # then apply scaling
    # When
    p3 = B * p2
    # Then
    assert p3 == Point(5, -5, 0)

    # then apply translation
    # When
    p4 = C * p3
    # Then
    assert p4 == Point(15, 0, 7)
def test_translation_does_not_affect_vectors():
    # Given
    transform = translation(5, -3, 2)
    v = Vector(-3, 4, 5)
    # Then
    assert transform * v == v
예제 #27
0
if __name__ == "__main__":
    # pattern = StripePattern(Color(1, 0, 0), Color(1, 1, 1))
    # pattern = CheckersPattern(Color(1, 0, 0), Color(1, 1, 1))
    pattern = GradientPattern(Color(1, 0, 0), Color(1, 1, 1))
    # pattern = RingPattern(Color(1, 0, 0), Color(1, 1, 1))
    pattern.transform = scaling(0.2, 0.2, 0.2)

    floor = Plane()
    floor.material = Material()
    floor.material.color = Color(1, 0.9, 0.9)
    # floor.material.pattern = pattern

    backdrop = Plane()
    backdrop.transform = \
        rotation_y(pi / 3) * translation(0, 0, 5) * rotation_x(pi / 2)

    backdrop2 = Plane()
    backdrop2.transform = \
        rotation_y(-pi / 3) * translation(0, 0, 5) * rotation_x(pi / 2)

    middle = Sphere()
    # middle = glass_sphere()
    middle.transform = translation(-0.5, 1, 0.5)
    # middle.reflective = 1.0
    middle.material = Material()
    middle.material.color = Color(0.1, 1, 0.5)
    # middle.material.pattern = pattern
    middle.material.diffuse = 0.7
    middle.material.specular = 0.3
    # middle.material.reflective = 1.0
def test_multiplying_by_a_translation_matrix():
    # Given
    transform = translation(5, -3, 2)
    p = Point(-3, 4, 5)
    # Then
    assert transform * p == Point(2, 1, 7)