Ok, I made a test project to see how it works in 3D, then copied it into the main program. Everything reflects at the correct angles now.
Thanks guys.
REM Project: Vectors
REM Created: 3/8/2008 9:59:24 AM
REM
REM ***** Main Source File *****
REM
sync on
sync rate 60
autocam off
position camera 0, 2, -3
point camera 0, 0, 0
make matrix 1, 4, 4, 10, 10
position matrix 1, -2, 0, -2
local incident as dword = 1
local phi1 as float
local theta1 as float
local normal as dword = 2
local phi2 as float
local theta2 as float
local reflected as dword = 3
null = make vector3(1000)
null = make vector3(incident)
null = make vector3(normal)
null = make vector3(reflected)
make object box incident, 0.1, 0.1, 1
color object incident, rgb(0, 255, 0)
make object box normal, 0.1, 0.1, 1
color object normal, rgb(0, 0, 255)
make object box reflected, 0.1, 0.1, 1
color object reflected, rgb(255, 0, 0)
do
ink -1, 0
text 0, 0, "Use the arrowkeys and WASD to control the vectors."
`control incident
inc phi1, upkey()- downkey()
inc theta1, rightkey() - leftkey()
SphereToVector(phi1, theta1)
copy vector3 incident, 1000
ink rgb(0, 255, 0), 0
text 0, 20, "incident x:" + str$(x vector3(incident))
text 0, 30, "incident y:" + str$(y vector3(incident))
text 0, 40, "incident z:" + str$(z vector3(incident))
position object incident, 0, 0, 0
point object incident, x vector3(incident), y vector3(incident), z vector3(incident)
move object incident, 0.4
`control normal
inc phi2, keystate(17) - keystate(31)
inc theta2, keystate(32) - keystate(30)
SphereToVector(phi2, theta2)
copy vector3 normal, 1000
ink rgb(0, 0, 255), 0
text 0, 60, "normal x:" + str$(x vector3(normal))
text 0, 70, "normal y:" + str$(y vector3(normal))
text 0, 80, "normal z:" + str$(z vector3(normal))
position object normal, 0, 0, 0
point object normal, x vector3(normal), y vector3(normal), z vector3(normal)
move object normal, 0.4
`calculate reflected
copy vector3 reflected, normal
multiply vector3 reflected, 2*dot product vector3(incident, normal)
subtract vector3 reflected, incident, reflected
`invert reflected ray because incident ray starts out inverted
set vector3 reflected, -x vector3(reflected), -y vector3(reflected), -z vector3(reflected)
ink rgb(255, 0, 0), 0
text 0, 100, "reflected x:" + str$(x vector3(reflected))
text 0, 110, "reflected y:" + str$(y vector3(reflected))
text 0, 120, "reflected z:" + str$(z vector3(reflected))
position object reflected, 0, 0, 0
point object reflected, x vector3(reflected), y vector3(reflected), z vector3(reflected)
move object reflected, 0.4
sync
loop
function SphereToVector(phi as float, theta as float)
set vector3 1000, sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta)
endfunction