Camera Help.

Does anyone have an example fps style camera.
All the ones I have found are look at cameras, and I can’t for the life of me get to work when moving the cameras world matrix.

I really don’t understand why the camera needs 3 matrices. I would think it would only need 2 possibly one.

A world matrix (I call it a transform matrix), and a projection matrix. There is also the view matrix which I am thinking would be the same as the projection matrix, so I messed around by setting it to:

= Matrix.CreateLookAt(transform.Position, Vector3.Forward, Vector3.Up)
= Matrix.Identity
= the projection matrix
= the transform matrix

and the cameras view and behavior was the exact same in all cases.

I’m just confused at this point.
Can someone explain please?

Does this help?

Uh I’ll let you know in an hour?
But why does changing view matrix not affect how objects are rendered?

1 Like

I think that would depend on your setup?

How do I put in code blocks? Or should I just paste bin?

In the text box down here, there are a few icons above it, it’s the one to the right of the ‘’ quotation marks, the best way to use it is by highlighting the bit you want displayed as code, then clicking the button.

Well for now without code.
I have a transform class, that has a Matrix, Position, Rotation, and Scale properties. Changing the rotation position or scale updates the matrix accordingly.
My camera, and my game objects have a Transform.
The camera then has aspect ratio, field of view, etc. for the projection matrix.
The camera’s forward and up direction is taken from the transform.Forward and transform.Up.

The game object’s view matrix is a Matrix.CreateLookAt() from the camera’s properties, and its projection matrix is a Matrix.CreatePerspectiveFieldOfView() also from camera properties. Their world matrix is their transform.Matrix

They are game components and render. If you zoom in and out, by moving the camera in the camera.transform.Forward direction, they appear as they should. As soon as you pan the camera and change it’s x and y values, instead of the camera itself panning left and right, the objects stay in the center of the camera’s view, and instead of moving in the opposite direction, do a weird combination of zooming and rotating at the same time.

Watch the video, and then look at other XNA tutorials on 3D cameras, I know how to do it all, but not very good at remembering off the bat…

I already made 2 engines, one with XNA 2.0, and one with MonoGame something.
I knew how to do it all, but can’t remember a thing now…
Thanks for the video.

1 Like

Think of it like this:
World matrix = position in the world
Projection matrix = Lens of the camera (FOV)
View matrix = part of the world that the camera sees

The world matrix of the camera is the inverse View matrix,
and (obviously) the View matrix is the inverse world matrix of the camera.

You are rendering everything from the perspective of the camera.
The shader transforms everything with the view matrix, which moves everything in ‘camera space’, with the camera now being at the origin [0,0,0] looking forward.
(you can imagine that you also transform the world matrix of the camera with the View matrix and you get Matrix.Identity, but at this point you no longer need that).

Alright well I get why there is 3 now. But I think I have something seriously screwy going on.
After following that hour long tutorial exactly (al lot of stuff I would of done differently) I have different results.
My camera is always pointing at the origin. Now I can pan up and down correctly but not zoom, and still can not pan left and right without rotating around the origin.

Also when I copy paste a camera from XNA’s chase camera I get the same result as the first attempt, as well as 2 other written examples I followed online.

I don’t what is to blame, but I am going to start a new project and see if its any better, and then one by one add all my other classes back in.
Thanks for help…

To add to what nkast and others have said.

Everything that you think of as a actual game object is positioned with a orientation matrix which is technically a world matrix. That includes a object you might define as a camera or a player that will act as the camera.

The above is a important concept to keep in mind that is nearly always skipped over.

That world matrix defines any object in your world by its total orientation including its position which is the Translational component of the matrix. The .Forward vector of a world matrix is the direction it is facing in relation to the coordinate system the monogame framework uses.

The view matrix is created from a world matrix specifically the one you choose to be the camera. It is a special matrix which creates a eye translation vector it is primarily needed to transform everything in the scene around it’s position. This only needs to be recreated if the camera’s (world) matrix changes position or orientation in any way.

The projection matrix creates a vanishing point at the end for a perspective projection or defines the viewing box area for a orthographic type of projection. This never needs to change unless you alter it which is typically not need to be done once created.

The multiplication of these matrices wvp = world * view * projection creates a final matrix that can be multiplyed by local model space vertices (that never change) on a shader to draw objects in the world this part lies in the realm of shaders or you can just use basic effect to pass all 3 matrices.
Such that you can draw the same model with different world matrices and the same view and projection matrices to draw the same model in many different positions or orientations in your scene.

To set up these matrices the Matrix class provides functions.

The world matrix is typically created with Matrix.CreateWorld( … ); this is for all objects including a object you deem to be a camera be it a player or a specifically created camera object that wont be drawn at all.

The view matrix is created with Matrix.CreateLookAt( … ); using values from the world matrix that belongs to a object you created or a existing game object with a world matrix you select to act as the camera in your world.

The projection matrix is typically created one time using Matrix.CreatePerspective or Orthagonal with values mostly derived from the graphics device viewport for width and heights and field of views ect.

Additional notes
CreateWorld takes a Forward directional vector as a parameter (this implys TargetPosition - PlayerPosition is to be passed) were CreateLookAt takes a target vector this is actually just a position in space to look at (implying pass targetPosition only).
If you want to use a direction instead of a position for the look at parameter, then take the camera.Forward vector of that world matrix which is the object you have selected to be the camera multiply it by say 10 and add it to that same world matrices position which is the camera.Translation then pass it as the target.
Both Forward and Target are basically were the world object or view looks at.
CreateLookAt also can be passed Vector3.Up for the Up value parameter if you want your camera to be fixed which is what most fps games do to keep the horizon stable.
Be aware with fixed cameras looking straight up or down will be the gimble lock directions.

