Esempio n. 1
0
    def render(self, d, view, t):
        if view is None:
            view = visible()

        push()
        try:
            style = d['style']
            if style == 'solid':
                color(d['color'], d['_alpha'])
                rectangle(view)
            elif style == 'horz':
                alpha = d['_alpha']
                top = colors.Color(d['color'], alpha)
                bottom = colors.Color(d['color2'], alpha)
                rectangle(view, sw=bottom, se=bottom, nw=top, ne=top)
            elif style == 'vert':
                alpha = d['_alpha']
                left = colors.Color(d['color'], alpha)
                right = colors.Color(d['color2'], alpha)
                rectangle(view, sw=left, se=right, nw=left, ne=right)
            else:
                raise ValueError, "Fill() element doesn't understand style '%s'" % (
                    style, )

        finally:
            pop()
Esempio n. 2
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))
Esempio n. 3
0
    def test_pattern(self):
        """Test that the pattern of a material can change its color"""

        m = materials.Material(pattern=patterns.StripePattern(
            colors.Color(
                0,
                0,
                0,
            ), colors.Color(1, 1, 1)),
                               ambient=1,
                               diffuse=0,
                               specular=0)

        eyev = vectors.Vector(0, 0, -1)
        normalv = vectors.Vector(0, 0, -1)

        light = lights.PointLight(points.Point(0, 0, -10),
                                  colors.Color(1, 1, 1))

        color_1 = m.lighting(light,
                             points.Point(0.9, 0, 0),
                             eyev,
                             normalv,
                             in_shadow=False)
        color_2 = m.lighting(light,
                             points.Point(1.1, 0, 0),
                             eyev,
                             normalv,
                             in_shadow=False)

        self.assertEqual(color_1, colors.Color(0, 0, 0))
        self.assertEqual(color_2, colors.Color(1, 1, 1))
Esempio n. 4
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))
Esempio n. 5
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))
Esempio n. 6
0
    def test_gradient(self):
        """Test that the gradient pattern works"""

        p = patterns.GradientPattern(WHITE, BLACK)

        self.assertEqual(p.pattern_at(points.Point(
            0,
            0,
            0,
        )), WHITE)
        self.assertEqual(p.pattern_at(points.Point(
            0.25,
            0,
            0,
        )), colors.Color(0.75, 0.75, 0.75))
        self.assertEqual(p.pattern_at(points.Point(
            0.5,
            0,
            0,
        )), colors.Color(0.5, 0.5, 0.5))
        self.assertEqual(p.pattern_at(points.Point(
            0.75,
            0,
            0,
        )), colors.Color(0.25, 0.25, 0.25))
Esempio n. 7
0
    def test_render_scene(self):
        """Test we can render a pixel in a simple scene"""


        # Inner sphere size 0.5, centered on the origin
        s1 = shapes.Sphere()
        s1.set_transform(transforms.Scale(0.5,0.5,0.5))

        # Outer sphere centered on the origin, size 1.0
        s2 = shapes.Sphere()
        s2.material = materials.Material(
            color=colors.Color(0.8, 1.0, 0.6), diffuse=0.7, specular=0.2)

        l1 = lights.Light(
            position=points.Point(-10, 10, -10),
            intensity=colors.Color(1, 1, 1)
            )

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

        cam = cameras.Camera(11, 11, math.pi/2)

        from_point = points.Point(0, 0, -5)
        to_point = points.Point(0, 0, 0)
        up = vectors.Vector(0, 1, 0)
        cam.transform = transforms.ViewTransform(from_point, to_point, up)

        image = cam.render(scene)
        self.assertEqual(image.get(5, 5),
                         colors.Color(0.3807, 0.4758, 0.2855))
Esempio n. 8
0
    def test_color_multiplication(self):
        """Test that we can multiple two colors"""

        c1 = colors.Color(1, 0.2, 0.4)
        c2 = colors.Color(0.9, 1, 0.1)

        c3 = c1 * c2

        self.assertEqual(c3, colors.Color(0.9, 0.2, 0.04))
Esempio n. 9
0
    def test_lighting__shadow(self):
        """Test that we get the ambient color if we're in shadow"""

        m = materials.Material()
        p = points.Point(0, 0, 0)

        eyev = vectors.Vector(0, 0, -1)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 0, -10),
                                  colors.Color(1, 1, 1))
        result = m.lighting(light, p, eyev, normalv, in_shadow=True)
        self.assertEqual(result, colors.Color(0.1, 0.1, 0.1))
