示例#1
0
 def test_subdivide_csg_subdivide_children(self):
     s1 = Sphere()
     s1.transform = Transformations.translation(-1.5, 0, 0)
     s2 = Sphere()
     s2.transform = Transformations.translation(1.5, 0, 0)
     left = Group()
     left.add_child(s1)
     left.add_child(s2)
     s3 = Sphere()
     s3.transform = Transformations.translation(0, 0, -1.5)
     s4 = Sphere()
     s4.transform = Transformations.translation(0, 0, 1.5)
     right = Group()
     right.add_child(s3)
     right.add_child(s4)
     shape = CSG("difference", left, right)
     shape.divide(1)
     self.assertIsInstance(left.members[0], Group)
     self.assertEqual(left.members[0].members, [s1])
     self.assertIsInstance(left.members[1], Group)
     self.assertEqual(left.members[1].members, [s2])
     self.assertIsInstance(right.members[0], Group)
     self.assertEqual(right.members[0].members, [s3])
     self.assertIsInstance(right.members[1], Group)
     self.assertEqual(right.members[1].members, [s4])
示例#2
0
    def test_normal_with_transform(self):
        s = Sphere()
        s.transform = Matrix.translate(0, 5, 0)
        n = s.normal(Point(1, 5, 0))
        self.assertEqual(n, Vector(1, 0, 0))

        s = Sphere()
        s.transform = Matrix.scale(1, 0.5, 1)
        r = math.sqrt(2) / 2
        n = s.normal(Point(0, r, -r))
        self.assertTupleEqual(n, Vector(0, 0.97014, -0.24254))
示例#3
0
 def test_partitioning_group_children(self):
     s1 = Sphere()
     s1.transform = Transformations.translation(-2, 0, 0)
     s2 = Sphere()
     s2.transform = Transformations.translation(2, 0, 0)
     s3 = Sphere()
     g = Group()
     g.add_child(s1)
     g.add_child(s2)
     g.add_child(s3)
     (left, right) = g.partition_children()
     self.assertEqual(g.members, [s3])
     self.assertEqual(left, [s1])
     self.assertEqual(right, [s2])
示例#4
0
 def test_pattern_object_and_pattern_transformation(self):
     shape = Sphere()
     shape.transform = Transformations.scaling(2, 2, 2)
     pattern = Pattern.test_pattern()
     pattern.transform = Transformations.translation(0.5, 1, 1.5)
     c = pattern.pattern_at_shape(shape, Point(2.5, 3, 3.5))
     self.assertEqual(c, Color(0.75, 0.5, 0.25))
示例#5
0
    def test_transformation(self):
        s = Sphere()
        self.assertEqual(s.transform, Matrix.identity())

        t = Matrix.translate(2, 3, 4)
        s.transform = t
        self.assertEqual(s.transform, t)
示例#6
0
    def test_intersect_with_transform(self):
        # intersect a scaled sphere
        r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
        s = Sphere()
        s.transform = Matrix.scale(2, 2, 2)
        xs = s.intersect(r)
        self.assertEqual(len(xs), 2)
        self.assertEqual(xs[0].t, 3)
        self.assertEqual(xs[1].t, 7)

        # intersect a translated sphere
        r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
        s = Sphere()
        s.transform = Matrix.translate(5, 0, 0)
        xs = s.intersect(r)
        self.assertEqual(len(xs), 0)
