Example #1
0
    def local_intersect(self, ray: Ray) -> Iterable[Intersection]:
        sphere_to_ray = ray.origin - Point(0, 0, 0)
        a = Vector.dot(ray.direction, ray.direction)
        b = 2 * Vector.dot(ray.direction, sphere_to_ray)
        c = Vector.dot(sphere_to_ray, sphere_to_ray) - 1
        discriminant = b**2 - 4 * a * c

        if discriminant < 0:
            return Intersection.intersections()

        t1 = (-b - math.sqrt(discriminant)) / (2 * a)
        t2 = (-b + math.sqrt(discriminant)) / (2 * a)

        return Intersection.intersections(Intersection(t1, self),
                                          Intersection(t2, self))
Example #2
0
 def test_hit_all_intersections_negative_t(self):
     s = Sphere()
     i1 = Intersection(-2, s)
     i2 = Intersection(-1, s)
     xs = Intersection.intersections(i2, i1)
     i = Intersection.hit(xs)
     self.assertIsNone(i)
Example #3
0
 def test_schlick_approximation_with_perpendicular_viewing_angle(self):
     shape = GlassSphere()
     r = Ray(Point(0, 0, 0), Vector(0, 1, 0))
     xs = Intersection.intersections(Intersection(-1,shape), Intersection(1, shape))
     comps = Computations.prepare_computations(xs[1], r, xs)
     reflectance = World.schlick(comps)
     self.assertAlmostEqual(reflectance, 0.04, delta = Constants.epsilon)
Example #4
0
 def test_hit_all_intersections_positive_t(self):
     s = Sphere()
     i1 = Intersection(1, s)
     i2 = Intersection(2, s)
     xs = Intersection.intersections(i2, i1)
     i = Intersection.hit(xs)
     self.assertEqual(i, i1)
Example #5
0
 def test_schlick_approximation_with_small_angle(self):
     shape = GlassSphere()
     r = Ray(Point(0, 0.99, -2), Vector(0, 0, 1))
     xs = Intersection.intersections(Intersection(1.8589, shape))
     comps = Computations.prepare_computations(xs[0], r, xs)
     reflectance = World.schlick(comps)
     self.assertAlmostEqual(reflectance, 0.48873, delta = Constants.epsilon)
Example #6
0
 def test_schlick_approximation_under_total_internal_reflection(self):
     shape = GlassSphere()
     r = Ray(Point(0, 0, math.sqrt(2) / 2), Vector(0, 1, 0))
     xs = Intersection.intersections(Intersection(-math.sqrt(2) / 2, shape), Intersection(math.sqrt(2) / 2, shape))
     comps = Computations.prepare_computations(xs[1], r, xs)
     reflectance = World.schlick(comps)
     self.assertEqual(reflectance, 1.0)
Example #7
0
 def test_findinf_n1_n2_at_various_intersections(self):
     a = GlassSphere()
     a.transform = Transformations.scaling(2, 2, 2)
     a.material.refractive_index = 1.5
     b = GlassSphere()
     b.transform = Transformations.translation(0, 0, -0.25)
     b.material.refractive_index = 2.0
     c = GlassSphere()
     c.transform = Transformations.translation(0, 0, 0.25)
     c.material.refractive_index = 2.5
     r = Ray(Point(0, 0, -4), Vector(0, 0, 1))
     xs = Intersection.intersections(Intersection(2, a), Intersection(2.75, b), Intersection(3.25, c), Intersection(4.75, b), Intersection(5.25, c), Intersection(6, a))
     RefractiveIndices = namedtuple("RefractiveIndices", ["n1", "n2"])
     refractive_indices_list = [
         RefractiveIndices(1.0, 1.5),
         RefractiveIndices(1.5, 2.0),
         RefractiveIndices(2.0, 2.5),
         RefractiveIndices(2.5, 2.5),
         RefractiveIndices(2.5, 1.5),
         RefractiveIndices(1.5, 1.0)
     ]
     for index, refractive_index in enumerate(refractive_indices_list):
         comps = Computations.prepare_computations(xs[index], r, xs)
         print(comps.n1)
         print(comps.n2)
         self.assertEqual(comps.n1, refractive_index.n1)
         self.assertEqual(comps.n2, refractive_index.n2)
Example #8
0
 def test_hit_some_intersections_negative_t(self):
     s = Sphere()
     i1 = Intersection(-1, s)
     i2 = Intersection(1, s)
     xs = Intersection.intersections(i2, i1)
     i = Intersection.hit(xs)
     self.assertEqual(i, i2)