There are quite a few example cameras if you search the monogame forums itself in code.

Just ask if you have more questions or get stuck.

2 Likes

First off, thanks to every who has helped explain things to me thus far.
I am stuck… Again.

Here are the 3 classes my camera movement depends upon.
Transform.cs
Camera.cs
ExampleInput.cs

Camera pan and zoom works until rotation is applied. The pan left-right should move along the camera’s view right axis, pan up-down is always along the Vector3.Up axis, and zoom should move along the camera’s view forward axis.
After rotating the camera (which I am sure I am not doing correctly) console output tells me that the camera’s view forward has changed, the pan zoom console’s output says it is moving along the correct now changed axis, but it doesn’t, it only moves along Vector3.Forward and Vector3.Right.

I am not sure how to properly tell my program to take one quaternion and then add a rotation to that quaternion from a another quaternion.
Since I was clueless on how to do that, I was originally trying to use Quaternion.CreateFromYawPitchRoll() but was getting gimble locked sometimes, and having my axis flipped other times, like the link @willmotil just gave me.
To solve this I did something similar to the code they use:

Matrix matrix = Matrix.CreateFromAxisAngle(camerasWorld.Up, MathHelper.ToRadians(radians));
LookAtDirection = Vector3.TransformNormal(LookAtDirection, matrix);

I handle rotation in the Transform class itself, as I need to be able to rotate more things than just a camera, and that code is in UpdateMatrix().
I also used to store a separate View matrix on the camera which would update itself to look in the same direction as the Transform.Forward direction, but that just resulted in two identical matrices, and there was no difference in my case from storing 2 identical matrices or just one, so I stuck with one.

I think the only problem is how I am applying rotation in the ExampleInput class. I think if someone could explain how to properly rotate there, things will work properly, but who knows, maybe I have some glaring errors elsewhere I just can not see.

I have searched online and to rotate form one quaternion the other I gathered that you had to Quaternion.Conjugate the first, then add the second, that didn’t work. Somewhere else said you could just Quaternion.Concatenate(From, To), but that didn’t work either.

Any ideas?
Thanks.

EDIT: I added a separate view matrix back in, and zooming along the forward axis works as intended, but panning left right is still locked to Vector3.Right axis…
All the examples I have been given are great if you lock the cameras freedom in one way or another, but don’t work at all if you are trying to make a fly cam like I am. A camera you can move about all axies, and flip 360 in all directions.

EDIT2: Turns out I was moving along the views right axis, not the transform’s right axis, now pan zoom works great. I need to figure out how to properly rotate now…

EDIT3: I stopped using the transform class all together and just added in a world matrix for the camera, camera now disappears when rotating, as opposed to not rotating the way I would like.

Alright The only thing I can’t figure out is my rotation, you think it would be simple.
Mouse moves left-right.

Then the stored quaternion in the transform is updated like so:

mainCamera.transform.Rotation = Quaternion.CreateFromAxisAngle(mainCamera.transform.Up, MathHelper.WrapAngle(MathHelper.ToRadians(Mouse.GetState().DeltaX())));

Then the world matrix is recalculated by doing this:

rotationMatrix = Matrix.CreateFromQuaternion(rotation);
matrix = Matrix.CreateWorld(Position, Position + rotationMatrix.Forward, rotationMatrix.Up);

Then the View matrix is recalculated by doing this:

view = Matrix.CreateLookAt(transform.Position, transform.Position + transform.Forward, transform.Up);

and then the camera does god knows what but does not rotate left and right.

EDIT:
Alright finally figured this out, I feel silly how long it took. The order in which I was apply things was messing me up 2 days ago before I bothered with Quaternions (which I am no longer bothering with).

// Rotate the camera.
// The camera’s position changes when recalcualting a rotation, as if it rotates around it’s lookat, not it’s center. Store the original position, and rest it at the end.
Vector3 _position = mainCamera.transform.Position;
// We must apply the x roation matrix prior to calculating the y rotation matrix, or the camera starts to roll even though we have not specified a z rotation.
Matrix rotationMatrix = Matrix.CreateFromAxisAngle(Vector3.Up, MathHelper.WrapAngle(-MathHelper.ToRadians(Mouse.GetState().DeltaX())) * (float)gameTime.ElapsedGameTime.TotalSeconds * mainCamera.speed);
mainCamera.transform.matrix *= rotationMatrix;
rotationMatrix = Matrix.CreateFromAxisAngle(mainCamera.transform.Right, MathHelper.WrapAngle(-MathHelper.ToRadians(Mouse.GetState().DeltaY())) * (float)gameTime.ElapsedGameTime.TotalSeconds * mainCamera.speed);
mainCamera.transform.matrix *= rotationMatrix;
mainCamera.transform.Position = _position;

If you look thru that link i posted about half way down there is a picture of grid in blue just below that is a fully working camera class with the grid as well.
All the code is right on the page so you could just copy paste it.

You probably should look at the bottom of the class though as i separated all the methods for motion and movement into there own little methods. The only thing i didn’t include in it is roll but you could easily add it as well to the local rotation controls.

Further up is a old camera class i made in another link so that link actually has a working camera and a link to another one both copy pasteable right off the topic.

It also has a free camera mode as well as a fixed camera the free camera shows how to make a free cam matrix that can’t gimble lock and explains how to avoid it with a fixed camera which is a bit more of a art. Quaternions can also gimble lock despite the common myth that they can’t they are best used when there are a ton of rotations alone that must be computed in a chain as they are slightly cheaper for the pure rotations but conversion is expensive.

Found this RBW guide on the Documents pages…

http://rbwhitaker.wikidot.com/monogame-basic-matrices

Hope it helps