Ejemplo n.º 1
0
    def hit(self, r: Ray, t_min: float, t_max: float) -> Optional[HitRecord]:
        oc: Vec3 = r.origin() - self.center(r.time())
        a: float = r.direction().length_squared()
        half_b: float = oc @ r.direction()
        c: float = oc.length_squared() - self.radius**2
        discriminant: float = half_b**2 - a * c

        if discriminant > 0:
            root: float = np.sqrt(discriminant)
            t_0: float = (-half_b - root) / a
            t_1: float = (-half_b + root) / a

            if t_min < t_0 < t_max:
                t = t_0
            elif t_min < t_1 < t_max:
                t = t_1
            else:
                return None

            point: Point3 = r.at(t)
            outward_normal: Vec3 = ((point - self.center(r.time())) /
                                    self.radius)

            rec = HitRecord(point, t, self.material)
            rec.set_face_normal(r, outward_normal)
            return rec

        return None
Ejemplo n.º 2
0
    def hit(self, r: Ray, t_min: float, t_max: float) -> Optional[HitRecord]:
        origin = r.origin().copy()
        direction = r.direction().copy()

        origin[0] = self.cos_theta * r.origin()[0] - self.sin_theta * r.origin(
        )[2]
        origin[2] = self.sin_theta * r.origin()[0] + self.cos_theta * r.origin(
        )[2]
        direction[0] = \
            self.cos_theta*r.direction()[0] - self.sin_theta*r.direction()[2]
        direction[2] = \
            self.sin_theta*r.direction()[0] + self.cos_theta*r.direction()[2]

        rotated_r = Ray(origin, direction, r.time())
        rec = self.obj.hit(rotated_r, t_min, t_max)
        if rec is None:
            return None

        p = rec.p.copy()
        normal = rec.normal.copy()

        p[0] = self.cos_theta * rec.p[0] + self.sin_theta * rec.p[2]
        p[2] = -self.sin_theta * rec.p[0] + self.cos_theta * rec.p[2]
        normal[0] = \
            self.cos_theta*rec.normal[0] + self.sin_theta*rec.normal[2]
        normal[2] = \
            -self.sin_theta*rec.normal[0] + self.cos_theta*rec.normal[2]

        rec.p = p
        rec.set_face_normal(rotated_r, normal)

        return rec
Ejemplo n.º 3
0
 def scatter(self, r_in: Ray, rec: HitRecord) \
         -> Optional[Tuple[Ray, Color]]:
     if not rec.front_face:
         return None
     scatter_direction: Vec3 = rec.normal + Vec3.random_unit_vector()
     scattered = Ray(rec.p, scatter_direction, r_in.time())
     attenuation = self.albedo.value(rec.u, rec.v, rec.p)
     return scattered, attenuation
Ejemplo n.º 4
0
    def hit(self, r: Ray, t_min: float, t_max: float) -> Optional[HitRecord]:
        # remove the offset to hit the real object
        moved_r = Ray(r.origin() - self.offset, r.direction(), r.time())
        rec = self.obj.hit(moved_r, t_min, t_max)
        if rec is None:
            return None

        # add the offset back to simulate the move
        rec.p += self.offset
        rec.set_face_normal(moved_r, rec.normal)
        return rec
Ejemplo n.º 5
0
 def scatter(self, r_in: Ray, rec: HitRecord) \
         -> Optional[Tuple[Ray, Color]]:
     scattered = Ray(rec.p, Vec3.random_in_unit_sphere(), r_in.time())
     attenuation = self.albedo.value(rec.u, rec.v, rec.p)
     return scattered, attenuation