def __init__(self, pos, at, c, cutoff, exp): self.pos = pos self.at = at self.d = normalize(sub(self.at, self.pos)) self.color = c self.cutoff = cutoff self.coscutoff = math.cos(math.radians(self.cutoff)) self.exp = exp
def get_intensity(self, pos): q = sub(self.pos, pos) dsq = dot(q, q) invlend = 1 / math.sqrt(dsq) cosangle = -dot(q, self.d) * invlend if cosangle < self.coscutoff: return (0.0, 0.0, 0.0) i = pow(dot(self.d, mul(d, -invlend)), self.exp) return mul(self.color, i * 100.0 / (99.0 + dsq))
def trace(amb, lights, scene, depth, raypos, raydir): i = scene.intersect(raypos, raydir) if i: #for ic in i: # print ic #print isect = i[0] if isect.t == Intersection.EXIT: return (0.0, 0.0, 0.0) sc, kd, ks, n = isect.primitive.get_surface(isect) c = get_ambient(sc, amb, kd) diffuse = (0.0, 0.0, 0.0) specular = (0.0, 0.0, 0.0) pos = isect.wpos normal = isect.normal for light in lights: lightdir, lightdistance = light.get_direction(pos) df = dot(normal, lightdir) if df > 0.0: poseps = add(pos, mul(lightdir, 1e-7)) i = scene.intersect(poseps, lightdir) if not i or (lightdistance and (lightdistance < i[0].distance)): ic = cmul(sc, light.get_intensity(pos)) if kd > 0.0: diffuse = add(diffuse, mul(ic, df)) if ks > 0.0: specular = add( specular, get_specular(ic, lightdir, normal, pos, raypos, n)) c = add(c, add(mul(diffuse, kd), mul(specular, ks))) if ks > 0.0 and depth > 0: refl_raydir = normalize( sub(raydir, mul(normal, 2 * dot(raydir, normal)))) poseps = add(pos, mul(refl_raydir, 1e-7)) rc = trace(amb, lights, scene, depth - 1, poseps, refl_raydir) return add(c, mul(cmul(rc, sc), ks)) else: return c else: return (0.0, 0.0, 0.0)
def intersect(self, raypos, raydir): tr = self.transform raydir = tr.inv_transform_vector(raydir) scale = 1.0 / length(raydir) raydir = mul(raydir, scale) # normalize raypos = tr.inv_transform_point(raypos) eps = 1e-15 tmin = None tmax = None p = sub((0.5, 0.5, 0.5), raypos) for i in range(3): face1, face2 = self.slabs[i] e = p[i] f = raydir[i] if abs(f) > eps: t1 = (e + 0.5) / f t2 = (e - 0.5) / f if t1 > t2: t1, t2 = t2, t1 face1, face2 = face2, face1 if tmin is None or t1 > tmin[0]: tmin = (t1, face1) if tmax is None or t2 < tmax[0]: tmax = (t2, face2) if tmin[0] > tmax[0]: return [] if tmax[0] < 0.0: return [] elif -e - 0.5 > 0.0 or -e + 0.5 < 0.0: return [] ts = [] if tmin[0] > 0.0: ts.append( Intersection(scale, tmin[0], raypos, raydir, self, Intersection.ENTRY, tmin[1])) if tmax[0] > 0.0: ts.append( Intersection(scale, tmax[0], raypos, raydir, self, Intersection.EXIT, tmax[1])) return ts
def get_specular(ic, lightdir, sn, pos, raypos, n): halfway = normalize(add(lightdir, normalize(sub(raypos, pos)))) sp = dot(sn, halfway) if sp > 0.0: return mul(ic, pow(sp, n)) return (0.0, 0.0, 0.0)
def get_direction(self, pos): d = sub(self.pos, pos) dl = length(d) return mul(d, 1.0 / dl), length(d)
def get_intensity(self, pos): d = sub(self.pos, pos) dsq = dot(d, d) return mul(self.color, 100.0 / (99.0 + dsq))