[FIXED]Camera not moving sideways based on direction it is looking in XNA

The camera needs to move in the direction it is moving. I can move forward and backwards but I don’t know how to move left or right. The idea is also that the camera moves forward, backwards, left and right while the y axis is fixed when it is moving. The code is written in C# and in monogame. The code first shown is the way in which we create our camera. Thanks in advance.

public Vector3 position = new Vector3(0, 0.5f, 4);

private float rotation;
Vector2 mouseMovement;
private Point screen;
public Vector3 lookAt;
private Vector3 baseCameraReference = new Vector3(0, 0.5f, 4);
public Vector3 cameraForward;

public Camera(Vector3 position, float rotation, GraphicsDevice graphicsDevice, float nearClip, float farClip)
{
    Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, graphicsDevice.Viewport.AspectRatio, nearClip, farClip);
    screen.X = graphicsDevice.Viewport.Width /2;
    screen.Y = graphicsDevice.Viewport.Height /2;
    cameraForward = baseCameraReference;
    //MoveTo(position, rotation);
}
#endregion

#region Helper Methods
private void UpdateLookAt()
{
    Vector3 normal = Vector3.Cross(cameraForward, Vector3.Up);
    cameraForward += mouseMovement.X * 0.01f * normal;
    cameraForward -= mouseMovement.Y * 0.01f * Vector3.Up;
    cameraForward.Normalize();
    lookAt = position + cameraForward;
    Matrix rotationMatrix = Matrix.CreateRotationY(rotation);
    needViewResync = true;
}

public void Update(GameTime gameTime)
{
    currentMouseState = Mouse.GetState();
    Mouse.SetPosition(screen.X, screen.Y);
    mouseMovement.X = (currentMouseState.X -screen.X);
    mouseMovement.Y = (currentMouseState.Y -screen.Y);
   // prevMouseState = currentMouseState;
    UpdateLookAt();
}

And this is the way in which we try to move it:

if (keyState.IsKeyDown(Keys.W))
{
    camera.position += (camera.cameraForward - new Vector3(0, camera.cameraForward.Y,0)) *0.05f;
}

if(keyState.IsKeyDown(Keys.S))
{
    camera.position -= (camera.cameraForward - new Vector3(0, camera.cameraForward.Y, 0)) * 0.05f;
}

if (keyState.IsKeyDown(Keys.D))
{
    float newx = camera.cameraForward.X;
    float newz = -camera.cameraForward.Z;

    camera.cameraForward.X = newz;
    camera.cameraForward.Z = newx;

    camera.position += (camera.cameraForward - new Vector3(0, camera.cameraForward.Y, 0))*0.05f
}

I have tried turning around the values but that just seems to make the camera change direction and bounce back to original direction.

Thanks in advance for any help.
Jeromer

your camera orientation is determined by its (forward or lookat direction) and its up vector that can be xna up or some other arbitrary up vector orientation.

The cross product of a look at direction and up vector, must be a left or right direction to that, which may simply be added to the camera position to move it in that direction.

Note.

Depending if you cross, up then forward, or forward then up, then the resulting Y axis vector will be left, or right…

Another note your forward is your desired lookat position - the cameras position, the result once normalized being your forward vector.

One more thing to do when you work with the matrixs is to make sure you mentally mark the difference, or keep in mind the difference between, a orientation and direction or position vector. A orientation is 3 full directional vectors any of its individual vectors can be multiplied by -1 to reverse that axis direction.

For example you can also simply do the below provided your orientation matrix is properly normalized.

Camera.position = Camera.position + viewMatrix.Left;

Oke, I think I understand what you mean. But the problem is that rotation float. Is a value I am not using any more. I forgot to take it out. That was being used to move the camera left or right via keyboard but we wanted to make the camera move via mouse so that value isn’t used anymore. So then your current method doesn’t apply anymore does it. The value of rotation is currently 0 when running as it doesn’t change as it isn’t used for rotation currently.

Once again thanks for the response, and thanks for the help.

Jeromer

