def intersect_caps(self, shape_ray: Ray, xs: GroupIntersections):
        # caps only matter if the cylinder is closed, and might possibly be
        # intersected by the ray.
        if not self.closed or abs(shape_ray.direction.y) < EPSILON:
            return

        # check for an intersection with the lower end cap by intersecting
        # the ray with the plane at y=cyl.minimum
        t = (self.minimum - shape_ray.origin.y) / shape_ray.direction.y
        if check_cap(shape_ray, t, self.minimum):
            xs.add_intersection(Intersection(t, self))

        # check for an intersection with the upper end by intersecting
        # the ray with the plane at y=cyl.maximum
        t = (self.maximum - shape_ray.origin.y) / shape_ray.direction.y
        if check_cap(shape_ray, t, self.maximum):
            xs.add_intersection(Intersection(t, self))
Example #2
0
    def local_intersect(self, shape_ray: Ray) -> GroupIntersections:
        a = shape_ray.direction.x**2 + shape_ray.direction.z**2

        # ray is parallel to the y axis
        if a < EPSILON:
            xs = GroupIntersections()
            self.intersect_caps(shape_ray, xs)
            return xs

        b = 2 * shape_ray.origin.x * shape_ray.direction.x +\
            2 * shape_ray.origin.z * shape_ray.direction.z
        c = shape_ray.origin.x**2 + shape_ray.origin.z**2 - 1
        discriminant = b**2 - 4 * a * c

        # ray does not intersect the cylinder
        if discriminant < 0:
            return GroupIntersections()

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

        if t0 > t1:
            t0, t1 = t1, t0

        xs = GroupIntersections()

        y0 = shape_ray.origin.y + t0 * shape_ray.direction.y
        if self.minimum < y0 < self.maximum:
            xs.add_intersection(Intersection(t0, self))

        y1 = shape_ray.origin.y + t1 * shape_ray.direction.y
        if self.minimum < y1 < self.maximum:
            xs.add_intersection(Intersection(t1, self))

        self.intersect_caps(shape_ray, xs)

        return xs
    def local_intersect(self, shape_ray: Ray) -> GroupIntersections:
        a = shape_ray.direction.x ** 2 - shape_ray.direction.y ** 2 + shape_ray.direction.z ** 2

        b = 2 * shape_ray.origin.x * shape_ray.direction.x - \
            2 * shape_ray.origin.y * shape_ray.direction.y + \
            2 * shape_ray.origin.z * shape_ray.direction.z

        xs = GroupIntersections()
        # if a == 0 and b == 0:
        if abs(a) < EPSILON and abs(b) < EPSILON:
            self.intersect_caps(shape_ray, xs)
            return xs

        c = (shape_ray.origin.x ** 2) - (shape_ray.origin.y ** 2) + (shape_ray.origin.z ** 2)

        if abs(a) < EPSILON:
            t = -c / (2 * b)
            xs.add_intersection(Intersection(t, self))
            self.intersect_caps(shape_ray, xs)
            return xs
        discriminant = b ** 2 - 4 * a * c

        # ray does not intersect the cylinder
        if discriminant < 0:
            return GroupIntersections()

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

        if t0 > t1:
            t0, t1 = t1, t0

        y0 = shape_ray.origin.y + t0 * shape_ray.direction.y
        if self.minimum < y0 < self.maximum:
            xs.add_intersection(Intersection(t0, self))

        y1 = shape_ray.origin.y + t1 * shape_ray.direction.y
        if self.minimum < y1 < self.maximum:
            xs.add_intersection(Intersection(t1, self))

        self.intersect_caps(shape_ray, xs)

        return xs