Example #9
0
 def test_aggregate_intersections(self):
     s = Sphere()
     i1 = Intersection(1, s)
     i2 = Intersection(2, s)
     xs = Intersection.intersections(i1, i2)
     self.assertEqual(len(xs), 2)
     self.assertEqual(xs[0].t, 1)
     self.assertEqual(xs[1].t, 2)
Example #10
0
 def test_refracted_color_with_opaque_surface(self):
     w = World.default_world()
     shape = w.objects[0]
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     xs = Intersection.intersections(Intersection(4, shape),
                                     Intersection(6, shape))
     comps = Computations.prepare_computations(xs[0], r, xs)
     c = World.refracted_color(w, comps, 5)
     self.assertEqual(c, Color(0, 0, 0))
Example #11
0
 def test_hit_lowest_nonnegative_intersection(self):
     s = Sphere()
     i1 = Intersection(5, s)
     i2 = Intersection(7, s)
     i3 = Intersection(-3, s)
     i4 = Intersection(2, s)
     xs = Intersection.intersections(i1, i2, i3, i4)
     i = Intersection.hit(xs)
     self.assertEqual(i, i4)
Example #12
0
 def test_under_point_offset_below_surface(self):
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     shape = GlassSphere()
     shape.transform = Transformations.translation(0, 0, 1)
     i = Intersection(5, shape)
     xs = Intersection.intersections(i)
     comps = Computations.prepare_computations(i, r, xs)
     self.assertGreater(comps.under_point.z, Constants.epsilon / 2)
     self.assertLess(comps.point.z, comps.under_point.z)
Example #13
0
 def test_refracted_color_at_max_recursive_depth(self):
     w = World.default_world()
     shape = w.objects[0]
     shape.material.transparency = 1.0
     shape.material.refractive_index = 1.5
     r = Ray(Point(0, 0, -5), Vector(0, 0, 1))
     xs = Intersection.intersections(Intersection(4, shape),
                                     Intersection(6, shape))
     comps = Computations.prepare_computations(xs[0], r, xs)
     c = World.refracted_color(w, comps, 0)
     self.assertEqual(c, Color(0, 0, 0))
Example #14
0
 def test_refracted_color_under_total_internal_reflection(self):
     w = World.default_world()
     shape = w.objects[0]
     shape.material.transparency = 1.0
     shape.material.refractive_index = 1.5
     r = Ray(Point(0, 0, math.sqrt(2) / 2), Vector(0, 1, 0))
     xs = Intersection.intersections(Intersection(-math.sqrt(2) / 2, shape),
                                     Intersection(math.sqrt(2) / 2, shape))
     # NOTE: this time you're inside the sphere, so you need
     # to look at the second intersection, xs[1], not xs[0]
     comps = Computations.prepare_computations(xs[1], r, xs)
     c = World.refracted_color(w, comps, 5)
     self.assertEqual(c, Color(0, 0, 0))
Example #15
0
 def test_refracted_color_with_refracted_ray(self):
     w = World.default_world()
     a = w.objects[0]
     a.material.ambient = 1.0
     a.material.pattern = Pattern.test_pattern()
     b = w.objects[1]
     b.material.transparency = 1.0
     b.material.refractive_index = 1.5
     r = Ray(Point(0, 0, 0.1), Vector(0, 1, 0))
     xs = Intersection.intersections(Intersection(-0.9899, a),
                                     Intersection(-0.4899, b),
                                     Intersection(0.4899, b),
                                     Intersection(0.9899, a))
     comps = Computations.prepare_computations(xs[2], r, xs)
     c = World.refracted_color(w, comps, 5)
     self.assertEqual(c, Color(0, 0.99888, 0.04725))
Example #16
0
 def test_filtering_list_intersections(self):
     s1 = Sphere()
     s2 = Cube()
     Operation = namedtuple("Operation", ["operation", "x0", "x1"])
     operatios = [
         Operation("union", 0, 3),
         Operation("intersection", 1, 2),
         Operation("difference", 0, 1)
     ]
     for operation in operatios:
         c = CSG(operation.operation, s1, s2)
         xs = Intersection.intersections(Intersection(1, s1), Intersection(2, s2), Intersection(3, s1), Intersection(4, s2))
         result = c.filter_intersections(xs)
         self.assertEqual(len(result), 2)
         self.assertEqual(result[0], xs[operation.x0])
         self.assertEqual(result[1], xs[operation.x1])
Example #17
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))
Example #18
0
 def test_preparing_normal_smooth_triangle(self):
     i = Intersection(1, self.tri, 0.45, 0.25)
     r = Ray(Point(-0.2, 0.3, -2), Vector(0, 0, 1))
     xs = Intersection.intersections(i)
     comps = Computations.prepare_computations(i, r, xs)
     self.assertEqual(comps.normalv, Vector(-0.5547, 0.83205, 0))