Jump to content

  • Log In with Google      Sign In   
  • Create Account


Calculating the new direction after collision


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 Floru   Members   -  Reputation: 124

Like
Likes
Like

Posted 13 August 2001 - 11:39 PM

Hi! I previously asked about collision detection with lines and circles and I got it work. Thanks for help! Now I''d like to know how should I calculate the new direction after a collision with line or circle? I have following variables for the objects: double dMovX; double dMovY; I made it work so that if the object hits something when going to right I just multiply the dMovX with -1 so that it changes direction etc. But it doesn''t look realistic with lines.Could someone tell how to do this? At most I''m intrested in collision with circles and lines. Floru

Sponsor:

#2 johnb   Members   -  Reputation: 347

Like
Likes
Like

Posted 14 August 2001 - 12:06 AM

The way a collision causes an object to change it''s motion is through an impulse. This causes an instantaneous change in momentum, with the change given by the size and magnitude of the impulse. For a single moving object you can ignore the mass and work with velocity rather than momentum.

In practice this means you need to:
1) work out the direction of the collision. e.g. for a circle/ball hitting a line/surface without friction it will be the perpendicular/normal direction.
2) work out the impact speed, the speed in the direction of the collision, i.e. the speed towards the line/surface.
3) work out the impulse. If there''s no rotation it will be simply between 1 and 2 times the impact speed, with 1 being no bounce and 2 being maximum bounce. It is in the direction as the normal/perpendicular, away from the edge/surface.
4) Add it to the object velocity to get the velocity after the collision.

This is for an object hitting a fixed edge/surface, in 2D or 3D, ignoring friciton and rotation. These can be added in to the above proceedure but they make the calculations a lot more complex, especially in 3D.

#3 ragonastick   Members   -  Reputation: 134

Like
Likes
Like

Posted 14 August 2001 - 12:09 AM

You need to find the surface normal, which is pretty much a line at 90 degrees to the point at which you are colliding with. Then, the angle between the ball''s original vector and the ball''s new vector are equal, but on opposite sides of the normal.

Trying is the first step towards failure.

#4 Floru   Members   -  Reputation: 124

Like
Likes
Like

Posted 14 August 2001 - 12:14 AM


Thanks! But could you please give some kind of example because I''m not so good at maths? If lines are described with two points (x1,y1 and x2,y2) and I know when for example that a ball hits the line. And I know what is ball''s direction. And there is no need to calculate friction and rotation.

Floru

#5 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 15 August 2001 - 06:18 PM

One way is to reflect the component of the ball''s velocity in the direction of the normal to the line.

I.e:
Using (dMovX, dMovY) as the ball''s initial velocity, and points (x1,y1) and (x2,y2) as defining the line.

; Find line normal to line (as (nx, ny))
nx = y2 - y1 ; Find direction
ny = -(x2 - x1)
length = SquareRoot (nx*nx + ny*ny)
nx = nx / length ; Normalise (scale to length 1)
ny = ny / length
; Find component of ball''s velocity in direction of normal
dotProd = dMovX * nx + dMovY * ny
componentX = nx * dotProd
componentY = ny * dotProd
; Reflect this component of the ball''s velocity
newDMovX = dMovX - 2 * componentX
newDMovY = dMovY - 2 * componentY

This is off the top of my head, and hasn''t been tested.
I suggest looking up normals, vector normalization and dot product (or simply 2D vector arithmetic in general).

#6 AblazeSpace   Members   -  Reputation: 161

Like
Likes
Like

Posted 15 August 2001 - 07:46 PM

I have some code for calculation the new directions.


// vDelta = Distance between the two actors:
float fContactAngle,
fXClosingVelocity, fYClosingVelocity, fResVelocity, fXContactVelocity,
fYContactVelocity, fClosingAngle, fMassFactor, fMass1, fMass2, fAdiff, fPortion;

// Determine the angle of contact
if(vDelta.fX != 0)
{
fContactAngle = (float) atan(vDelta.fY/vDelta.fX);
if(fContactAngle < 0)
fContactAngle = -fContactAngle;
}
else
fContactAngle = (float) PId2;

// To determine how the objects will rebound off of each
// other, we are not concerned with the speed of each
// object, but rather the relative, or closing, speeds
// of the two objects.
fXClosingVelocity = pActor2->vWorldVelocity.fX-pActor1->vWorldVelocity.fX;
fYClosingVelocity = pActor2->vWorldVelocity.fY-pActor1->vWorldVelocity.fY;
// Calculate the x & y speed in the direction of contact
fResVelocity = ASFastSqrt(fXClosingVelocity*fXClosingVelocity+fYClosingVelocity*fYClosingVelocity);
fXContactVelocity = (float) cos(fContactAngle)*fResVelocity;
fYContactVelocity = (float) sin(fContactAngle)*fResVelocity;

// Now, determine the closing angle.
if(fXClosingVelocity != 0)
{
fClosingAngle = (float) atan(fYClosingVelocity/fXClosingVelocity);
if(fClosingAngle < 0)
fClosingAngle = -fClosingAngle;
}
else
fClosingAngle = (float) PId2;

