Jump to content
  • Advertisement
Sign in to follow this  
Vincent_M

Quick and Simple Collision Detection

This topic is 3404 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

Ok, I have spent so, so much time trying to get some simple sphere-triangle collision detection to work. I've looked at a bunch of tutorials over the internet, and have not been able to figure it out. So far, the best result I hve had so far was my own implementation, however, it is a bit flawed when it comes to colliding into two polygons that are sticking out at a point... It's close, but not perfect. Anyway, I just need some simple collision detection between a sphere and a triangle, I have some physics code to handle the collision response. EDIT: I developed my sphere-tri code based on the flipcode.net article by Paul Nettle (amazing!). My ray-tri intersection code works fine, it's just when it comes to sphere-tri intersection... I'm a bit confused on how I should go about using this... I have used this code in a few homebrew projects, but now that I am an iPhone developer, I need to perfect this code.

Share this post


Link to post
Share on other sites
Advertisement
a triangle has 3 verts each with position and the sphere has a center and radius

One easy way to do it would be

.for each vert
. if((sphere.center - vert.pos).length() < radius)
. you collided

The problem would be that the length function takes excess processing power. but there are ways around it. Just look up vector length or magnitude formula and you might see what I mean.

Share this post


Link to post
Share on other sites
Instead of using the length of the vector you can use the squared length and compare it to the squared radius. Thus the computation boils down to x*x + y*y + z*z < r*r (no costly operations involved).

The problem with this approach is that it won't detect collisions if the triangle is hitting the sphere but not its vertices.

Have a look at this thread. Basically you'd first perform a sphere-plane test with the triangle's plane. If the test is negative, there's no collision, if the sphere hits the plane, check if the collision point lies within the triangle. If not you have to check against the edges and vertices of the triangle.

So a collision takes place, if:

- the sphere hits the plane
- and the collision point is inside the triangle or the sphere hits and edge or vertex.

Hope that helps.

Thomas

Share this post


Link to post
Share on other sites
I dont know if this would be faster but if you get the closest point on a line for the center point of the sphere for each of the 3 edges then compair the distance versus the radius you get collision detection in 3 checks at most.

Just an idea though I havent taken the time to do the compairison between closest point on line and sphere to plain test.

Share this post


Link to post
Share on other sites
Quote:
One easy way to do it would be

.for each vert
. if((sphere.center - vert.pos).length() < radius)
. you collided
This is the problem with 'do it yourself' solutions to collision detection problems such as this: it's very easy to get it wrong. (The above algorithm, for example, will miss cases where the sphere collides with an edge of the triangle.)

IIRC, even the algorithm in the Nettle article has some issues (there's a follow-up article by Kaspar Fauerby that describes what I believe is a more robust version of the algorithm).

Anyway, if you just need a static test, all you really need is a 'closest point on triangle to point' function; from there, you can determine if there's an intersection, and also construct the minimum translational vector, if needed.

The dynamic test is more complicated. If you need more info on this, you might try Fauerby's paper if you can find it (I had pretty good luck with it), or check out Dave Eberly's docs and code at geometrictools.com.

Another option would be to use a pre-existing physics or collision detection engine (if you've been charged with writing a production-quality application, this might be the best choice).

Share this post


Link to post
Share on other sites
Quote:
I dont know if this would be faster but if you get the closest point on a line for the center point of the sphere for each of the 3 edges then compair the distance versus the radius you get collision detection in 3 checks at most.
Still not sufficient (collisions between the sphere and the interior of the triangle will be missed).

Share this post


Link to post
Share on other sites
in broad terms, this is what it does...


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

struct Triangle
{
Vector m_v0;
Vector m_v1;
Vector m_v2;
Vector m_normal;
};

bool solve( const Sphere* sphere, // the sphere
const Triangle* triangle, // the triangle
float& tcoll, // time of collision
Vector& pcoll) // point of collision on triangle
{
Vector pplane; // point of intersection on triangle plane
Vector pclosest; // point on triangle closest to pplane.

// project velocity onto normal.
float v = sphere->m_velocity.dotProduct(triangle->m_normal);

// sphere centre distance to triangle plane.
float h = (sphere->m_position - triangle->m_v0).dotProduct(triangle->m_normal);

// sphere underneath triangle. ignore (works only with closed geometry).
if(h < 0.0f) return false;

// sphere moving away from triangle plane. ignore. (works only with closed geometry).
if(v > 0.0f) return false;

// sphere intersects triangle plane.
// or velocity parallel to plane.
if((h < sphere->m_radius) || (v > -0.00001f))
{
// point on plane is projection of sphere position onto the plane
pplane = sphere->m_position - triangle->m_normal * h;
}
else
{
// time of collision of the sphere with the plane
float tplane = (sphere->m_radius - h) / v;

// point of collision of the sphere with the plane
pplane = sphere->m_position + sphere->m_velocity * tplane;
}

// find closest point to pplane on triangle.
// if pplane 'inside' triangle, pclosest will be equal to pplane.
Vector pclosest = triangle->closestPoint(pplane);

// distance vector between the sphere position and the point on triangle.
Vector distance = (sphere->m_position - pclosest);

float dist2 = (distance.dotProduct(distance));

// closest point inside the sphere. we have an intersection.
if(dist2 < (sphere->m_radius * sphere->m_radius))
{
tcoll = 0.0f; // time of collision (0).
pcoll = pclosest; // point of collision on triangle.
return true;
}

// time of intersection of the sphere against a ray started
// from closest point, and going against the velocity.
// if we miss, no collision.
float tray;
if(!sphere->intersect(pclosest, -sphere->m_velocity, tray))
return false;

// ray intersected. setup the collision info.
tcoll = tray; // time of collision
pcoll = pclosest; // point of collision on triangle
return true;
}

Share this post


Link to post
Share on other sites
The code above looks really good! I'll definitely check it out tomorrow. I scanned through it, and I am not sure what the "triangle->closestPoint(pplane)" function call does mathematically. I'm assuming it finds the closest point on the triangle from intersection point only if the intersection point is not within the triangle to see if the sphere has still made a collision with the edge of the current triangle. This is the part I am having trouble in within my own implementation...

I also had another question too! Did you guys (the ones using it) copy and paste the peroxide.dk code into your game, or did you make your own implementation based on the reading? I have tried to just copy and paste the code into my own project, and by the time I convert it into standard ANSI-C, it works somewhat. Anyway, the code has two syntax errors in it: one in the TCollisionPacket structure where there should be a semi-colon after eRadius, and there is an extra bracket in the collideWithWorld() function... The new and improved version is the one I was working on, and my camera will often get stuck in small gaps, and trying to get it to 'jump' does not work at all.

Since there's code posted, I'll try it out first though! =D

I also have another question too. Lets say my object collides with multiple planes at once. Should handle the collision response for every single plane, or should I add all of their normals together, and make one response based off of it?

[Edited by - Vincent_M on January 27, 2009 5:39:58 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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!