Simple 3D camera rotation not working

Hello everyone,

I know this is a very basic question, but I’ve been struggling for too long and right now I’m just try-and-error-ing. I would be really thankful for an explanation what is going on.

So, what I’m trying to do is implement a simple 3D camera. I managed to get the movement right, but I really struggle with the rotation. Imagine the camera is looking at (0, 0, 0). I want my camera to orbit the point around the Y-Axis (“left and right”) as well as around the axis pointing left from the camera (“Up and down”).
Now, I’ve managed to do just that. The Camera rotates as I want, but only if I disable the other rotation. Also, when I do the vertical rotation before the horizontal rotation, the camera only rotates horizontally. When I do the horizontal rotation before the vertical rotation, the rotation becomes really messy.

I know that matrix multiplication is not commutative, so I’m assuming this is where the error comes from. But I don’t exactly understand what the problem is, since it doesn’t work properly no matter the order.

This is what I do in my camera class:
Up is a property that stores the cameras Up direction, which is initially (-1, 1, 0).Normalized();
Position is initialized to (1000, 1000, 0)
Target is (0, 0, 0)
Left is the normalized cross of Up x (Target - Position)

At the end of the camera update code, I calculate a new ViewMatrix using
Matrix.CreateLookAt(Position, Target, Up);

var deltaX = Mouse.GetState().X - 100; //Get mouse movement since last frame with right mouse button pressed
var deltaY = Mouse.GetState().Y - 100;
deltaX = -deltaX; // invert for right feeling

var direction = Position - Target; //Vector pointing from target to position

 //Vertical rotation:
var rotLeft = Matrix.CreateFromAxisAngle(Left, deltaY * rotationSpeed);
Position = Vector3.Transform(direction, rotLeft) + Target;
Up = Vector3.Transform(Up, rotLeft);

//Horizontal rotation:
var rotY = Matrix.CreateRotationY(deltaX * rotationSpeed);
Position = Vector3.Transform(direction, rotY) + Target;
Up = Vector3.Transform(Up, rotY);


Mouse.SetPosition(100, 100);

I don’t have time to look it over right now.
Your using axis angle for the up down mouse but rotation y for the other. I think you should be using axis angle and pulliing a vector from the previous matrix to use as the axis. Once you tilt up the other rotation i don’t think will be right without axis angle as the rotational plane has changed.

… this isn’t the same as what your doing but its sort of similar maybe it will help.

void OrbitTarget(Vector3 TargetToOrbit, Vector3 AxisToRotateAbout, float heightAlongRotationAxis, float distanceFromTarget)
{
    var m = Matrix.CreateFromAxisAngle(AxisToRotateAbout, orbitPerSeconds.GetFullCycleCompletionPercentage * (pi * 2f));
    var cossDistanceVector = new Vector3(AxisToRotateAbout.Z, AxisToRotateAbout.X, AxisToRotateAbout.Y) * distanceFromTarget;
    var cameraPositionOffset = Vector3.Transform(cossDistanceVector, m) + AxisToRotateAbout * heightAlongRotationAxis;
    UpdateCamera(cameraPositionOffset + TargetToOrbit, TargetToOrbit, AxisToRotateAbout);
}

void UpdateCamera(Vector3 position, Vector3 target, Vector3 camUp)
{
    worldCamera = Matrix.CreateWorld(position, target - position, camUp);
    effect.View = (view = Matrix.CreateLookAt(worldCamera.Translation, worldCamera.Translation + worldCamera.Forward, worldCamera.Up));
}

void UpdateObject(Vector3 position, Vector3 target)
{
    effect.World = (worldSurface = Matrix.CreateWorld(position, target - position, Vector3.Up));
}

If this works for you, it’s probably an easier method.

yaw += deltaX;
pitch += deltaY;

Matrix camMatrix = Matrix.CreateFromYawPitchRoll(yaw, pitch, 0);
Vector camDir = camMatrix.Forward;
Vector camPos = Target - camDir * distance;

Matrix viewMatrix = Matrix.CreateLookAt(camPos, Target, Vector.Up);

Untested, but the basic principle should work.