As my previous answer got a downvote because it was too code-heavy I'll explain a little more:
For a camera which is not locked to any target point you should not use lookAt
but rather compute the camera transformation matrix yourself.
You will need a camera position (x,y,z) and at least two rotation angles (i.e. pitch and yaw). To get the full tranformation matrix you multiply a translation matrix and one rotation matrix for each angle together, but as matrix multiplication is not commutative the order is important here. You can either first rotate and then translate, or the other way around, which yields totally different results. To understand the behavior I suggest just messing around with the order, but for a typical first person camera you will want to translate first and then rotate.
To achieve the correct movement of the camera you need to do two things:
- First you need to capture the mouse delta, i.e. the mouse movement since the last time you checked for mouse movement and add these up to your rotation angles. Additionally you may want to incorporate some kind of mouse speed multiplier here.
- Second you need to apply movement to the camera position correctly. This gets a little tricky as soon as the angles are not zero anymore, because movement is not along any of the axis. You will need to calculate the correct movement direction using the current rotation angles and some trigonometry. Here you may want to add some movement speed multiplier.
I hope that cleared things up a bit, and gives more insight into what my code actually does.
Previous answer:
I would suggest not using lookAt
and just creating the transformation matrix yourself. I did that a while ago in C# using DirectX, but I think it's self-explanatory what happens here:
public void ApplyFreeLookCamera(Context ctx)
{
if (Enabled)
{
HandleInput(ctx);
}
Vector3 transPos = GetPosition();
transPos.Multiply(-1);
Matrix view = Matrix.Translation(transPos);
view *= Matrix.RotationY(Yaw); // left-right rotation
view *= Matrix.RotationX(Pitch); // up-down rotation
view *= Matrix.RotationZ(Roll); // ah snake, snaaake!
ctx.Graphics.Transform.View = view;
}
And to handle input something like that:
private void HandleInput(Context ctx)
{
// calculate movement direction
var distance = MovementSpeed * ctx.FrameSeconds;
var dx = (float)Math.Sin(Yaw) * distance;
var dz = (float)Math.Cos(Yaw) * distance;
//float dy = (float)Math.Sin(Pitch) * distance;
var movement = new Vector3();
// check keys
if (ctx.Input.KeyPressed(Constants.CameraForward))
{
movement.X -= dx;
movement.Z += dz;
}
if (ctx.Input.KeyPressed(Constants.CameraBackward))
{
movement.X += dx;
movement.Z -= dz;
}
if (ctx.Input.KeyPressed(Constants.CameraLeft))
{
movement.X -= dz;
movement.Z -= dx;
}
if (ctx.Input.KeyPressed(Constants.CameraRight))
{
movement.X += dz;
movement.Z += dx;
}
if (ctx.Input.KeyPressed(Constants.CameraUp))
{
movement.Y += distance;
}
if (ctx.Input.KeyPressed(Constants.CameraDown))
{
movement.Y -= distance;
}
Position.Add(movement);
// view direction
var mouseDelta = ctx.Input.GetMouseDelta();
if (ctx.Input.MouseButtonPressed(Constants.CameraMouseButton))
{
Yaw -= mouseDelta.X * MouseSpeed;
Pitch -= mouseDelta.Y * MouseSpeed;
ctx.Input.CenterMouseInWindow();
}
}
lookAt
? For a free camera I would just create the transformation matrix myself. \$\endgroup\$