Attempting 3D but my Camera doesn't roll?

I’ve been using a camera set up I found online and it has been working perfectly. But I’m having trouble getting the camera to roll. I don’t think the code I found was set up for this and I’m not familiar enough to get it working.

public class _3DCamera //: GameComponent
{
	//Attributes
	private Vector3 cameraPosition;
	private Vector3 cameraRotation;
	private float cameraSpeed;
	private Vector3 cameraLookAt; //defines the direction camera is currently looking
	private Vector3 mouseRotationBuffer;
	private MouseState currentMouseState;
	private MouseState prevMouseState;
	private bool enableMouse = false;


	private Vector3 savedCameraPosition;
	private Vector3 savedCameraRotation;
	private Vector3 destinationCameraPosition;
	private Vector3 destinationCameraRotation;
	public float lifeSpan = 0;
	public float lifeTimer = 0;
	private bool DestinationReachedCameraPosition = true;
	private bool DestinationReachedCameraRotation = true;

	//Properties
	public Matrix Projection
	{
		get;
		protected set;
	}

	public Vector3 Position
	{
		get { return cameraPosition; }
		set
		{
			cameraPosition = value;
			UpdateLookAt(); //any time the position changes, it calls update look at
		}
	}

	public Vector3 Rotation
	{
		get { return cameraRotation; }
		set
		{
			cameraRotation = value;
			UpdateLookAt(); //any time the rotation changes, it calls update look at
		}
	}

