Vector/Matrix maths is at the heart of most of what we do in a raytracer. An understanding of these basic types is key to building 3d graphics applications. Although at first glance these structures seem quite daunting, they’re actually pretty easy to understand.

To help people who aren’t fully up to speed on vector/matrix maths I’m going to go through some basics here.

First off then, the two dimensional vector. Each pixel on the screen you’re looking at is at a seperate position, and this position is referenced using an x and a y position. This location can be represented by a 2d vector written as (x, y). The code to define a 2d vector is…

`class Vector2`

{

double x;

double y;

};

A three dimensional vector is exactly the same thing, except we’re now going to add a z component. This z component refers to how far into the screen that location is. A 3d vector can be written as (x, y, z).

`class Vector3`

{

double x;

double y;

double z;

};

This 3d vector can be used to describe two key things for our raytracer. A position and a direction. Directions are represented as simple 3d vectors originating at the origin (0,0,0).

It’s worth talking about normalisation for a quick sentence too as directions are nearly always normalised inside a raytracer. A normal vector is one which has a length of 1. i.e. sqrt(x*x + y*y + z*z) = 1. To normalise a vector we simply divide each component by the length.

`void Normalise()`

{

double length = sqrt(x*x + y*y + z*z);

x /= length;

y /= length;

z /= length;

}

So onto the ray, which is a fundamental component of a raytracer. A ray within a scene is described by 2 things. The position that the ray starts, and the direction the ray goes in. These two components can both be described by 3d vectors giving us the simple definition of a ray…

`class Ray`

{

Vector3 origin;

Vector3 direction;

};

Hopefully you’re staying with this so far. If not then google Vector3, 3d vector and try to get your head round it, because there’s no point reading any more!

Assuming this did make sense, the next leap is to move on to a matrix. You can think about a matrix as a grid of numbers. Mathematically that’s the definition, but in computer graphics matrices are far more commonly used to express an orthonormal basis. Don’t worry what that means, but basically we’re describing an X, Y and Z axis which are all at right angles to each other.

Imagine we want to describe the direction that our head is pointing in using a 3×3 Matrix. To get this encoded into a matrix we have to imagine 3 arrows attached to our head. One pointing up, one pointing to the right, and one pointing forwards. We can then build a 3×3 matrix where the top row will describe the “right” vector. The second row describes the “up” vector. The third row describes the “to” vector.

Something facing in a neutral direction is represented using the identity matrix which has the value…

`1, 0, 0`

0, 1, 0

0, 0, 1

If you take your head and twist it 90 degrees to the right then the three arrows have now moved. The one that was going to the right now faces along the negative z vector (0, 0, -1). The up vector is still facing up (0, 1, 0), and the to vector is now facing to the right (1, 0, 0). The rotation matrix can now be described as…

`0, 0, -1`

0, 1, 0

1, 0, 0

These matrices become really cool when we try to rotate a 3d position. For example, imagine that you want to rotate the point (1, 1, 1) using this matrix. We do this by multiplying the vector by each column of the matrix and summing the values…

`x = 1*0 + 1*0, + 1*1 = 1;`

y = 1*0 + 1*1 + 1*0 = 1;

z = 1*-1 + 1*0 + 1*0 = -1;

The new vector is therefore (1, 1, -1).

Woo, we can now rotate arbitrary vectors by a specified rotation matrix. We can also do something else pretty neat with a 3×3 matrix. We can scale points.

Lets change the matrix we’re using to this…

`2, 0, 0`

0, 2, 0

0, 0, 2

Now when we multiply the vector (1, 1, 1) we get the position (2, 2, 2). We have effectively scaled the vector by a factor of 2. Neat huh? Of course, you would be right to point out that all we actually needed to do was multiply each component by 2 rather than using a matrix. But later on I’ll come back to why the matrix representation matters.

If you’ve done much graphics work before you’ll know that we actually use a 4×4 matrix to describe transformations. Huh? 4×4? What’s the 4th dimension? Well it’s not time… In fact, it’s used to encode a translation vector.

Lets take the 3×3 rotation matrix we built above and convert it into a 4×4 matrix with an arbitrary translation (a, b, c). The result looks like this…

`0, 0, -1, 0,`

0, 1, 0, 0,

1, 0, 0, 0,

a, b, c, 1

Now to multiply a vector by this matrix we need to add a 4th component from somewhere. In graphics we use 1 for the translation trick to work. Our 3d vector (x, y, z) now becomes a 4d vector (x, y, z, 1).

The result of the multiplication now looks like this…

`x = 1*0 + 1*0, + 1*1 + 1*a = 1 + a;`

y = 1*0 + 1*1 + 1*0 + 1*b = 1 + b;

z = 1*-1 + 1*0 + 1*0 + 1*c = -1 + c;

w = 1*0 + 1*0 + 1*0 + 1*1 = 1;

…giving the vector (1+a, 1+b, -1+c, 1).

This trick is fundamental to computer graphics, but there’s one other great property about these matrices which is used a lot in computer graphics. Let’s say we have 3 matrices, a scaling matrix, a rotation matrix, and a translation matrix.

`Scaling`

2, 0, 0, 0

0, 2, 0, 0

0, 0, 2, 0

0, 0, 0, 1

```
```Rotation

0, 0, 1, 0

0, 1, 0, 0

-1, 0, 0, 0

0, 0, 0, 1

`Translation`

1, 0, 0, 0

0, 1, 0, 0

0, 0, 1, 0

a, b, c, 1

We can string these all together to give a single matrix that looks like this.

`0, 0, -2, 0,`

0, 2, 0, 0

2, 0, 0, 0

a, b, c, 1

Even better, to work out what the new matrix should be we just multiply the matrices together. We can even multiply it by another rotation, and another, and we’ll still just end up with a single matrix. This means that to take any point and move it through an arbitrary number of rotations, scaling and translations we just need to multiply the position by the single compound matrix. This is super efficient and actually pretty damn elegant, it’s also the end of this quick primer on vector / matrix maths.

I hope this has helped you to understand the basics. If I’ve skimmed anything too quickly let me know.