How you want to do input is basically a separate issue to moving the camera or orienting it.
You could in fact use all 8 keys from q to c to increase or decrease rotations then hold down one of the mouse buttons or the other to move forward and back. You could look with the mouse and move only forward back with two keys or use 2 more keys to spin around the forward vector you could allow your position to drift and look around with the mouse.

The first thing you must do is clearly describe what you are trying to achieve. A specific scenario if possible will help of exactly what action you want to take and what result you expect or want to see from that. Current matrix or camera code you are using is also helpful.

Basically when you move the camera you just add to the camera’s position and typically the look at position as well (though not required), both of which are vectors. You want to add some directional vector to them. in this case your camera’s oriention matrix’s Left or Right vectors which are found in m21 m22 m23 of your view orientation matrix. Aka viewMatrix.Left or viewMatrix.Left *-1f = viewMatrix.Right

Oke, what i want to have a camera which resembles the FPS genre camera. The mouse should be able to control the direction and angle the player is looking at. The player can look the full 360 degrees all around him. Then I want the player to be able to move the camera forward, backward, right and left. All this while not changing the height value of the camera. The mouse properly changes the camera in the way I want the camera to move. The W and S buttons make the player move forward and backwards without changing the height value. But the problem is that I can’t make the camera move left or right.

Altough the camera does still get the rotation float as a value in its parameter it doens’t do anything with it. We do still need to clean that up as well.
This is the code for the camera itself:

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace Cube_chaser
{
    public class Camera
    {
        #region Fields
        public Vector3 position = new Vector3(0, 0.5f, 1);
        private Vector2 mouseMovement;
        private Point screen;
        public Vector3 lookAt;
        private Vector3 baseCameraReference = new Vector3(0, 0.5f, 1);
        public Vector3 cameraForward;
        private bool needViewResync = true;
        private Matrix cachedViewMatrix;
        public const float rotationSpeed = 0.3f;
        public const float moveSpeed = 30.0f;
        private MouseState currentMouseState, prevMouseState;
        private KeyboardState currentkey;
        Vector3 cameraPosition = new Vector3(0, 0.5f, 1);
        #endregion

    #region Properties
    public Matrix Projection { get; private set; }
    public Vector3 Position
    {
        get
        {
            return position;
        }
        set
        {
            position = value;
            UpdateLookAt();
        }
    }

  /*  public float Rotation
    {
        get
        {
            return rotation;
        }
        set
        {
            rotation = value;
            UpdateLookAt();
        }
    }*/

    public Matrix View
    {
        get
        {
            if(needViewResync) cachedViewMatrix = Matrix.CreateLookAt(Position, lookAt, Vector3.Up);
                
            return cachedViewMatrix;
        }
    }
    #endregion

    #region Constructor
    public Camera(Vector3 position, float rotation, GraphicsDevice graphicsDevice, float nearClip, float farClip)
    {
        Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, graphicsDevice.Viewport.AspectRatio, nearClip, farClip);
        screen.X = graphicsDevice.Viewport.Width /2;
        screen.Y = graphicsDevice.Viewport.Height /2;
        cameraForward = baseCameraReference;
        //MoveTo(position, rotation);
    }
    #endregion

    #region Helper Methods
    public void UpdateLookAt()
    {
        Vector3 normal = Vector3.Cross(cameraForward, Vector3.Up);
        cameraForward += mouseMovement.X * 0.01f * normal;
        cameraForward -= mouseMovement.Y * 0.01f * Vector3.Up;
        cameraForward.Normalize();
        lookAt = position + cameraForward;
       // Matrix rotationMatrix = Matrix.CreateRotationY(rotation);
        needViewResync = true;
    }

    #endregion

    public void Update(GameTime gameTime)
    {
        currentkey = Keyboard.GetState();
        currentMouseState = Mouse.GetState();
        Mouse.SetPosition(screen.X, screen.Y);
        mouseMovement.X = (currentMouseState.X -screen.X);
        mouseMovement.Y = (currentMouseState.Y -screen.Y);
        // prevMouseState = currentMouseState;

        UpdateLookAt();
    }'

And this is the code for the movement at the moment. Yeah sorry for the “loose” code, We are trying to make it work and need to improve on how we make changes.

protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            camera = new Camera(new Vector3(0.5f, 1f, 1f), 0, GraphicsDevice, 0.05f, 100f);
            effect = new BasicEffect(GraphicsDevice);
            map = new Map(GraphicsDevice);
            IsMouseVisible = false;
            // camera.UpdateViewMatrix();
            Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
            orignalMouseState = Mouse.GetState();
            base.Initialize();
        }

