# View Matrix

In the previous article we saw that our input mesh data (all vertices) requires 7 main stages of transformations to finally reach the window space coordinates. The first 4 stages are represented by matrix multiplications. You may still wonder why do we need three matrices and why we multiply them. Well, we use matrices to move a vertex from one space to another using this chain of multiplications. Think that every matrix represent a space.

In this article I will break this chain down and see what’s really happening behind each multiplication and finally we will talk in depth about the view matrix. Also, I’ll introduce World Space with its World Matrix just to clarify the whole thing with these spaces, and after that I will remove it because we don’t actually need it. 🙂

**Model Space Transformation **

**Note!!!** When I’m reading this chain of transformations I usually read it backwards – as if the transformations were multiplied in row major order. This is just easier for me to see and track down all vertex transformations. But this is just my approach to picture this chain (I also started graphics programming with DirectX). GLSL will multiply these matrices as usual, from left to right order, like any other math library.

We already saw in the previous article the importance of the Model Matrix. I will consider that multiplying the model matrix with the input vertex is going to be our first operation. This multiplication with model matrix is required in order to apply transformations (translate, rotate, scale) to our model. These transformations will change the vertex’s initial position.

Let’s imagine that our artist created this box wrong, with the tape on the bottom (in the previous article we had the Stanford Dragon). Now I want to rotate my box so that the tape will be on the top. This operation can be done in this model space.

All initial vertices are going to have new positions after the multiplication with the model matrix.

**World Space Transformation **

Next, we have to bring this model in the world space. This is done by multiplying our model matrix with the world matrix. World space can be seen as a common ground for all models in the scene.

Let’s imagine that we have a big world (like Skyrim). Now, I also want to add our box model in this world. Notice that I also added the world coordinate system.

As you can see in “my Skyrim world” I have a bunch of models. I also added and translated my rotated box on that stone. Also, each model has its model space as well.

** View Space Transformation**

The Skyrim world space is enormous and we don’t want to see it all when we are playing the game from multiple reasons:

- Performance. We can’t load all models in the world.
- Gameplay. We are only interested in our character’s actions.
- It’s impossible to project it on the screen without view matrix and projection matrix.

So what’s the view space?. It’s a point in space towards which the observer will look along with its **Up** direction. This point can be seen as a virtual model/camera (invisible for us in the scene) and it is also called a Camera or Eye. The view matrix together with the projection matrix will give us the world volume required to generate a 2D image that will end up on the screen. If we exclude them from the equation, we will end up with nothing on the screen.

We can create the view matrix only from three 3D vectors (x,y,z components):

- Position Vector (
**p**). The position of the camera in 3D space or eye position. - Target Vector (
**e**). The position where you want to look at. The point of interest. - Up Vector (
**u**). Camera orientation. This helps if you want to get a tilt effect.

Using basic vector operations, we can construct our view matrix camera base on this 3 vectors defined above:

- First we have to find the direction vector of the camera. This is done by normalizing the difference between vectors
and*p*Let’s call this vector**e**.*f* - Immediately we can find another direction called “right or sideways” by taking the cross product between the new vector
and the**f****Up**vector. Of course this vector must be normalized too. This vector called**u**is orthogonal (perpendicular) on*s*and**f**.**u** - Now,
and**u**might not be orthogonal so we want to make sure that we have an orthogonal vector on**f**and**f**from the previous steps. So we can take the cross product between**s**and**f**. Since**s**and**f**are already unit vectors we don’t need to normalize the result. We call this vector**s**.**v**

So will end up with the following matrix:

Where * p * is the translation (position as defined above) in world space.

The problem is that our models are in world space. So how we can we reverse from world space to view space? Answer: We inverse the world matrix.

The inverse matrix operation is expensive on the CPU. Luckily we can avoid this using some matrix properties to quickly find the view matrix:

- Composition. We can write
**N = T * R**. Where**T**is our transpose matrix and**R**is the rotation matrix. -
**N**^{-1}= (T * R)^{-1 }= R^{-1 }* T^{-1} **R**is orthogonal (all unit vectors and orthonormals) so**R**Don’t confuse transpose operation (^{-1}=R^{T}^{T}) with translate matrix**T**.

Applying these properties we will end up with our view matrix (column major):

**Tips:** A quick way to find the matrix in row major is to translate V.

The view matrix simplifies our lives a little because we can describe our vertices directly to view space so we don’t care about the world anymore…I mean the world space/world matrix 🙂 we don’t have to be suicidal here. Just consider the World matrix an Identity matrix.

All matrix libraries for Computer Graphics must provide a method to compute the view matrix from three vectors. I think that’s really important to know what’s happening behind the LookAt methods. Now we know what GLM or other math library is doing when we call this method. 😀

Matrix4 LookAt(const Vector3& position, //camera position (eye) const Vector3& target, //camera target const Vector3& up) { Vector3 f = position - target; f.normalize(); Vector3 s = Vector3::Cross(f, up); //cross product s = f X up s.normalize(); Vector3 v = Vector3::Cross(s, f); //Note! Vectors f,s,v must create a rotation matrix //To check if rotation matrix is OK, transpose and inverse //of rotation matrix must be equal //Check R^T = R^-1 //One more thing; The camera is not looking forward, it's looking //backwards. Camera position is on a positive Z but it's looking //in the opposite direction. Ex: position (0,0,100) target (0,0,0) //So the view direction is -100. So let's turn f negative. //This way the R determinant is going to be equal to 1 and not -1 f.negate(); //build V matrix; Matrix4 V = Matrix4(s.x, s.y, s.z, -Vector3::Dot(s,p), v.x, v.y, v.z, -Vector3::Dot(v,p), f.x, f.y, f.z, Vector3::Dot(f,p), 0, 0, 0, 1); return V; }

In the next tutorial we will talk about the projection matrix, the next important piece in our chain.