Jump to content
  • Advertisement
Sign in to follow this  
peterbone

Sphere collision response

This topic is 3757 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'm looking for information on sphere collision detection and response. I only need to detect elastic collisions with flat surfaces and other spheres. Can anyone suggest a good physics engine that handle this or a good article on the subject? Regards, Peter

Share this post


Link to post
Share on other sites
Advertisement
Any physics engine can handle that sort of things. Bullet Physics Engine has lots of followers.

But it depends how far you wanna go. If it's just having spheres bouncing around (say Quake 3 style physics)...

http://www.gamedev.net/reference/articles/article1026.asp

If yuo want the full rigid body dynamics (for example monkey ball), then it's more invovled, and you start going towards proper physics engine implementation.

a couple of links, where I attempt to explain how to do simple sphere - triangle intersection test, and very basic linear collision response between two spheres with varying mass.

http://www.gamedev.net/community/forums/topic.asp?topic_id=433765&whichpage=1�

http://www.gamedev.net/community/forums/topic.asp?topic_id=441997

http://www.gamedev.net/community/forums/topic.asp?topic_id=446296

Also look for Chris Hecker tutorials for collison response and general physics.

Share this post


Link to post
Share on other sites
Thanks, that's useful. I should have said that this is for a 3D implementation. It doesn't need to be a very accurate physics simulation but it would be good if it gave realistic results. Here's what I've done on my own already. I've included my physics code (pascal).

http://www.ninjaonfire.co.uk/3d_ball_physics.zip

I'm quite pleased with this at the moment because the code is very simple and the result looks ok.
At the moment there is no collision detection between spheres. This is where I need help. Can I do this without having to go into a complex full rigid body dynamics implementation. Also, I would like code or to write the code myself rather than using compiled libraries.

Thanks,
Peter Bone

Share this post


Link to post
Share on other sites
detection is easy, you just check if the centres are at distance (radius1 + radius2) from each other. Or better, check the squared distances.


struct Sphere
{
Vector m_position;
float m_radius;
bool collide(const Sphere& sphere) const;
};

bool Sphere::collide(const Sphere& sphere) const
{
Vector delta = (m_position - sphere.m_position);
float r = m_radius + sphere.m_radius;
vector dist2 = delta.dotProduct(delta);

if(dist2 > r*r) return false;

return true;
}


if the spheres collide, you want the collision plane, so you can apply a collision impulse along the collision normal.

Also, the spheres will be interesecting, so you'll need to move them away from each other. That's called the MTD vector (Minimum Translation Distance vector), and for spheres, the MTD provides also the collision plane.


struct Sphere
{
Vector m_position;
float m_radius;
bool collide(const Sphere& sphere) const;
};

bool Sphere::collide(const Sphere& sphere, Vector& mtd) const
{
Vector delta = (m_position - sphere.m_position);
float r = m_radius + sphere.m_radius;
vector dist2 = delta.dotProduct(delta);

if(dist2 > r*r) return false;

float dist = sqrt(dist2);
if(dist < 1.0E-5f) return false;

mtd = delta * (r - dist) / dist;

return true;
}


then you can apply the collision response


struct Sphere
{
Vector m_position;
Vector m_velocity;
float m_radius;
float m_mass;

bool collide(Sphere& sphere);
bool resolveIntersection(Sphere& sphere, const Vector& mtd);
bool resolveCollision(Sphere& sphere, const Vector& Normal);
bool colliding(const Sphere& sphere) const;

};

bool Sphere::colliding(const Sphere& sphere, Vector& mtd) const
{
// delta vector
Vector delta = (m_position - sphere.m_position);

float r = m_radius + sphere.m_radius;

// square distance
vector dist2 = delta.dotProduct(delta);

// square distance > radius squared. no collision
if(dist2 > r*r) return false;

// find the mtd (or the amount of intersection along the delta vector).
float dist = sqrt(dist2);

mtd = delta * (r - dist) / dist;

return true;
}

