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): 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 get_direction(self, x, y): direction = (self.u * x) + (self.v * y) - (self.w * self.view_dist) return Normalize(direction)