How can I rotate a camera around its own axis based on a rotation Vector3?

I’ve been looking all over for an answer to my question, but I can’t really find what I’m looking for.
Here’s the camera class I’m making:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace First_Person_Controller
{
    public class Camera
    {
        public Matrix Projection { get; protected set; }
        public Matrix View { get; protected set; }
        public Matrix World { get; protected set; }

        public Vector3 Position 
        { 
            get
            {
                return position;
            } 
            set 
            {
                position = value;
                UpdatePerspective();
            } 
        }
        public Vector3 Rotation
        {
            get
            {
                return rotation;
            }
            set
            {
                rotation = value;
                UpdatePerspective();
            }
        }
        public Vector3 Target 
        { 
            get
            {
                return target;
            }
            set
            {
                target = value;
                UpdatePerspective();
            }
        }

        private Vector3 position;
        private Vector3 rotation;
        private Vector3 target;


        public Camera(float fov, float near, float far, GraphicsDevice graphicsDevice)
        {
            Position = new Vector3(0, 0, 100);
            Target = Vector3.Zero;

            Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(fov), graphicsDevice.DisplayMode.AspectRatio, near, far);
            View = Matrix.CreateLookAt(Position, Target, Vector3.Up);
            World = Matrix.CreateWorld(Target, Vector3.Forward, Vector3.Up);
        }

        private void UpdatePerspective()
        {
            View = Matrix.CreateLookAt(Position, Target, Vector3.Up);
            World = Matrix.CreateWorld(Target, Vector3.Forward, Vector3.Up);
            // Rotate the camera based on the rotation variable.
        }
    }
}

If you need any more info let me know.

You could use a rotated up vector instead of Vector3.Up. Untested, but something like this:

Vector3 camDir = Vector3.Normalize(Target - Position);
Matrix rotMat = Matrix.CreateFromAxisAngle(camDir , angle);
Vector3 rotatedUp = Vector3.Transform(Vector3.Up, rotMat);
View = Matrix.CreateLookAt(Position, Target, rotatedUp);

Another option would be to create a camera world matrix first, then invert, to get the view matrix.

Matrix lookat = Matrix.CreateWorld(Position, Target - Position, Vector3.Up);
Matrix rot = Matrix.CreateRotationZ(angle);
Matrix cam = rot * lookat;
View = Matrix.Invert(cam);

I think cameras point in the z-direction. In case they don’t, use Matrix.CreateRotationX or Y.

1 Like

The second solution worked perfectly.
The first one gives me an error:
Matrix does not contain a definition for Transform

But any ways thanks :grinning:

Ok after further testing I found out that with the new method you can’t change the camera’s position.

Oops, the transform function belongs to Vector, not Matrix. I fixed my original post. I also added a normalization which I think is needed.

Weird, I would need to test this to figure out why it’s not working. I’m sure I used a similar method in the past successfully.

EDIT:
I just did a quick test. Changing the position does work for me.

Oh yeah, I meant if I change the Position and the Target of the camera the camera doesn’t move.

EDIT:
I figured it out:
Instead of this:
World = Matrix.CreateWorld(Target, Vector3.Forward, Vector3.Up
do this:
World = Matrrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up

Ok, final answer (hopefully :grin:):
Again based on the answer given by @markus :
Replace the UpdatePerspective() method’s code with the fpllowing:

Matrix lookat = Matrix.CreateWorld(position, target - position, Vector3.Up);

// Rotations
Matrix rotX = Matrix.CreateRotationX(MathHelper.ToRadians(Rotation.X));
Matrix rotY = Matrix.CreateRotationY(MathHelper.ToRadians(Rotation.Y));
Matrix rotZ = Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation.Z));

Matrix cam = rotX * rotY * rotZ * lookat;
View = Matrix.Invert(cam);
World = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up);

You are essentially creating an identity matrix here, which does nothing. You might as well just use Matix.Identity or remove the world matrix from the camera class. Cameras usually only have a view and a projection matrix. The world matrix is usually used to place objects, so it belongs to the object being rendered, not to the camera.

2 Likes

OK. Thanks for the tip. :slight_smile:

Kinda old and in hindsite im not sure i liked the idea of the styles i put in it.
but in addition to some free rotations.
All the basic individual rotations and stuff are at the bottom of the class in this post.