def schlick(self, incident: 'Vector3', normal: 'Vector3', n1: 'float', n2: 'float'): r0 = (n1 - n2) / (n1 + n2) r0 *= r0 cosX = Vector3.dot(normal, incident) if n1 > n2: n = n1 / n2 sinT2 = n * n * (1.0 - cosX * cosX) if sinT2 > 1.0: return 1.0 cosX = math.sqrt(1.0 - sinT2) x = 1.0 - cosX return r0 + (1.0 - r0) * math.pow(x, 5)
def trilineart_interp(self, c, u, v, w): uu = u * u * (3 - 2 * u) vv = v * v * (3 - 2 * v) ww = w * w * (3 - 2 * w) accum = 0 for i in range(2): for j in range(2): for k in range(2): weight_v = Vector3(u - i, v - j, w - k) accum += (i * uu + (1 - i) * (1 - uu)) * \ (j * vv + (1 - j) * (1 - vv)) * \ (k * ww + (1 - k) * (1 - ww)) * Vector3.dot(c[i * 2 + j * 2 + k], weight_v) return accum
def hit(self, ray: Ray, t_min: float, t_max: float) -> (bool, HitRecord): """Checks if the ray 'ray' hits with the sphere between t_min and t_max. Returns true if there is a collision, false otherwise. Return the hitRecord information if the collision is true. """ current_center = self.get_center(t=ray.time) oc = ray.origin - current_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(b * b - a * c)) / a if t_max > temp > t_min: record = HitRecord() record.t = temp record.hit_point = ray.point_at_parameter(record.t) record.hit_point_normal = (record.hit_point - current_center) / self._radius record.u, record.v = self.get_sphere_uv(p=record.hit_point) record.material = self._material return True, record temp = (-b + math.sqrt(b * b - a * c)) / a if t_max > temp > t_min: record = HitRecord() record.t = temp record.hit_point = ray.point_at_parameter(record.t) record.hit_point_normal = (record.hit_point - current_center) / self._radius record.u, record.v = self.get_sphere_uv(p=record.hit_point) record.material = self._material return True, record return False, None
def value(self, direction: Vector3) -> float: cosine = Vector3.dot(Vector3.normalize(direction), self._uvw.w()) if cosine > 0: return cosine / math.pi else: return 0