For those looking for a copy/paste answer, or something a little more code like, here is an implementation for OpenGL. It supports a zoom feature to zoom in/out on the center of the view. I think the variable names are fairly self explanatory.
Camera is defined by it's position, direction it's looking and its up vector. The view matrix is made up of these values.
The "lens" you're using (I suppose it could be called?) describes the "cone" that represents what you're looking at in the world. It takes the view angle (how wide narrow the cone of view is) the size of your game window and the near and far cut offs for your view cone. These values make up the projection matrix.
The code below is working and taken from my game. I don't know if this is the most fashionable way to make the matrices, but it works for me and supports the older hardware the I'm targeting.
view = createView(getCameraPosition(), getCameraDirection(), getCameraUpVector());
projection = createProjection(cameraViewAngle * zoomFactor, (float) getWindowX() / (float) getWindowY(), nearPlane, farPlane);
Matrix4f createView(Vector3f position, Vector3f direction, Vector3f up) {
Vector3f.cross(up, direction, getRightVector());
setRightVector((Vector3f) getRightVector().normalise());
result.m00 = getRightVector().x;
result.m10 = getRightVector().y;
result.m20 = getRightVector().z;
result.m30 = -(Vector3f.dot(getRightVector(), position));
result.m01 = up.x;
result.m11 = up.y;
result.m21 = up.z;
result.m31 = -(Vector3f.dot(up, position));
result.m02 = direction.x;
result.m12 = direction.y;
result.m22 = direction.z;
result.m32 = -(Vector3f.dot(direction, position));
return result;
}
Matrix4f createProjection(float fov, float aspect, float znear, float zfar) {
float ymax, xmax;
ymax = (float) (znear * Math.tan(fov * Math.PI / 360.0));
xmax = ymax * aspectRatio;
Matrix4f result = new Matrix4f();
glhFrustumf2(result, -xmax, xmax, -ymax, ymax, znear, zfar);
return result;
}
private Matrix4f glhFrustumf2(Matrix4f matrix, float left, float right, float bottom, float top, float znear, float zfar) {
float twoZNear, deltaW, deltaH, deltaZ;
twoZNear = 2.0f * znear;
deltaW = right - left;
deltaH = top - bottom;
deltaZ= zfar - znear;
matrix.m00 = twoZNear / deltaW;
matrix.m01 = 0.0f;
matrix.m02 = 0.0f;
matrix.m03 = 0.0f;
matrix.m10 = 0.0f;
matrix.m11 = twoZNear / deltaH;
matrix.m12 = 0.0f;
matrix.m13 = 0.0f;
matrix.m20 = (right + left) / deltaW;
matrix.m21 = (top + bottom) / deltaH;
matrix.m22 = (-zfar - znear) / deltaZ;
matrix.m23 = -1.0f;
matrix.m30 = 0.0f;
matrix.m31 = 0.0f;
matrix.m32 = (-twoZNear * zfar) / deltaZ;
matrix.m33 = 0.0f;
return matrix;
}