def sphere_intersection_point(ray, sphere): a = vector_math.dot_vector(ray.dir, ray.dir) b = 2 * vector_math.dot_vector( ray.dir, vector_math.difference_point(ray.pt, sphere.center)) c = vector_math.dot_vector( vector_math.difference_point(ray.pt, sphere.center), vector_math.difference_point(ray.pt, sphere.center)) - (sphere.radius** 2) d = discriminant(a, b, c) if d < 0: return None elif d == 0: t = solve_quadratic(a, b, c) if t > 0: return point_along_ray(ray, t) else: return None elif d > 0: t1 = solve_quadratic(a, b, c) t2 = solve_quadratic_2(a, b, c) if t1 > 0 and t2 > 0: return point_along_ray(ray, min(t1, t2)) elif xor(t1 > 0, t2 > 0): return point_along_ray(ray, max(t1, t2)) elif t1 == 0 and t2 == 0: return ray.pt else: return None else: return "something went wrong"
def sphere_intersection_point(ray,sphere): a = vector_math.dot_vector(ray.dir, ray.dir) b = (2 * (vector_math.dot_vector(vector_math.difference_point(ray.pt, sphere.center), ray.dir))) c = vector_math.dot_vector(vector_math.difference_point(ray.pt, sphere.center), (vector_math.difference_point(ray.pt, sphere.center))) - sphere.radius**2 d = b**2 - 4*a*c if d < 0: return None if d == 0: t1 = (-b + math.sqrt(b**2 - 4*a*c)) / (2*a) if t1 > 0: x = (t1 * ray.dir.x) + ray.pt.x y = (t1 * ray.dir.y) + ray.pt.y z = (t1 * ray.dir.z) + ray.pt.z return data.Point(x,y,z) else: return None if d > 0: t1 = (-b + math.sqrt(b**2 - 4*a*c)) / (2*a) t2 = (-b - math.sqrt(b**2 - 4*a*c)) / (2*a) if t2 < 0 and t1 < 0: return None elif t2 < 0: x = (t1 * ray.dir.x) + ray.pt.x y = (t1 * ray.dir.y) + ray.pt.y z = (t1 * ray.dir.z) + ray.pt.z return data.Point(x,y,z) else: x = (t2 * ray.dir.x) + ray.pt.x y = (t2 * ray.dir.y) + ray.pt.y z = (t2 * ray.dir.z) + ray.pt.z return data.Point(x,y,z)
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 sphere_intersection_point(ray,sphere): def point_t(t): return vector_math.translate_point(ray.pt, vector_math.scale_vector(ray.dir,t)) diff_pt = vector_math.difference_point(ray.pt,sphere.center) a = vector_math.dot_vector(ray.dir, ray.dir) b = vector_math.dot_vector(vector_math.scale_vector(diff_pt,2), ray.dir) c = vector_math.dot_vector(diff_pt,diff_pt) - sphere.radius ** 2 disc = b ** 2 - 4 * a * c if disc < 0: return None elif disc == 0: t3 = (-b / (2 * a)) if t3 >= 0: return point_t(t3) else: return None else: disc_root = math.sqrt(disc) t1 = (-b + disc_root) / (2 * a) t2 = (-b - disc_root) / (2 * a) if t1 >= 0 and t2 >= 0: return point_t(min(t1,t2)) elif t1 < 0 and t2 < 0: return None else: if t1 >= 0: return point_t(t1) elif t2 >= 0: return point_t(t2)
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 cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list, ambient, light, file_name): # not certain about the file type of the image file here, I put .txt for now image_file = open(file_name, "w") num_of_pixel_x = (max_x - min_x) / float(width) num_of_pixel_y = (max_y - min_y) / float(height) #print("P3") #print(str(width), str(height)) #print("255") image_file.write("P3\n") image_file.write(str(width) + " " + str(height) + "\n") image_file.write("255\n") #print("before going in double for loop in cast_all_rays") count = 0 for row in range(height): #print("in row loop") y = max_y - row * num_of_pixel_y for col in range(width): x = min_x + col * num_of_pixel_x # z-coordinate is constant there for z = 0.0 for all point on image plane point_on_image_plane = data.Point(x, y, 0.0) ray_direction_vector = vector_math.difference_point(point_on_image_plane, eye_point) constructed_ray = data.Ray(eye_point, ray_direction_vector) pixel_color = cast_ray(constructed_ray, sphere_list, light, ambient, eye_point) #print('{:4d}{:4d}{:4d}'.format(min(int(pixel_color.r * 255), 255), min(int(pixel_color.g * 255), 255), min(int(pixel_color.b * 255), 255)), end=' ') image_file.write('{0:4d}{1:4d}{2:4d}'.format(min(int(pixel_color.r * 255), 255), min(int(pixel_color.g * 255), 255), min(int(pixel_color.b * 255), 255))) count += 1 print("loop time " + str(count)) image_file.write("\n") #print("loop time " + str(count)) image_file.close()
def sphere_intersection_point(ray, sphere): def point_t(t): return vector_math.translate_point( ray.pt, vector_math.scale_vector(ray.dir, t)) diff_pt = vector_math.difference_point(ray.pt, sphere.center) a = vector_math.dot_vector(ray.dir, ray.dir) b = vector_math.dot_vector(vector_math.scale_vector(diff_pt, 2), ray.dir) c = vector_math.dot_vector(diff_pt, diff_pt) - sphere.radius**2 disc = b**2 - 4 * a * c if disc < 0: return None elif disc == 0: t3 = (-b / (2 * a)) if t3 >= 0: return point_t(t3) else: return None else: disc_root = math.sqrt(disc) t1 = (-b + disc_root) / (2 * a) t2 = (-b - disc_root) / (2 * a) if t1 >= 0 and t2 >= 0: return point_t(min(t1, t2)) elif t1 < 0 and t2 < 0: return None else: if t1 >= 0: return point_t(t1) elif t2 >= 0: return point_t(t2)
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list, color, light): w = math.fabs(min_x) + math.fabs(max_x) changeX = w / width xval = [(min_x + (vals * changeX)) for vals in range(width)] yheight = math.fabs(min_y) + math.fabs(max_y) changeY = yheight / height yval = [(max_y - (vals * changeY)) for vals in range(height)] xstep = (max_x - min_x) / float(width) ystep = (max_y - min_y) / float(height) print 'P3' print str(width) + ' ' + str(height) print '255' for y in yval: for x in xval: ray = data.Ray( eye_point, vector_math.difference_point(data.Point(x, y, 0), eye_point)) finalColors = cast_ray(ray, sphere_list, color, light, eye_point) if finalColors: print str(int(finalColors.r * 255)) + ' ' + str( int(finalColors.g * 255)) + ' ' + str( int(finalColors.b * 255)) else: print '255 255 255'
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list,ambient_color,light): delta_x = (max_x - min_x) / float(width) delta_y = (max_y - min_y) / float(height) f = open('image.ppm','w') f.write('P3 ' + str(width) + ' ' + str(height) + ' ' + str(255) + ' ') for y in reverse_frange(min_y,max_y,delta_y): for x in frange(min_x,max_x,delta_x): cr_out = cast_ray(data.Ray(eye_point, vector_math.difference_point(data.Point(x,y,0), eye_point)), sphere_list, ambient_color, light, eye_point) if cr_out != data.Color(1.0,1.0,1.0): ppm_sphere_color = float_to_ppm(cr_out) f.write(str(ppm_sphere_color.r)+' '+ str(ppm_sphere_color.g)+' '+ str(ppm_sphere_color.b)+' ') else: f.write(str(255)+' '+ str(255)+' '+ str(255)+' ') f.close()
def sphere_intersection_point(theRay, theSphere): dotvector_of_raydir_sqr = vector_math.dot_vector(theRay.dir, theRay.dir) diffpoint_of_raypt_sphcen = vector_math.difference_point( theRay.pt, theSphere.center) dotvector_of_raydir_diffpoint = vector_math.dot_vector( diffpoint_of_raypt_sphcen, theRay.dir) dotvector_of_diffpoint_sqr = vector_math.dot_vector( diffpoint_of_raypt_sphcen, diffpoint_of_raypt_sphcen) A = dotvector_of_raydir_sqr #(theRay.dir * theRay.dir) B = dotvector_of_raydir_diffpoint * 2 #(2 * (theRay.pt - theSphere.center) * theRay.dir) C = dotvector_of_diffpoint_sqr - theSphere.radius**2 #(((theRay.pt - theSphere.center) * (theRay.pt - theSphere.center)) - theSphere.radius ** 2) D = B**2 - 4 * A * C #discriminant if D < 0: #D < 0 means no real roots, thus sphere does not intersect with ray return 'None' elif D == 0: t = (-B + math.sqrt(D)) / (2 * A) if t < 0: return 'None' else: pointt = vector_math.translate_point( theRay.pt, vector_math.scale_vector(theRay.dir, t)) return pointt else: t1 = (-B + math.sqrt(D)) / (2 * A) t2 = (-B - math.sqrt(D)) / (2 * A) if t1 >= 0 and t2 >= 0: pointt = vector_math.translate_point( theRay.pt, vector_math.scale_vector(theRay.dir, min(t1, t2))) return pointt elif t1 < 0 and t2 < 0: return 'None' elif t1 < 0 or t2 < 0: pointt = vector_math.translate_point( theRay.pt, vector_math.scale_vector(theRay.dir, max(t1, t2))) return pointt
def test_difference_point_1(self): p1 = data.Point(0.0, 0.0, 0.0) p2 = data.Point(1.0, 2.0, 3.0) p3 = vector_math.difference_point(p1, p2) self.assertAlmostEqual(p3.x, -1.0) self.assertAlmostEqual(p3.y, -2.0) self.assertAlmostEqual(p3.z, -3.0)
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 point_unobstructed(point, light, sphere_list): light_dir = vector_math.normalize_vector(vector_math.difference_point( light.pt, point)) ray_to_light = data.Ray(point, light_dir) spheres_intersected = collisions.find_intersection_points(sphere_list, ray_to_light) if spheres_intersected == []: return True else: return False
def sphere_intersection_point(ray, sphere): #define variables A = vector_math.dot_vector(ray.dir, ray.dir) B = vector_math.dot_vector( vector_math.scale_vector( (vector_math.difference_point(ray.pt, sphere.center)), 2), ray.dir) C = vector_math.dot_vector( vector_math.difference_point(ray.pt, sphere.center), vector_math.difference_point(ray.pt, sphere.center)) - sphere.radius**2 discriminant = B**2 - 4 * A * C if discriminant < 0: return None #define t t = (-B + math.sqrt(discriminant)) / (2.0 * A) t_2 = (-B - math.sqrt(discriminant)) / (2.0 * A) point_t = vector_math.translate_point(ray.pt, vector_math.scale_vector(ray.dir, t)) point_t2 = vector_math.translate_point( ray.pt, vector_math.scale_vector(ray.dir, t_2)) #Cases if t >= 0 and t_2 >= 0: if t_2 > t: return point_t else: return point_t2 elif t < 0 and t_2 < 0: return None elif (t < 0 and t_2 >= 0) or (t >= 0 and t_2 < 0): if t >= 0: return point_t else: return point_t2 else: return None
def sphere_intersection_point(ray, sphere): a = vector_math.dot_vector(ray.dir, ray.dir) b = (2 * (vector_math.dot_vector( vector_math.difference_point(ray.pt, sphere.center), ray.dir))) c = vector_math.dot_vector( vector_math.difference_point(ray.pt, sphere.center), (vector_math.difference_point(ray.pt, sphere.center))) - sphere.radius**2 d = b**2 - 4 * a * c if d < 0: return None if d == 0: t1 = (-b + math.sqrt(b**2 - 4 * a * c)) / (2 * a) if t1 > 0: x = (t1 * ray.dir.x) + ray.pt.x y = (t1 * ray.dir.y) + ray.pt.y z = (t1 * ray.dir.z) + ray.pt.z return data.Point(x, y, z) else: return None if d > 0: t1 = (-b + math.sqrt(b**2 - 4 * a * c)) / (2 * a) t2 = (-b - math.sqrt(b**2 - 4 * a * c)) / (2 * a) if t2 < 0 and t1 < 0: return None elif t2 < 0: x = (t1 * ray.dir.x) + ray.pt.x y = (t1 * ray.dir.y) + ray.pt.y z = (t1 * ray.dir.z) + ray.pt.z return data.Point(x, y, z) else: x = (t2 * ray.dir.x) + ray.pt.x y = (t2 * ray.dir.y) + ray.pt.y z = (t2 * ray.dir.z) + ray.pt.z return data.Point(x, y, z)
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 cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list, ambient_color, light): delta_x = (max_x - min_x) / float(width) delta_y = (max_y - min_y) / float(height) f = open('image.ppm', 'w') f.write('P3 ' + str(width) + ' ' + str(height) + ' ' + str(255) + ' ') for y in reverse_frange(min_y, max_y, delta_y): for x in frange(min_x, max_x, delta_x): cr_out = cast_ray( data.Ray( eye_point, vector_math.difference_point(data.Point(x, y, 0), eye_point)), sphere_list, ambient_color, light, eye_point) if cr_out != data.Color(1.0, 1.0, 1.0): ppm_sphere_color = float_to_ppm(cr_out) f.write( str(ppm_sphere_color.r) + ' ' + str(ppm_sphere_color.g) + ' ' + str(ppm_sphere_color.b) + ' ') else: f.write(str(255) + ' ' + str(255) + ' ' + str(255) + ' ') f.close()
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list, ambient_color, light, filename): y_interval = (max_y - min_y) / float(height) x_interval = (max_x - min_x) / float(width) outfile = open(filename, "w") print >> outfile, "P3" print >> outfile, "%d %d" % (width, height) print >> outfile, "255" for i in range(height): for j in range(width): y = max_y - (i * y_interval) x = min_x + (j * x_interval) viewpoint = data.Point(x, y, 0) ray_dir = vector_math.difference_point(viewpoint, eye_point) ray_to_cast = data.Ray(eye_point, ray_dir) spherecolor = cast_ray(ray_to_cast, sphere_list, ambient_color, light, eye_point) print >> outfile, "%d %d %d" % (spherecolor.r * 255, spherecolor.g * 255, spherecolor.b * 255)
def test_difference_point_2(self): point1 = data.Point(3, 1, 9) point2 = data.Point(1, 5, -4) vec = vector_math.difference_point(point1, point2) self.assertEqual(vec, data.Vector(2, -4, 13))
def test_difference_point_1(self): point1 = data.Point(1, 2, 3) point2 = data.Point(0, 0, 0) vec = vector_math.difference_point(point1, point2) self.assertEqual(vec, data.Vector(1, 2, 3))
def test_difference_point_1(self): point1 = data.Point(0, 1, 2) point2 = data.Point(3, 4, 5) difference_point = data.Vector(-3, -3, -3) self.assertEqual(vector_math.difference_point(point1, point2), difference_point)
def sphere_normal_at_point(sphere,point): v = vector_math.difference_point(point, sphere.center) return vector_math.normalize_vector(v)
def test_pointDiff_1(self): p1 = data.Point(1,2,3) p2 = data.Point(1,2,3) equals = data.Point(0,0,0) self.assertEqual(vector_math.difference_point(p1, p2) == equals, True) pass
def test_difference_points_2(self): pt_1 = data.Point(3, 4, 5) pt_2 = data.Point(1, 1, 1) pt = data.Vector(2, 3, 4) self.assertAlmostEqual(vector_math.difference_point(pt_1, pt_2), pt)
def test_difference_point(self): dp = vector_math.difference_point(data.Point(1, -2, 3), data.Point(3, 3, 3)) self.assertEqual(dp, data.Vector(-2, -5, 0))
def test_difference_point_again(self): dp = vector_math.difference_point(data.Point(2.2, -4.5, 9), data.Point(1, 0, 2)) self.assertEqual(dp, data.Vector(1.2, -4.5, 7))
def sphere_normal_at_point(sphere, point): v = vector_math.difference_point(point, sphere.center) return vector_math.normalize_vector(v)
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_difference_point_2(self): point3 = data.Point(5, -7, -13) point4 = data.Point(0, 4, 8) difference_point = data.Vector(5, -11, -21) self.assertEqual(vector_math.difference_point(point3, point4), difference_point)
def test_pointDiff_2(self): p1 = data.Point(4,5,6) p2 = data.Point(3,2,1) equals = data.Point(1, 3, 5) self.assertEqual(vector_math.difference_point(p1, p2) == equals, True) pass
def test_difference_point_2(self): p1 = data.Point(1.0, 2.0, 3.0) p2 = data.Point(1.0, 2.0, 3.0) p3 = vector_math.difference_point(p1, p2) self.assertAlmostEqual(p3, data.Point(0.0, 0.0, 0.0))