View Full Version : Simple Camera Rotation Around a Point

11-02-2016, 08:28 PM
I'm trying to do simple camera rotation through mouse trackball. Currently, I calculate the displacement of the mouse and use that to generate the rotation matrix, which I use to update the camera position and up vectors.

However, the camera only rotates along one single plane right now. For example, it will move left and right if I move my mouse in those directions at first, but if I turn it 90 degrees to one side, it will rotate up and down only even if I am stilling moving my mouse left to right.

The following code is used to calculate the viewpoint matrix. rotAxis and rotAngle are generated by trackball mapping which maps the mouse position to a sphere.

I know I need to multiply something by the rotation matrix that takes into account the location of the camera in respect to the world matrix. However, I have no idea what that matrix is.

cam_pos = [unknown_matrix] * glm::rotate(cam_pos, rotAngle / 180.0f * glm::pi<float>(), rotAxis);
cam_up = [unknown_matrix] * glm::rotate(cam_up, rotAngle / 180.0f * glm::pi<float>(), rotAxis);
V = glm::lookAt(cam_pos, cam_look_at, cam_up);

Can someone please help me out?

11-03-2016, 04:20 AM
It should be merely a different rotation axis, although I would have to play with the code a bit to get it to work and tell you exactly how to code it. The LookAt doesn't seem to make sense to me; that may be part of the problem. Cam_pos should be a vector, not a matrix if you are going to store it separately from the View matrix (actually a 3D position stored as a vector and not even an actual vector). I'm still getting my caffeine this morning... starting to get my eyes open. cam_up is the area "above" the camera; to move the camera up you need to move the position. UP is just a vector that can either be pulled out of the view matrix from the previous frame or calculated. But I would have taken an entirely different approach.

I would do something more like this, where the PivotPoint matrix could be the object's world matrix:

glm::mat4 PivotPoint;
glm::mat4 Camera;
glm::mat4 View;
float RotationSPeed = 0.05f;

PivotPoint = glm::mat4(1.0f);
Camera = glm::mat4(1.0f);
View = glm::mat4(1.0f);
Camera = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -1.0f)) * Camera; //Offset it by some distance from the pivot point

do //fake game loop per frame
if (OrbitRight) Camera = glm::rotate(glm::mat4(1.0f), RotationSpeed, glm::vec3(0.0f, 1.0f, 0.0f)) * Camera;
if (OrbitLeft) Camera = glm::rotate(glm::mat4(1.0f), -RotationSpeed, glm::vec3(0.0f, 1.0f, 0.0f)) * Camera;
if (OrbitUp) Camera = glm::rotate(glm::mat4(1.0f), RotationSpeed, glm::vec3(1.0f, 0.0f, 0.0f)) * Camera;
if (OrbitDown) Camera = glm::rotate(glm::mat4(1.0f), -RotationSpeed, glm::vec3(1.0f, 0.0f, 0.0f)) * Camera;
if (PanRight) PivotPoint = glm::translate(glm::mat4(1.0f), glm::vec3(0.1f, 0.0f,0.0f)) * PivotPoint;
if (PanLeft) PivotPoint = glm::translate(glm::mat4(1.0f), glm::vec3(-0.1f, 0.0f,0.0f)) * PivotPoint;
if (ZoomIn) Camera = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f,0.1f)) * Camera;
if (ZoomOut) Camera = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f,-0.1f)) * Camera;
if (Forward) PivotPoint = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f,0.1f)) * PivotPoint;
if (Back) PivotPoint = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f,-0.1f)) * PivotPoint;

View = PivotPoint * Camera;
View = glm::inverse(View); //More academic than actually necessary.

I should mention that I haven't tested this code and I may have the order of multiplication wrong in any or all of these cases. If so, just reverse the multiplication order. Reversing the multiplication order should make the difference between rotating on it's own axis or orbiting the origin, which in this case would be the position of the pivot point matrix, since they are being combined each frame to form a View matrix. View matrices are inverted. You can either do that explicitly, or when you are altering the Camera matrix each frame you can just do the alteration backwards (6 of one or half a dozen of the other). Also, I did not put in any code to prevent from zooming in too much and coming out the other side which could be a problem. I don't think you have to correct the position the camera looks at and that as long as you don't zoom through the object or something it should always look towards the origin/pivot. If I'm wrong on that, you could use LookAt to have it look at the origin.