Here's how I did it:

The camera has 4 variables.
A position (P) and a point in the level where it's looking (Tar)
Then for smooth interpolation, there is a Target Position (TP)
And a Target Tar variable (TTar).

These are where the camera *wants* to look..

[pascal]
Procedure TLevel.TickCamera;
begin
//Do the interpolation
//T is just a timing variable.
with Camera do
begin
P[0] := P[0]-(P[0]-TP[0])*0.005*T;
P[1] := P[1]-(P[1]-TP[1])*0.005*T;
P[2] := P[2]-(P[2]-TP[2])*0.005*T;

Tar[0] := Tar[0]-(Tar[0]-Ttar[0])*0.005*T;
Tar[1] := Tar[1]-(Tar[1]-Ttar[1])*0.005*T;
Tar[2] := Tar[2]-(Tar[2]-Ttar[2])*0.005*T;
end;
end;

Procedure TLevel.LookFromCamera;
begin
glLoadIdentity;
glscalef(0.1, 0.1, 0.1);
with Camera do
gluLookAt(P[0], P[1], P[2], Tar[0], Tar[1], Tar[2], 0, 1, 0);
Camera.Frustum.CalculateFrustum;
end;
[/pascal]

The format of the gluLookAt function is 3 coordinates for where the camera should be placed (same as glTranslatef())
Then 3 coordinates of the object you want to look at,
Then your Up vector. Which is usually in the Y direction, but depends on your engine.