Last active
July 23, 2020 16:23
-
-
Save omaraflak/bafb7bdb21e10e8ace44aedb07551be9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
import matplotlib.pyplot as plt | |
def normalize(vector): | |
return vector / np.linalg.norm(vector) | |
def sphere_intersect(center, radius, ray_origin, ray_direction): | |
b = 2 * np.dot(ray_direction, ray_origin - center) | |
c = np.linalg.norm(ray_origin - center) ** 2 - radius ** 2 | |
delta = b ** 2 - 4 * c | |
if delta > 0: | |
t1 = (-b + np.sqrt(delta)) / 2 | |
t2 = (-b - np.sqrt(delta)) / 2 | |
if t1 > 0 and t2 > 0: | |
return min(t1, t2) | |
return None | |
def nearest_intersected_object(objects, ray_origin, ray_direction): | |
distances = [sphere_intersect(obj['center'], obj['radius'], ray_origin, ray_direction) for obj in objects] | |
nearest_object = None | |
min_distance = np.inf | |
for index, distance in enumerate(distances): | |
if distance and distance < min_distance: | |
min_distance = distance | |
nearest_object = objects[index] | |
return nearest_object, min_distance | |
width = 300 | |
height = 200 | |
camera = np.array([0, 0, 1]) | |
ratio = float(width) / height | |
screen = (-1, 1 / ratio, 1, -1 / ratio) # left, top, right, bottom | |
objects = [ | |
{ 'center': np.array([-0.2, 0, -1]), 'radius': 0.7 }, | |
{ 'center': np.array([0.1, -0.3, 0]), 'radius': 0.1 }, | |
{ 'center': np.array([-0.3, 0, 0]), 'radius': 0.15 } | |
] | |
image = np.zeros((height, width, 3)) | |
for i, y in enumerate(np.linspace(screen[1], screen[3], height)): | |
for j, x in enumerate(np.linspace(screen[0], screen[2], width)): | |
pixel = np.array([x, y, 0]) | |
origin = camera | |
direction = normalize(pixel - origin) | |
# check for intersections | |
nearest_object, min_distance = nearest_intersected_object(objects, origin, direction) | |
if nearest_object is None: | |
continue | |
# compute intersection point between ray and nearest object | |
intersection = origin + min_distance * direction | |
# image[i, j] = ... | |
print("%d/%d" % (i + 1, height)) | |
plt.imsave('image.png', image) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment