matrix layout

3D Matrix Definition
Memory Layout
Matrix Code Definition
C++ class definition
row major implementation
column major implementation
generic definition

A matrix for 3D rendering is usually 4x4 elements large and describes transforms between coordinate systems (e.g. rotation and translation). There are two confusing issues however...
  1. using column or row vectors
  2. 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 m13 m14    x
  m21 m22 m23 m24    y
  m31 m32 m33 m34    z
  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 m34
                 m41 m42 m43 m44

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  m43  m14 m24 m34  m44] 
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  m34  m41 m42 m43  m44]
Notice 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.

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, m44	tx ty tz 1
which - using the above class definition - would end up in memory like this:
  [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    0    tx   ty   tz    1
Which is exactly how directX would like to have it - perfect.

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  0  tx
	m21, m22, m23, m24	0  1  0  ty
	m31, m32, m33, m34  =	0  0  1  tz
	m41, m42, m43, m44	0  0  0  1
which - using the above class definition - would end up in memory like this:
  [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]  [8]  [9] [10] [11] [12] [13] [14] [15]
   1    0    0    tx   0    1    0   ty    0    0    1   tz    0    0    0    1
Which is 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 column
        m14, m24, m34, m44; // 4th column 
};
We use the same translation-values, but now they end up in memory like this:
  [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    0    tx   ty   tz    1
which is exactly what openGL would like to have it - perfect.

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)
}


JSN Teki template designed by JoomlaShine.com