Sign in to follow this  
johnnyBravo

Is this correct (linear collision)?

Recommended Posts

When my two objects collide, I calculate the net force and apply it to both: float forceAmount = VecLength(object1.linearVelocity/object1.mass) + VecLength(object2.linearVelocity/object2.mass) Vector forceDir = VecNormalize(object1.position - object2.position) object1.linearVelocity += forceDir*forceAmount/object1.mass object2.linearVelocity -= forceDir*forceAmount/object2.mass Except the objects go off at less of an angle, eg instead of going off at 45 degress, it would be more like 5degrees. But if I change it to this: object1.linearVelocity = forceDir*forceAmount/object1.mass object2.linearVelocity = -forceDir*forceAmount/object2.mass It seems to move much more realistic, which way is right? and I have also being reading a little about impulses (don't understand yet), would that have any involvement in this? Thanks [Edited by - johnnyBravo on November 26, 2006 9:54:57 AM]

Share this post


Link to post
Share on other sites
I think you're confusing alot of topics, I'm not recognizing the way you're trying to handle the collision. Anyway, for a collision model you want to model it kinematically, using forces is just going to give you problems down the road. What you need is an exact equation to use for a collision.

Check out my article on the Coefficient of Restitution at Wikipedia. Scroll down to the "Use" section, and you'll see an equation that will give you an exact collision model to use. This will let you control the type of collision (elastic, inelastic, or somewhere inbetween) and be sure that the results are physically accurate.

I'll try to help you if you have any problems.

Share this post


Link to post
Share on other sites
nice article,

my spheres are now colliding off each other at the correct velocities.


Though I have a problem when they hit off centre, eg


I assume the equations either need to incorporate direction of the spheres to each other, or their positions. What do you think I should do now?

btw this is my source

D3DXVECTOR3 v1 = ships[i].linearVelocity;
D3DXVECTOR3 v2 = ships[j].linearVelocity;
float m1 = ships[i].mass;
float m2 = ships[j].mass;
float cof = 1;
ships[i].linearVelocity = ((cof+1)*m2*v2 + v1*(m1-cof*m2))/(m1+m2);
ships[j].linearVelocity = ((cof+1)*m1*v1 + v2*(m2-cof*m1))/(m1+m2);





Thanks


edit:
is scalar velocity the same as velocity or does it mean momentum or something completely different?

[Edited by - johnnyBravo on November 26, 2006 9:45:07 AM]

Share this post


Link to post
Share on other sites
The equations are formed in the collision's frame of reference. The article alludes to this, but doesn't directly show how to handle this (since it's not really the article's point). I should probably set up a website and write a few articles on this sort of thing at some point in the future.

What you need to do is form the collision vector = (A's position - B's position).normalized

Then take the dot product between your velocity vectors and this collision vector. That is the scalar velocity term you want to use in the equations.

After that you'll need to reconstruct the velocity terms back into the original frame of reference.

Here's the code from my own project for colliding spheres, with all the extraneous bits stripped out:

/*Collisions are modified by a slider
that changes the value of e between [0,1].

e = (V2Final - V1Final)
-----------------------
(V2Initial - V1Initial)

where velocities are along vector between bot1 and bot2

e = 0 represents inelastic collisions
e = 1 represents perfectly elastic collisions

the algorithm for implementing this is detailed in
Tricks of the Windows game programming gurus 2nd edition
by Andre LaMothe
page 847
"Real 2D Object-to-Object Collision Response (Advanced)"

Basically, the algorithm looks like:
1. Compute normal and tangent unit vectors to collision (n and t)
2. Transform the spheres' velocities into velocities along
n and t.

3. V1final = (e+1)M2V2 + V1(M1 - eM2)
------------------------
M1 + M2
V2final = (e+1)M1V1 - V2(M1 - eM2)
------------------------
M1 + M2

4. De-transform the velocities from n and t back into the cartesian
system.

SimOpts.ElasticCoefficient represents e

Also, see http://en.wikipedia.org/wiki/Coefficient_of_restitution
which Numsgil heavily contributed to.
*/


//sets a hard constraint that drags bots that are too close to each other apart
Vector3f normal = rob[x]->pos - this->pos;

float mindist = me->radius + rob[x]->radius;
mindist *= mindist;//squared

float currdist = normal.LengthSquared();

if(currdist < mindist) //bots colliding
{
currdist = sqrtf(currdist);
mindist = sqrtf(mindist);
normal /= currdist; //normalize normal

/**************************************/
//UPDATE CHANGES IN VELOCITY
const float e = SimOpts.ElasticCoefficient = 0.5f;
const float M1 = this->mass;
const float M2 = rob[x]->mass;

Vector3f V1 = (this->vel * normal) * normal;
Vector3f V2 = (rob[x]->vel * normal) * normal;

Vector3f V1f = ((e + 1.0f) * M2 * V2 + V1 * (M1 - e * M2))/
(M1 + M2);

Vector3f V2f = ((e + 1.0f) * M1 * V1 + V2 * (M2 - e * M1))/
(M1 + M2);

this->vel += V1f - V1;
rob[x]->vel += V2f - V2;
float overlap = mindist - currdist;

//UPDATE POSITIONS
normal *= overlap;

rob[x]->pos += normal * 0.5f;
this->pos -= normal * 0.5f;
}



The only thing to watch for is the overloading of the * operator between vectors (indicating a dot product).

Share this post


Link to post
Share on other sites
Yeah the overloaded operator confused me for a second :)

