def test_mixed_hit(): s = Sphere() i1 = Intersection(-1, s) i2 = Intersection(1, s) xs = Intersections(i1, i2) i = xs.hit() assert i == i2
def test_positive_hit(): s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i1, i2) i = xs.hit() assert i == i1
def test_negative_hit(): s = Sphere() i1 = Intersection(-2, s) i2 = Intersection(-1, s) xs = Intersections(i1, i2) i = xs.hit() assert i is None
def test_assert_lowest_hit(): s = Sphere() i1 = Intersection(5, s) i2 = Intersection(7, s) i3 = Intersection(-3, s) i4 = Intersection(2, s) xs = Intersections(i1, i2, i3, i4) i = xs.hit() assert i == i4
def local_intersect(self, ray: Ray): a = ray.direction.x**2 + ray.direction.z**2 if abs(a) < EPSILON: xs = Intersections() self.intersect_caps(ray, xs) return xs b = 2 * ray.origin.x * ray.direction.x + 2 * ray.origin.z * ray.direction.z c = ray.origin.x**2 + ray.origin.z**2 - 1 disc = b**2 - 4 * a * c if disc < 0: return Intersections() t0 = (-b - math.sqrt(disc)) / (2 * a) t1 = (-b + math.sqrt(disc)) / (2 * a) if t0 > t1: t0, t1 = (t1, t0) xs = Intersections() y0 = ray.origin.y + t0 * ray.direction.y if self.minimum < y0 and y0 < self.maximum: xs.append(Intersection(t0, self)) y1 = ray.origin.y + t1 * ray.direction.y if self.minimum < y1 and y1 < self.maximum: xs.append(Intersection(t1, self)) self.intersect_caps(ray, xs) return xs
def local_intersect(self, ray: Ray): xtmin, xtmax = check_axis(ray.origin.x, ray.direction.x) ytmin, ytmax = check_axis(ray.origin.y, ray.direction.y) ztmin, ztmax = check_axis(ray.origin.z, ray.direction.z) tmin = max(xtmin, ytmin, ztmin) tmax = min(xtmax, ytmax, ztmax) if tmin > tmax: return Intersections() else: return Intersections(Intersection(tmin, self), Intersection(tmax, self))
def local_intersect(self, ray: Ray): obj_to_ray = ray.origin - self.origin a = ray.direction.dot(ray.direction) b = 2 * ray.direction.dot(obj_to_ray) c = obj_to_ray.dot(obj_to_ray) - 1 discriminant = b**2 - 4 * a * c if discriminant < 0: return Intersections() t1 = (-b - math.sqrt(discriminant)) / (2 * a) t2 = (-b + math.sqrt(discriminant)) / (2 * a) return Intersections(Intersection(t1, self), Intersection(t2, self))
def test_schlick_perpendicular(): s = GlassSphere() r = Ray(Point(0, 0, 0), Vector(0, 1, 0)) xs = Intersections(Intersection(-1, s), Intersection(1, s)) comps = xs[1].prepare_computation(r, xs) reflectance = comps.schlick() assert equal(reflectance, 0.04)
def test_schlick_small_angle(): s = GlassSphere() r = Ray(Point(0, 0.99, -2), Vector(0, 0, 1)) xs = Intersections(Intersection(1.8589, s)) comps = xs[0].prepare_computation(r, xs) reflectance = comps.schlick() assert equal(reflectance, 0.48873)
def test_aggregate_intersections(): s = Sphere() i1 = Intersection(1, s) i2 = Intersection(2, s) xs = Intersections(i1, i2) assert len(xs) == 2 assert xs[0].t == 1 assert xs[1].t == 2
def test_schlick_tir(): rt2 = math.sqrt(2) / 2 s = GlassSphere() r = Ray(Point(0, 0, rt2), Vector(0, 1, 0)) xs = Intersections(Intersection(-rt2, s), Intersection(rt2, s)) comps = xs[1].prepare_computation(r, xs) reflectance = comps.schlick() assert reflectance == 1.0
def test_refracted_opaque(): w = World().default() s = w.objects[0] r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) xs = Intersections(Intersection(4, s), Intersection(6, s)) comps = xs[0].prepare_computation(r, xs) c = w.refracted_color(comps, 5) assert c == Color(0, 0, 0)
def test_under_point(): r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) s = GlassSphere() s.set_transform(Translation(0, 0, 1)) i = Intersection(5, s) xs = Intersections(i) comps = i.prepare_computation(r, xs) assert comps.under_point.z > EPSILON / 2 assert comps.point.z < comps.under_point.z
def test_refracted_max_depth(): w = World().default() s = w.objects[0] s.material.transparency = 1.0 s.material.refractive_index = 1.5 r = Ray(Point(0, 0, -5), Vector(0, 0, 1)) xs = Intersections(Intersection(4, s), Intersection(6, s)) comps = xs[0].prepare_computation(r, xs) c = w.refracted_color(comps, 0) assert c == Color(0, 0, 0)
def local_intersect(self, ray: Ray): dir_cross_e2 = ray.direction.cross(self.e2) det = self.e1.dot(dir_cross_e2) if abs(det) < EPSILON: return Intersections() f = 1.0 / det p1_to_origin = ray.origin - self.p1 u = f * p1_to_origin.dot(dir_cross_e2) if u < 0 or u > 1: return Intersections() origin_cross_e1 = p1_to_origin.cross(self.e1) v = f * ray.direction.dot(origin_cross_e1) if v < 0 or (u + v) > 1: return Intersections() t = f * self.e2.dot(origin_cross_e1) return Intersections(Intersection( t, self)) # BOGUS TO TEST AGAINST POSITIVE
def test_refracted_total(): w = World().default() s = w.objects[0] s.material.transparency = 1.0 s.material.refractive_index = 1.5 r = Ray(Point(0, 0, math.sqrt(2) / 2), Vector(0, 1, 0)) xs = Intersections( Intersection(-math.sqrt(2) / 2, s), Intersection(math.sqrt(2) / 2, s) ) comps = xs[1].prepare_computation(r, xs) c = w.refracted_color(comps, 5) assert c == Color(0, 0, 0)
def local_intersect(self, ray: Ray): total_xs = Intersections() for obj in self.objects: xs = obj.intersect(ray) total_xs.extend(xs) total_xs.sort() for x in total_xs: print(x) return total_xs
def shade_hit_transparent(): w = World().default() floor = Plane() floor.set_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.set_transform(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 = Intersections(Intersection(math.sqrt(2), floor)) comps = xs[0].prepare_computations(r, xs) color = w.shade_hit(comps, 5) assert color == Color(0.93642, 0.68642, 0.68642)
def test_refracted_color(): w = World().default() a = w.objects[0] a.material.ambient = 1.0 a.material.pattern = _TestPattern() 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 = Intersections( Intersection(-0.9899, a), Intersection(-0.4899, b), Intersection(0.4899, b), Intersection(0.9899, a), ) comps = xs[2].prepare_computation(r, xs) c = w.refracted_color(comps, 5) print(c) assert c == Color(0, 0.99888, 0.04725)
def check_n1_n2(index): a = GlassSphere() a.set_transform(Scaling(2, 2, 2)) a.material.refractive_index = 1.5 b = GlassSphere() b.set_transform(Translation(0, 0, -0.25)) b.material.refractive_index = 2.0 c = GlassSphere() c.set_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), ) comps = xs[index].prepare_computation(r, xs) return (comps.n1, comps.n2)
def local_intersect(self, ray: Ray): if abs(ray.direction.y) < EPSILON: return Intersections() t = -ray.origin.y / ray.direction.y return Intersections(Intersection(t, self))
def intersect(self, ray): xs = Intersections() for obj in self.objects: xs.extend(obj.intersect(ray)) xs.sort() return xs