I'm working on a scenario that involves some cone meshes that are to be used as spot lights in a deferred renderer. I need to scale, rotate and translate these cone meshes so that they point in the correct direction. According to one of my lecturers I can rotate the cones to align with a direction vector and move them to the correct position by multiplying its model matrix with the matrix returned by this,
glm::inverse(glm::lookAt(spot_light_direction, spot_light_position, up));
however this doesn't seem to work, doing this causes all of the cones to be placed on the world origin. If I then translate the cones manually using another matrix it seems that the cones aren't even facing the right direction.
Is there a better way to rotate objects so that they face a specific direction?
Here is my current code that gets executed for each cone,
//Move the cone to the correct place
glm::mat4 model = glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
spot_light_position.x, spot_light_position.y, spot_light_position.z, 1);
// Calculate rotation matrix
model *= glm::inverse(glm::lookAt(spot_light_direction, spot_light_position, up));
float missing_angle = 180 - (spot_light_angle / 2 + 90);
float scale = (spot_light_range * sin(missing_angle)) / sin(spot_light_angle / 2);
// Scale the cone to the correct dimensions
model *= glm::mat4(scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, spot_light_range, 0,
0, 0, 0, 1);
// The origin of the cones is at the flat end, offset their position so that they rotate around the point.
model *= glm::mat4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, -1, 1);
I've noted this in the comments but I'll mention again that the cones origin is at center of the flat end of the cone, I don't know if this makes a difference or not, I just thought I'd bring it up.
Your order of the matrices seems correct, but the lookAt function expects:
glm::mat4 lookAt ( glm::vec3 eye, glm::vec3 center, glm::vec3 up )
Here eye is the location of the camera, center is the location of the object you are looking at (in your case if you dont have that location, you can use spot_light_direction + spot_light_position ).
so just change
glm::lookAt(spot_light_direction, spot_light_position, up)
to
glm::lookAt(spot_light_position, spot_light_direction + spot_light_position, up)