Esempio n. 10
0
    def test_color_basic_operations(self):
        """Test that the basic operations work on colors"""

        c1 = colors.Color(0.9, 0.6, 0.75)
        c2 = colors.Color(0.7, 0.1, 0.25)

        c3 = c1 + c2
        self.assertEqual(c3, colors.Color(1.6, 0.7, 1.0))

        c4 = c1 - c2
        self.assertEqual(c4, colors.Color(0.2, 0.5, 0.5))

        c5 = c1 * 2
        self.assertEqual(c5, colors.Color(1.8, 1.2, 1.5))
Esempio n. 11
0
    def test_lighting(self):
        """Tests on the lighting function for various angles and colors"""

        m = materials.Material()
        p = points.Point(0, 0, 0)

        #the eye is positioned directly between the light and the surface, with
        #the normal pointing at the eye. Expect ambient, diffuse, and specular
        #to all be at full strength. This means that the total intensity should
        #be 0.1 (the ambient value) + 0.9 (the diffuse value) + 0.9 (the
        #specular value), or 1.9
        eyev = vectors.Vector(0, 0, -1)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 0, -10),
                                  colors.Color(1, 1, 1))

        result = m.lighting(light, p, eyev, normalv)
        self.assertEqual(result, colors.Color(1.9, 1.9, 1.9))

        eyev = vectors.Vector(0, math.sqrt(2) / 2, -math.sqrt(2) / 2)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 0, -10),
                                  colors.Color(1, 1, 1))
        result = m.lighting(light, p, eyev, normalv)
        self.assertEqual(result, colors.Color(1.0, 1.0, 1.0))

        eyev = vectors.Vector(0, 0, -1)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 10, -10),
                                  colors.Color(1, 1, 1))
        result = m.lighting(light, p, eyev, normalv)
        self.assertEqual(result, colors.Color(0.7364, 0.7364, 0.7364))

        eyev = vectors.Vector(0, -math.sqrt(2) / 2, -math.sqrt(2) / 2)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 10, -10),
                                  colors.Color(1, 1, 1))
        result = m.lighting(light, p, eyev, normalv)
        self.assertEqual(result, colors.Color(1.6364, 1.6364, 1.6364))

        # Light behind the object, its color should be the ambient value
        eyev = vectors.Vector(0, 0, -1)
        normalv = vectors.Vector(0, 0, -1)
        light = lights.PointLight(points.Point(0, 0, 10),
                                  colors.Color(1, 1, 1))

        result = m.lighting(light, p, eyev, normalv)
        self.assertEqual(result, colors.Color(0.1, 0.1, 0.1))
Esempio n. 12
0
    def __init__(self, width: int, height: int) -> None:

        self.width = width
        self.height = height

        self.canvas = [[colors.Color(0, 0, 0)] * height for
                           _ in range(width)]
Esempio n. 13
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))
Esempio n. 14
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))
Esempio n. 15
0
    def test_default_scene(self):
        """Test that the default scene is correct"""

        self.assertEqual(self.default_scene.lights[0].intensity,
                         colors.Color(1, 1, 1))

        self.assertEqual(self.default_scene.objects[0], self.s1)
Esempio n. 16
0
    def shade_hit(self,
                  computations: intersections.Computations,
                  remaining=5) -> Tuple[colors.Color, int]:
        """Given some pre-calculated values about a hit, calculate its color"""

        surface = colors.Color(0, 0, 0)

        for light in self.lights:

            in_shadow = self.is_shadowed(computations.over_point, light)

            surface += computations.object.material.lighting(
                light,
                computations.over_point,
                computations.eyev,
                computations.normalv,
                in_shadow=in_shadow)

            reflected, _ = self.reflected_color(computations,
                                                remaining=remaining)
            refracted, _ = self.refracted_color(computations,
                                                remaining=remaining)

        material = computations.object.material
        if material.reflective > 0 and material.transparency > 0:
            reflectance = computations.schlick
            return (surface + reflected * reflectance + refracted *
                    (1 - reflectance), remaining)

        return surface + reflected + refracted, remaining
