Ejemplo n.º 1
0
    def test_refraction__total_internal_reflection(self):
        """Test that we return black if we hit total internal reflection"""

        world = copy.deepcopy(self.default_scene)

        s = world.objects[1]

        s.material.transparency = 1.0
        s.material.refractive_index = 1.5

        r = rays.Ray(points.Point(0, 0,
                                  math.sqrt(2) / 2), vectors.Vector(0, 1, 0))

        xs = intersections.Intersections(
            intersections.Intersection(s, -math.sqrt(2) / 2),
            intersections.Intersection(s,
                                       math.sqrt(2) / 2))

        # n.b. the camera is inside the inner-sphere so use the second
        # intersection
        comps = xs.intersections[1].precompute(r, all_intersections=xs)

        result, _ = world.refracted_color(comps, 5)

        self.assertEqual(result, colors.Color(0, 0, 0))
Ejemplo n.º 2
0
    def test_refraction__standard(self):
        """Test that we return the correct color under normal refraction"""

        world = copy.deepcopy(self.default_scene)

        # s1 = A
        s1 = world.objects[1]
        s1.material.ambient = 1.0
        s1.material.pattern = patterns.TestPattern()

        # s2 = B
        s2 = world.objects[0]
        s2.material.transparency = 1.0
        s2.material.refractive_index = 1.5

        r = rays.Ray(points.Point(0, 0, 0.1), vectors.Vector(0, 1, 0))

        xs = intersections.Intersections(
            intersections.Intersection(s1, -0.9899),
            intersections.Intersection(s2, -0.4899),
            intersections.Intersection(s2, 0.4899),
            intersections.Intersection(s1, 0.9899))

        # Intersections[2] because the first two are behind the camera
        comps = xs.intersections[2].precompute(r, all_intersections=xs)

        result, _ = world.refracted_color(comps, 5)

        # Remember the test pattern returns the x, y, z coordinates of the
        # input point as the color so we can inspect positions
        self.assertEqual(result, colors.Color(0, 0.99888, 0.0475))
Ejemplo n.º 3
0
    def test_hits__some_negative(self):
        """Test we get the correct hit for some negative intersections"""

        shape = shapes.Sphere()

        i1 = intersections.Intersection(shape, -1)
        i2 = intersections.Intersection(shape, 1)
        isections = intersections.Intersections(i1, i2)

        self.assertEqual(isections.hit(), i2)
Ejemplo n.º 4
0
    def test_hits__all_negative(self):
        """Test we get no hits for all negative intersections"""

        shape = shapes.Sphere()

        i1 = intersections.Intersection(shape, -1)
        i2 = intersections.Intersection(shape, -2)
        isections = intersections.Intersections(i1, i2)

        self.assertIsNone(isections.hit())
Ejemplo n.º 5
0
    def test_hits__positive(self):
        """Test we get the correct hit for multiple positive intersections"""

        shape = shapes.Sphere()

        i1 = intersections.Intersection(shape, 2)
        i2 = intersections.Intersection(shape, 1)
        isections = intersections.Intersections(i1, i2)

        self.assertEqual(isections.hit(), i2)
Ejemplo n.º 6
0
    def test_schlick__perpendicular(self):
        """Test that we calculate the reflectance for a perpendicular ray
        """

        r = rays.Ray(points.Point(0, 0, 0), vectors.Vector(0, 1, 0))

        xs = intersections.Intersections(
            intersections.Intersection(self.glass_sphere, -1),
            intersections.Intersection(self.glass_sphere, 1))

        comps = xs.intersections[1].precompute(r, all_intersections=xs)

        self.assertAlmostEqual(comps.schlick, 0.04)
Ejemplo n.º 7
0
    def test_hits__multiple(self):
        """Test we get the correct hit for some negative intersections"""

        shape = shapes.Sphere()

        i1 = intersections.Intersection(shape, -1)
        i2 = intersections.Intersection(shape, 7)
        i3 = intersections.Intersection(shape, -5)
        i4 = intersections.Intersection(shape, 2)
        i5 = intersections.Intersection(shape, 3)
        isections = intersections.Intersections(i1, i2, i3, i4, i5)

        self.assertEqual(isections.hit(), i4)
