There is a way simpler way to get a reflection vector.
Let's construct it piece by piece. Say you have an incoming vector V:
And you would like to obtain the reflected vector R:
You also happen to know the normal vector of your surface, N:
So, we're aiming at something that is roughly the opposite direction of V. We can obtain the dot product of V and N, and it'll give us, well, something for a start:
(I'm visualising this rather unconventionally, just note that the dot product will be negative in this instance, something like -0.8)
Now check this out. What if you take that dot product, and multiply V with it in some way? And then add
(V*d)
on top of N?
Hell yeah, we're GETTING somewhere now! (actually you should subtract to get this result, because remember, the dot product is negative in this case)
Now, this is not actually it. Instead of
N - V*d
let's actually try
-2N*d + V
and see what happens:
This expression can be simplified a bit:
V - 2*N*d
So yeah, there's your formula right there.
const float doubleDot = 2.0f * direction.Dot( normal );
return direction - (doubleDot * normal);
If you don't believe me, here's how some engines & maths libraries do it:
https://github.com/godotengine/godot/blob/master/core/math/vector3.h#L516 -> Godot game engine
https://github.com/g-truc/glm/blob/master/glm/detail/func_geometric.inl#L104 -> GLM maths library
I'm surprised this isn't present in some engines & physics engines I know.
What you can do next is also add a bias that multiplies the influence of the normal:
Vector Reflect( const Vector& normal, float normalBias = 1.0f )
{
const float doubleDot = 2.0f * normalBias * Dot( normal );
return *this - (doubleDot * normal);
}
And then have a random number on each bounce to simulate surface imperfections. I guess you don't want that, but it's just a fun thought.
Also I honestly don't know how people came up with the exact formula, and I don't know myself, but through experimentation it eventually makes somewhat of a sense. No wonder I'm failing Maths in college lmao. But yeah, hope this helps!