Esempio n. 17
0
    def test_color__tuple(self):
        """Test that we can initialize and read from a color"""

        p = colors.Color(-0.5, 0.4, 1.7)

        self.assertEqual(p.red, -0.5)
        self.assertEqual(p.green, 0.4)
        self.assertEqual(p.blue, 1.7)
Esempio n. 18
0
    def test_point_light_initialization(self):

        position = points.Point(-1, 3, 5)
        intensity = colors.Color(0.5, 1, 1)
        light = lights.PointLight(position, intensity)

        self.assertEqual(light.position, position)
        self.assertEqual(light.intensity, intensity)
Esempio n. 19
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))
Esempio n. 20
0
 def diagram_eval( self, *junk ):
     for k, v in self.tkvars.iteritems():
         if isinstance( v, tuple ):
             self.pdict[k] = colors.Color( v[0].get(), v[1].get(), v[2].get(), v[3].get() )
         else:
             self.pdict[k] = v.get()
     self.marklist = None
     self.s.redraw()
     self.s.focus()
Esempio n. 21
0
    def test_write_to_canvas(self):
        """Test we can write to and read from a canvas"""

        c = canvas.Canvas(10, 20)
        red = colors.Color(1, 0, 0)

        c.set(2, 3, red)

        self.assertEqual(c.canvas[2][3], red)
Esempio n. 22
0
    def setUp(self):
        """Set up a default scene for quick testing"""

        # Inner sphere size 0.5, centered on the origin
        self.s1 = shapes.Sphere()
        self.s1.set_transform(transforms.Scale(0.5, 0.5, 0.5))

        # Outer sphere centered on the origin, size 1.0
        self.s2 = shapes.Sphere()
        self.s2.material = materials.Material(color=colors.Color(
            0.8, 1.0, 0.6),
                                              diffuse=0.7,
                                              specular=0.2)

        self.l1 = lights.Light(position=points.Point(-10, 10, -10),
                               intensity=colors.Color(1, 1, 1))

        self.default_scene = scenes.Scene(objects=[self.s1, self.s2],
                                          lights=[self.l1])
Esempio n. 23
0
    def lighting(self,
                 light: lights.Light,
                 point: points.Point,
                 eyev: vectors.Vector,
                 normalv: vectors.Vector,
                 in_shadow: bool=False) -> colors.Color:
        """Calculate Phong lighting model for a material"""

        if self.pattern is not None:
            color = self.pattern.pattern_at_shape(self.shape, point)
        else:
            color = self.color

        if in_shadow is True:
            return color * self.ambient

        # combine the surface color with the light's color/intensity
        effective_color = color * light.intensity

        # find the direction to the light source
        light_to_point = light.position - point
        lightv = light_to_point.normalize()

        # compute the ambient contribution
        ambient = effective_color * self.ambient

        # light_dot_normal represents the cosine of the angle between the
        # light vector and the normal vector. A negative number means the
        # light is on the other side of the surface.
        light_dot_normal = lightv.dot(normalv)
        if light_dot_normal < 0:
            diffuse = BLACK
            specular = BLACK
        else:
            # compute the diffuse contribution
            diffuse = effective_color * self.diffuse * light_dot_normal

        # reflect_dot_eye represents the cosine of the angle between the
        # reflection vector and the eye vector. A negative number means the
        # light reflects away from the eye.
        reflectv = -lightv.reflect(normalv)
        reflect_dot_eye = reflectv.dot(eyev)

        if reflect_dot_eye <= 0:
            specular = BLACK
        else:
            # compute the specular contribution
            factor = math.pow(reflect_dot_eye, self.shininess)
            specular = light.intensity * self.specular * factor

        return colors.Color(
            red=ambient.red + diffuse.red + specular.red,
            green=ambient.green + diffuse.green + specular.green,
            blue=ambient.blue + diffuse.blue + specular.blue)
Esempio n. 24
0
def _get_color(value):
    test_value = getattr(colors, value, None)
    if test_value is not None:
        return test_value

    with suppress(ValueError):
        test_value = list(map(int, value.split(',')))
        if len(test_value) in (3, 4):
            return colors.Color(*test_value)

    return None