	public Matrix View //Defines entire view of camera. Where it's located, it's target and the up vector.  Essentially creating a transform with forward, up, and relative camera position.
	{ //view and projection needed for camera's orientation in 3D space.
		get
		{
			return Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);
		}
	}

	//Constructor
	public _3DCamera(Game game, Vector3 position, Vector3 rotation, float speed)
	//	: base(game)
	{
		cameraSpeed = speed;

		//set up projection matrix
		//Orthographic project = 2D, Perspective = 3D
		Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, game.GraphicsDevice.Viewport.AspectRatio, 0.05f, 1000.0f);
		//1000 = draw distance .  That's when things are drawn into camera, or "pop in"

		//Set camera position and rotation
		MoveTo(position, rotation);

		prevMouseState = Mouse.GetState();
	}

	//Method that essentially just moves camera
	//Set camera's position and rotation
	private void MoveTo(Vector3 pos, Vector3 rot)
	{
		Position = pos;
		Rotation = rot;
	}

	public void CameraMoveTo(Vector3 DestinationCameraPosition, float TimeToReach)
	{
		CameraMoveTo(DestinationCameraPosition, Rotation, TimeToReach);
	}
	public void CameraMoveTo(Vector3 DestinationCameraPosition, Vector3 DestinationCameraRotation, float TimeToReach)
	{
		savedCameraPosition = Position;
		savedCameraRotation = Rotation;

		destinationCameraPosition = DestinationCameraPosition;
		destinationCameraRotation = DestinationCameraRotation;

		DestinationReachedCameraPosition = false;
		DestinationReachedCameraRotation = false;

		lifeTimer = 0;
	lifeSpan = TimeToReach;
	}

	private void MoveCamera(float elapsedTime)
	{
		
		lifeTimer += elapsedTime;
		float xTime = lifeTimer / lifeSpan;


		//Vector3 moveVector = Vector3.Zero;


		
		Position = new Vector3(
			savedCameraPosition.X + ((destinationCameraPosition.X - savedCameraPosition.X) * xTime),
			savedCameraPosition.Y + ((destinationCameraPosition.Y - savedCameraPosition.Y) * xTime),
			savedCameraPosition.Z + ((destinationCameraPosition.Z - savedCameraPosition.Z) * xTime)
			);
			

		
		Rotation = new Vector3(
			savedCameraRotation.X + ((destinationCameraRotation.X - savedCameraRotation.X) * xTime),
			savedCameraRotation.Y + ((destinationCameraRotation.Y - savedCameraRotation.Y) * xTime),
			savedCameraRotation.Z + ((destinationCameraRotation.Z - savedCameraRotation.Z) * xTime)
		);






		if (lifeTimer > lifeSpan)
		{
			DestinationReachedCameraPosition = true;
			DestinationReachedCameraRotation = true;
			lifeTimer = 0;
			Position = destinationCameraPosition;
			Rotation = destinationCameraRotation;
		}
	}

	private bool DestinationReached()
	{
		return DestinationReachedCameraPosition && DestinationReachedCameraRotation;
	}

	//Method that simulates movement
	private Vector3 PreviewMove(Vector3 amount)
	{
		//Create a rotate matrix
		//this will only include the rotation around the y axis, the yaw
		Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
		//Create a movement vector
		Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
		movement = Vector3.Transform(movement, rotate);
		//return the value of camera position + movement vector
		return cameraPosition + movement;
	}

	//Method that actually moves the camera, by a scale factor
	private void Move(Vector3 scale)
	{
		MoveTo(PreviewMove(scale), Rotation);
	}

	//update the look at vector
	private void UpdateLookAt()
	{
		//first build a rotation matrix
		Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y) * Matrix.CreateRotationZ(cameraRotation.Z); 

		//second create a lookat offset.  The change in lookat based on change on rotation and the forward vector, unit z
		Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);

		//third, update the camera's look at vector
		cameraLookAt = cameraPosition + lookAtOffset;
	}

	public void Update(GameTime gameTime, Game game)
	{
		float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

		if(!DestinationReached())
			MoveCamera(dt);


		currentMouseState = Mouse.GetState();

		KeyboardState ks = Keyboard.GetState();

		//Handle basic key movement
		/*
		Vector3 moveVector = Vector3.Zero;
		if (ks.IsKeyDown(Keys.I) || ks.IsKeyDown(Keys.NumPad5))
			moveVector.Z = 1;
		if (ks.IsKeyDown(Keys.K)  || ks.IsKeyDown(Keys.NumPad1) || ks.IsKeyDown(Keys.NumPad3))
			moveVector.Z = -1;
		if (ks.IsKeyDown(Keys.J) || ks.IsKeyDown(Keys.NumPad4))
			moveVector.X = 1;
		if (ks.IsKeyDown(Keys.L) || ks.IsKeyDown(Keys.NumPad6))
			moveVector.X = -1;
		if (ks.IsKeyDown(Keys.NumPad8))
			moveVector.Y = 1;
		if (ks.IsKeyDown(Keys.NumPad2))
			moveVector.Y = -1;
		

		if (moveVector != Vector3.Zero)
		{
			//normalize the vector
			//so that we don't move faster diagonally
			//because what happens is... because the hypotenuse has to be greater than the other two sides of a triangle
			//but if we normalize it, we can ensure the same speed
			moveVector.Normalize();
			//now we add in smooth and speed
			moveVector *= dt * cameraSpeed;

			//Move camera
			Move(moveVector);

		}
		*/


		if (ks.IsKeyDown(Keys.Space))
			enableMouse = true;
		else
			enableMouse = false;

		if (enableMouse)
		{
		
			float deltaX;
			float deltaY;
			float deltaZ;

			if (currentMouseState != prevMouseState)
			{
				if (currentMouseState.LeftButton == ButtonState.Pressed)
				{
					// Do cool stuff here
					deltaZ = currentMouseState.X - (game.GraphicsDevice.Viewport.Width / 2);
					mouseRotationBuffer.Z -= 0.05f * deltaZ * dt;

					Rotation = new Vector3(Rotation.X, Rotation.Y, MathHelper.WrapAngle(mouseRotationBuffer.Z));
					
				}
				else
				{

					//Cache mouse location
					deltaX = currentMouseState.X - (game.GraphicsDevice.Viewport.Width / 2);
					deltaY = currentMouseState.Y - (game.GraphicsDevice.Viewport.Height / 2);

					mouseRotationBuffer.X -= 0.05f * deltaX * dt;
					mouseRotationBuffer.Y -= 0.05f * deltaY * dt;

					if (mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
						mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));

					if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
						mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));

					Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)),
						MathHelper.WrapAngle(mouseRotationBuffer.X), 0);

					deltaX = 0;
					deltaY = 0;
				}
			}

			Mouse.SetPosition(game.GraphicsDevice.Viewport.Width / 2, game.GraphicsDevice.Viewport.Height / 2);
		}
		prevMouseState = currentMouseState;

	//	base.Update(gameTime);
	}

}

Hey i had the same Problem, i hope i can help you with my Camera:

The roll angle (cameraRotation.Z) is used in this function, but since rolling the camera doesn’t affect the lookAt position, it doesn’t do anything. You might as well remove the roll angle from the calculation here, it won’t change anything.

This is where the view matrix for the camera is created. The 3rd parameter locks the roll angle. It keeps the camera up-vector aligned with the world up-vector.

Multplying the lookat matrix with a roll matrix should do it:

`return Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up) * Matrix.CreateRotationZ(-cameraRotation.Z);

Thank you!

I just kind of gave up on this and forgot about it but I came back to the forums and found your solution and it works great!