Ejemplo n.º 8
0
    def test_initialization(self):

        shape = shapes.Sphere()
        t1 = 3.5
        t2 = -3.5

        i1 = intersections.Intersection(shape, t1)
        self.assertEqual(i1.t, 3.5)
        self.assertEqual(i1.shape, shape)

        i2 = intersections.Intersection(shape, t2)
        self.assertEqual(i2.t, -3.5)

        i = intersections.Intersections(i1, i2)
        self.assertEqual(i.intersections, [i2, i1])
Ejemplo n.º 9
0
    def test_reflective_transparent_material(self):
        """Test shade_hit with a reflective, transparent material"""

        world = copy.deepcopy(self.default_scene)

        floor = shapes.Plane(material=materials.Material(
            reflective=0.5, transparency=0.5, refractive_index=1.5))
        floor.set_transform(transforms.Translate(0, -1, 0))

        ball = shapes.Sphere(material=materials.Material(
            color=colors.Color(1, 0, 0), ambient=0.5))
        ball.set_transform(transforms.Translate(0, -3.5, -0.5))

        r = rays.Ray(points.Point(0, 0, -3),
                     vectors.Vector(0, -math.sqrt(2) / 2,
                                    math.sqrt(2) / 2))
        xs = intersections.Intersections(
            intersections.Intersection(floor, math.sqrt(2)))

        world.add_object(floor)
        world.add_object(ball)

        comps = xs.intersections[0].precompute(r, all_intersections=xs)

        color, _ = world.shade_hit(comps, remaining=5)

        self.assertEqual(color, colors.Color(0.93391, 0.69643, 0.69243))
Ejemplo n.º 10
0
    def test_shadows__full_scene(self):
        """Test that we identify a shadow in a full scene"""

        # First sphere is at z=10
        s1 = shapes.Sphere()
        s1.set_transform(transforms.Translate(0, 0, 10))

        # Second sphere is at the origin
        s2 = shapes.Sphere()
        s2.material = materials.Material()

        # Light is at z=-10
        l1 = lights.Light(position=points.Point(0, 0, -10),
                          intensity=colors.Color(1, 1, 1))

        scene = scenes.Scene(objects=[s1, s2], lights=[l1])

        # The ray is at z=5 (i.e. between the spheres), pointing at the further
        # out sphere
        ray = rays.Ray(points.Point(0, 0, 5), vectors.Vector(0, 0, 1))

        isection = intersections.Intersection(s2, 4)
        comps = isection.precompute(ray)

        result, _ = scene.shade_hit(comps)

        self.assertEqual(result, colors.Color(0.1, 0.1, 0.1))
Ejemplo n.º 11
0
    def test_reflection__reflective(self):
        """Test the reflection color of a reflective material is not black"""

        p = shapes.Plane(material=materials.Material(reflective=0.5))
        p.set_transform(transforms.Translate(0, -1, 0))

        world = copy.deepcopy(self.default_scene)

        world.objects.append(p)

        r = rays.Ray(points.Point(0, 0, -3),
                     vectors.Vector(0, -math.sqrt(2) / 2,
                                    math.sqrt(2) / 2))

        i = intersections.Intersection(p, math.sqrt(2))

        comps = i.precompute(r)

        # Test reflected color alone
        result, _ = world.reflected_color(comps)
        self.assertEqual(result, colors.Color(0.19032, 0.2379, 0.14274))

        # Now test the reflected color is added to the surface color
        result, _ = world.shade_hit(comps)
        self.assertEqual(result, colors.Color(0.87677, 0.92436, 0.82918))
Ejemplo n.º 12
0
    def test_schlick__total_internal_reflection(self):
        """Test that we calculate the reflectance under total internal
        reflection
        """

        r = rays.Ray(points.Point(0, 0,
                                  math.sqrt(2) / 2), vectors.Vector(0, 1, 0))

        xs = intersections.Intersections(
            intersections.Intersection(self.glass_sphere, -math.sqrt(2) / 2),
            intersections.Intersection(self.glass_sphere,
                                       math.sqrt(2) / 2))

        comps = xs.intersections[1].precompute(r, all_intersections=xs)

        self.assertEqual(comps.schlick, 1)