And the movement:

            if (keyState.IsKeyDown(Keys.W))
            {
                camera.position += (camera.cameraForward - new Vector3(0, camera.cameraForward.Y,0)) *0.05f;
            }

            if(keyState.IsKeyDown(Keys.S))
            {
                camera.position -= (camera.cameraForward - new Vector3(0, camera.cameraForward.Y, 0)) * 0.05f;
            }

I currently commented the movement for the left and right out as it isn’t working. I hope this clarifies a bit. And once again thanks for helping me. Really appreciate it

no problem.

All of your directional values are within cachedViewMatrix

you can access the vectors within like so.

cachedViewMatrix.Forward
cachedViewMatrix.Back
cachedViewMatrix.Left
cachedViewMatrix.Right

so in this case you only need to worry about not altering the value of the height lets say you have a variable that holds your desired height called playerheight.

if (keyState.IsKeyDown(Keys.A))
{
camera.position += cachedViewMatrix.Left * speed;
camera.position.Y = playerheight;
}

if(keyState.IsKeyDown(Keys.D))
{
camera.position += cachedViewMatrix.Right * speed;
camera.position.Y = playerheight;
}

Ah oke thanks, I’ll try that. I appreciate it.

Hello, I am back again. For some reason all the vectors, for some reason make the camera move back instead of the directions the vectors should be doing. So I think I have done something wrong with how I have coded my camera or am I wrong?

In the above code here
Vector3 normal = Vector3.Cross(cameraForward, Vector3.Up);
cameraForward += mouseMovement.X * 0.01f * normal;

This is actually in error camera forward and vector3 up creates a left or right directional vector.
Which would actually cause this next assignment to do i don’t even know what.
cameraForward += mouseMovement.X * 0.01f * normal;
All the lines after that will be bugged though.

Further you can’t rotate a matrix via the mouse like that properly. I think its not really what you want anyway.

What you normally do is start off your view matrix by initializing its position and its lookat vector at some other nearby position this can be arbitrary, as long as its not at the same position as the camera itself.

You then create the viewMatrix with createLookat as you have done already, use Vector3.Up for the up vector. and Vector3.Right for the right or left ect to pass to that creat look at function.

This then gives you a viewMatrix that is setup with all the values that you can use to add to your position as shown.

To rotate the view matrix you must take the value of the mouse x y when its far off to the side and simply say if its over to the left or right ill create a rotationX with like .01 rads as input to it and multiply it to my viewMatrix that will actually turn your view matrix and you do the same for the mouse Y.

Most people use the quaterunions for this but just starting out and in this case a matrix should be fine.

I suggest you also look at other peoples camera matrix code there are many examples and tutorials simply doing a google search.

Oke thanks man really appreciate it. I’ll try to read up on it a bit more so I understand a bit better what needs to be done. Becasue it is partly a bit magic for me at the moment. But I do understand the gist of it.

Thats pretty much all the steps you need to do though.

but ya

Search even on here for camera code or posts for it and look at how other people did it, look at more then just one guys camera code too or look up questions relating to the view matrix or a camera.
Especially at how you rotate a view matrix its actually just straight out mulitplying it by another rotation but quaternions are the way to go for that normally.

That deserves some reading and a tutorial especially since gimble lock can be a thing with matrixes, in your specific case even when you get it working, when you look straight up.

Thanks, got it working now. I just rewrote the code with the new knowledge I had gained.
Thanks for the response and the help:)

Jeromer