def test_normal_point_1(self): sphere = data.Sphere(data.Point(0, 0, 0), 5, data.Color(0, 1, 0), data.Finish(.2, 1, 0, 0)) point_x = data.Point(5, 0, 0) point_y = data.Point(0, 5, 0) point_z = data.Point(0, 0, 5) vec_x = data.Vector(1, 0, 0) vec_y = data.Vector(0, 1, 0) vec_z = data.Vector(0, 0, 1) self.assertEqual(collisions.sphere_normal_at_point(sphere, point_x), vec_x) self.assertEqual(collisions.sphere_normal_at_point(sphere, point_y), vec_y) self.assertEqual(collisions.sphere_normal_at_point(sphere, point_z), vec_z)
def test_determine_diffuse_contribution(self): sphere = data.Sphere(data.Point(0, 0, 0), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05)) light = data.Light(data.Point(0, 0, 100), data.Color(1.5, 1.2, 1.3)) inter_point = data.Point(0, 0, 1) inter_list = [ ( data.Sphere(data.Point(0, 0, 102), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05)), data.Point(0, 0, 101), ) ] normal = collisions.sphere_normal_at_point(sphere, inter_point) off_pt = cast.find_pt_off_sphere(inter_point, normal) dir_vect = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt)) ray = data.Ray(off_pt, dir_vect) sphere_list = [] l_dir = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt)) l_dot_n = vector_math.dot_vector(normal, l_dir) result = cast.determine_diffuse_contribution(sphere, off_pt, light, normal, sphere_list, l_dir, l_dot_n) self.assertEqual( result[0], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[0] ) self.assertEqual( result[1], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[1] ) self.assertEqual( result[2], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[2] )
def compute_Pe( sphere_point: typing.Tuple[data.Sphere, data.Point]) -> data.Point: normal = collisions.sphere_normal_at_point(sphere_point[0], sphere_point[1]) scaled = v_math.scale_vector(normal, 0.01) Pe = v_math.translate_point(sphere_point[1], scaled) return Pe
def calculate_light_components( sphere_point: typing.Tuple[data.Sphere, data.Point], spheres_list: typing.List[data.Sphere], eye_point: data.Point, light: data.Light) -> typing.Tuple[float, float]: Pe = compute_Pe(sphere_point) normal = collisions.sphere_normal_at_point(sphere_point[0], sphere_point[1]) L_dir = v_math.normalize_vector(v_math.vector_from_to(Pe, light.pt)) L_ray = data.Ray(Pe, L_dir) for other_sphere in spheres_list: if other_sphere is not sphere_point[0]: L_ray_intersection = collisions.sphere_intersection_point( L_ray, other_sphere) if L_ray_intersection: distance_sphere = distance_between_points( Pe, L_ray_intersection) distance_light = distance_between_points(Pe, light.pt) if distance_sphere < distance_light: return (0, 0) normal_Ldir = v_math.dot_vector(normal, L_dir) if normal_Ldir > 0: specular_intensity = compute_specular_intensity( Pe, normal, L_dir, normal_Ldir, eye_point) return (normal_Ldir, specular_intensity) else: return (0, 0)
def test_cast_ray_1(self): ray = data.Ray(data.Point(0, 10, 6), data.Vector(0, 0, -2)) sphere_list = [ data.Sphere(data.Point(0, 10, -2), 3, data.Color(0, 0.5, 1.0), data.Finish(0.5, 0.4, 0.5, 0.05)), data.Sphere(data.Point(0, 10, -20), 0.5, data.Color(0, 0.3, 0.2), data.Finish(0.5, 0.4, 0.5, 0.05)), ] ambient_color = data.Color(0.25, 0.5, 0.75) light = data.Light(data.Point(-100.0, 100.0, -100.0), data.Color(1.5, 1.5, 1.5)) eye_position = data.Point(0, 0, -14) cr = cast.cast_ray(ray, sphere_list, ambient_color, light, eye_position) inter_point = collisions.sphere_intersection_point(ray, sphere_list[0]) normal = collisions.sphere_normal_at_point(sphere_list[0], inter_point) off_pt = cast.find_pt_off_sphere(inter_point, normal) l_dir = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt)) l_dot_n = vector_math.dot_vector(normal, l_dir) diffuse_list = cast.determine_diffuse_contribution( sphere_list[0], off_pt, light, normal, sphere_list, l_dir, l_dot_n ) spec_list = cast.determine_specular_contribution( l_dir, l_dot_n, normal, eye_position, off_pt, light.color, sphere_list[0].finish ) self.assertEqual( cr, data.Color( 0 + diffuse_list[0] + spec_list[0], 0.125 + diffuse_list[1] + spec_list[1], 0.375 + diffuse_list[2] + spec_list[2], ), )
def getSpecular(ray, intersection_list, light, point): closest = findClosestSphere(ray, intersection_list) csphere = closest[0] cpoint = closest[1] n_vector = collisions.sphere_normal_at_point(csphere, cpoint) scaled_vector = vector_math.scale_vector(n_vector, 0.01) p_e = vector_math.translate_point(cpoint, scaled_vector) light_vector = vector_math.vector_from_to(p_e, light.pt) L_dir = vector_math.normalize_vector(light_vector) light_dot_product = vector_math.dot_vector(n_vector, L_dir) #gets spec values n_scale = vector_math.scale_vector(n_vector, (2 * light_dot_product)) reflection = vector_math.difference_vector(L_dir, n_scale) pe_eyevec = vector_math.normalize_vector( vector_math.difference_point(p_e, point)) specularIntensity = vector_math.dot_vector(pe_eyevec, reflection) if specularIntensity > 0: sphere_spec = csphere.finish.specular sphere_rough = csphere.finish.roughness specCont_r = (light.color.r * sphere_spec) * (specularIntensity**( 1 / float(sphere_rough))) specCont_g = (light.color.g * sphere_spec) * (specularIntensity**( 1 / float(sphere_rough))) specCont_b = (light.color.b * sphere_spec) * (specularIntensity**( 1 / float(sphere_rough))) else: specCont_r = 0 specCont_g = 0 specCont_b = 0 return (specCont_r, specCont_g, specCont_b)
def test_normal_point_3(self): sphere = data.Sphere(data.Point(1, -2, 2), 3, data.Color(0, 1, 0), data.Finish(.2, 1, 0, 0)) point = data.Point(0, 0, 0) l = 3.0 vec = data.Vector(-1 / l, 2 / l, -2 / l) self.assertEqual(collisions.sphere_normal_at_point(sphere, point), vec) self.assertAlmostEqual(vector_math.length_vector(vec), 1)
def point_light_same_side(point, sphere, light): normal = collisions.sphere_normal_at_point(sphere, point) pt_light_vec = vector_math.normalize_vector( vector_math.difference_point(light.pt, point)) dot_product = vector_math.dot_vector(normal, pt_light_vec) if dot_product <= 0: return False else: return True
def cast_ray(ray, sphere_list, ambient, light, point): a = collisions.find_intersection_points(sphere_list, ray) if a == []: return data.Color(1.0, 1.0, 1.0) sphere_look = a[0] for x in a: if distance(ray.pt, x[1]) < distance(ray.pt, sphere_look[1]): sphere_look = x red = sphere_look[0].color.r * sphere_look[0].finish.ambient * ambient.r green = sphere_look[0].color.g * sphere_look[0].finish.ambient * ambient.g blue = sphere_look[0].color.b * sphere_look[0].finish.ambient * ambient.b n = collisions.sphere_normal_at_point(sphere_look[0], sphere_look[1]) pe = vector_math.translate_point(sphere_look[1], vector_math.scale_vector(n, .01)) visible_ray = data.Ray(pe, vector_math.vector_from_to(pe, light.point)) ldir = vector_math.normalize_vector(visible_ray.dir) visible = vector_math.dot_vector(ldir, n) n = collisions.sphere_normal_at_point(sphere_look[0], sphere_look[1]) ldir_dot_n = vector_math.dot_vector(ldir, n) reflection_vector = vector_math.difference_vector( vector_math.scale_vector(n, ldir_dot_n * 2), ldir) vdir = vector_math.normalize_vector(vector_math.vector_from_to(point, pe)) specular_intensity = vector_math.dot_vector(reflection_vector, vdir) if visible > 0: if collisions.find_intersection_points(sphere_list, visible_ray) == []: red += (visible * light.color.r * sphere_look[0].color.r * sphere_look[0].finish.diffuse) green += (visible * light.color.g * sphere_look[0].color.g * sphere_look[0].finish.diffuse) blue += (visible * light.color.b * sphere_look[0].color.b * sphere_look[0].finish.diffuse) if specular_intensity > 0: spec_intensity_calc = specular_intensity**( 1 / sphere_look[0].finish.roughness) red += light.color.r * sphere_look[ 0].finish.specular * spec_intensity_calc green += light.color.g * sphere_look[ 0].finish.specular * spec_intensity_calc blue += light.color.b * sphere_look[ 0].finish.specular * spec_intensity_calc return data.Color(red, green, blue)
def cast_ray(ray, sphere_list, color, light): """Find the rendered color at the nearest intersection point along ray""" nearest = closest_intersect(ray, sphere_list) if not nearest: # No intersection, return white return Color(1.0, 1.0, 1.0) point, sphere = nearest # Compute initial ambient colors r = sphere.color.r * sphere.finish.ambient * color.r g = sphere.color.g * sphere.finish.ambient * color.g b = sphere.color.b * sphere.finish.ambient * color.b # Calculate diffuse value normal = sphere_normal_at_point(sphere, point) to_light = normalize_vector(vector_from_to(point, light.pt)) l_dot = dot_vector(normal, to_light) diffuse = sphere.finish.diffuse * l_dot if diffuse < 0: diffuse = 0 else: # Check for shadows new_point = translate_point(point, scale_vector(normal, 0.01)) light_ray = Ray(new_point, to_light) shadow_intersect = closest_intersect(light_ray, sphere_list) if (shadow_intersect and length_vector_sq(vector_from_to(new_point, shadow_intersect[0])) < length_vector_sq(vector_from_to(new_point, light.pt))): diffuse = 0 # Add diffuse to existing colors r += sphere.color.r * diffuse * light.color.r g += sphere.color.g * diffuse * light.color.g b += sphere.color.b * diffuse * light.color.b # Compute specular intensity if diffuse > 0: reflection = difference_vector(to_light, scale_vector(normal, 2 * l_dot)) intensity = dot_vector(reflection, normalize_vector(ray.dir)) power = 1. / sphere.finish.roughness if intensity > 0: r += light.color.r * sphere.finish.specular * intensity ** power g += light.color.g * sphere.finish.specular * intensity ** power b += light.color.b * sphere.finish.specular * intensity ** power # Max out colors at 1.0 if r > 1: r = 1 if g > 1: g = 1 if b > 1: b = 1 return Color(r, g, b)
def get_diffuse_color(tu, light, s_list): pE = get_pe(tu) N = collisions.sphere_normal_at_point(tu[0], tu[1]) lDir = vector_math.vector_from_to(pE, light.pt) lDir = vector_math.normalize_vector(lDir) lDirection = vector_math.dot_vector(N, lDir) sI = get_specular_intensity(lDir, lDirection, N, pE, light, tu[0]) ray = data.Ray(pE, lDir) if lDirection <= 0 or collides_with_spheres(ray, s_list, pE, light): return data.Color(0, 0, 0) dif = get_diffuse(lDirection, light, tu[0], tu[0].finish.diffuse) finalColor = data.Color(sI.r + dif.r, sI.g + dif.g, sI.b + dif.b) return finalColor
def test_get_diffuse_contribution(self): sphere = data.Sphere(data.Point(0, 0, 0), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05)) light = data.Light(data.Point(0, 0, 100), data.Color(1.5, 1.2, 1.3)) inter_point = data.Point(0, 0, 1) normal = collisions.sphere_normal_at_point(sphere, inter_point) inter_list = [] off_pt = cast.find_pt_off_sphere(inter_point, normal) dir_vect = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt)) ray = data.Ray(off_pt, dir_vect) result = cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt) self.assertEqual(result[0], (vector_math.dot_vector(normal, dir_vect) * 1.5 * 0.5 * 0.5)) self.assertEqual(result[1], (vector_math.dot_vector(normal, dir_vect) * 1.2 * 0.7 * 0.5)) self.assertEqual(result[2], (vector_math.dot_vector(normal, dir_vect) * 1.3 * 0.8 * 0.5))
def get_diffuse_color(tu, light, s_list): pE = get_pe(tu) N = collisions.sphere_normal_at_point(tu[0], tu[1]) lDir = vector_math.vector_from_to(pE, light.pt) lDir = vector_math.normalize_vector(lDir) lDirection = vector_math.dot_vector(N, lDir) sI = get_specular_intensity(lDir, lDirection, N, pE, light, tu[0]) ray = data.Ray(pE, lDir) if lDirection <= 0 or collides_with_spheres(ray, s_list, pE, light): return data.Color(0,0,0) dif = get_diffuse(lDirection, light, tu[0], tu[0].finish.diffuse) finalColor = data.Color(sI.r + dif.r, sI.g + dif.g, sI.b + dif.b) return finalColor
def find_specular_intensity(spherepair, light, eye_point, l_dot_n): light_dir = vector_math.normalize_vector(vector_math.difference_point( light.pt, spherepair[1])) sphere_normal = collisions.sphere_normal_at_point(spherepair[0], spherepair[1]) reflection_vector = vector_math.difference_vector(light_dir, vector_math.scale_vector(sphere_normal, 2 * l_dot_n)) view_dir = vector_math.normalize_vector(vector_math.difference_point( spherepair[1], eye_point)) specular_intensity = vector_math.dot_vector(view_dir, reflection_vector) return specular_intensity
def cast_ray(ray,sphere_list,ambient_color,light,eye_position): inter_list = collisions.find_intersection_points(sphere_list, ray) if inter_list != []: mindex = 0 for i in range(1,len(inter_list)): if (distance(ray.pt,inter_list[i][1]) < distance(ray.pt,inter_list[mindex][1])): mindex = i result_sphere = inter_list[mindex][0] inter_point = inter_list[mindex][1] sphere_color = result_sphere.color sphere_finish = result_sphere.finish sphere_normal = collisions.sphere_normal_at_point(result_sphere, inter_point) pt_off_sphere = find_pt_off_sphere(inter_point,sphere_normal) l_dir = vector_math.normalize_vector( vector_math.vector_from_to(pt_off_sphere, light.pt)) l_dot_n = vector_math.dot_vector(sphere_normal,l_dir) ray_off_to_l = data.Ray(pt_off_sphere,l_dir) inter_list = collisions.find_intersection_points(sphere_list,ray_off_to_l) diffuse_list = determine_diffuse_contribution(result_sphere, pt_off_sphere, light,sphere_normal, sphere_list,l_dir, l_dot_n,ray_off_to_l, inter_list) spec_intensity = determine_specular_contribution(l_dir,l_dot_n, sphere_normal, eye_position, pt_off_sphere, light, result_sphere.finish, ray_off_to_l,inter_list) result_r = ((sphere_color.r * sphere_finish.ambient * ambient_color.r) + diffuse_list[0] + spec_intensity[0]) result_g = ((sphere_color.g * sphere_finish.ambient * ambient_color.g) + diffuse_list[1] + spec_intensity[1]) result_b = ((sphere_color.b * sphere_finish.ambient * ambient_color.b) + diffuse_list[2] + spec_intensity[2]) return data.Color(result_r,result_g,result_b) else: return ambient_color
def cast_ray(ray, sphere_list, ambient_color, light, eye_position): inter_list = collisions.find_intersection_points(sphere_list, ray) if inter_list != []: mindex = 0 for i in range(1, len(inter_list)): if (distance(ray.pt, inter_list[i][1]) < distance( ray.pt, inter_list[mindex][1])): mindex = i result_sphere = inter_list[mindex][0] inter_point = inter_list[mindex][1] sphere_color = result_sphere.color sphere_finish = result_sphere.finish sphere_normal = collisions.sphere_normal_at_point( result_sphere, inter_point) pt_off_sphere = find_pt_off_sphere(inter_point, sphere_normal) l_dir = vector_math.normalize_vector( vector_math.vector_from_to(pt_off_sphere, light.pt)) l_dot_n = vector_math.dot_vector(sphere_normal, l_dir) ray_off_to_l = data.Ray(pt_off_sphere, l_dir) inter_list = collisions.find_intersection_points( sphere_list, ray_off_to_l) diffuse_list = determine_diffuse_contribution( result_sphere, pt_off_sphere, light, sphere_normal, sphere_list, l_dir, l_dot_n, ray_off_to_l, inter_list) spec_intensity = determine_specular_contribution( l_dir, l_dot_n, sphere_normal, eye_position, pt_off_sphere, light, result_sphere.finish, ray_off_to_l, inter_list) result_r = ( (sphere_color.r * sphere_finish.ambient * ambient_color.r) + diffuse_list[0] + spec_intensity[0]) result_g = ( (sphere_color.g * sphere_finish.ambient * ambient_color.g) + diffuse_list[1] + spec_intensity[1]) result_b = ( (sphere_color.b * sphere_finish.ambient * ambient_color.b) + diffuse_list[2] + spec_intensity[2]) return data.Color(result_r, result_g, result_b) else: return ambient_color
def getDiffuse(ray, intersection_list, sphere_list, light): closest = findClosestSphere(ray, intersection_list) csphere = closest[0] cpoint = closest[1] normalVec = collisions.sphere_normal_at_point(csphere, cpoint) scaled_vector = vector_math.scale_vector(normalVec, 0.01) p_e = vector_math.translate_point(cpoint, scaled_vector) light_vector = vector_math.vector_from_to(p_e, light.pt) L_dir = vector_math.normalize_vector(light_vector) ldotProduct = vector_math.dot_vector(normalVec, L_dir) light_ray = data.Ray(p_e, L_dir) light_intersections = collisions.find_intersection_points( sphere_list, light_ray) light_distance = vector_math.length_vector(light_vector) if_diffuse = True if ldotProduct > 0: if light_intersections != []: for spheres_and_points in light_intersections: point = spheres_and_points[1] difference_lengths = vector_math.length_vector( vector_math.difference_point(point, p_e)) if difference_lengths < light_distance: if_diffuse = False else: if_diffuse = False if if_diffuse: lClr_r = light.color.r lClr_g = light.color.g lClr_b = light.color.b sp_r = csphere.color.r sp_g = csphere.color.g sp_b = csphere.color.b diff_r = ldotProduct * lClr_r * sp_r * csphere.finish.diffuse diff_g = ldotProduct * lClr_g * sp_g * csphere.finish.diffuse diff_b = ldotProduct * lClr_b * sp_b * csphere.finish.diffuse else: diff_r = 0 diff_g = 0 diff_b = 0 return (diff_r, diff_g, diff_b)
def comp(sphere_list,inter,light,sphere,int,eye_point): n = collisions.sphere_normal_at_point(sphere,int) scaled_normal = vector_math.scale_vector(n,.01) Pe = vector_math.translate_point(inter[0][1],scaled_normal) vr_light = vector_math.vector_from_to(Pe,light.pt) L_dir = vector_math.normalize_vector(vr_light) dot_product = vector_math.dot_vector(n,L_dir) reflection_vr = vector_math.difference_vector(L_dir,vector_math.scale_vector(n,(2 * dot_product))) V_dir = vector_math.normalize_vector(vector_math.vector_from_to(eye_point,Pe)) intensity = vector_math.dot_vector(reflection_vr,V_dir) ray = data.Ray(Pe,L_dir) inter2 = collisions.find_intersection_points(sphere_list,ray) if dot_product>0 and inter2 == []: diff_r = sphere.color.r*sphere.finish.diffuse*dot_product*light.color.r diff_g = sphere.color.g*sphere.finish.diffuse*dot_product*light.color.g diff_b = sphere.color.b*sphere.finish.diffuse*dot_product*light.color.b spec_r = light.color.r*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness)) spec_g = light.color.g*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness)) spec_b = light.color.b*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness)) return data.Color(diff_r,diff_g,diff_b),data.Color(spec_r,spec_g,spec_b) else : return data.Color(0,0,0), data.Color(0,0,0)
def test_sphere_normal_at_point(self): sphere = data.Sphere(data.Point(1, 1, 1), 1) point = data.Point(0, 0, 0) normalvector = collisions.sphere_normal_at_point(sphere, point) self.assertTrue(id(normalvector), 4379149376)
def test_sphere_normal_at_point1(self): sphere = data.Sphere(data.Point(3, 1, 4), 6) point = data.Point(0, 1, 0) normalvector = collisions.sphere_normal_at_point(sphere, point) self.assertTrue(id(normalvector), 4379198528)
def get_pe(tu): vector = collisions.sphere_normal_at_point(tu[0], tu[1]) sVector = vector_math.scale_vector(vector, .01) scaledPoint = vector_math.translate_point(tu[1], sVector) return scaledPoint
def test_normal_point_2(self): sphere = data.Sphere(data.Point(1, 1, 1), math.sqrt(3), data.Color(0, 1, 0), data.Finish(.2, 1, 0, 0)) point = data.Point(2, 2, 2) vec = data.Vector(1 / math.sqrt(3), 1 / math.sqrt(3), 1 / math.sqrt(3)) self.assertEqual(collisions.sphere_normal_at_point(sphere, point), vec)
def test_sphere_normal_at_point2(self): sphere8 = data.Sphere(data.Point(5, 10, 15), 10, data.Color(1.0, 1.0, 1.0)) point11 = data.Point(6, 12, 13) normalize_vector2 = data.Vector(0.3333333333333, 0.6666666666667, -0.66666666666667) self.assertEqual(collisions.sphere_normal_at_point(sphere8, point11), normalize_vector2)
def test_sphere_normal_at_point1(self): sphere7 = data.Sphere(data.Point(0,0,0), 1, data.Color(1.0, 1.0, 1.0)) point10 = data.Point(0,1,0) normalize_vector1 = data.Vector(0,1,0) self.assertEqual(collisions.sphere_normal_at_point(sphere7, point10), normalize_vector1)
def cast_ray(ray, sphere_list, ambient_color, light, eye_point): reslist = collisions.find_intersection_points(sphere_list, ray) if reslist == []: return data.Color(1, 1, 1) closest_sphere_pair = find_closest_sphere(ray.pt, reslist) sphere_color = closest_sphere_pair[0].color l_dot_n = vector_math.dot_vector( collisions.sphere_normal_at_point(closest_sphere_pair[0], closest_sphere_pair[1]), vector_math.normalize_vector(vector_math.difference_point(light.pt, closest_sphere_pair[1]))) specular_intensity = find_specular_intensity(closest_sphere_pair, light, eye_point, l_dot_n) ambient_component = find_ambient_component(closest_sphere_pair[0], ambient_color) if specular_intensity > 0 and light_hits_point(closest_sphere_pair, sphere_list, light): diffuse_component = find_diffuse_component(l_dot_n, light, closest_sphere_pair[0]) specular_component = find_specular_component(light, closest_sphere_pair[0], specular_intensity) newr = specular_component.r + diffuse_component.r + ambient_component.r newg = specular_component.g + diffuse_component.g + ambient_component.g newb = specular_component.b + diffuse_component.b + ambient_component.b pixelcolor = data.Color(newr, newg, newb) pixelcolor = fix_specular_color(pixelcolor, ambient_component, diffuse_component) elif light_hits_point(closest_sphere_pair, sphere_list, light): diffuse_component = find_diffuse_component(l_dot_n, light, closest_sphere_pair[0]) newr = diffuse_component.r + ambient_component.r newg = diffuse_component.g + ambient_component.g newb = diffuse_component.b + ambient_component.b pixelcolor = data.Color(newr, newg, newb) pixelcolor = fix_color_issues(pixelcolor, ambient_component) # if color is past max/min, sets it to the max/min else: # light doesn't hit ray newr = ambient_component.r newg = ambient_component.g newb = ambient_component.b pixelcolor = data.Color(newr, newg, newb) pixelcolor = fix_color_issues(pixelcolor, ambient_component) return pixelcolor
def test_sphere_2(self): sphere = data.Sphere(data.Point(1, 0, 0), 1) point = data.Point(0, 0, 0) result = data.Vector(-1, 0, 0) self.assertEqual(collisions.sphere_normal_at_point(sphere, point) == result, True) pass
def test_find_pt_off_sphere(self): sphere = data.Sphere(data.Point(0, 0, 0), 1, data.Color(0, 0, 0), data.Finish(0.5, 0.5, 0.5, 0.05)) point = data.Point(0, 0, 1) normal = collisions.sphere_normal_at_point(sphere, point) off_pt = cast.find_pt_off_sphere(point, normal) self.assertEqual(off_pt, data.Point(0, 0, 1.01))
def test_find_pt_off_sphere_again(self): sphere = data.Sphere(data.Point(1, 6, 2), 2, data.Color(1, 1, 1), data.Finish(0.2, 0.7, 0.5, 0.05)) point = data.Point(1, 8, 2) normal = collisions.sphere_normal_at_point(sphere, point) off_pt = cast.find_pt_off_sphere(point, normal) self.assertEqual(off_pt, data.Point(1, 8.01, 2))
def find_point_near_sphere(sphere, point): normal_vector = collisions.sphere_normal_at_point(sphere, point) translate_vec = vector_math.scale_vector(normal_vector, 0.01) return vector_math.translate_point(point, translate_vec)
def test_sphere_normal_at_point_3(self): sphere = data.Sphere(data.Point(2, 32, -8), 7, data.Color(120, 130, 140), data.Finish(0.5, 0.4, 0.5, 0.05)) point = data.Point(2, 32 - math.sqrt(29), -8 - math.sqrt(20)) snap = collisions.sphere_normal_at_point(sphere, point) self.assertEqual(snap, data.Vector(0, -math.sqrt(29) / 7.0, -math.sqrt(20) / 7.0))
def test_sphere_normal_at_point_2(self): sphere = data.Sphere(data.Point(0, 3, 4), 5, data.Color(0.2, 0.2, 0.2), data.Finish(0.5, 0.4, 0.5, 0.05)) point = data.Point(0, 0, 0) snap = collisions.sphere_normal_at_point(sphere, point) self.assertEqual(snap, data.Vector(0, -3 / 5.0, -4 / 5.0))
def test_sphere_normal_at_pont_2(self): s = data.Sphere(data.Point(0, 0, 0), 5) p = data.Point(0, 0, 5) normalized = data.Vector(0, 0, 1) self.assertEqual(collisions.sphere_normal_at_point(s, p), normalized)
def test_sphere_normal_at_point4(self): sphere = data.Sphere(data.Point(-7, -9, -11), -6, data.Color(1.0, 1.0, 1.0)) point = data.Point(-4, -3, -2) normalize_vector = data.Vector(0.2672612419, 0.5345224838, 0.8017837257) self.assertEqual(collisions.sphere_normal_at_point(sphere, point), normalize_vector)
def test_sphere_normal_at_point1(self): sphere1 = data.Sphere(data.Point(0, 0, 0), 1) #This one should go left self.assertEqual( collisions.sphere_normal_at_point(sphere1, data.Point(-1, 0, 0)), data.Vector(-1, 0, 0))
def test_sphere_normal_at_point3(self): sphere = data.Sphere(data.Point(3,3,3), 3, data.Color(1.0, 1.0, 1.0)) point = data.Point(5,5,5) normalize_vector = data.Vector(0.5773502692, 0.5773502692, 0.5773502692) self.assertEqual(collisions.sphere_normal_at_point(sphere, point), normalize_vector)
def test_sphere_normal_at_point2(self): sphere2 = data.Sphere(data.Point(1, 2, 0), 1) #This should go up self.assertEqual( collisions.sphere_normal_at_point(sphere2, data.Point(1, 1, 0)), data.Vector(0, -1, 0))
def test_sphere_normal_at_point(self): sphere = data.Sphere(data.Point(0, 0, 0), 5, data.Color(0.22, 0.23, 0.24), data.Finish(0.5, 0.4, 0.5, 0.05)) point = data.Point(0, 0, 5) snap = collisions.sphere_normal_at_point(sphere, point) self.assertEqual(snap, data.Vector(0, 0, 1))
def cast_ray(ray, sphere_list, light = light_obj, ambient = data.Color(), eye_point = data.Point(0, 0, -14)): # intersections contains a list of tuples of spheres and points, ex: [(Sphere_1, Point_1), (Sphere_2, Point_2), ...] intersections = collisions.find_intersection_points(sphere_list, ray) if len(intersections) == 0: return data.Color(1.0, 1.0, 1.0) else: # initializing variable that stores the index and the distance of the tuple with the smallest distance index_of_nearest_sphere = 0 distance_of_nearest_sphere = vector_math.distance_between(intersections[0][1], ray.pt) # loop through all_intersection_point and find the index of the tuple that contains the sphere & intersection with the smallest distance from ray's point for index in range(0, len(intersections)): distance_between_points = vector_math.distance_between(intersections[index][1], ray.pt) if distance_between_points < distance_of_nearest_sphere: index_of_nearest_sphere = index distance_of_nearest_sphere = distance_between_points # storing the sphere and intersection point in to variables for later usage nearest_sphere = intersections[index_of_nearest_sphere][0] nearest_intersection = intersections[index_of_nearest_sphere][1] # ==== color calculation based on ambient light, diffusion, light color and location ==== # Impricision of floats can create collision issues with the sphere where the point lies when using the computed intersection # A point "pe" that is 0.01 above te intersection point will be used instead sphere_normal_vector = collisions.sphere_normal_at_point(nearest_sphere, nearest_intersection) pe_translate_direction_vector = vector_math.scale_vector(sphere_normal_vector, 0.01) # new point PE is now found pe = vector_math.translate_point(nearest_intersection, pe_translate_direction_vector) # === determine whether diffusivity is applicable -- determine if there are any obstruction of light vectors === # comput vector from pe to light point then compute normalized vector from pe to to light point l_dir = vector_math.normalize_vector(vector_math.vector_from_to(pe, light.pt)) n_dot_l_dir = vector_math.dot_vector(sphere_normal_vector, l_dir) # === computing the specular_intensity === reflection_vector = vector_math.difference_vector(l_dir ,vector_math.scale_vector(sphere_normal_vector, 2 * n_dot_l_dir)) #creating the direction vector that points from eye_point to pe v_dir = vector_math.normalize_vector(vector_math.vector_from_to(eye_point, pe)) #Vdir # specular_intensity is defined to be the dot product of reflection_vector and the direction vector from eye_point to pe specular_intensity = vector_math.dot_vector(v_dir, reflection_vector) ambient_color = compute_ambient_color(nearest_sphere, ambient) if n_dot_l_dir > 0: ray_to_point = data.Ray(pe,l_dir) inter = collisions.find_intersection_points(sphere_list, ray_to_point) if len(inter) == 0: diffuse_color = compute_diffuse_color(n_dot_l_dir, light, intersections[index_of_nearest_sphere][0]) if specular_intensity > 0: specular_color = compute_specular_color(light, nearest_sphere, specular_intensity) return add_color(add_color(specular_color, diffuse_color), ambient_color) else: return add_color(diffuse_color, ambient_color) else: return ambient_color elif specular_intensity > 0: specular_color = compute_specular_color(light, nearest_sphere, specular_intensity) return add_color(specular_color, ambient_color) else: return ambient_color