Ejemplo n.º 13
0
    def test_refraction__opaque(self):
        """Test the refraction color of an opaque material is black"""

        world = copy.deepcopy(self.default_scene)

        s = world.objects[1]

        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 0, 1))

        xs = intersections.Intersections(intersections.Intersection(s, 4),
                                         intersections.Intersection(s, 6))

        comps = xs.intersections[0].precompute(r, all_intersections=xs)

        result, _ = world.refracted_color(comps, 5)

        self.assertEqual(result, colors.Color(0, 0, 0))
Ejemplo n.º 14
0
    def local_intersect(self, local_ray: rays.Ray):
        """Return to t values for where the ray intersects the shape.  All in
        local coordinates for the shape
        """

        sphere_to_ray = local_ray.origin - points.Point(0, 0, 0)

        a = local_ray.direction.dot(local_ray.direction)
        b = 2 * local_ray.direction.dot(sphere_to_ray)
        c = sphere_to_ray.dot(sphere_to_ray) - 1
        discriminant = b**2 - 4 * a * c

        if discriminant < 0:
            return intersections.Intersections()
        else:
            t1 = (-b - math.sqrt(discriminant)) / (2 * a)
            t2 = (-b + math.sqrt(discriminant)) / (2 * a)
            return intersections.Intersections(
                intersections.Intersection(self, t1),
                intersections.Intersection(self, t2))
Ejemplo n.º 15
0
    def test_refraction__recursion_limit(self):
        """Test that we return black if we hit the refraction limit"""

        world = copy.deepcopy(self.default_scene)

        s = world.objects[1]

        s.material.transparency = 1.0
        s.material.refractive_index = 1.5

        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 0, 1))

        xs = intersections.Intersections(intersections.Intersection(s, 4),
                                         intersections.Intersection(s, 6))

        comps = xs.intersections[0].precompute(r, all_intersections=xs)

        result, _ = world.refracted_color(comps, 0)

        self.assertEqual(result, colors.Color(0, 0, 0))
Ejemplo n.º 16
0
    def test_schlick__small_angle(self):
        """Test that we calculate the reflectance at a small angle
        """

        r = rays.Ray(points.Point(0, 0.99, -2), vectors.Vector(0, 0, 1))

        xs = intersections.Intersections(
            intersections.Intersection(self.glass_sphere, 1.8589), )

        comps = xs.intersections[0].precompute(r, all_intersections=xs)

        self.assertAlmostEqual(comps.schlick, 0.48873081)
Ejemplo n.º 17
0
    def local_intersect(self, local_ray: rays.Ray):
        """Return the t-value where the ray intersects with the plane, in local
        units
        """

        # If the y-direction of the ray is small it is approximately parallel to
        #the plane, no intersections
        if abs(local_ray.direction.y) < MIN_Y_FOR_PLANE_INTERSECT:
            return intersections.Intersections()

        t = -local_ray.origin.y / local_ray.direction.y
        return intersections.Intersections(intersections.Intersection(self, t))
Ejemplo n.º 18
0
    def test_shade_hit__outside(self):
        """Test that we shade an individual hit the correct color when outside
        an object"""

        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 0, 1))

        shape = self.default_scene.objects[1]

        i = intersections.Intersection(shape, 4)
        computations = i.precompute(r)

        color, _ = self.default_scene.shade_hit(computations)
        self.assertEqual(color, colors.Color(0.38066, 0.47583, 0.2855))
