# Calculating the new direction after collision

###
#1
Members - Reputation: **124**

Posted 13 August 2001 - 11:39 PM

###
#2
Members - Reputation: **351**

Posted 14 August 2001 - 12:06 AM

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
Members - Reputation: **134**

Posted 14 August 2001 - 12:09 AM

*Trying is the first step towards failure.*

###
#4
Members - Reputation: **124**

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:

Posted 15 August 2001 - 06:18 PM

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
Members - Reputation: **161**

Posted 15 August 2001 - 07:46 PM

// 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
Members - Reputation: **122**

Posted 16 August 2001 - 02:33 AM

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
Members - Reputation: **124**

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
Members - Reputation: **122**

Posted 27 August 2001 - 02:31 AM

(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
Members - Reputation: **124**

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