示例#7
0
 def test_hit_offset_point(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     shape = Sphere()
     shape.transform = Transformations.translation(0, 0, 1)
     i = Intersection(5, shape)
     comps = Computations.prepare_computations(i, r)
     self.assertLess(comps.over_point.z, -Constants.epsilon / 2)
     self.assertGreater(comps.point.z, comps.over_point.z)
 def test_offset1(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     shape = Sphere()
     shape.transform = translate(0, 0, 1)
     i = Intersection(5, shape)
     comps = i.prepare_computations(r)
     self.assertTrue(comps.over_point.z < -EPSILON / 2)
     self.assertTrue(comps.point.z > comps.over_point.z)
示例#9
0
 def test_csg_bounding_box(self):
     left = Sphere()
     right = Sphere()
     right.transform = Transformations.translation(2, 3, 4)
     shape = CSG("difference", left, right)
     box = shape.bounds_of()
     self.assertEqual(box.min, Point(-1, -1, -1))
     self.assertEqual(box.max, Point(3, 4, 5))
示例#10
0
 def test_intersecting_ray_with_nonempty_group(self):
     g = Group()
     s1 = Sphere()
     s2 = Sphere()
     s2.transform = Transformations.translation(0, 0, -3)
     s3 = Sphere()
     s3.transform = Transformations.translation(5, 0, 0)
     g.add_child(s1)
     g.add_child(s2)
     g.add_child(s3)
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     xs = g.local_intersect(r)
     self.assertEqual(len(xs), 4)
     self.assertEqual(xs[0].object, s2)
     self.assertEqual(xs[1].object, s2)
     self.assertEqual(xs[2].object, s1)
     self.assertEqual(xs[3].object, s1)
示例#11
0
 def test_intersect_scaled_sphere_with_ray(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     s = Sphere()
     s.transform = Transformations.scaling(2, 2, 2)
     xs = s.intersect(r)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].t, 3)
     self.assertEqual(xs[1].t, 7)
示例#12
0
 def test_intersecting_transformed_group(self):
     g = Group()
     g.transform = Transformations.scaling(2, 2, 2)
     s = Sphere()
     s.transform = Transformations.translation(5, 0, 0)
     g.add_child(s)
     r = Ray(Point(10, 0, -10), Vector(0, 0, 1))
     xs = g.intersect(r)
     self.assertEqual(len(xs), 2)
示例#13
0
 def test_group_partitions_children(self):
     s1 = Sphere()
     s1.transform = Transformations.translation(-2, -2, 0)
     s2 = Sphere()
     s2.transform = Transformations.translation(-2, 2, 0)
     s3 = Sphere()
     s3.transform = Transformations.scaling(4, 4, 4)
     g = Group()
     g.add_child(s1)
     g.add_child(s2)
     g.add_child(s3)
     g.divide(1)
     self.assertEqual(g.members[0], s3)
     subgroup = g.members[1]
     self.assertIsInstance(subgroup, Group)
     self.assertEqual(len(subgroup.members), 2)
     self.assertEqual(subgroup.members[0].members, [s1])
     self.assertEqual(subgroup.members[1].members, [s2])
 def test_finding_normal_on_child_object(self):
     g1 = Group()
     g1.transform = Transformations.rotation_y(math.pi / 2)
     g2 = Group()
     g2.transform = Transformations.scaling(1, 2, 3)
     g1.add_child(g2)
     s = Sphere()
     s.transform = Transformations.translation(5, 0, 0)
     g2.add_child(s)
     n = s.normal_at(Point(1.7321, 1.1547, -5.5774))
     self.assertEqual(n, Vector(0.2857, 0.4286, -0.8571))
 def test_converting_point_from_world_to_object_space(self):
     g1 = Group()
     g1.transform = Transformations.rotation_y(math.pi / 2)
     g2 = Group()
     g2.transform = Transformations.scaling(2, 2, 2)
     g1.add_child(g2)
     s = Sphere()
     s.transform = Transformations.translation(5, 0, 0)
     g2.add_child(s)
     p = s.world_to_object(Point(-2, 0, -10))
     self.assertEqual(p, Point(0, 0, -1))
 def test_converting_normal_from_object_to_world_space(self):
     g1 = Group()
     g1.transform = Transformations.rotation_y(math.pi / 2)
     g2 = Group()
     g2.transform = Transformations.scaling(1, 2, 3)
     g1.add_child(g2)
     s = Sphere()
     s.transform = Transformations.translation(5, 0, 0)
     g2.add_child(s)
     n = s.normal_to_world(Vector(math.sqrt(3) /3, math.sqrt(3) / 3, math.sqrt(3) / 3))
     self.assertEqual(n, Vector(0.2857, 0.4286, -0.8571))
示例#17
0
 def test_ray_hits_csg_object(self):
     s1 = Sphere()
     s2 = Sphere()
     s2.transform = Transformations.translation(0, 0, 0.5)
     c = CSG("union", s1, s2)
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     xs = c.local_intersect(r)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].t, 4)
     self.assertEqual(xs[0].object, s1)
     self.assertEqual(xs[1].t, 6.5)
     self.assertEqual(xs[1].object, s2)
