def scatter(self, r_in, rec): outward_normal = Vec3() reflected = Vec3.reflect(r_in.direction, rec["normal"]) ni_over_nt = 0.0 attenuation = Vec3(1.0, 1.0, 1.0) cosine = 0.0 if Vec3.dot(r_in.direction, rec["normal"]) > 0: outward_normal = -rec["normal"] ni_over_nt = self.ref_idx cosine = self.ref_idx * Vec3.dot( r_in.direction, rec["normal"]) / r_in.direction.length() else: outward_normal = rec["normal"] ni_over_nt = 1.0 / self.ref_idx cosine = -Vec3.dot(r_in.direction, rec["normal"]) / r_in.direction.length() scattered = Ray() reflect_prob = 0.0 refracted = Vec3.refract(r_in.direction, outward_normal, ni_over_nt) if refracted is not None: reflect_prob = schlick(cosine, self.ref_idx) else: reflect_prob = 1.0 if random() < reflect_prob: scattered = Ray(rec["p"], reflected) else: scattered = Ray(rec["p"], refracted) return attenuation, scattered
def scatter(self, r_in, rec): outward_normal = Vec3() reflected = Vec3.reflect(r_in.direction,rec["normal"]) ni_over_nt = 0.0 attenuation = Vec3(1.0,1.0,1.0) cosine = 0.0 if Vec3.dot(r_in.direction,rec["normal"]) > 0: outward_normal = -rec["normal"] ni_over_nt = self.ref_idx cosine = self.ref_idx * Vec3.dot(r_in.direction,rec["normal"])/ r_in.direction.length() else: outward_normal = rec["normal"] ni_over_nt = 1.0 / self.ref_idx cosine = -Vec3.dot(r_in.direction,rec["normal"])/ r_in.direction.length() scattered = Ray() reflect_prob = 0.0 refracted = Vec3.refract(r_in.direction,outward_normal,ni_over_nt) if refracted is not None: reflect_prob = schlick(cosine,self.ref_idx) else: reflect_prob = 1.0 if random() < reflect_prob: scattered = Ray(rec["p"],reflected) else: scattered = Ray(rec["p"],refracted) return attenuation, scattered
def hit(self,r,t_min,t_max): rec = None oc = r.origin - self.center(r.time) a = Vec3.dot(r.direction,r.direction) b = Vec3.dot(oc,r.direction) c = Vec3.dot(oc,oc) - (self.radius*self.radius) discriminant = (b*b) - (a*c) if discriminant > 0: rec = {} temp = (-b - sqrt(discriminant)) / a if t_min < temp < t_max: rec["t"] = temp rec["p"] = r.point_at_parameter(rec["t"]) rec["u"],rec["v"] =getSphereUv((rec["p"] - self.center) / self.radius) rec["normal"] = (rec["p"] - self.center(r.time)) / self.radius rec["material"] = self.material return rec temp = (-b + sqrt(discriminant)) / a if t_min < temp < t_max: rec["t"] = temp rec["p"] = r.point_at_parameter(rec["t"]) rec["u"],rec["v"] =getSphereUv((rec["p"] - self.center) / self.radius) rec["normal"] = (rec["p"] - self.center(r.time)) / self.radius rec["material"] = self.material return rec return None
def hit_sphere(center,radius,r): oc = r.origin -center a = Vec3.dot(r.direction,r.direction) b = 2.0 * Vec3.dot(oc,r.direction) c = Vec3.dot(oc,oc) - radius * radius discriminant = b*b - 4*a*c return discriminant > 0
def scatter(self, r_in,rec): reflected = Vec3.reflect(Vec3.unit_vector(r_in.direction),rec["normal"]) scattered = Ray(rec["p"],reflected + self.fuzz * Material.random_in_unit_sphere()) attenuation = self.albedo if Vec3.dot(scattered.direction,rec["normal"]) > 0: return attenuation,scattered else: return None,None
def scatter(self, r_in, rec): reflected = Vec3.reflect(Vec3.unit_vector(r_in.direction), rec["normal"]) scattered = Ray( rec["p"], reflected + self.fuzz * Material.random_in_unit_sphere()) attenuation = self.albedo if Vec3.dot(scattered.direction, rec["normal"]) > 0: return attenuation, scattered else: return None, None
def hit(self,r,t_min,t_max): rec = None oc = r.origin - self.center a = Vec3.dot(r.direction,r.direction) b = Vec3.dot(oc,r.direction) c = Vec3.dot(oc,oc) - (self.radius*self.radius) discriminant = (b*b) - (a*c) if discriminant > 0: rec = {} temp = (-b - sqrt(discriminant)) / a if t_min < temp < t_max: rec["t"] = temp rec["p"] = r.point_at_parameter(rec["t"]) rec["normal"] = (rec["p"] - self.center) / self.radius return rec temp = (-b + sqrt(discriminant)) / a if t_min < temp < t_max: rec["t"] = temp rec["p"] = r.point_at_parameter(rec["t"]) rec["normal"] = (rec["p"] - self.center) / self.radius return rec return None
def trilinear_interp(c,u,v,w): uu = u*u*(3-2*u) vv = v*v*(3-2*v) ww = w*w*(3-2*w) accum = 0.0 for i in range(2): for j in range(2): for k in range(2): weight_v= Vec3(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)) * Vec3.dot(c[i][j][k],weight_v)) return accum
def createFromVectors(v1, v2): """ Function createFromVectors expects two 3d vectors. Quat has the Sofa format i.e (x,y,z,w). Examples: >>> q = Quat.createFromVectors([1,0,0],[0,1,0]) >>> print(q) [0.,0.,0.707,0.707] """ from quat import Quat from vec3 import Vec3 from math import sqrt q = Quat() v = Vec3.cross(v1, v2) q[0:3] = v q[3] = sqrt((Vec3(v1).getNorm()**2) * (Vec3(v2).getNorm()**2)) + Vec3.dot(v1, v2) q.normalize() return q
def random_in_unit_sphere(cls): while True: p = 2.0 * Vec3(random(), random(), random()) - Vec3(1, 1, 1) if Vec3.dot(p, p) < 1.0: return p
def get_closest_point_to(self, point): n = self.get_normal() return point - (Vec3.dot(Vec3.from_to(self.origin, point), n)*n)
def random_in_unit_disk(): while True: p = 2.0 * Vec3(random(),random(),0) -Vec3(1,1,0) if Vec3.dot(p,p) < 1.0: return p
def random_in_unit_sphere(cls): while True: p = 2.0*Vec3(random(),random(),random()) - Vec3(1,1,1) if Vec3.dot(p,p) < 1.0: return p
def reflect(v_in: Vec3, normal: Vec3): return v_in - 2*v_in.dot(normal)*normal
def get_closest_point_to(self, point): l = self.direction.get_unit() return self.origin + (Vec3.dot(Vec3.from_to(self.origin, point), l)*l)
def random_in_unit_disk(): while True: p = 2.0 * Vec3(random(), random(), 0) - Vec3(1, 1, 0) if Vec3.dot(p, p) < 1.0: return p