Ejemplo n.º 19
0
    def test_refractive_index_intersections(self):
        """Test we can calculate the refractive indices between intersections"""

        # Set up a scene with three glass spheres.  One at the origin with size
        # 2 then inside of that 2 that are offset along z by different amounts
        A = shapes.Sphere(material=materials.Material(refractive_index=1.5,
                                                      transparency=1.0))
        B = shapes.Sphere(material=materials.Material(refractive_index=2.0,
                                                      transparency=1.0))
        C = shapes.Sphere(material=materials.Material(refractive_index=2.5,
                                                      transparency=1.0))

        A.set_transform(transforms.Scale(2, 2, 2))
        B.set_transform(transforms.Translate(0, 0, -0.25))
        C.set_transform(transforms.Translate(0, 0, 0.25))

        r = rays.Ray(points.Point(0, 0, -4), vectors.Vector(0, 0, 1))

        xs = intersections.Intersections(intersections.Intersection(A, 2),
                                         intersections.Intersection(B, 2.75),
                                         intersections.Intersection(C, 3.25),
                                         intersections.Intersection(B, 4.75),
                                         intersections.Intersection(C, 5.25),
                                         intersections.Intersection(A, 6))

        expected_results = [
            {
                "n1": 1.0,
                "n2": 1.5
            },
            {
                "n1": 1.5,
                "n2": 2.0
            },
            {
                "n1": 2.0,
                "n2": 2.5
            },
            {
                "n1": 2.5,
                "n2": 2.5
            },
            {
                "n1": 2.5,
                "n2": 1.5
            },
            {
                "n1": 1.5,
                "n2": 1.0
            },
        ]

        for index, expected in enumerate(expected_results):

            comps = xs.intersections[index].precompute(r, all_intersections=xs)
            self.assertDictEqual(expected, {"n1": comps.n1, "n2": comps.n2})
Ejemplo n.º 20
0
    def test_precompute_reflectv(self):
        """Test that we can calculate the reflection vector"""

        p = shapes.Plane()
        r = rays.Ray(points.Point(0, 1, -1),
                     vectors.Vector(0, -math.sqrt(2) / 2,
                                    math.sqrt(2) / 2))
        i = intersections.Intersection(p, math.sqrt(2))

        comps = i.precompute(r)

        self.assertEqual(comps.reflectv,
                         vectors.Vector(0,
                                        math.sqrt(2) / 2,
                                        math.sqrt(2) / 2))
Ejemplo n.º 21
0
    def test_precompute__inside(self):
        """Test that we can precompute vectors for an intersection and ray when
        inside of a shape"""

        r = rays.Ray(points.Point(0, 0, 0), vectors.Vector(0, 0, 1))
        s = shapes.Sphere()
        i = intersections.Intersection(s, 1)

        computations = i.precompute(r)

        self.assertEqual(computations.t, 1)
        self.assertEqual(computations.point, points.Point(0, 0, 1))
        self.assertEqual(computations.eyev, vectors.Vector(0, 0, -1))
        self.assertEqual(computations.normalv, vectors.Vector(0, 0, -1))
        self.assertTrue(computations.inside)
Ejemplo n.º 22
0
    def test_precompute__over_vector(self):
        """Test that we calculate a vector just inside of the surface of a
        shape
        """

        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 0, 1))

        s = shapes.Sphere()
        s.set_transform(transforms.Translate(0, 0, 1))

        i = intersections.Intersection(s, 5)

        computations = i.precompute(r)
        self.assertTrue(computations.under_point.z > computations.point.z)
        self.assertTrue(computations.under_point.z > intersections.EPSILON / 2)
Ejemplo n.º 23
0
    def test_reflection__non_reflective(self):
        """Test the reflection color of a nonreflective material is not black"""

        world = copy.deepcopy(self.default_scene)

        s = world.objects[0]
        s.material.ambient = 1

        # The ray is inside the inner sphere of the default scene
        r = rays.Ray(points.Point(0, 0, 0), vectors.Vector(0, 0, 1))

        i = intersections.Intersection(s, 1)

        comps = i.precompute(r)

        result, _ = world.reflected_color(comps)

        self.assertEqual(result, colors.Color(0, 0, 0))
Ejemplo n.º 24
0
    def test_shade_hit__inside(self):
        """Test that we shade an individual hit the correct color when inside
        an object"""

        r = rays.Ray(points.Point(0, 0, 0), vectors.Vector(0, 0, 1))

        self.default_scene.lights = [
            lights.PointLight(points.Point(0, 0.25, 0), colors.Color(1, 1, 1))
        ]

        shape = self.default_scene.objects[0]

        i = intersections.Intersection(shape, 0.5)
        computations = i.precompute(r)

        color, _ = self.default_scene.shade_hit(computations)

        self.assertEqual(color, colors.Color(0.90498, 0.90498, 0.90498))