Find Collision response of two objects

Started by
21 comments, last by oliii 14 years, 11 months ago
Hi, how can i find collision response between rectangle and circle like in this picture : i want to identify the direction and magnitude of V1 vector and the V2 vector after they collided , With : + V1 : initial veloc vector of Circle + M1 : mass of Circle + V2 : initial veloc vector of Rectangle + M2 : mass of Rectangle does anyone have some idea about this ? [Edited by - knonk on April 15, 2009 2:26:36 AM]
Advertisement
picture not working.

Everything is better with Metal.

You mgiht need to be logged into physicsforums.com to view the picture...that or they just flat out block hotlinking (it's still called that isn't it?).
well, no pics, so I'll stab in the dark.

to find the intersection of a sphere and triangle, you need to find the point on the triangle periphery the closest to the sphere centre.

Once you have that point, it is straight forward to find the two contact points.

as for the response, given mass and velocity of the two objects, there's been many discussions about that, some from last week.

example :

bool applyReponse(RigidBody& a, RigidBody& b, const Vector& mtd){    // inverse masses (for static objects, inversemass = 0).    float ima = a.m_inverseMass;    float imb = b.m_inverseMass;    float im  = ima + imb;    if(im < 0.000001f) im = 1.0f;    // separate the objects so they just touch each other    const float relaxation = 0.8f; // relaxation coefficient, arbitrary value in range [0, 1].    a.m_position += mtd * (ima / im) * relaxation;    b.m_position -= mtd * (imb / im) * relaxation;    // collision plane normal. It's the mtd vector, but normalised.    Vector n = mtd;     n.normalise();    // impact velocity along normal of collision 'n'    Vector v = (a.m_velocity - b.m_velocity);    float vn = v.dotProduct(n);    // objects already separating, no reflection    if (vn > 0.0f) return true;    const float cor = 0.7f; // coefficient of restitution. Arbitrary value, in range [0, 1].      // relative collision impulse    float j = -(1.0f + cor) * vn / (im);      // apply collision impulse to the two objects    a.m_velocity += n * (j * ima);    b.m_velocity -= n * (j * imb);    return true;}

Everything is better with Metal.

Oh, Thank's for your explaination so much, Oliii. I will show the picture more clearly :
Please look at this picture :



We consider that :
V1 : veloc vector of circle BEFORE they collide
V2 : veloc vector of rectangle BEFORE they collide
and I have to find v1f,v2f with :
v1f : veloc vector of Circle AFTER they collide
v2f : veloc vector of Rectangle AFTER they collide

This is the oblique collision and the contact point(the collision point) of two object doesn't lie on line of action(the line from center of circle to center of rectangle), I did try some way, but it didn't response as real as i want,Could you explain more clear about this for me please !

[Edited by - knonk on April 15, 2009 2:47:05 AM]
The picture doesn't display if you're not logged into the physicsforums.com website. I don't have an account there, so I can't see the picture at all. I would suggest you upload the picture to flickr or photobucket or some other site where we can see it without having to sign up...
Oh,Im sorry, I did post to google, so hope u can see it :
Please look at this picture :


We consider that :
V1 : veloc vector of circle BEFORE they collide
V2 : veloc vector of rectangle BEFORE they collide

and I have to find v1f,v2f with :
v1f : veloc vector of Circle AFTER they collide
v2f : veloc vector of Rectangle AFTER they collide

This is the oblique collision and the contact point(the collision point) of two object doesn't lie on line of action(the line from center of circle to center of rectangle), I did try some way, but it didn't response as real as i want,Could you explain more clear about this for me please !
I thought that function closestPointToRectangle () was relatively clear.

basically, you find the point on the rectangle contour the closest to the sphere centre, which is what the code does above, and that gives you the collision point.

once you have that point, then you can apply the collision response above, which is based on the conservation of momentum.

the MTD is bascially the vector separation between the two points of contact on the objects. Since your objects are not intersecting, the MTD will be zero, so you'll need another way to find the collision normal. In case of a sphere, it's quite simple, it's just the vector (V1 - sphere.centre), normalised.

then the complete response code would be :

Vector closestPoint(const Vector& p, const Rectangle& r){    // relative position of sphere centre from the rectangle centre    Vector d = (p - r.m_centre);    // rectangle half-size    Vector h = r.m_halfSize;    // special case when the sphere centre is inside the rectangle    if(fabs(d.x) < h.x && fabs(d.y) < h.y)     {        // use left or right side of the rectangle boundary        // as it is the closest        if((h.x - fabs(d.x)) < (h.y - fabs(d.y)))        {             d.y = 0.0f;             d.x = h.x * sign(d.x);        }        // use top or bottom side of the rectangle boundary        // as it is the closest        else        {             d.x = 0.0f;             d.y = h.y * sign(d.y);        }    }    else    {        // clamp to rectangle boundary        if(fabs(d.x) > h.x) d.x = h.x * sign(d.x);        if(fabs(d.y) > h.y) d.y = h.y * sign(d.y);    }    // the closest point on rectangle from p    Vector c = r.m_centre + d;    return c;}bool applyReponse(sphere& a, rectangle& b, const Vector& normal){    // inverse masses (for static objects, inversemass = 0).    float ima = a.m_inverseMass;    float imb = b.m_inverseMass;    float im  = ima + imb;    if(im < 0.000001f) im = 1.0f;    // impact velocity along normal of collision 'n'    Vector v = (a.m_velocity - b.m_velocity);    float vn = v.dotProduct(normal);    // objects already separating, no reflection    if (vn > 0.0f) return true;    const float cor = 0.7f; // coefficient of restitution. Arbitrary value, in range [0, 1].      // relative collision impulse    float j = -(1.0f + cor) * vn / (im);      // apply collision impulse to the two objects    a.m_velocity += normal * (j * ima);    b.m_velocity -= normal * (j * imb);    return true;}void collisionResponse(sphere& s, rectangle& r){    Vector closest = closestPoint(s.m_centre, r);    Vector normal = (s.m_centre - closest);    normal.normalise();    applyReponse(s, r, normal);}


Everything is better with Metal.

Hi Oliii,
I did try to read your explain but still don't get it clearly,
Let me say again your method :

1) Finding the closest point between rectangle and sphere, also is collision point

2) Apply the collision response from collision point

