You can do this using the dot product. Move the problem to 2D first.
Here is a solution in 2D:
Code:
struct ball
{
int x;
int y;
int lastx;
int lasty;
float xinc;
float yinc;
};
void ComputeReflection2D(ball &_theball)
{
//Form a right triangle based on last position
//Since we know we have hit a wall our current location is the basis for the right
//triangle
//The X vector or base of triangle
int diffx=_theball.lastx-_theball.x;
//The Y vector or height of triangle
int diffy=_theball.lasty-_theball.y;
//The length of the hypotenuse - the path we just took
int length=sqrt((diffx*diffx)+(diffy*diffy));
//The new vectors normalized
_theball.xinc=(float)(diffx/length);
_theball.yinc=(float)(diffy/length);
//Update last position for next hit calculation
_theball.lastx=_theball.x;
_theball.lasty=_theball.y;
}
Notice that the above equation knows nothing about the wall. In 2D you really don't need to unless you want slanted walls which then you must take the normal into account. But for simple boxed in playing field you can assume that if you have entered the above function...you have hit a wall.
Quickly you will notice that this can also be accomplished by using cos(). Essentially that is what the code is doing, if I wrote it right. It's been sometime since I approached this problem.
But in 3D this is a very simple calculation and could be used in 2D as well as long as Z was always assumed to be 1.0f.
Here is the formula:
Arccos(theta)=||N dot V||
Or the arccos of theta is equal to the magnitude of the dot product of the normal to the plane and the vector in question. We need the magnitude because we want this to be normalized.
So the angle between two vectors in 3D can be computed by taking the arccos of the dot product of the two vectors (magnitude for non-unit vectors).
Since you know the normal and you know the vector of the ball you can compute the reflection angle quite easily.
The vector for the ball is the current position, but it might have to be computed by:
ball.vector=ball.pos-ball.lastpos;
Just simply using ball.pos will only work if your world is centered at 0,0,0 - which it should be. If the ball is moving to the left that would mean that x would be less than 0 which would make the formula work correctly.
This should work for your needs.
Code:
void ComputeReflection3D(Vector3 &NormalVector,Vector3 &BallVector,Vector3 &BallVelocityVector)
{
//Normalize the BallVector
Vector3 nrmBallVector=Vector3Normalize(BallVector);
//Compute dot product
float dot=Vector3Dot(NormalVector,nrmBallVector);
//Now based on dot product compute new BallVelocityVectors
...
}
Again if this doesn't work exactly as coded I apologize. I did get perfect reflections working in my pong game but that was ages ago.