Sign in to follow this  

help working out if 2 spheres overlap / colided

This topic is 4761 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 have been looking on gamasutra,at the sphere on sphere sweep tests, but i cant figure out the code, partly as its in c++ ( i only know c#) and 2nd that im not fantastic at maths. can anyone explain better how i can work out if spheres have colided?

Share this post


Link to post
Share on other sites
Quote:
can anyone explain better how i can work out if spheres have colided?

Maybe I'm over simplifying it, but given a center and radius for each sphere, the following logic is all thats needed:

1. Calculate the distance between the two center points:
dist = square_root( a*a + b*b + c*c )
where:
- a = (sphere1_x - sphere2_x)
- b = (sphere1_y - sphere2_y)
- c = (sphere1_z - sphere2_z)


2. if the distance is GREATER THAN the sum of the two radii then the spheres are not touching/intersecting

3. if the distance is EQUAL TO the sum of the two radii they are just touching on the surfaces.

4. if the distance is LESS THEN the sum of the two radii they are intersecting/overlapping each other.

I'm sure you can convert that into relatively simple C# code [grin]

hth
Jack

Share this post


Link to post
Share on other sites
I think he's asking about a swept test, not static intersection.

What part of the code/algorithm are you having trouble with? The algorithm is fairly straightforward and involves solving a quadratic equation to find the first time, if any, of contact between the spheres. If you can tell us what you're uncertain about, someone here will be able to clarify things for you.

Share this post


Link to post
Share on other sites
Quote:
I think he's asking about a swept test, not static intersection.

oops! my bad... thought it sounded a bit too simple - I usually don't get my hands dirty in M&P for this reason [grin]..

Jack

Share this post


Link to post
Share on other sites
It is easy enough to see that sweep sphere test is the same as ray-sphere intersection. Let one sphere is stationary, other is moving along some ray. Let radiuses is r1,r2 respectively. Then, spheres collide when distance between centers <r1+r2 . Same as intersection of ray with sphere that have radius r1+r2.

If both spheres is moving, you need to do everything relatively to one of spheres.

I have posted my ray-sphere intersection code to this forum about 7 times.

//
// Ray-sphere intersection.
// p=(ray origin position - sphere position),
// d=ray direction,
// r=sphere radius,
// Output:
// i1=first intersection distance,
// i2=second intersection distance
// i1<=i2
// i1>=0
// returns true if intersection found,false otherwise.
//
bool RaySphereIntersect(const Vec3 &p, const Vec3 &d,double r, double &i1, double &i2){
double det,b;
b = -DotProduct(p,d);
det=(b*b) - DotProduct(p,p) + r*r;
if (det<0){
return false;
}
det= sqrt(det);
i1= b - det;
i2= b + det;
// intersecting with ray?
if(i2<0) return false;
if(i1<0)i1=0;
return true;
};



note that direction must be normalized.
If you call this with
// doing everything relatively to first sphere
Vec3 V=Velocity2-Velocity1;
double l=Length(V);
V*=1/l;
double i1,i2
... RaySphereIntersect(Position2-Position1,V,radius1+radius2,i1,i2);
i1/=l;
you'll get i1=time of first collision. i1=0 if already collided.

You can optimize code if you like. I think, that

//
// Warning: Non-tested function.
//
// Ray-sphere intersection that works as moving point-sphere collision.
// p=(point start position - sphere center position),
// v=point velocity,
// r=sphere radius,
// Output:
// i1=first intersection time,
// i2=second intersection time
// i1<=i2
// i1>=0
// returns true if intersection found,false otherwise.
//
bool RaySphereIntersectTime(const Vec3 &p, const Vec3 &v,double r, double &i1, double &i2){
double det,b,k;
k = DotProduct(v,v);
b = -DotProduct(p,v)/k;
det=b*b - (DotProduct(p,p) - r*r)/k;
if (det<0){
return false;
}
det= sqrt(det);
i1= b - det;
i2= b + det;
// intersecting with ray?
if(i2<0) return false;
if(i1<0)i1=0;
return true;
};



if(RaySphereIntersectTime(Position2-Position1,Velocity2-Velocity1,radius1+radius2,i1,i2)){
i1=time of first collision. i1=0 if already collided.
};

P.S. for Nth time, DotProduct(d,d) or DotProduct(p,p) is not a typo.

Share this post


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