Original Post
I read this post and decided to implement the algorithm in java for my space-based android game:

I started out by testing it with a spaceship starting at 0,0,0 (the ray origin) and heading in direction (0,0,1) at speed 5 (making the ray vector (0,0,5)). With a spacestation at (100,0,100) (sphere centre), the sum of their bounding spheres (sphere radius) I set at 15. If the ray inersects the sphere, the ship is on a collision course with the station. I wanted also to get the coordinates of the point where the ship would hit the station
However, the first call gives the angle between the two vectors as 60 degrees rather than the expected 45. The ship turns, over a number of ticks, and eventually settles on a direction/ray vector of (0.6, 0.0 ,0.4), the same as the vector from the ship to the station. Logically, I'd expect the angle between two identical vectors to be zero, but it isn't
Anyway, not sure where I've gone wrong. Is it just the zero-case I'm using in my example or something more fundamental?
public class PhysicsUtil{
public static Vector3d[] rayItersectSphere(Vector3d rayVector, Vector3d rayOrigin, Vector3d sphereCentre, double sphereRadius){
Vector3d a = new Vector3d(rayVector); // vector of ray
Vector3d b = new Vector3d(); // vector from ray origin to sphere centre
b.x = sphereCentre.x - rayOrigin.x;
b.y = sphereCentre.y - rayOrigin.y;
b.z = sphereCentre.z - rayOrigin.z;
a.normalise();
b.normalise();
double dotProduct = PhysicsUtil.dotProduct(a, b);
double T = Math.acos(dotProduct); // angle between vectors
if(T>Math.PI/2 || T<-Math.PI/2){
// vector is in wrong direction
return new Vector3d[]{};
}
double B = PhysicsUtil.getDistance(sphereCentre, rayOrigin); // distance from ray origin to sphere centre
double A = B * Math.cos(T); // distance from ray origin to closest point on ray to sphere centre
double C = B * Math.sin(T); // shortest distance from sphere centre to ray
if(C > sphereRadius){
// no intersections
return new Vector3d[]{};
} else if(C == sphereRadius){
// 1 intersection
// assuming a (ray vector) is normalised, multiply by A to get (relative) point
a.x *= A;
a.y *= A;
a.z *= A;
return new Vector3d[]{
new Vector3d(rayOrigin.x + a.x, rayOrigin.y + a.y, rayOrigin.z + a.z)};
} else {
// 2 intersections
double D = Math.sqrt(sphereRadius*sphereRadius - C*C); // distance between nearest point on ray to sphere centre and intersection of ray and sphere edge
Vector3d aplus = new Vector3d(a);
Vector3d aminus = new Vector3d(a);
aplus.x *= (A+D);
aplus.y *= (A+D);
aplus.z *= (A+D);
aminus.x *= (A-D);
aminus.y *= (A-D);
aminus.z *= (A-D);
return new Vector3d[]{
new Vector3d(rayOrigin.x + aplus.x, rayOrigin.y + aplus.y, rayOrigin.z + aplus.z),
new Vector3d(rayOrigin.x + aminus.x, rayOrigin.y + aminus.y, rayOrigin.z + aminus.z)
};
}
}
public static double getDistance(Vector3d point1, Vector3d point2){
double diffX = point1.x - point2.x;
double diffY = point1.y - point2.y;
double diffZ = point1.z - point2.z;
double hyp = Math.sqrt(diffX*diffX + diffY*diffY);
return Math.sqrt(hyp*hyp + diffZ*diffZ);
}
public static double dotProduct(Vector3d vector, Vector3d vector2){
return vector.x*vector2.x + vector.y*vector2.y + vector.z*vector2.z;
}
}
public class Vector3d {
double x;
double y;
double z;
public void normalise(){
double magnitude = Math.abs(x) + Math.abs(y) + Math.abs(z);
x /= magnitude;
y /= magnitude;
z /= magnitude;
}
public double length(){
return x + y + z;
}
public static void normalise(Vector3d vector){
double magnitude = Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z);
vector.x /= magnitude;
vector.y /= magnitude;
vector.z /= magnitude;
}
}

I started out by testing it with a spaceship starting at 0,0,0 (the ray origin) and heading in direction (0,0,1) at speed 5 (making the ray vector (0,0,5)). With a spacestation at (100,0,100) (sphere centre), the sum of their bounding spheres (sphere radius) I set at 15. If the ray inersects the sphere, the ship is on a collision course with the station. I wanted also to get the coordinates of the point where the ship would hit the station
However, the first call gives the angle between the two vectors as 60 degrees rather than the expected 45. The ship turns, over a number of ticks, and eventually settles on a direction/ray vector of (0.6, 0.0 ,0.4), the same as the vector from the ship to the station. Logically, I'd expect the angle between two identical vectors to be zero, but it isn't
Anyway, not sure where I've gone wrong. Is it just the zero-case I'm using in my example or something more fundamental?