2D collision response and gravity

Started by
1 comment, last by BrickInTheWall 14 years, 7 months ago
Hey guys, whaaaats happening, I've been working on my program to simulate collision detection using SAT and it works nicely, the shapes that are moving move nicely along the surfaces of the static polygons they are hitting. But now I'm looking to handle the response of the collision. I would like to do this for static vs. moving poly first, but would like to work out an algorithm that will later also be useful for moving vs. moving poly. Thats why I was thinking of something impulse-based. Right now what I am doing as a response is calculating the angle between the velocity vector and the edge of the static shape, and the rotating the velocity vector by two times that angle. This works, but I'm pretty sure there is a better way to handle that, especially since I would like to be able to change the responce based on bounce and friction settings. The only possibility I see to solve thise would include the normal of the edge being hit. For example assigning the normal (normalized too) * velocity.Magnitude to the velocity vector and then working from there. I would appreciate it if you guys could give me some tips/links etc. on how I should best approach this topic. I forgot most of the stuff I learned about mechanics in physics as it was many years ago, but it shouldn't be too hard for me to learn. Also, what would be the best way to simulate gravity. I have never done this and just tried something like this: velocityVect.Y += velocityVect.Y * acceleration. (I would do this every time I updated the position...framerate is about 31 fps, using C#). It kinda looked like gravity, but it came into conflict with my collisiong detection, as the poly would eventually just falls through the static poly while sliding along it. My theory on this error. Every time my animation and therefore my poly's position is updated, I move it by the velocity: polygonA + velocityVect, and then the minimum translation vector is calculated (if there is a collision) and I check whether it is facing the correct way. Then I move the polygon by that vector: polygonA + minimumTranslationVector. This works well and the shape slides along the surface nicely. But if I add velocityVect.Y * acceleration at every tick, it will eventually get very big, so the penetration distance gets bigger and bigger as it slides along and eventually it is so far in that a new minimum translationvector is calculated and the whole thing messes up. If anyone could give me a tip on what I was doing wrong and how to improve this, that would be greeeaat. Cheers, Chris
Fate fell short this time your smile fades in the summer.
Advertisement
For the collision response, the simple case is to treat the object like a ray of light (remember any optics from physics?) An incident ray is reflected about the surface normal at an angle equal to the angle of incidence. I think "bounce" would act as some sort of multiplier on the magnitude of the reflected velocity vector, but wouldn't change the direction. "Friction" on the surface could be modeled by making the reflected angle more oblique (larger) than a "frictionless" reflected ray would be, and making it proportional to the magnitude of the velocity. ie. a slow moving object would be more affected by friction than a faster moving object. And friction should probably reduce the bounce factor as well.

If you colocate the tails of the surface normal vector and the incident velocity vector and change the signs of the velocity vector components, then the angle between them (A1) will be in the range of [0 to pi/2]. The reflected angle (with respect to the surface normal) will then be -(A1 + frictionFunction(magnitudeOfvelocity)). drawing it on a piece of paper helps.

As for gravity,
velocityVect.Y += (acceleration.Y * timeSinceLastUpdate)

As with most physics problems, the units help:
meters/second += (meters/second/second) * seconds
Okay, thanks so I guess I could use the timer interval as delta t in the acceleration formula. As for the "reflection", here is what I was thinking:

I calculate the new velocity vector (after having detected a collision) by splitting it into a component perpendicular and one orthogonal to the edge that is being hit. Here is what I had in mind (using an example):

An edge defined by the vectors OA = (3, 5) and OB = (9, 7) -> AB = edge = (6, 2).
A velocity vector of v = (2, 2).

Get the angle between these two vectors -> alpha = 26.5650... degrees.
Use this to calculate the magnitudes of the orthogonal and parallel (to the edge) component of the current velocity.
I get: |vOrth| = |v| * sin(26) = 1.2649...(analog for vPar). |vPar| = 2.5421...

Now all I have to do is calculate the components of the new vector. For the component of the new velocity vector orthogonal to the edge, I can use the normalized minimum translation vector (mtv) as a reference, like so:
vNewOrth = mtv(normalized) * |vOrth| = (0.4, -1.2).
I am using the mtv since I know it is pointing in the right direction (I check for this in my collision test algorithm using the dot product of this and the vector between the two centers of the polygons).

I can also calculate the parallel compenent like so:
vNewPar = edge(normalized) * |vPar| = (2.4, 0.8).

Now getting the new velocity vector (vNew) is as easy as adding the two components: vNew = vNewOrth + vNewPar = (2.8, -0.4).
This is also what I get when I draw everything on paper like you suggested.

I could now use vNewOrth and vNewPar to represent friction and bounce, by just multiplying them with a certain value, right?

What do you guys think of doing it this way? Would you encourage I calculate everything like this or do you have other suggestion/see bad problems in my way of doing it? I am uncertain at the point...errors and bugs always come up when testing everything.

Cheers,
Chris
Fate fell short this time your smile fades in the summer.

This topic is closed to new replies.

Advertisement