Reputation: 16061
My question simply is: what is the correct format for the Projection and ModelView matrix?
I've been told that the following example matrices are transposed and are not built like OpenGL matrices should be.
ModelView Matrix
{(1, 0, 0, 0)
(0, 0.7071068, 0.7071068, 0)
(0, -0.7071068, 0.7071068, 0)
(0, -141.4214, -141.4214, 1)}
Projection Matrix
{(1.931371, 0, 0, 0)
(0, 2.414213, 0, 0)
(0, 0, -1.0002, -1)
(0, 0, -2.0002, 0)}
Upvotes: 12
Views: 17235
Reputation: 482
You can use whichever notation you like, as long as you're consistent with the ordering of matrix operations. Quoting from https://www.opengl.org/archives/resources/faq/technical/transformations.htm:
9.005 Are OpenGL matrices column-major or row-major?
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 as described in section 2.11.2 of the OpenGL 2.1 Specification.
Column-major versus row-major is purely a notational convention. Note that post-multiplying with column-major matrices produces the same result as pre-multiplying with row-major matrices. The OpenGL Specification and the OpenGL Reference Manual both use column-major notation. You can use any notation, as long as it's clearly stated.
i.e. in a shader you can load transformation matrices as float arrays ordered by columns into a uniform and pre-multiply a vertex to transform it:
gl_Position = Proj * View * Model * vPosition;
or load the same matrices as float arrays ordered by rows and post-multiply to achieve the same effect:
gl_Position = vPosition * Model * View * Proj;
By transposing a matrix you effectively transform it to be stored in the opposite notation, which is why OpenGL has options to transpose matrices as they are inputted.
Upvotes: 6
Reputation: 4340
Edit: this answer is in serious need of an update. Namely, there is no consideration about shaders.
As @gman points out in the comments, whether to use row-major or column-major depends on how you do your math. You may choose one or the other (or even both at different times if you don't think that's confusing) just as long as they match your coordinate systems and order of operations.
I'm leaving this answer as community wiki in case someone has the time and will to update it.
OpenGL specifies matrices as a one-dimensional array listed in column-major order, ie with elements ordered like this:
m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15
So if you initialize an array this way, in C or pretty much any other language, the resulting matrix will look like it needs transposing, because C code reads left-to-right first and then top-to-bottom (in other words, like if it were in row-major order):
int mat[16] = {
0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,
12, 13, 14, 15,
}
By the way, OpenGL has both glLoadTransposeMatrix and glMultTransposeMatrix, which you can use instead of glLoadMatrix and glMultMatrix, so this shouldn't be a problem.
Upvotes: 25