def hit(self, r: Ray, t_min: float, t_max: float):
        oc = r.origin() - self.center
        a = np.dot(r.direction(), r.direction())
        b = np.dot(oc, r.direction())
        c = np.dot(oc, oc) - self.radius * self.radius
        discriminant = b * b - a * c

        if discriminant > 0:
            temp = (-b - sqrt(b * b - a * c)) / a
            if (temp < t_max) and (temp > t_min):
                t = temp
                p = r.point_at_parameter(t)
                normal = (p - self.center) / self.radius
                rec = hit_record(t, p, normal, self.material)
                return True, rec

            temp = (-b + sqrt(b * b - a * c)) / a
            if (temp < t_max) and (temp > t_min):
                t = temp
                p = r.point_at_parameter(t)
                normal = (p - self.center) / self.radius
                rec = hit_record(t, p, normal, self.material)
                return True, rec

        return False, None
Exemple #2
0
    def scatter(self, r_in: Ray, rec: hit_record):
        unit_direction = r_in.direction() / np.linalg.norm(r_in.direction())

        reflected: np.ndarray = reflect(unit_direction, rec.normal)
        scattered = Ray(rec.p, reflected + self.fuzz * random_in_unit_sphere())
        attenuation = self.albedo
        return (np.dot(scattered.direction(), rec.normal) > 0), attenuation, scattered
Exemple #3
0
    def hit(self, r: Ray, t_min: float, t_max: float):
        t: float = (self.k - r.origin()[2]) / r.direction()[2]

        if (t < t_min) or (t > t_max):
            return False, None
        x: float = r.origin()[0] + t * r.direction()[0]
        y: float = r.origin()[1] + t * r.direction()[1]

        if (x < self.x0) or (x > self.x1) or (y < self.y0) or (y > self.y1):
            return False, None

        u = (x - self.x0) / (self.x1 - self.x0)
        v = (y - self.y0) / (self.y1 - self.y0)
        p = r.point_at_parameter(t)
        normal = np.array((0, 0, 1))

        return True, hit_record(t, p, normal, self.material, u, v)
    def scatter(self, r_in: Ray, rec: hit_record):
        reflected: np.ndarray = reflect(r_in.direction(), rec.normal)
        attenuation = np.array((1, 1, 1), float)
        if np.dot(r_in.direction(), rec.normal) > 0:
            outward_normal = -rec.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * np.dot(r_in.direction(),
                                           rec.normal) / np.linalg.norm(
                                               r_in.direction())

        else:
            outward_normal = rec.normal
            ni_over_nt = 1.0 / self.ref_idx
            cosine = float(-np.dot(r_in.direction(), rec.normal) /
                           np.linalg.norm(r_in.direction()))

        has_refracted, refracted = refract(r_in.direction(), outward_normal,
                                           ni_over_nt)
        if has_refracted:
            reflect_prob = schlick(cosine, self.ref_idx)

        else:
            reflect_prob = 1

        if random() < reflect_prob:
            scattered = Ray(rec.p, reflected, r_in.time())

        else:
            scattered = Ray(rec.p, refracted, r_in.time())

        return True, attenuation, scattered
Exemple #5
0
    def scatter(self, ray_in: Ray, hit_record: hit_record):
        outward_normal = Vector3(1, 1, 1)
        reflected = ray_in.direction().reflect(hit_record.normal)
        ni_over_nt = 0
        attenuation = Vector3(1, 1, 1)
        scattered = Vector3(0, 0, 0)
        reflect_prob = 0
        cosine = 0

        if (ray_in.direction().dot(hit_record.normal) > 0):
            outward_normal = Vector3(0, 0, 0) - hit_record.normal
            ni_over_nt = self.ref_idx
            cosine = self.ref_idx * ray_in.direction().dot(
                hit_record.normal) / ray_in.direction().length()
        else:
            outward_normal = hit_record.normal
            ni_over_nt = 1 / self.ref_idx
            cosine = -ray_in.direction().dot(
                hit_record.normal) / ray_in.direction().length()

        is_scattered, refracted = refract(ray_in.direction(), outward_normal,
                                          ni_over_nt)
        if (is_scattered):
            reflect_prob = schlick(cosine, self.ref_idx)
        else:
            scattered = Ray(hit_record.p, reflected)
            reflect_prob = 1.0

        if (random.uniform(0, 1) < reflect_prob):
            scattered = Ray(hit_record.p, reflected)
        else:
            scattered = Ray(hit_record.p, refracted)

        return (True, scattered, attenuation)
Exemple #6
0
    def hit(self, ray: Ray, t_min: float, t_max: float, rec: hit_record):
        oc = ray.origin() - self.center
        a = Vector3.dot(ray.direction(), ray.direction())
        b = Vector3.dot(oc, ray.direction())
        c = Vector3.dot(oc, oc) - self.radius * self.radius
        discriminant = b * b - a * c

        if (discriminant > 0):
            temp = (-b - math.sqrt(discriminant)) / a
            if (temp < t_max and temp > t_min):
                rec.t = temp
                rec.p = ray.point_at_parameter(rec.t)
                rec.normal = (rec.p - self.center).scalar_div(self.radius)
                return True
            temp = (-b + math.sqrt(discriminant)) / a
            if (temp < t_max and temp > t_min):
                rec.t = temp
                rec.p = ray.point_at_parameter(rec.t)
                rec.normal = (rec.p - self.center).scalar_div(self.radius)
                return True

        return False
Exemple #7
0
    def generate_ray(self, sample, width, height):
        ray = Ray()
        ray.pos = self.eye

        u, v, w = self._uvw()

        i = sample[0]
        j = sample[1]

        aspect = width / height
        a = np.tan(np.deg2rad(
            self.fov / 2)) * aspect * (j - width / 2) / (width / 2)
        b = np.tan(np.deg2rad(self.fov / 2)) * (height / 2 - i) / (height / 2)

        d = a * u + b * v - w
        ray.direction = np.hstack([d / np.linalg.norm(d), 0])

        return ray
    def hit(self, r: Ray, tmin: float, tmax: float):
        for a in range(3):
            invD = 1.0 / r.direction()[a]

            t0 = (self._min[a] - r.origin()[a]) * invD

            t1 = (self._max[a] - r.origin()[a]) * invD

            if invD < 0.0:
                aux = t1
                t1 = t0
                t0 = aux

            tmin = t0 if t0 > tmin else tmin
            tmax = t1 if t1 < tmax else tmax

            if tmax <= tmin:
                return False

        return True
Exemple #9
0
    def intersect(self, ray: Ray) -> Optional[Point]:
        if ray in self._intersections:
            return self._intersections[ray]

        d = ray.direction()
        delta = self._discriminant(d)
        if delta < 0:
            self._intersections[ray] = None
            return None

        first = - d.dot(self._e_m_c)
        den = d.squared()
        sqrt_delta = math.sqrt(delta)
        t1 = (first + sqrt_delta) / den
        t2 = (first - sqrt_delta) / den
        t = min(t1, t2)

        inter = self._e + d.scale(t)
        p = Point(inter.x(), inter.y(), inter.z())
        self._intersections[ray] = p
        return p
Exemple #10
0
 def scatter(self, ray_in: Ray, hit_record: hit_record):
     reflected = ray_in.direction().normalize().reflect(hit_record.normal)
     scattered = Ray(hit_record.p, reflected)
     attenuation = self.albedo
     should_scatter = scattered.direction().dot(hit_record.normal) > 0
     return (should_scatter, scattered, attenuation)