## matrix layout

3D Matrix Definition

Memory Layout

Matrix Code Definition

C++ class definition

row major implementation

column major implementation

generic definition

- using column or row vectors
- the layout of matrices in memory

### 3D Matrix Definition

**column vectors**

In this case the translation will be in elements m14, m24, m34 (marked in bold).

Mathematicians and OpenGL, prefer column vectors (vector on the right)

m11 m12 m13m14x m21 m22 m23m24y m31 m32 m33m34z m41 m42 m43 m44 1

**row vectors**

In this case the translation will be in elements m41, m42 and m43 (marked in bold).

DirectX prefers row vectors (vector on the left)

m11 m12 m13 m14 m21 m22 m23 m24 x y z 1 m31 m32 m33 m34m41 m42 m43m44

### Matrix Memory Layout

Now if we take the above matrix definition, and put it in a 'flat, contiguous' block of memory of 16 floats - what value should each float represent?

We have two options: we can either go through the rows first, or alternatively we can go through the columns first...

**Column Major**

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [m11 m21 m31 m41 m12 m22 m32 m42 m13 m23 m33 m43m14 m24 m34m44]

**Row Major**

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [m11 m12 m13 m14 m21 m22 m23 m24 m31 m32 m33 m34Notice that in both cases , the translation is in the elements at index 12, 13 and 14 in both OpenGL and DirectX. These locations map to m41, m42 and m43 in the DirectX convention - and to m14, m24, m34 in the OpenGL convention.m41 m42 m43m44]

## Matrix Code Definition

Now it's important to know where openGL or directX expect the values to be when they are passed a pointer to a matrix - as this determines how we have to define our C++ class.

OpenGL assumes colum major memory layout

DirectX assumes row major memory layout

### C++ class definition

Now let's see how we put that into C/C++ sourcecode. Assume we want to use 16 seperate float-values in our matrix class. It could look like this:

class matrix4 { float m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44; }

### row major implementation

Now if we assume row-major (directX) a translation matrix would look like this:

m11, m12, m13, m14 1 0 0 0 m21, m22, m23, m24 0 1 0 0 m31, m32, m33, m34 = 0 0 1 0 m41, m42, m43, m44which - using the above class definition - would end up in memory like this:tx ty tz1

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] 1 0 0 0 0 1 0 0 0 0 1 0Which is exactly how directX would like to have it - perfect.tx ty tz1

### column major implementation

Now let's assume a column-major matrix (openGL) a translation matrix would look like this:

m11, m12, m13, m14 1 0 0which - using the above class definition - would end up in memory like this:txm21, m22, m23, m24 0 1 0tym31, m32, m33, m34 = 0 0 1tzm41, m42, m43, m44 0 0 0 1

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] 1 0 0Which istx0 1 0ty0 0 1tz0 0 0 1

**not**how openGL would like to have it. The matrix and the values are ok - but they just end up in the wrong location in memory.

How can we fix this?

What if we would change the order of the member-variables in the class like this:

class matrix4_col { float m11, m21, m31, m41, // 1st column m12, m22, m32, m42, // 2nd column m13, m23, m33, m43, // 3rd columnWe use the same translation-values, but now they end up in memory like this:m14, m24, m34, m44; // 4th column };

[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] 1 0 0 0 0 1 0 0 0 0 1 0which is exactly what openGL would like to have it - perfect.tx ty tz1

### another example

Now if we see a matrix as 4 seperate vectors (in either row or column order, depending on the graphics API) and we make sure we fill the 4 vectors appropriately ourselves - then we can use the same matrix

*class-definition*for both ( however operations on the values are

**not**necessarily the same!)

class vector4 { float x,y,z,w; } class matrix4 { vector4 x; // either row 1 (directX) or column 1 (openGL) vector4 y; // either row 2 (directX) or column 2 (openGL) vector4 z; // either row 3 (directX) or column 3 (openGL) vector4 w; // either row 4 (directX) or column 4 (openGL) }