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
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
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
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)
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
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
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
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)