Code: Select all
// Include the Irrlicht header
#include "irrlicht.h"
#include <assert.h>
#pragma comment(lib, "Irrlicht.lib")
// Irrlicht Namespaces
using namespace irr;
using namespace core;
vector3df reflectVectorFromSurface(const vector3df & incident,
const vector3df & surfaceNormal)
{
vector3df reflection(incident);
const f32 dot = vector3df(reflection).normalize().dotProduct(vector3df(surfaceNormal).normalize());
// I'm assuming that the surface is double sided, and that rays coming from inside it
// are reflected internally. If you want to make it single sided, perform this check.
//if(dot > 0.f)
// return incident;
// Otherwise, we have to reject parallel vectors or we get NaN results.
if(equals(dot, 1.f))
return incident;
// Pretend that it's being emitted from the surface.
reflection.invert();
quaternion MrQuaternion;
// Calculate the quaternion that will rotate the (inverted) incident to match the normal.
(void)MrQuaternion.rotationFromTo(reflection, surfaceNormal);
// Make it a matrix
matrix4 rotationMatrix;
MrQuaternion.getMatrix(rotationMatrix);
// And apply it twice to the inverted incident vector.
rotationMatrix.rotateVect(reflection);
rotationMatrix.rotateVect(reflection);
return reflection;
}
void testReflection(const vector3df & incident,
const vector3df & surfaceNormal,
const vector3df & expectedReflection)
{
vector3df reflection = reflectVectorFromSurface(incident, surfaceNormal);
(void)printf("Result %f %f %f\n", reflection.X, reflection.Y, reflection.Z);
assert(reflection == expectedReflection);
}
int main()
{
testReflection(vector3df(5, 0, 0), vector3df(-1, 0, 1), vector3df(0, 0, 5));
// This is coming from inside the surface. We'll reflect it, but it could
// also be emitted; see the comments in reflectVectorFromSurface()
testReflection(vector3df(-5, 0, 0), vector3df(-1, 0, 1), vector3df(0, 0, -5));
// This is coming in orthogonally, so should be reflected directly back.
testReflection(vector3df(5, 0, -5), vector3df(-1, 0, 1), vector3df(-5, 0, 5));
// This is perpendicular, so should be emitted unchanged.
testReflection(vector3df(5, 0, 0), vector3df(1, 0, 0), vector3df(5, 0, 0));
}