示例#18
0
 def test_subdividing_group_too_few_children(self):
     s1 = Sphere()
     s1.transform = Transformations.translation(-2, 0, 0)
     s2 = Sphere()
     s2.transform = Transformations.translation(2, 1, 0)
     s3 = Sphere()
     s3.transform = Transformations.translation(2, -1, 0)
     subgroup = Group()
     subgroup.add_child(s1)
     subgroup.add_child(s2)
     subgroup.add_child(s3)
     s4 = Sphere()
     g = Group()
     g.add_child(subgroup)
     g.add_child(s4)
     g.divide(3)
     self.assertEqual(g.members[0], subgroup)
     self.assertEqual(g.members[1], s4)
     self.assertEqual(len(subgroup.members), 2)
     self.assertEqual(subgroup.members[0].members, [s1])
     self.assertEqual(subgroup.members[1].members, [s2, s3])
 def test_shadow5(self):
     w = World()
     light = Light(Point(0, 0, -10), Color(1, 1, 1))
     w.light = light
     s1 = Sphere()
     s2 = Sphere()
     s2.transform = translate(0, 0, 10)
     w.objs = [s1, s2]
     r = Ray(Point(0, 0, 5), Vector(0, 0, 1))
     i = Intersection(4, s2)
     comps = i.prepare_computations(r)
     c = w.shade_hit(comps)
     self.assertTrue(Color(0.1, 0.1, 0.1).equals(c))
示例#20
0
 def test_shade_hit_intersection_in_shadow(self):
     w = World()
     w.light = PointLight(Point(0, 0, -10), Color(1, 1, 1))
     s1 = Sphere()
     w.objects.append(s1)
     s2 = Sphere()
     s2.transform = Transformations.translation(0, 0, 10)
     w.objects.append(s2)
     r = Ray(Point(0, 0, 5), Vector(0, 0, 1))
     i = Intersection(4, s2)
     comps = Computations.prepare_computations(i, r)
     c = World.shade_hit(w, comps)
     self.assertEqual(c, Color(0.1, 0.1, 0.1))
示例#21
0
    def test_default_world(self):
        light = PointLight(Point(-10, 10, -10), Color(1, 1, 1))
        s1 = Sphere()
        s1.material.color = Color(0.8, 1.0, 0.6)
        s1.material.diffuse = 0.7
        s1.material.specular = 0.2

        s2 = Sphere()
        s2.transform = Transformations.scaling(0.5, 0.5, 0.5)

        w = World.default_world()
        self.assertEqual(w.light, light)
        self.assertTrue(s1 in w.objects)
        self.assertTrue(s2 in w.objects)
示例#22
0
 def test_group_bounding_box_contains_children(self):
     s = Sphere()
     s.transform = Transformations.translation(2, 5, -3).dot(
         Transformations.scaling(2, 2, 2))
     c = Cylinder()
     c.minimum = -2
     c.maximum = 2
     c.transform = Transformations.translation(-4, -1, 4).dot(
         Transformations.scaling(0.5, 1, 0.5))
     shape = Group()
     shape.add_child(s)
     shape.add_child(c)
     box = shape.bounds_of()
     self.assertEqual(box.min, Point(-4.5, -3, -5))
     self.assertEqual(box.max, Point(4, 7, 4.5))
示例#23
0
 def test_shade_hit_with_transparent_material(self):
     w = World.default_world()
     floor = Plane()
     floor.transform = Transformations.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 = Transformations.translation(0, -3.5, -0.5)
     w.objects.append(ball)
     r = Ray(Point(0, 0, -3), Vector(0, -math.sqrt(2) / 2,
                                     math.sqrt(2) / 2))
     xs = Intersection.intersections(Intersection(math.sqrt(2), floor))
     comps = Computations.prepare_computations(xs[0], r, xs)
     color = World.shade_hit(w, comps, 5)
     self.assertEqual(color, Color(0.93642, 0.68642, 0.68642))
示例#24
0
 def test_normal_translated_sphere(self):
     s = Sphere()
     s.transform = Transformations.translation(0, 1, 0)
     n = s.normal_at(Point(0, 1.70711, -0.70711))
     self.assertEqual(n, Vector(0, 0.70711, -0.70711))
