OpenGL camera rotation

27,096

Solution 1

One of the more tricky aspects of 3D programming is getting complex transformations right.

In OpenGL, every point is transformed with the model/view matrix and then with the projection matrix.

the model view matrix takes each point and translates it to where it should be from the point of view of the camera. The projection matrix converts the point's coordinates so that the X and Y coordinates can be mapped to the window easily.

To get the mode/view matrix right, you have to start with an identity matrix (one that doesn't change the vertices), then apply the transforms for the camera's position and orientation, then for the object's position and orientation in reverse order.

Another thing you need to keep in mind is, rotations are always about an axis that is centered on the origin (0,0,0). So when you apply a rotate transform for the camera, whether you are turning it (as you would turn your head) or orbiting it around the origin (as the Earth orbits the Sun) depends on whether you have previously applied a translation transform.

So if you want to both rotate and orbit the camera, you need to:

  1. Apply the rotation(s) to orient the camera
  2. Apply translation(s) to position it
  3. Apply rotation(s) to orbit the camera round the origin
  4. (optionally) apply translation(s) to move the camera in its set orientation to move it to orbit around a point other than (0,0,0).

Things can get more complex if you, say, want to point the camera at a point that is not (0,0,0) and also orbit that point at a set distance, while also being able to pitch or yaw the camera. See here for an example in WebGL. Look for GLViewerBase.prototype.display.

The Red Book covers transforms in much more detail.

Also note gluLookAt, which you can use to point the camera at something, without having to use rotations.

Solution 2

Rather than doing this using matrices, you might find it easier to create a camera class which stores a position and orthonormal n, u and v axes, and rotate them appropriately, e.g. see:

https://github.com/sgolodetz/hesperus2/blob/master/Shipwreck/MapEditor/GUI/Camera.java

and

https://github.com/sgolodetz/hesperus2/blob/master/Shipwreck/MapEditor/Math/MathUtil.java

Then you write things like:

if(m_keysDown[TURN_LEFT])
{
    m_camera.rotate(new Vector3d(0,0,1), deltaAngle);
}

When it comes time to set the view for the camera, you do:

gl.glLoadIdentity();
glu.gluLookAt(m_position.x, m_position.y, m_position.z,
              m_position.x + m_nVector.x, m_position.y + m_nVector.y, m_position.z + m_nVector.z,
              m_vVector.x, m_vVector.y, m_vVector.z);

If you're wondering how to rotate about an arbitrary axis like (0,0,1), see MathUtil.rotate_about_axis in the above code.

Solution 3

If you don't want to transform based on the camera from the previous frame, my suggestion might be just to throw out the matrix compounding and recalc it every frame. I don't think there's a way to do what you want with a single matrix, as that stores the translation and rotation together.

I guess if you just want a pitch/yaw camera only, just store those values as two floats, and then rebuild the matrix based on that. Maybe something like pseudocode:

onFrameUpdate() {
  newPos = camMatrix * (0,0,speed) //move forward along the camera axis
  pitch += mouse_move_x;
  yaw += mouse_move_y;

  camMatrix = identity.translate(newPos)
  camMatrix = rotate(camMatrix, (0,1,0), yaw)
  camMatrix = rotate(camMatrix, (1,0,0), pitch)
}
Share:
27,096
user1318091
Author by

user1318091

Updated on July 09, 2022

Comments

  • user1318091
    user1318091 almost 2 years

    In OpenGL I'm trying to create a free flight camera. My problem is the rotation on the Y axis. The camera should always be rotated on the Y world axis and not on the local orientation. I have tried several matrix multiplications, but all without results. With

    camMatrix = camMatrix  * yrotMatrix 
    

    rotates the camera along the local axis. And with

    camMatrix = yrotMatrix * camMatrix
    

    rotates the camera along the world axis, but always around the origin. However, the rotation center should be the camera. Somebody an idea?

  • SigTerm
    SigTerm about 12 years
    Camera matrix already contains necessary vectors (transposed). No need for extra calculations and gluLookAt.
  • Stuart Golodetz
    Stuart Golodetz about 12 years
    @SigTerm: True enough, I guess I missed a trick there :) Thanks.