def fromnormals_faster(n1, n2): axis = vec3.normalize(vec3.cross(n1, n2)) half_n = vec3.normalize(vec3.add(n1, n2)) cos_half_angle = vec3.dot(n1, half_n) sin_half_angle = 1.0 - cos_half_angle ** 2 return vec3.mulN(axis, sin_half_angle) + (cos_half_angle,)
def fromnormals_faster(n1,n2): axis= vec3.normalize(vec3.cross(n1, n2)) half_n= vec3.normalize(vec3.add(n1, n2)) cos_half_angle= vec3.dot(n1, half_n) sin_half_angle= 1.0 - cos_half_angle**2 return vec3.mulN(axis, sin_half_angle) + (cos_half_angle,)
def __init__(self, origin, lookat, up, fov, aspect): theta = fov * math.pi / 180 half_height = math.tan(theta / 2) half_width = aspect * half_height self.origin = origin w = vec3.normalize(vec3.subtract(origin, lookat)) u = vec3.normalize(vec3.cross(up, w)) v = vec3.cross(w, u) self.horizontal = vec3.scale(u, 2 * half_width) self.vertical = vec3.scale(v, 2 * half_height) center = vec3.subtract(origin, w) shift = vec3.scale(vec3.add(self.horizontal, self.vertical), 0.5) self.llc = vec3.subtract(center, shift)
def scatter(self, ray, record): reflected = vec3.reflect(vec3.normalize(ray.direction), record.normal) outward_normal = (0, 0, 0) idx_ratio = 0 if vec3.dot(ray.direction, record.normal) > 0: outward_normal = vec3.scale(record.normal, -1) idx_ratio = self.ri cos = self.ri * vec3.dot(vec3.normalize(ray.direction), record.normal) else: outward_normal = record.normal idx_ratio = 1.0 / self.ri cos = -vec3.dot(vec3.normalize(ray.direction), record.normal) refracted = vec3.refract(ray.direction, outward_normal, idx_ratio) if refracted: reflect_prob = self.schlick(cos, self.ri) if random.random() < reflect_prob: return Ray(record.p, reflected) return Ray(record.p, refracted) else: return Ray(record.p, reflected)
def color(ray, world, depth): record = world.hit(ray, eps, float('inf')) if record: # camera receives color from a ray scattered randomly off surface if (depth < 10): scattered = record.material.scatter(ray, record) if scattered: return vec3.mult(color(scattered, world, depth + 1), record.material.attenuation) unit = vec3.normalize(ray.direction) t = 0.5 * (unit[1] + 1.0) c1 = vec3.scale((1.0, 1.0, 1.0), 1.0 - t) c2 = vec3.scale((0.5, 0.7, 1.0), t) return vec3.add(c1, c2)
def hit(self, ray, t_min, t_max): record = HitRecord() oc = vec3.subtract(ray.origin, self.center) a = vec3.squared_length(ray.direction) b = vec3.dot(oc, ray.direction) c = vec3.squared_length(oc) - self.radius**2 discriminant = b**2 - a * c if discriminant > 0: t = (-b - math.sqrt(discriminant)) / a if (t < t_max and t > t_min): record.t = t record.p = ray.point_at_time(t) record.normal = vec3.normalize( vec3.subtract(record.p, self.center)) record.material = self.material return record return None
def fromvectors(v1, v2): return fromnormals(vec3.normalize(v1), vec3.normalize(v2))
def fromnormals(n1, n2): axis, angle = vec3.normalize(vec3.cross(n1, n2)), math.acos(vec3.dot(n1, n2)) return fromaxisangle((axis, angle))
def fromvectors(v1,v2): return fromnormals(vec3.normalize(v1), vec3.normalize(v2))
def fromnormals(n1,n2): axis,angle= vec3.normalize(vec3.cross(n1, n2)), math.acos(vec3.dot(n1, n2)) return fromaxisangle((axis,angle))
def scatter(self, ray, record): reflected = vec3.reflect(vec3.normalize(ray.direction), record.normal) scattered = Ray(record.p, reflected) return scattered if vec3.dot(scattered.direction, record.normal) > 0 else None