def intersect(self, ray): r = Normalize(ray.d) # Checando se o triangulo e o raio são paralelos if Dot(r, self.normal) == 0.0: # Raio nao intersecta o triangulo hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal) ray_dir = Normalize(ray.d) # Calculando o ponto que pode está no plano do triangulo t = Dot(self.normal, (self.A - ray.o)) / Dot(ray_dir, self.normal) hit_point = ray.get_hitpoint(t) if t < 0.0001: # Raio nao intersecta o triangulo hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal) # Checando se o Ponto está dentro do triangulo # Inside-OutSide Test vectorAB = self.B - self.A; vectorBC = self.C - self.B; vectorCA = self.A - self.C; C0 = hit_point - self.A C1 = hit_point - self.B C2 = hit_point - self.C if (Dot(self.normal, Cross(vectorAB, C0)) > 0 and Dot(self.normal, Cross(vectorBC, C1)) > 0 and Dot(self.normal, Cross(vectorCA, C2))) > 0: #print("Acertou: " + str (vectorAB)) hit = True distance = t hit_point = ray.get_hitpoint(t) return (hit, distance, hit_point, self.normal) # tuple if (Dot(self.normal, Cross(vectorAB, C0)) < 0 and Dot(self.normal, Cross(vectorBC, C1)) < 0 and Dot(self.normal, Cross(vectorCA, C2))) < 0: #print("Acertou") hit = True distance = t hit_point = ray.get_hitpoint(t) return (hit, distance, hit_point, self.normal) # tuple # Didn't hit the triangule hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal)
def trace_ray(self, ray, depth): difuso = BLACK especular = BLACK # Checando interseções com cada objeto dist = 100 hit = False objeto = 1 hit_point = Vector3D(0.0, 0.0, 0.0) normal = Vector3D(0.0, 0.0, 0.0) for obj in self.obj_list: inter = obj.intersect(ray) tmp_hit = inter[0] distance = inter[1] if tmp_hit and distance < dist: dist = distance objeto = obj hit = tmp_hit hit_point = inter[2] normal = inter[3] if hit: ## Se o raio bateu no objeto calculamos a cor do ponto if isinstance(objeto, Light): return objeto.color else: result = local_color(objeto, normal, ray, self.ambient) else: return self.background # Calculando os Raios Secúndarios ktot = obj.kd + obj.ks + obj.kt aleatorio = random.random()*ktot if depth > 0: if aleatorio < obj.kd: ## Raio Difuso x = random.random() y = random.random() dir = random_direction(x, y, normal) new_ray = Ray(hit_point, Normalize(dir)) difuso = self.trace_ray(new_ray, depth - 1) elif aleatorio < obj.kd + obj.ks: # ## Raio especular L = Normalize(flip_direction(ray.d)) N = objeto.normal R = (N * (Dot(N, L)) - L) * 2.0 new_ray = Ray(hit_point, Normalize(R)) especular = self.trace_ray(new_ray, depth - 1) else: ## Raio Transmitido pass return result + difuso*objeto.trans_difusa + especular*objeto.trans_especular
def __init__(self, eye_point, focal_point, view_distance, up_vector, image_height, image_width, samples_per_pixel): self.eye = eye_point self.focal = focal_point self.view_dist = view_distance self.up = up_vector self.height = image_height self.width = image_width self.spp = samples_per_pixel # setup orthonormal basis #####default values self.u = Vector3D(-1.0, 0.0, 0.0) self.v = Vector3D(0.0, 1.0, 0.0) self.w = Vector3D(0.0, 0.0, -1.0) self.compute_uvw() # create empty image array self.image_array = array.array('B', [0] * (image_width * image_height * 3))
def photon_ray(self, ray, depth): # Checando interseções com cada objeto dist = 100 hit = False objeto = 1 hit_point = Vector3D(0.0, 0.0, 0.0) normal = Vector3D(0.0, 0.0, 0.0) for n in self.numeroPhotons: for obj in self.obj_list: # setado com os valores da fonte de luz para o primeiro caso if self.depth == 4: inter = obj.intersect(-0.9100, 3.8360 - 23.3240), (0.0, -1.0, 0.0) else: inter = obj.intersect(ray) tmp_hit = inter[0] distance = inter[1] if tmp_hit and distance < dist: dist = distance objeto = obj hit = tmp_hit hit_point = inter[2] normal = inter[3] if hit: ## Se o raio bateu no objeto adicionamos o photon a estrutura de dados R1 = uniform(0.0, 1.0) R2 = uniform(0.0, 1.0) direcaoPhi = 1 / cos(sqrt(R1)) direcaoTheta = 2 * pi * R2 R = 1.0 T = 1.0 self.photons_list[self.contador] = Photon( hit_point, R * 1.0 / self.numeroPhotons, T * 1.0 / self.numeroPhotons, direcaoPhi, direcaoTheta) self.contador = self.contador + 1
def compute_uvw(self): # w self.w = self.eye - self.focal self.w = Normalize(self.w) # u self.u = Cross(self.up, self.w) self.u = Normalize(self.u) # v self.v = Cross(self.w, self.u) self.v = Normalize(self.v) # check for singularity. if conditions met, camera orientations are hardcoded # camera looking straight down if (self.eye.x == self.focal.x and self.eye.z == self.focal.z and self.focal.y < self.eye.y): self.u = Vector3D(0.0, 0.0, 1.0) self.v = Vector3D(1.0, 0.0, 0.0) self.w = Vector3D(0.0, 1.0, 0.0) # camera looking straight up if (self.eye.x == self.focal.x and self.eye.z == self.focal.z and self.focal.y > self.eye.y): self.u = Vector3D(1.0, 0.0, 0.0) self.v = Vector3D(0.0, 0.0, 1.0) self.w = Vector3D(0.0, -1.0, 0.0)
def intersect(self, ray): d = ray.d - ray.o dx = d[0] dy = d[1] dz = d[2] x0 = ray.o[0] y0 = ray.o[1] z0 = ray.o[2] acoef = 2 * self.f * dx * dz + 2 * self.e * dy * dz + self.c * dz * dz + self.b * dy * dy + self.a * dx * dx + 2 * d * dx * dy bcoef = (2 * self.b * y0 * dy + 2 * self.a * x0 * dx + 2 * self.c * z0 * dz) + \ (2 * self.h * dy + 2 * self.g * dx + 2 * self.j * dz + 2 * d * x0 * dy) + \ (2 * self.e * y0 * dz + 2 * self.e * z0 * dy + 2 * d * y0 * dx) + \ (2 * self.f * x0 * dz + 2 * self.f * z0 * dx) ccoef = (self.a * x0 * x0 + 2 * self.g * x0 + 2 * self.f * x0 * z0 + self.b * y0 * y0) + \ (2 * self.e * y0 * z0 + 2 * d * x0 * y0 + self.c * z0 * z0 + 2 * self.h * y0) + \ (2 * self.j * z0 + self.k) ## The following was modified by David J. Brandow to allow for planar ## quadrics if 1.0 + acoef == 1.0: if 1.0 + bcoef == 1.0: hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal) t = (-ccoef) / (bcoef) else: disc = bcoef * bcoef - 4 * acoef * ccoef if 1.0 + disc < 1.0: hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal) root = sqrt(disc) t = (-bcoef - root) / (acoef + acoef) if t < 0.0: t = (-bcoef + root) / (acoef + acoef) if (t < 0.001): hit = False distance = 0.0 hit_point = Vector3D(0.0, 0.0, 0.0) return (hit, distance, hit_point, self.normal) hit_point = ray.get_hitpoint(t) normal = hit_point - Vector3D(self.a, self.b, self.c) return (True, t, hit_point, normal)
elif line_type in obj_types_list: new_objs_list = (read(line_type, values)) obj_list = obj_list + new_objs_list elif line_type in prop_types_list: prop_dict[line_type] = (read(line_type, values)) else: print("Tipo não encontrado") print(line_type) FILENAME = str(prop_dict['output']) #print("Lista de objetos: ", obj_list) #print("Lista de propriedades: ", prop_dict) #Create Camera eye = Vector3D(prop_dict['eye'][0], prop_dict['eye'][1], prop_dict['eye'][2]) #higher z = more narrow view focal = Vector3D(0.0, 0.0, 0.0) view_distance = 1000 up = Vector3D(0.0, 1.0, 0.0) height = int(prop_dict['size'][0]) width = int(prop_dict['size'][1]) spp = int(prop_dict['npaths']) cam = Camera(eye, focal, view_distance, up, height, width, spp) # Realiza o path tracing pathTracer = PathTraceIntegrator() pathTracer.obj_list = obj_list cam.render(pathTracer, FILENAME, int(prop_dict["deepth"]), float(prop_dict["tonemapping"])) #-------------------------------------------------Temporary GUI