Introduction
This post will talk on how to build reflection matrix along a given axis using simple projection equations.
This matrix could be useful in a variety of gameplay mechanics, from simple physics used to bounce bullets off the walls to complex ray tracing techniques to bounce rays off the meshes from a light source.
The image below gives an overview of what we are trying to achieve.
Variables in play
These are the following variables in play:
- b = incident vector
- b’ = reflected vector
- q = axis along with reflection should happen
- p = projection vector of b along q
For input, we would just need the single axis, which is a normalized vector. It should be normalized to make the calculations easier and to not have the resultant matrix modify the magnitude of vectors that operate on it.
For those short on time and couldn’t read through the explanation, here are the equations:
Reflection Matrix: I – 2 qqT
Reflection vector: b’ = b – (2 qqT) b
There’s also a code snippet at the bottom.
Reflection Matrix generation
Given the incident vector(b), we want to reflect on the plane, which is defined by the normal vector q, to produce the reflected vector(b’).
We restrict the axis vector (q) to be normalized so that qTq will be equal to 1 and make calculations simpler.
To give a general idea, we need to add/subtract a mystery vector from b to land at vector b’.
This vector happens to be the projection(p) of vector b on our given axis vector q.
On adding -p to b will put us on the plane perpendicular to q. Adding on more -p to it will give us our reflection vector.
The image below should summarize all the equations in play that are going to be translated to the code.
//NOTE: This code is not optimized.
// Mat3x3 and Vec3 are my custom structures
inline Mat3x3 makeReflectionMatrix(const Vec3& axis)
{
Mat3x3 refMat = Mat3x3::Identity();
Vec3 normAxis = axis;
normAxis.normalize();
for(int i = 0; i < 3; ++i)
{
for(int j = 0; j < 3; ++j)
{
float val = refMat.get(i, j); // get ith row and jth col element
val = val - (2 * normAxis.buffer[i] * normAxis.buffer[j]);
refMat.set(i, j, val);
}
}
return refMat;
}
Conclusion
Hope this helped someone in some capacity.
As always, please do visit again 🙂