With the above tutorial I highly suggest to stop reading at (or skipping) the chapter Euler Angles, unless first person is all you need. Mostly because otherwise it might be 1-2 weeks before a "I have gimbal lock and/or my camera rotation is acting funny"-thread. Also, the assumption that 0,1,0 is always a working approximation for "up" will fail if your camera can be upside down (flight simulator, space game, fancy camera movement in cutscenes).
The easiest way is to store a regular transformation matrix for your camera, treat it like any other object and invert it to get your view matrix:
//Quick inverse (transpose rotation part, multiply translation with transposed rotation)
Matrix Camera::getViewMatrix()
{
return Matrix(
transformation[0], transformation[4], transformation[8], 0,
transformation[1], transformation[5], transformation[9], 0,
transformation[2], transformation[6], transformation[10], 0,
-(transformation[0]*transformation[12] + transformation[1]*transformation[13] + transformation[2]*transformation[14]),
-(transformation[4]*transformation[12] + transformation[5]*transformation[13] + transformation[6]*transformation[14]),
-(transformation[8]*transformation[12] + transformation[9]*transformation[13] + transformation[10]*transformation[14]), 1);
}
//Going the matrix route for translation is a bit overkill, but better demonstrates the difference between moving along local or global axes
void Camera::move(float x, float y, float z, bool global, float distance)
{
Matrix translation = Matrix::createTranslation(x,y,z);
if (global)
transformation = transformation * translation;
else
transformation = translation * transformation;
}
void Camera::rotate(float deg, float x, float y, float z, bool global)
{
Matrix rotation = Matrix::rotationFromAxisAngle(deg, x,y,z);
if (global)
transformation = transformation * rotation;
else
transformation = rotation * transformation;
}
Edit: well, thank the forum gods for deleting everything after the code block when editing.
If whatever matrix library doesn't let you access by index (or has a different memory layout):
0-3: x-axis aka "camera right" (x,y,z,0)
4-7: y-axis aka "camera up" (x,y,z,0)
8-11: z-axis aka "camera forward" (x,y,z,0) (might be backward, depending on handed-ness)
12-15: origin aka "camera position" (x,y,z,1)
If you need zoom, this goes into the projection matrix (simply reduce the fov). Zooming is NOT scaling and NOT "moving closer" (or any other weird thing that causes clipping errors when zooming "too much").