bool Sphere::resolveIntersection(Sphere& sphere, const Vector& mtd)
{
// inverse mass quantities
float im1 = 1 / m_mass;
float im2 = 1 / sphere.m_mass;

// resolve intersection
m_position += mtd * (im1 / (im1 + im2));
sphere.m_position -= mtd * (im2 / (im1 + im2));

return true;
}

bool Sphere::resolveCollision(Sphere& sphere, const Vector& n)
{
const float cor = 0.7f;

// inverse mass quantities
float im1 = 1 / m_mass;
float im2 = 1 / sphere.m_mass;

// impact speed
Vector v = (m_velocity - sphere.m_velocity);
float vn = v.dotProduct(n);

// sphere intersecting but moving away from each other already
if(vn > 0.0f) return false;

// collision impulse
float i = (-(1.0f + cor) * vn) / (im1 + im2);
Vector impulse = n * i;

// change in momentum
m_velocity += impulse * im1;
sphere.m_velocity -= impulse * im2;

return true;
}

bool Sphere::collide(Sphere& sphere)
{
Vector mtd;
Vector normal;

if(!colliding(sphere, mtd))
return false;

normal = (m_position - sphere.m_position);
normal.normalise();

resolveIntersection(sphere, mtd);
resolveCollision(sphere, normal);

return true;
}



[Edited by - oliii on September 17, 2009 4:24:53 AM]

Share this post


Link to post
Share on other sites
Thanks. Your collision response code will be useful to me but I think your collision detection needs improving. For small spheres moving at high speed they are unlikely to ever overlap even when their paths cross. The way I did it with sphere plane collision is by testing if the line between old and new positions intersects the plane.
I can't think how a similar method could be used for sphere sphere intersection. Perhaps by modelling the spheres path as a cylinder between successive frames and testing intersection with other paths - and also taking into account the velocities since the spheres may miss each other in time even if their path cylinders intersect.

Pete

Share this post


Link to post
Share on other sites
you need to solve a quadratic equation for that.

sphere [P, V, r] (position, velocity, radius).

at time t :

sphere.P(t) = sphere.P + sphere.V * t

sphere A and B collide when :

(A.P(t) - B.P(t))^2 = (A.r + B.r)^2

develop with eq1 and you get

((A.P - B.P) + (A.V - B.V) * t)^2 - (A.r + B.r)^2 = 0

(A.V - B.V)^2 * t^2 + 2 * ((A.V - B.V) * (A.P - B.P)) * t + (A.P - B.P)^2 - (A.r + B.r)^2 = 0

Quadratic equation in the form a*t^2 + b*t + c = 0
where :
a = (A.V - B.V)^2
b = (A.V - B.V) * (A.P - B.P) * 2
c = (A.P - B.P)^2 - (A.r + B.r)^2

and you solve it for t, that will give you two times of collision, you take the first positive and move spheres to that time.

[Edited by - oliii on June 10, 2008 9:48:50 AM]

Share this post


Link to post
Share on other sites
Thanks, that's helpful. A second order equation makes it sound like a differential equation. I assume you mean a quadratic. I guess that after moving the spheres to the computed collision time, the calculation for collision response will be the same as you gave before?
If you knew this method, why do you not use it in your code? Just wondering.

I'm a bit confused by your code. Where is m_position defined? Should it be m_centre?

Pete

Share this post


Link to post
Share on other sites
Well, not knowing what your skill levels are, I just posted the easiest methoid for sphere collisions, which is just checking for intersections.

The swept test is the more advanced method.

The collision response does not change, although the computation of the MTD and normal may need to change (since there will be no intersection at the time of collision). Since the MTD will most likely be (0, 0, 0), there is no need to resolve intersections, and the collision normal is just along th line passing through the sphere centres.

Yes, position = centre. I'll amend the code later on.

Also, I mean a quadratic equation.

This response will not produce rotations. If you want rotations, you will need some more complete rigid body dynamics. Chris hecker has some code (albeit in 2D). The complete code is a bit more involved (probably using quaternions).

Note that sphere collisions are just like any other collision shapes. You can abstract the collisoin part, and the rigid body part, and work on contacts to resolve collisions.

I'l lsort it out, got to rush.

[Edited by - oliii on June 10, 2008 8:28:24 AM]

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!