Is it right?, I don't understand from second step in your explain(It's easier to understand if u could explain more clearly here) ,Could you tell me more clearly and basically your method,please !
Quote:Original post by knonk
Hi Oliii,
I did try to read your explain but still don't get it clearly,
Let me say again your method :

1) Finding the closest point between rectangle and sphere, also is collision point

2) Apply the collision response from collision point

Is it right?


Yup. That's the standard collision detection and response process. What you also need is the collision normal, so you can apply a collision impulse.

Quote:I don't understand from second step in your explain(It's easier to understand if u could explain more clearly here) ,Could you tell me more clearly and basically your method,please !


Well, I'll give it a shot.

taking my cues from

http://chrishecker.com/images/e/e7/Gdmphys3.pdf

Friction aside, when objects collide, their linear momentum (in short, velocities) will change along the normal of collision. The amount of change to apply to the two objects depends on a few parameters, such as the direction of the collision (defined by the collision normal vector), the object's respective mass (when colliding heavy objects against light objects, the light objects will be the most influenced by the collision), and the objects' respective velocities.

a collision impulse is like an instantaneous force. It affects the momentum (velocities) of objects directly.

v' : new velocity after impulse
v : velocity before impulse
i : impulse vector
m : object mass

v' = v + i / m

when two bodies collide, the impulse applied on object a will be transfered to the object b, but opposite (Newton 3rd law). The impulse vector i will be an impulse amount along the normal of collision n, so you get.

(eq1) va' = va + (j * n) / ma
(eq2) vb' = vb - (j * n) / mb

for the final equation, the effect of a elastic collision on two objects velocity will be such as :

(eq3) (va' - vb') . n = -(va - vb) . n

the relative velocity is basically reflected (imagine a particle hitting a static object, the particle velocity will be flipped along the normal of collision, hence reflected).



if you want some energy loss, and a more realistic effect after collision (there will always be some energy lost after a collision, in the form of heat, sound, and magical dust).

(eq4) (va' - vb') . n = -cor * ((va - vb) . n)

cor is the coefficient of restitution, in the range [0, 1].

so, you have three unknowns (va', vb', j) and three equations (eq1, eq2, and eq4).

substitute va' and vb' from eq1 and eq2 into eq4, and you'll get

[va + (j * n) / ma - vb + (j * n) / mb] . n = -cor * [(va - vb) . n]

so now, you can solve that equation, and get a value for j.

j = - (1 + cor) * [(va - vb) . n] / [(n.n) * (1/ma + 1/mb)]

apply j in (eq1) and (eq2), and you get the new velocities for both objects.

In your example, the collision point is used to work out the normal of collision, which will be the vector passing through the collision point, and the sphere centre.

n = (ball.centre - collision_point);

preferably normalised.

Everything is better with Metal.

This topic is closed to new replies.

Advertisement