Matrix vs Vector for Location

Started by
3 comments, last by patrisia 5 months, 1 week ago

I was reading and you can encapsulate the location of a renderable with matrices, yet I always used vectors. Do I build a matrix every frame, or update one, and use a simple 3d vector for the location for calculations? Please can someone explain in some detail the best way to do this. I know you want matrices for transformations of the object.

Advertisement

Read this wikipedia article on transformations. The basic idea is to represent position, rotation, scaling, and skew with a single matrix. The matrix is 1 row and column larger than the number of dimensions in your scene (e.g. 3x3 for 2D, 4x4 for 3D). The last column contains the position, and the upper left 3x3 part of a 4x4 matrix has the rotation, scale and skew.

In most game engines, you would store position for your objects as separate position (3D vector), rotation (quaternion or 3x3 matrix), and scale (3D vector). Then, each frame you would combine those into a single 4x4 matrix representing the full transform. This matrix can then be used by the graphics API to transform meshes to the correct positions in the scene.

scruthut said:
I was reading and you can encapsulate the location of a renderable with matrices, yet I always used vectors. Do I build a matrix every frame, or update one, and use a simple 3d vector for the location for calculations?

Transformation matrices are easy to understand geometrically. It's not a blackbox of a complex transformation - you can and should use all of it's numbers as needed.

Think of how 3D modeling tools like Blender show the transform of any object. It's three colored arrows with a common origin. We could express the data like this:

struct Transform
{
	vec3 xAxis; // shown as red arrow
	vec3 yAxis; // green arrow
	vec3 zAxis; // blue arrow
	vec3 origin;
};

Eventually, e.g. because of SIMD alignment, we may use vec4 for everything. I'll also introduce initialization to default values. We get:

struct Transform
{
	vec4 xAxis   = vec4(1,0,0, 0); // this is a vector, so the 4th. number is a zero. If we transform such vector by a transformation matrix, it will only rotate (, scale, or skew), but it will not move.
	vec4 yAxis   = vec4(0,1,0, 0);
	vec4 zAxis   = vec4(0,0,1, 0);
	
	vec4 origin  = vec4(0,0,0, 1); // this is a point, so the 4th. number is a zero. If we transfrom it, it will rotate AND move.
};

The mumbo jumbo about the 4th. number is not important at this point, but it helps to come to our conclusion:

The Transform struct we just did is equivalent to a 4x4 matrix, which is often used to represent a transformation in 3D space.

If we have this typical matrix data structure:

struct Matrix4x4
{
	vec4 rows[4];
	// or float values[4][4];
	// or float values[16];
};

Both our data structures are the same in memory, but also in intuitive geometric representation.
In C or C++, we can cast one to the other and it will work.
And if you're already familiar with vectors, then you are already familiar with transformation matrices too. Just imagine (and actually use) it this way:

There are 3 basis vectors to define orientation. It's the upper left 3x3 section of the matrix. I tried to make this visible by using spaces in my default initialization code above.
There is a 4th vector to define position.

If we make a transformation which does nothing - neither moving or rotating our space, we get the identity matrix. And you can see those numbers (diagonal is 1, rest is 0) again in the initialization values.

I hope that's clear, and eventually you have known it before. Otherwise this is the concept you need to grasp first, imo.

The rest of your question sounds like ‘when and why should i use matrices?’.
I'll rephrase this to ‘when and why can i use matrices?’, because it's up to you what you prefer.

You talk about a ‘location’, but you may ignore the case where position is not enough to represent some object, e.g. a pointer of a clock. It's location always remains the center of the clock, only it's orientation changes. It rotates.
That's when you need to define this too. We can use the 3 basis vectors to have x,y & z axis. That's our matrix, and a very common and intuitive way. We can also use a quaternion, which requires less numbers, can do some things more easily, but can nt represent exotic transforations like nonuniform scale or skew.
Most people will use both, and there are also other ways to work with 3D rotations. But mostly it's the need to handle rotations which brings us to matrices. That's also the hard part of the whole topic, probably.

There are also cases where we must use matrices, and as specified. E.g. when working with graphics APIs, physics libraries, etc. There are different conventions. What i've written above would be compatible with the OpenGL API, but for DirectX the rows and columns are swapped. This can be confusing, and requires to make a choice. However, the theory and math remains the same.
And the math is made mostly from vector operations. If you understand the vector Dot Product geometrically, it's easy to see that matrix multiplication is just an application of that, if we look at it from this perspective.

I would say, if you work in 3D, yes you should use matrices.
In 2D not so much, but matrices remain useful here too.

@scruthut I use vectors for position and scaling. I rebuild the World transform for the renderable object when it changes position, scaling. I rebuild the view when the camera position changes, and rebuild the projection when the field of view changes. I am using directX , which has functions that convert a vector to a position matrix or a scaling matrix. Using vectors for positions is nice because it's more intutive and you can easily calculate distances between objects.

This topic is closed to new replies.

Advertisement