I'm pretty sure its working properly now... this is my d3dx version of your dot product section:

D3DXVECTOR3 normal;
D3DXVec3Normalize(&normal, &(ships[i].position - ships[j].position));

D3DXVECTOR3 V1 = D3DXVec3Dot(&(ships[i].linearVelocity), &normal)* normal;
D3DXVECTOR3 V2 = D3DXVec3Dot(&(ships[j].linearVelocity), &normal)* normal;




I have a few more questions, is it possible to give the ships different elasticity values? like just giving the two places where e is present in your code different values would be the same as giving the objects different elasticity?

And how does the equations above factor into providing torque?

I think it has something to do with the coefficient of friction, is this what I be looking at?

Thanks alot.

Share this post


Link to post
Share on other sites
Quote:
Original post by johnnyBravo
I'm pretty sure its working properly now... this is my d3dx version of your dot product section:
*** Source Snippet Removed ***


Looks right ;)

Quote:

I have a few more questions, is it possible to give the ships different elasticity values? like just giving the two places where e is present in your code different values would be the same as giving the objects different elasticity?


The Coefficient of Restitution is technically a property of a collision instead of an object. In real life, it depends a great deal on how the objects' surfaces interact when they touch. It's usually determined experimentally, and that value is used in further simulation.

As game programmers, we're working from the other direction, which means we need to fudge this particular issue. A good working solution is to give a COR for every object, and use the minimum of the two COR for the collision's COR. But really feel free to experiment. I don't think there are any really right or wrong answers when it comes to providing a COR, so long as its consistant and between [0,1].

Quote:

And how does the equations above factor into providing torque?

I think it has something to do with the coefficient of friction, is this what I be looking at?


The equation is strictly about the linear momentum of the colliding objects. Angular momentum isn't factored in at all. I haven't worked out the issue of generating torque before (for my purposes the linear momentum was enough), so you're largely on your own. But you can probably derive it without too much difficulty.

It will probably involve the velocity term perpindicular to the collision's velocity scalar you found above. This will be a 2 dimensional vector quantity (or 1 dimensional if you're doing 2D physics). A great deal of how you implement it is going to depend on your model for angular inertia and things like that.

This is the beginning of a very long road where things get pretty sticky. It's not for the faint of heart, and if you're delving into physics for a game that's not really about physics, you can quickly lose sight of the final goal and get swamped in the implementation details for physics (this is also true for graphics programming from what I've seen). Depending on your purposes, you'll probably need to:

1. Move to a 3rd party physics library. There are alot of high quality free engines out there. PhysX has recently moved to allow any developer to use its SDK free of charge (presumably to hype their physics card).

2. Learn a great deal of physics (things like inertial tensors, and you'll need to be able to use matricies for rotations, etc.). This can be alot of fun, but it's going to be alot of learning. By the end you probably will know as much as someone with a minor concentration in physics from a university.

3. Accept some limitations in your simulated model.

That said, I'm sure angular momentum isn't going to be too hard to figure out. If you're making a game that's about colliding spheres, making your own engine isn't too hard. If you want to delve into articulated bodies, joints, and this sort of thing, it's going to be alot of work.

Share this post


Link to post
Share on other sites
Do you have an integration step set up? This should be really easy if you've figured out collisions. Just add an Impulse vector to your sphere representing the thrust from the engines. Divide my mass, and use this as your acceleration vector. Then just integrate to find the changes in velocity.

The simplest integration method is Euler.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this