Reputation: 4050
I'm looking at some iOS sample code from Apple which shows off GLES2 functionality, and I see them doing this:
mat4f_MultiplyMat4f(proj, modelview, modelviewProj);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEW_PROJECTION_MATRIX], 1, GL_FALSE, modelviewProj);
Based on the definition of their mat4f_MultiplyMat4f function, it looks like they're pre-multiplying the modelview matrix by the projection matrix and storing the resultinto modelviewProj. Though I'm still very new, that doesn't feel right to me; shouldn't it be mvp = mv*p, and not mvp = p*mv like they're doing?
Here's their mat4f_MultiplyMat4f function pasted to verify:
void mat4f_MultiplyMat4f(const float* a, const float* b, float* mout)
{
mout[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2] + a[12] * b[3];
mout[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2] + a[13] * b[3];
mout[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2] + a[14] * b[3];
mout[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3];
mout[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6] + a[12] * b[7];
mout[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6] + a[13] * b[7];
mout[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6] + a[14] * b[7];
mout[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7];
mout[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10] + a[12] * b[11];
mout[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10] + a[13] * b[11];
mout[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10] + a[14] * b[11];
mout[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11];
mout[12] = a[0] * b[12] + a[4] * b[13] + a[8] * b[14] + a[12] * b[15];
mout[13] = a[1] * b[12] + a[5] * b[13] + a[9] * b[14] + a[13] * b[15];
mout[14] = a[2] * b[12] + a[6] * b[13] + a[10] * b[14] + a[14] * b[15];
mout[15] = a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15];
}
I would guess that this is a mistake, but I don't know. Doesn't doing Proj*Modelview*Vert apply the projection matrix first, and then the modelview on top of that? Wouldn't that give weird results like translations moving things more than they should in certain directions depending on the projection's aspect ratio? Isn't it Modelview*Proj*Vert that you want, and isn't that after all why it's called the MVP matrix and not the PMV matrix? Could it just be that this simple little spinning square the apple sample code draws just isn't complicated enough for the mistake to come to light?
Upvotes: 2
Views: 2439
Reputation: 162194
Matrix multiplication is right associative, i.e. the expression is evaulated right to left. So the correct multiplication is indeed
MVP = P * MV
You can easily deduce this by remembering that you want to multiply a column vector with a matrix, resulting in another column vector. By definition of matrix multiplication
v'_j = \sum_i M_ij * v_i
or short
v' = M * v
you may rewrite the whole transformation as
v_eye = MV * v
and
v_clip = P * v_eye
substituting v_eye
v_clip = P * (MV * v) = P * MV * v
Upvotes: 5