示例#25
0
W = 200
H = 200
D = 200
im = Image.new('RGB', (W, H))
pix = im.load()

sphere = Sphere()
sphere.material.color = Color(1, 0.2, 1)
light_color = Color(1, 1, 1)
light_position = Point(-10, 10, -10)
light = PointLight(light_position, light_color)

## this is done in object coordinates
eye = Point(0, 0, -5)
tt = Matrix.translate(0, 0, -2)
sphere.transform = tt
wall = (-3, 3, -3, 3)  # LRBT

# the -1 flips the y-coordinate so it's up
my = Matrix.scale(1.0, -1.0, 1.0)
ms = Matrix.scale(
    float(wall[1] - wall[0]) / W,
    float(wall[3] - wall[2]) / H, 1.0)
mt = Matrix.translate(wall[0], wall[2], 0)
m = my * mt * ms

_debug = False
_pause = _debug


def dprint(s):
from canvas import Canvas
from point import Point
from color import Color
from ray import Ray
from sphere import Sphere
from material import Material
from light import Light
from time import time
from world import World
from camera import Camera

if __name__ == '__main__':
    t1 = time()

    floor = Sphere()
    floor.transform = scale(10, 0.01, 10)
    floor.material = Material()
    floor.material.color = Color(1, 0.9, 0.9)
    floor.material.specular = 0

    left_wall = Sphere()
    left_wall.transform = translate(0, 0, 5) * \
        rotate_y(-pi/4) * \
        rotate_x(pi/2) * \
        scale(10, 0.01, 10)
    left_wall.material = floor.material

    right_wall = Sphere()
    right_wall.transform = translate(0, 0, 5) * \
        rotate_y(pi/4) * \
        rotate_x(pi/2) * \
示例#27
0
 def test_normal_transformed_sphere(self):
     s = Sphere()
     m = Transformations.scaling(1, 0.5, 1).dot(Transformations.rotation_z(math.pi / 5))
     s.transform = m
     n = s.normal_at(Point(0, math.sqrt(2) / 2, -(math.sqrt(2) / 2)))
     self.assertEqual(n, Vector(0, 0.97014, -0.24254))
示例#28
0
 def test_intersect_translated_sphere(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     s = Sphere()
     s.transform = Transformations.translation(5, 0, 0)
     xs = s.intersect(r)
     self.assertEqual(len(xs), 0)
示例#29
0
import math

from camera import Camera
from color import Color
from light import PointLight
from material import Material
from sphere import Sphere
from transformations import Transformations
from tuple import Point, Vector
from world import World

if __name__ == '__main__':
    # The floor is an extremely flattened sphere with a matte texture
    floor = Sphere()
    floor.transform = Transformations.scaling(10, 0.1, 10)
    floor.material = Material()
    floor.material.color = Color(1, 0.9, 0.9)
    floor.material.specular = 0

    # The wall on the left has the same scale and color as the floor, but is also rotated and translated into place
    left_wall = Sphere()
    left_wall.transform = Transformations.translation(0, 0, 5)
    left_wall.transform = left_wall.transform.dot(
        Transformations.rotation_y(-math.pi / 4))
    left_wall.transform = left_wall.transform.dot(
        Transformations.rotation_x(math.pi / 2))
    left_wall.transform = left_wall.transform.dot(
        Transformations.scaling(10, 0.1, 10))
    left_wall.material = floor.material

    # The wall on the right is identical to the left wall, but is rotated the opposite direction in y
示例#30
0
from sphere import Sphere
from ray import Ray

W = 200
H = 200
D = 200
im = Image.new('RGB', (W, H))
pix = im.load()

if False:
    ## this is done in image coordinates
    eye = Point(W / 2, H / 2, D)
    sphere = Sphere()
    ts = Matrix.scale(50, 50, 50)
    tt = Matrix.translate(W / 2, H / 2, D / 4)
    sphere.transform = tt * ts

    for x in range(W):
        for y in range(H):
            ray = Ray(eye, Point(x, y, 0) - eye)
            xs = sphere.intersect(ray)
            if xs:
                pix[x, y] = (255, 0, 0)
        print(x)

else:
    ## this is done in object coordinates
    eye = Point(0, 0, -5)
    sphere = Sphere()
    tt = Matrix.translate(0, 0, -2)
    sphere.transform = tt