# Moving a sphere in a basic ray tracer

I have written a really basic ray tracer. It generates primary rays and sets the colour of the pixel to the colour of the object that I have set myself. The code for which can be seen below.

from PIL import Image, ImageDraw
from Sphere import Sphere
import numpy as np

imgx = 300
imgy = 300

img = Image.new('RGB', (imgx, imgy), color = 'black')

#Place a Sphere in centre, distance 10 away.
#Sphere has a constructor (centre, colour, radius)
sphere1 = Sphere(np.array([0,0,-1]), (255, 255, 255), 100)
#sphere2 = Sphere(np.array([300,0,-1]), (255, 0, 0), 100)

objects = [sphere1]

for i in range(img.size[0]):
for j in range(img.size[1]):

u = -imgx/2 + (imgx)*(i+0.5)/imgx
v = -imgy/2 + (imgy)*(j+0.5)/imgy

rayDirection = -1*np.array([0,0,1]) + u*np.array([1,0,0]) + v*np.array([0,1,0])
rayOrigin = np.array([0,0,0])
#p(t) = rayorigin + t*raydirect

#Sphere intersection
for obj in objects:
a = np.dot(rayDirection, rayDirection)
b = np.dot(2*rayDirection, (rayOrigin - obj.centre))
c = np.dot((rayOrigin - obj.centre), (rayOrigin - obj.centre)) - obj.radius**2

eminc = rayOrigin - obj.centre

discrim = (np.dot(rayDirection, eminc))**2 - ((np.dot(rayDirection, rayDirection))*(np.dot(eminc, eminc))-obj.radius**2)
if(discrim >= 0):
print("intersect")
pixelMap[i,j] = obj.colour
else:
pixelMap[i,j] = (0, 0,0)

img.save('output.png')


It works in the sense that when I run the code, I get an image of a white circle. My issue arises when I change the centre of the sphere. Instead of shifting to the left, right, up or down. I get a skewed image. Seen below when I set the Sphere to have centre np.array([3,0,-1]).

I believe the problem may be to do with the translation between world co-ordinates and camera co-ordinates? However, I am not sure what transformation matrix to use or how to use it. For what it's worth, my code takes ideas from Fundamentals of Computer Graphics by Pete Shirley and Steve Marschner.

• discrim = (np.dot(rayDirection, eminc))**2 - ((np.dot(rayDirection, rayDirection))*(np.dot(eminc, eminc))-obj.radius**2), use discrim = b * b-4*a*c – lightxbulb Jul 15 at 13:34
• @lightxbulb discrim is equivalent to b^2-4ac with the values for a,b and c substituted in. – Tim Jul 15 at 16:26
• It is not. It would be if you actually wrote (np.dot(rayDirection, eminc))**2 - 4*((np.dot(rayDirection, rayDirection))*(np.dot(eminc, eminc)-obj.radius**2)). So just put in b * b - 4 * a * c, and check whether it works. – lightxbulb Jul 15 at 18:37