Esempio n. 25
0
    def test_color_at(self):
        """Tests on the color_at function"""

        # The ray points away from the object
        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 1, 0))
        self.assertEqual(
            self.default_scene.color_at(r)[0], colors.Color(0, 0, 0))

        # The ray points at the outer sphere
        r = rays.Ray(points.Point(0, 0, -5), vectors.Vector(0, 0, 1))
        self.assertEqual(
            self.default_scene.color_at(r)[0],
            colors.Color(0.38066, 0.47583, 0.2855))

        # The ray is outside the inner sphere, but inside the outer sphere,
        # pointing in.  It should return the color of the inner sphere
        scene = copy.deepcopy(self.default_scene)
        scene.objects[0].material.ambient = 1
        scene.objects[1].material.ambient = 1
        r = rays.Ray(points.Point(0, 0, 0.75), vectors.Vector(0, 0, -1))
        self.assertEqual(scene.color_at(r)[0], scene.objects[0].material.color)
Esempio n. 26
0
    def test_empty_canvas(self):
        """Test that an empty canvas is filled with black pixels"""

        c = canvas.Canvas(10, 20)

        self.assertEqual(len(c.canvas), 10)
        self.assertEqual(len(c.canvas[0]), 20)

        for i in range(10):
            for j in range(20):
                self.assertEqual(c.canvas[i][j],
                                 colors.Color(0, 0, 0))
Esempio n. 27
0
    def test_ppm_file_content(self):
        """Test the content of the PPM header is correct"""

        c = canvas.Canvas(5, 3)
        c1 = colors.Color(1.5, 0, 0)
        c2 = colors.Color(0, 0.5, 0)
        c3 = colors.Color(-0.5, 0, 1)

        c.set(0, 0, c1)
        c.set(2, 1, c2)
        c.set(4, 2, c3)

        ppm_content = c._get_ppm_file_content()

        ppm_lines = ppm_content.split("\n")

        self.assertEqual(ppm_lines[0], "P3")
        self.assertEqual(ppm_lines[1], "5 3")
        self.assertEqual(ppm_lines[2], "255")
        self.assertEqual(ppm_lines[3], "255 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
        self.assertEqual(ppm_lines[4], "0 0 0 0 0 0 0 128 0 0 0 0 0 0 0")
        self.assertEqual(ppm_lines[5], "0 0 0 0 0 0 0 0 0 0 0 0 0 0 255")
Esempio n. 28
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))
Esempio n. 29
0
    def reflected_color(self,
                        precomputes: intersections.Computations,
                        remaining: int = 5) -> Tuple[colors.Color, int]:
        """Calculate the reflected color of a hit on a surface.

        remaining tracks how many levels of recursion we have done, and when
        it is zero, simply returns black
        """
        if remaining == 0:
            # If we have gone too far down the recursion stack, just return
            # black
            return colors.Color(0, 0, 0), 0

        if precomputes.object.material.reflective == 0:
            # If the material is not reflective, return black
            return colors.Color(0, 0, 0), 0

        # Fire a new ray from the intersection point at the reflection angle
        reflect_ray = rays.Ray(precomputes.over_point, precomputes.reflectv)

        remaining -= 1

        color, remaining = self.color_at(reflect_ray, remaining=remaining)
        return color * precomputes.object.material.reflective, remaining
Esempio n. 30
0
    def refracted_color(self,
                        precomputes: intersections.Computations,
                        remaining: int = 5) -> Tuple[colors.Color, int]:
        """Calculate the refracted color of a hit on a surface.

        remaining tracks how many levels of recursion we have done, and when
        it is zero, simply returns black
        """

        if remaining == 0:
            # If we have gone too far down the recursion stack, just return
            # black
            return colors.Color(0, 0, 0), remaining

        if precomputes.object.material.transparency == 0:
            # If the material is not transparent, return black
            return colors.Color(0, 0, 0), remaining

        # Check for total internal refraction
        n_ratio = precomputes.n1 / precomputes.n2
        cos_i = precomputes.eyev.dot(precomputes.normalv)
        sin2_t = n_ratio**2 * (1 - cos_i**2)
        if sin2_t > 1:
            return colors.Color(0, 0, 0), remaining

        cos_t = math.sqrt(1.0 - sin2_t)

        direction = (precomputes.normalv * (n_ratio * cos_i - cos_t) -
                     precomputes.eyev * n_ratio)

        refract_ray = rays.Ray(precomputes.under_point, direction)

        color = (self.color_at(refract_ray, remaining - 1)[0] *
                 precomputes.object.material.transparency)

        return color, remaining