Jump to content
  • Advertisement
Sign in to follow this  
Spoon Thumb

Problem with Ray Sphere Intersection Points

This topic is 2608 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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



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;

}

}



raysphereintersect.png

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?

Share this post


Link to post
Share on other sites
Advertisement
firs of all you have sh&&&tty vector math

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){

th length and magnitude is not correct


double magnitude = Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z);

vector.x /= magnitude;
vector.y /= magnitude;
vector.z /= magnitude;

}

}[/quote]








t3dpoint __fastcall ClosestPointOnLine (t3dpoint vA,t3dpoint vB,t3dpoint vPoint)
{
t3dpoint vVector1, vVector2, vVector3;// : t3dpoint;
t3dpoint vClosestPoint;// : t3dpoint;
float D, T;// : Single;

//First, we create a vector from our end point vA to our point vPoint
vVector1.x = vPoint.x - vA.x;
vVector1.y = vPoint.y - vA.y;
vVector1.z = vPoint.z - vA.z;

//Now we create a normalized direction vector from end point vA to end point vB
vVector2.x = vB.x - vA.x;
vVector2.y = vB.y - vA.y;
vVector2.z = vB.z - vA.z;
vVector2 = Normalize(vVector2);

//Now we use the distance formula to find the distance of the line segment
D = n3ddistance(vA, vB);

//Using the dot product, we project the vVector1 onto the vector vVector2. This essentially
//gives us the distance of our projected vector from vA
T = Dot(vVector2, vVector1);

//If our projected distance from vA, "t", is greater than or equal to 0, it must be closest to the end point
//vA. So we return this end point.
if (T<=0) return vA;

//If our projected distance from vA, "t", is greater than or equal to the magnitude or distance of the line
//segment, it must be closest to the end point vB, so we return vB.
if (T>=0) return vB;
//Here we create a vector that is of length T and in the direction of vVector2
vVector3.x = vVector2.x * T;
vVector3.y = vVector2.y * T;
vVector3.z = vVector2.z * T;

//To find the closest point on the line, we just add vVector3 to the original end point vA
vClosestPoint.x = vA.x + vVector3.x;
vClosestPoint.y = vA.y + vVector3.y;
vClosestPoint.z = vA.z + vVector3.z;

return vClosestPoint;
}

[/quote]





and then let: A,B will be you line, r is a radius of sphere and s is the center of the sphere

so

t3dpoint closestpoint = ClosestPointOnLine(A,B,s) ;



float __fastcall n3ddistance(t3dpoint first_point,t3dpoint second_point )
{

float val = dopotegi(first_point.x-second_point.x)+dopotegi(first_point.y-second_point.y)+dopotegi(first_point.z-second_point.z);
if (val > 0.0) val = sqrt(val);
return val;
}

[/quote]




if (n3ddistance(closestpoint,s < r) { whe have intersection




and some math







t3dpoint __fastcall Normalize(t3dpoint v)
{
float magni;
t3dpoint result;
magni = magnitude(v);
// = 1.0;
if (IsNan(magni) == true) magni = 1.0;
if (magni <= 0.0) magni = 1.0;

result.x = v.x/magni;
result.y = v.y/magni;
result.z = v.z/magni;
// = v;
return result;
}


float __fastcall magnitude(t3dpoint Vector)
{
// if ( ( IsNan(Vector.x) == true) || (IsNan(Vector.y) == true) || (IsNan(Vector.z) == true) ) return 1.0f;

//float result;
return sqrt(
(Vector.x*Vector.x) +
(Vector.y*Vector.y) +
(Vector.z*Vector.z));
//if (result == 0.0f) result = 1.0f;
//return result;
}




float __fastcall VectorLength(t3dpoint vec)
{
return sqrt(Dot(vec,vec));
}




vectorlength equals to square root(x*x+y*y+z*z)




[/quote]



Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!