Advertisement

reflection vectors for bouncing

Started by May 03, 2002 08:05 AM
38 comments, last by endo 22 years, 9 months ago
I have used the following code to calculate the reflection vector for my ball, the problem is it just bounces back in the direction it came from Any idea why? I followed the theory from one of the tutorials on the nehe site.
  	if( ball.getActive( ) )		//if inactive ball is drawn but doesnt move

	{
		ball.moveBall( );
		MyPolygon hit;

		if( ballPaddleCollision( paddle, *ball.getLoc( ), ball.getRadius( ), hit ) )
		{
//			cout << *hit.getNormal( ) << endl;

//			cout << *ball.getMove( ) << endl;

			Vector3d newVector;
			Vector3d hitNormal = *hit.getNormal( );
			Vector3d ballMovement = *ball.getMove( );
			hitNormal.normalise( );
			ballMovement.normalise( );
			newVector = hitNormal + ballMovement * dotProduct( -ballMovement, hitNormal ) * 2;
			newVector = newVector * ballMovement.length( );
			ball.setMove( newVector );
		}
	}  
This line seems not to be right:

newVector = hitNormal + ballMovement * dotProduct( -ballMovement, hitNormal ) * 2;
shouldn''t it be:
newVector = ballMovement + hitNormal * dotProduct( -ballMovement, hitNormal ) * 2;

Hope that was the bug.
-----The scheduled downtime is omitted cause of technical problems.
Advertisement
Sorry, doesnt seem to have made any difference - although I''m sure its more correct than the way I had it
a-((a.b)/(b.b))*b is the component of a orthogonal to b. If the magnitude of b is 1 then that reduces to a-(a.b)*b. You don''t want orthogonal, but the reflection so it is a-2*(a.b)*b. (a.b)*b is the component of a parallel to b and (-a).b = -(a.b). If you normal either points the wrong direction or is does not have a magnitude of one then you don''t get the right answer.
Keys to success: Ability, ambition and opportunity.
I''m sure the normal is correct and as you can see the code normalises it before it is used.
That may very well be your problem. You wrote

newVector = newVector * ballMovement.length( );

ballMovement''s length is 1 if it is normalized. In fact, once your vectors are normalized, you have just lost the magnitude of your speed, which isn''t very good. You can try this

Normal = Normalize(Normal);
finalspeed = initialspeed + Normal * Dot(initialspeed, Normal) * 2

Don''t normalize the initialspeed. This should work if your normal is pointing outside the paddle. However, if your code really bounces the ball back in the direction it came from, then your code for evaluating the normal might have a problem.

Cédric
Advertisement
It seems the speed has to be normalised otherwise it tends to be amplified every time a collision occurs. Quite funny but not very helpful.

I am still sure that the normal is fine, it is a flat paddle at the bottom of the screen. When I print all the vertex data, including normal, to a file I get this:

normal : ( 0 , 1 , 0 )
( 52 , -88 , -10 )
( 52 , -88 , 10 )
( 82 , -88 , 10 )
( 82 , -88 , -10 )


This looks like it corresponds to the top polygon of the paddle exactly, apart from the changes due to translation.
Let''s take a look at your code (with omnibrain''s change)

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

If normal = (0,1,0) and ballmovement = (3,-4,0)

hitNormal = (0,1,0)
ballmovement = Normalize(ballmovement) = (3/5, -4/5, 0)
newVector = (3/5 + 0, -4/5 + 1 * -4/5 * 2, 0) = (3/5, 4/5, 0)
newVector = newVector * 1 (since ballMovement is normalized)

Notice that newVector = (3/5, 4/5, 0) regardless of the magnitude of ballmovement. You could have chose (6, -8, 0) and still get the same results. If you insist on keeping the code as it is, then you have to store the length of ballMovement _before_ normalizing it, and multiply by that variable at the end, instead of multiplying by ballMovement.length().

Cédric
If you are getting an amplification on reflection then your normal doesn''t have a magnitude of one. Lets use a simple case. You are bouncing off the x axis and the point of collision is the origin. Your velocity vector is (x,y) and the normal is (0,1). Your velocity vector after reflection is (x,y)-2*((0,1).(x,y))*(0,1) = (x,y)-2*y*(0,1) = (x,y)-(0,2y) = (x,y-2y)=(x,-y). Now how did your magnitude change?
Keys to success: Ability, ambition and opportunity.
Updated code:

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

hitNormal.normalise( );
ballMovement.normalise( );

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

ball.setMove( newVector );

This is how it stand at present, the speed after collision is fine - looks the same. The problem is in the angle of reflection, it is inconsistent. Looking at it carefully, the ball reflects at an angle increasing closer to 90 degrees, parallel with the normal. Any other thoughts? I was hoping to solve this and make some significant progress today....

This topic is closed to new replies.

Advertisement