Advertisement

reflection vectors for bouncing

Started by May 03, 2002 08:05 AM
38 comments, last by endo 22 years, 9 months ago
Now, this doesn''t work at all. The idea of collision is that a certain normal force is applied over a brief period of time. Integrating this force gives us the impulse, which is a change in the linear momentum of the object (= speed * mass).

To deal with collisions properly (ie.: in a convincing way), you should express it like so (although I''m sure there are other ways to look at it):

finalspeed = initialspeed + impulse (vectors)

impulse is a vector orientated along the surface normal, so

impulse = Normal * k

The impulse should not be affected by the component of speed that is parallel to the plane, only the component that is parallel to the normal. This is why we use the dot product, and so we get the formula I posted in my original post:

finalspeed = initialspeed + Normal * Dot(initialspeed, -Normal) * r

where r is a coefficient of "restitution" that varies between 1 and 2.

r = 1.5
Vector3d newVector;
Vector3d hitNormal = *hit.getNormal( );
Vector3d ballMovement = *ball.getMove( );
hitNormal.normalise( );
newVector = ballMovement + hitNormal * dotProduct(ballMovement, -hitNormal ) * r;
ball.setMove( newVector );

Cédric
The problem must be elsewhere then, I copied cedricl's code exactly and had a problem with the ball accelerating after the collision. The code I posted last is the closest I have get except for the problem with the reflection angle - so I'm still stuck

[edited by - endo on May 3, 2002 8:10:02 PM]
Advertisement
Sorry for bumping this, but what is the likely cause of my reflection vector ebcoming increasingly closer to 90 degrees, ie parallel with normal?
hey i like this board. just got done proving division of a scalar against a vector is defined anon. thought hey time for me to get a name =)

anyway:

this has to be wrong:
ballMovement.normalise( ); newVector = newVector * ballMovement.length( );

i took out a middle line to make it obvious. ballMovement.length() == 1 as true by definition of a normal at the point you grab it. you need to save its length ahead of time. then normalise it.

havent decided if thats your error yet. im still reading the thread =) but its definatly one bug.

[edit bah it was in the thread.]

[edited by - declspec on May 5, 2002 9:49:59 AM]
picture the crossproduct vector of the
-move X normal = TowardsYou. right?

But now imagine
newmove X normal = -TowardsYou

normal X -TowardsYou = newmove // ops on a cross product

replacement of towardsyou

normal X - ( -move X normal) = newmove

note:
in this version move doesnt need to be normalized first (read squareroots removed). the info about magnitude is preserved and applied in the crossproduct ops.

just a different way to look at the prob. using crossproducts implies having to solve out each component of the vector. thats where it went wrong. a third approach would be rotations.

[edited by - declspec on May 5, 2002 10:14:34 AM]

notes that make this approach seem solid:
towardsyou is arbitrary but note that the target resultant vector, the normal vector and the negation of the move vector are all coplanar. coplanar crossproducts will have scalar transformations of the resultant vector.

thats to say i draw two lines on a page crossproduct them and i get a line coming out of the page. now no matter what i do to the lines in the page their cross product will always be on that ray coming out of the page. so that accounts for using the direction right. the up and down of it using your old "curl your fingers in the right hand through the first vector first" aint hard to see.

now bout magnitude. the vectors share magnitude by our game rules.

so we know the resultant vector over both cross products will be on the same ray and have the same magnitude. sooo that accounts for magnitude and direction.... hence my recomendation of crossproducts to avoid division.

note again:
that the magnitude of the crossproduct is equal to the two magnitudes mulitplied by each other and the sine of the angle between them. i say this cause if the ball had -move = normal the resultant crossproduct vector would be 0. while the above is still mathematically clean important when you actual write the code would be to note the possibility of 0. never pass a 0 case without examining what will happen as they are lightning rods for bugs.




[edited by - declspec on May 5, 2002 10:23:54 AM]

[edited by - declspec on May 5, 2002 10:30:14 AM]
Thanks for the reply declspec, but seeing as my maths brain is still catching up with my C++ brain I am having difficulty picturing 3d vector cross products Most of your post could well have been in Mongolian and I probably would've understood just as well.

Anyway despite this, it is better now than it was. Now the reflection vector is exactly the same as the original, which seems like progress to me. Here is the code I used based on what you said:

.
.
.
Vector3d newVector;
Vector3d hitNormal = *hit.getNormal( );
Vector3d ballMovement = *ball.getMove( );

GLfloat length = ballMovement.length( );
hitNormal.normalise( );
ballMovement.normalise( );

newVector = ballMovement + hitNormal * -crossProduct( -ballMovement, hitNormal ) * 2;
newVector = newVector*length;

ball.setMove( newVector );
.
.
.

The sign before the crossProduct(..) appears to make no difference



[edited by - endo on May 5, 2002 10:46:45 AM]
Advertisement
ok well skipping to the code i think might work since your actively working this thread i would try:

newVector = CrossProduct( -ballMovement, hitNormal);
newVector = CrossProduct( hitNormal, -newVector);

no normalizing... none replace the code starting with the normalizing with the above.

		if( ballPaddleCollision( paddle, *ball.getLoc( ), ball.getRadius( ), hit ) )		{//			cout << *hit.getNormal( ) << endl;//			cout << *ball.getMove( ) << endl;			Vector3d newVector;			        Vector3d hitNormal = *hit.getNormal( ); //assuming this is magnitude 1        newVector = CrossProduct( -ballMovement, hitNormal);        newVector = CrossProduct( hitNormal, -newVector);        Vector3d ball.setMove( newVector );		} 
Nice try, now the ball hits the polygon and travels off along the x axis. The normal of the polygon it is hitting is definitly ( 0, 1, 0 ) just in case that was the next question
hmm interesting. wonder where i went wrong. you did see you read a guide to this didnt ya. got a link we''ll try to sort out the guides version as it relates to your code. also i''ll plug some numbers. still curious where i went wrong =)
I have a workaround for the problem but I''m sure there must be a proper way to fdo it and a reason why it doesn''t work as it should in my program, kinda worrying really.....

Anyway I just added the original absolute Y value to the new vector which was travelling along the X axis.

newVector = crossProduct( -ballMovement, hitNormal );
newVector = crossProduct( hitNormal, -newVector );
newVector.triple[ Y ] += absolute( ballMovement.triple[ Y ] );

ball.setMove( newVector );

Certainly not ideal but it''ll have to do until I find a better way. Now off to the library to find some maths books...

This topic is closed to new replies.

Advertisement