I am rendering a 3D model of an object, and I want the user to be able to rotate around that object by dragging the mouse. To do this, I want to use the cursor position to continually update the modelview matrix.
To start with, my modelview matrix is:
1 0 0 0
0 1 0 0
0 0 1 -100
0 0 0 1
So the camera is looking at the origin of the object, and 100 units away from it. Let’s say the mouse now moves onto the right-hand side of the screen. This means I want the camera to rotate around the object – by 90 degrees, for example.
In order to compute the new modelview matrix, I take the identity matrix, rotate it by 90 degrees, and then move away from the object along the camera’s z-axis by using glm::translate().
However, the problem I am having is that glm::translate() seems to move the matrix with respect to the world coordinate system, not the camera coordinate system. Therefore, “moving away from the object along the camera’s z-axis” does not hold, because the z-axes of the world and camera coordinate systems are no longer aligned after the rotation.
Please could somebody explain how I should be achieving this?
It depends upon the order in which the individual transformations are multiplied. Matrix multiplication isn’t commutative (symmetric), i.e. AB isn’t equal to BA.
The GLM functions which emulate the legacy fixed-function OpenGL matrix functions perform multiplication with the passed-in matrix on the left and the generated matrix (translation, rotation, etc) on the right. So the matrix generated by glm::translate() results in the translation being interpreted within the coordinate system established by the passed-in matrix.
If you want to rotate the object while keeping it in front of the camera, you need to start with an identity matrix, translate by (0,0,-distance), then rotate. Alternatively, generate the translation and rotation separately (each starting with an identity matrix), then multiply them with the translation on the left and the rotation on the right.
Orbiting the camera around the object is identical, except that the rotation angle has the opposite sign, i.e. rotating the camera clockwise about an object is the same as rotating the object anti-clockwise.
If you want to apply an incremental rotation to an object, where the incremental rotation is defined in eye space rather than object space, it needs to be multiplied on the left, i.e. rotation = increment * rotation. In order to do this, the translation and rotation components of the model-view matrix need to be kept separate, as the increment needs to be applied between the translation and the current rotation.