def step(self, ext_input: np.array): if (self.cfg.run_scheme == SchemeType.Advection_Projection): self.advect(self.cfg.dt) self.externalForce(ext_input, self.cfg.dt) self.project() self.grid.subtract_gradient(self.grid.v_pair.cur, self.grid.p_pair.cur) elif (self.cfg.run_scheme == SchemeType.Advection_Reflection): # ref: https://github.com/ShaneFX/GAMES201/blob/master/HW01/Smoke3d/smoke_3D.py self.advect(self.cfg.half_dt) self.externalForce(ext_input, self.cfg.half_dt) utils.copy_ti_field(self.grid.tmp_v, self.grid.v_pair.cur) # cur_v = tmp_v = u^{~1/2}, in Fig.2 in advection-reflection solver paper self.project() self.grid.subtract_gradient(self.grid.tmp_v, self.grid.p_pair.cur) # after projection, tmp_v = u^{1/2}, cur_v = u^{~1/2} utils.reflect(self.grid.v_pair.cur, self.grid.tmp_v) self.advect(self.cfg.half_dt) self.externalForce(ext_input, self.cfg.half_dt) self.project() self.grid.subtract_gradient(self.grid.v_pair.cur, self.grid.p_pair.cur) self.render_frame()
def castRay(self, origin, direction, recursion=0): material, intersect = self.sceneIntersect(origin, direction) if material is None or recursion >= MAX_RECURSION_DEPTH: return self.currentColor # Si el rayo no golpeo nada o si llego al limite de recursion lightDir = norm(sub(self.light.position, intersect.point)) lightDistance = length(sub(self.light.position, intersect.point)) offsetNormal = mul(intersect.normal, 1.1) shadowOrigin = sub( intersect.point, offsetNormal) if dot(lightDir, intersect.normal) < 0 else sum( intersect.point, offsetNormal) shadowMaterial, shadowIntersect = self.sceneIntersect( shadowOrigin, lightDir) shadowIntensity = 0 if shadowMaterial and length(sub(shadowIntersect.point, shadowOrigin)) < lightDistance: shadowIntensity = 0.9 intensity = self.light.intensity * max( 0, dot(lightDir, intersect.normal)) * (1 - shadowIntensity) reflection = reflect(lightDir, intersect.normal) specularIntensity = self.light.intensity * (max( 0, -dot(reflection, direction))**material.spec) if material.albedo[2] > 0: reflectDir = reflect(direction, intersect.normal) reflectOrigin = sub(intersect.point, offsetNormal) if dot( reflectDir, intersect.normal) < 0 else sum( intersect.point, offsetNormal) reflectedColor = self.castRay(reflectOrigin, reflectDir, recursion + 1) else: reflectedColor = self.currentColor if material.albedo[3] > 0: refractDir = refract(direction, intersect.normal, material.refractionIndex) refractOrigin = sub(intersect.point, offsetNormal) if dot( refractDir, intersect.normal) < 0 else sum( intersect.point, offsetNormal) refractedColor = self.castRay(refractOrigin, refractDir, recursion + 1) else: refractedColor = self.currentColor diffuse = material.diffuse * intensity * material.albedo[0] specular = Color(255, 255, 255) * specularIntensity * material.albedo[1] reflected = reflectedColor * material.albedo[2] refracted = refractedColor * material.albedo[3] return diffuse + specular + reflected + refracted
def ray_trace(self, ray, depth=0): # Find nearest intersection for ray, compute reflected ray and call recursively # with depth += 1 until depth == max_depth or no intersection is found. color = np.array([0, 0, 0], dtype=np.float32) dist, obj = self.find_nearest_hit(ray) if dist is None: return color point = ray.origin + ray.dir * dist normal = obj.get_normal(point) if np.dot(-ray.dir, normal) < 0: normal = -normal lights = [] for light in self.scene.lights: dist = math.inf if type(light) == scene.point_light.PointLight: dist = np.linalg.norm(point - light.pos) if not self.is_blocked(point + normal * self.bias, light, dist): lights.append(light) color += obj.material.get_color(point, normal, ray, lights) if depth < self.max_depth: if type(obj.material) is RefBlinnMaterial or type( obj.material) is ReflectiveMaterial: color += self.ray_trace( Ray(point + normal * self.bias, None, reflect(ray.dir, normal)), depth + 1) * obj.material.ref else: kr = obj.material.fresnel(ray.dir, normal) outside = np.dot(ray.dir, normal) < 0 bias = self.bias * normal refraction_col = np.zeros(3) if kr < 1: if outside: refraction_orig = point - bias else: refraction_orig = point + bias refraction_dir = refract(ray.dir, normal, obj.material.ior) refraction_col = self.ray_trace( Ray(refraction_orig, None, refraction_dir), depth + 1) reflection_dir = reflect(ray.dir, normal) if outside: reflection_orig = point + bias else: reflection_orig = point - bias reflection_col = self.ray_trace( Ray(reflection_orig, None, reflection_dir), depth + 1) color += (reflection_col * kr + refraction_col * (1 - kr) * self.refr_att) return color
def castRay(self, origin, direction): material, intersect = self.sceneIntersect(origin, direction) if material is None: return self.currentColor lightDir = norm(sub(self.light.position, intersect.point)) lightDistance = length(sub(self.light.position, intersect.point)) offsetNormal = mul(intersect.normal, 1.1) shadowOrigin = sub(intersect.point, offsetNormal) if dot(lightDir, intersect.normal) < 0 else sum(intersect.point, offsetNormal) shadowMaterial, shadowIntersect = self.sceneIntersect(shadowOrigin, lightDir) shadowIntensity = 0 if shadowMaterial and length(sub(shadowIntersect.point, shadowOrigin)) < lightDistance: shadowIntensity = 0.9 intensity = self.light.intensity * max(0, dot(lightDir, intersect.normal)) * (1 - shadowIntensity) reflection = reflect(lightDir, intersect.normal) specularIntensity = self.light.intensity * ( max(0, -dot(reflection, direction)) ** material.spec ) diffuse = material.diffuse * intensity * material.albedo[0] specular = Color(255, 255, 255) * specularIntensity * material.albedo[1] return diffuse + specular
def calculate_intensity(self, origin, direction, intersection, dept): light_intensity = 0 specular_light_intensity = 0 if not self._options['light']: return 1, 0 for light in self._scene.lights: light_dir = (light.position - intersection.point).normalize() light_distance = (light.position - intersection.point).norm() if self._options['shadow']: shadow_origin = utils.build_origin(intersection.point, light_dir, intersection.normal) shadow_intersection = self._scene.intersect(shadow_origin, light_dir) if shadow_intersection: if (shadow_intersection.point - shadow_origin).norm() < light_distance: continue light_intensity += light.intensity * max(0, light_dir * intersection.normal) if self._options['specular_light']: reflect_scalar = -utils.reflect(-light_dir, intersection.normal) * direction reflect_scalar = max(0, reflect_scalar) specular_light_intensity += math.pow(reflect_scalar, intersection.material.specular_exponent) * light_intensity else: specular_light_intensity = 0 return light_intensity, specular_light_intensity
def scatter(self, ray, hitrec): reflected = reflect(ray.direction, hitrec.normal) if (np.dot(ray.direction, hitrec.normal) > 0.0): outward_normal = -hitrec.normal ni_over_nt = self.ref_idx cosine = self.ref_idx * np.dot(ray.direction, hitrec.normal) / ( math.sqrt(np.sum(ray.direction * ray.direction))) else: outward_normal = hitrec.normal ni_over_nt = 1.0 / self.ref_idx cosine = -np.dot(ray.direction, hitrec.normal) / (math.sqrt( np.sum(ray.direction * ray.direction))) is_refract, refracted = refract(ray.direction, outward_normal, ni_over_nt) if (is_refract): reflect_prob = schlick(cosine, self.ref_idx) else: reflect_prob = 1.0 if (random.uniform(0.0, 1.0) < reflect_prob): scattered = Ray(hitrec.p, reflected) else: scattered = Ray(hitrec.p, refracted) return True, scattered, np.array([1.0, 1.0, 1.0])
def scatter(self, info, r): normal = info['normal'] ray_inside = info['ray_inside'] p = info['P'] v = r.direc cos_theta = numpy.dot(-v, normal) sin_theta = sqrt(1 - cos_theta**2) eta_ratio = self.eta if ray_inside else 1 / self.eta if eta_ratio * sin_theta > 1.0: return Ray(p, reflect(v, normal)) if random() < schlick(cos_theta, eta_ratio): return Ray(p, reflect(v, normal)) return Ray(p, refract(v, normal, eta_ratio))
def scatter(self, info, r): normal = info['normal'] p = info['P'] v = r.direc ref_v = reflect(v, normal) + self.blur * random_unit_sphere() if numpy.dot(ref_v, normal) > 0.0: return Ray(p, ref_v) else: return None
def collides_with_player(self): """Update the velocity when a collision with the player occurs.""" if self.current_power_up == PowerUpType.CATCH: self.stick(self.player) self.bottom = self.player.top else: v = Vector(x=self.change_x, y=self.change_y) location = self.player.collision_location(self) normal = Vector(0, 1) # Determine where the ball collided to "enhance" angle of reflection if location == Player.LEFT: normal = Vector(0.196, -0.981) elif location == Player.RIGHT: normal = Vector(-0.196, -0.981) new_v = reflect(v, normal) self.change_x = new_v.x self.change_y = new_v.y # Increase the speed modifier on each collision when the # SLOW power up is picked up self.increase_speed_mod()
def extract_v(array, collumns): out = array[:, collumns] return reflect(out)
def _reflect(cls, v, normal): return utils.reflect(v, normal)