// Hmmmm...
// With equal masses,
// the max rebound speed is 1/2 the closing speed.
// With unequal masses,
// the max rebound speed is the closing speed.
// Okay then,
// Normalize the two masses to be: mass1 + mass2 = 2.0
fMassFactor = 2/(pActor1->fMass+pActor2->fMass);
fMass1 = pActor1->fMass*fMassFactor;
fMass2 = pActor2->fMass*fMassFactor;

// Quadrant-specific stuff
if(pActor1->vWorldPos.fX > pActor2->vWorldPos.fX)
{
if(pActor1->vWorldPos.fY < pActor2->vWorldPos.fY)
{
// pActor1 is contacting upper right quadrant of pActor2
if(fYClosingVelocity < 0)
{
if(fXClosingVelocity < 0)
fAdiff = (float) PI-fContactAngle-fClosingAngle;
else
fAdiff = fContactAngle-fClosingAngle;
}
else
fAdiff = fContactAngle+fClosingAngle;
fPortion = (float) cos(fAdiff);
pActor1->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass1;
}
else
{
// pActor1 is contacting lower right quadrant of pActor2
if(fYClosingVelocity > 0)
{
if(fXClosingVelocity < 0)
fAdiff = (float) PI-fContactAngle-fClosingAngle;
else
fAdiff = fContactAngle-fClosingAngle;
}
else
fAdiff = fContactAngle+fClosingAngle;
fPortion = (float) cos(fAdiff);
pActor1->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass1;
}
}
else
{
if(pActor1->vWorldPos.fY < pActor2->vWorldPos.fY)
{
// pActor1 is contacting upper left quadrant of pActor2
if(fYClosingVelocity < 0)
{
if(fXClosingVelocity < 0)
fAdiff = fContactAngle-fClosingAngle;
else
fAdiff = (float) PI-fContactAngle-fClosingAngle;
}
else
fAdiff = fContactAngle+fClosingAngle;
fPortion = (float) cos(fAdiff);
pActor1->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass1;
}
else
{
// pActor1 is contacting lower left quadrant of pActor2
if(fYClosingVelocity > 0)
{
if(fXClosingVelocity < 0)
fAdiff = fContactAngle-fClosingAngle;
else
fAdiff = (float) PI-fContactAngle-fClosingAngle;
}
else
fAdiff = fContactAngle+fClosingAngle;
fPortion = (float) cos(fAdiff);
pActor1->vWorldVelocity.fX -= fXContactVelocity*fPortion*fMass2;
pActor1->vWorldVelocity.fY += fYContactVelocity*fPortion*fMass2;
pActor2->vWorldVelocity.fX += fXContactVelocity*fPortion*fMass1;
pActor2->vWorldVelocity.fY -= fYContactVelocity*fPortion*fMass1;
}
}



At the moment it only works for 2D. Could someone help me to add the third dimension??

#7 it   Members   -  Reputation: 122

Like
Likes
Like

Posted 16 August 2001 - 02:33 AM

A realy simple technique,
which looks pretty good is to swap the velocity vectors of the colliding bodies.

//store the velocity of the first body in a seperate variable
velocity_body1 = intermediate_storage;

//set velocity body 1 = velocity of body 2
velocity_body1 = velocity_body2;

//set velocity of body 2 = velocity body 1 original value
velocity_body2 = intermediate_storage;

and you''ve swapped there velocity vectors!!
its not physically perfect, but its simple ao give it a shot


#8 Floru   Members   -  Reputation: 124

Like
Likes
Like

Posted 27 August 2001 - 01:58 AM


Thanks for help!

I have now a working collision detection and I also know how to calculate new direction. I have a problem and I don''t know how common it is. I''ve seen demos where balls bounce in box or in area but sometimes the balls don''t work correctly. For example they stick into walls or go through them or bounce funny. I have same kind on problems. Rarely but I''d like to my system work perfectly. I also have a object which is controlled by the user (like in pinball game the flipper). But usually the balls go through. So how can I make my system perfect? Is this a common problem?

Floru

#9 MothaBrain   Members   -  Reputation: 122

Like
Likes
Like

Posted 27 August 2001 - 02:31 AM

I think the sticking-together problem is caused by the fact, that you only do coll-detection in finite time steps, i.e. you can only detect collisions if objects stick together already.
(Also if sometimes only a little bit)
I''ve had and still have some problems with that penetration problem, but you can solve it.
Try to find out "how much" the one object is inside the other one and then move your object away along the collision normal by your measured penetration. This will create a non-penetration state of the bodies.

A little bit hard to explain, but perhaps have a look into the FastCar source code.
http://www.oxforddynamics.co.uk

Ciao!
Roppi

http://www.moonbyte.de


#10 Floru   Members   -  Reputation: 124

Like
Likes
Like

Posted 28 August 2001 - 04:11 AM


Thanks for the link but the documentation was quite complicated although the demo was quite impressive. Is there any simpler sample or documentation? I think some info how flipper games are made could also be useful. What about the sticking problem?

Floru




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS