OpenGL compliant matrix functions

I’ve seen defferent implementations of inverse of a matrix and matrix-vector multiplications on the internet, and I’m not quite sure what is the correct one to use with opengl. I think
“the Matrix and Quaternion FAQ” had differently oriented matrices than what opengl uses.

So… I would be very grateful if someone could post a sample functions for the inverse of a 4x4 matrix and vector-matrix multiplication, that can be used with matrices retrieved from opengl and vice versa.

[This message has been edited by blender (edited 08-24-2003).]

// Multiplies v by m (3x3) and adds translation
void VecMatrixMult(float v[3], float res[3], float *m)
{
res[0]=(v[0]*m[0])+(v[1]*m[4])+(v[2]*m[8])+m[12];
res[1]=(v[0]*m[1])+(v[1]*m[5])+(v[2]*m[9])+m[13];
res[2]=(v[0]*m[2])+(v[1]*m[6])+(v[2]*m[10])+m[14];
}

void MatrixInvert(float *m)
{
float res[16];

res[0]=m[0];
res[1]=m[4];
res[2]=m[8];
res[3]=0.0f;
res[4]=m[1];
res[5]=m[5];
res[6]=m[9];
res[7]=0.0f;
res[8]=m[2];
res[9]=m[6];
res[10]=m[10];
res[11]=0.0f;
res[12]=-(m[12]*m[0])-(m[13]*m[1])-(m[14]*m[2]);
res[13]=-(m[12]*m[4])-(m[13]*m[5])-(m[14]*m[6]);
res[14]=-(m[12]*m[8])-(m[13]*m[9])-(m[14]*m[10]);
res[15]=1.0f;

memcpy(m, res, sizeof(float)*16);
}

Your function for inverting matrices looks like a special case function only. It will only work for orthonormalized matrices with a translation part. Any other matrix won’t be inverted properly. If that’s all you need then there’s no problem, but for general matrices it won’t work.

I need an invert function for arbitrary matrices. This is what I have at them moment (unfortunetly I can’t tell myself wether it’s ok or not, because I can’t inderstand it at all):

void MatrixInverse(mat44_t inv, mat44_t m)
{

int i, j, k, swap;
float t;
float temp[4][4];

for(i=0; i<4; i++)
for(j=0; j<4; j++)
temp[i][j] = m[(i*4)+j];

MatrixLoadIdentity(inv);

for(i=0; i<4; i++)
{
swap = i;
for(j=i+1; j<4; j++)
if( FAB(temp[j][i])>FAB(temp[i][i]) )
swap = j;

  if(swap!=i)
  {
  	for(k=0; k<4; k++)
  	{
  		t	= temp[i][k];
  		temp[i][k]	= temp[swap][k];
  		temp[swap][k]	= t;

  		t	= inv[(i*4)+k];
  		inv[(i*4)+k]	= inv[(swap*4)+k];
  		inv[(swap*4)+k]	= t;
  	}
  }

  if(temp[i][i]==0)
  	return;

  t	= temp[i][i];
  for(k=0; k<4; k++)
  {
  	temp[i][k]	/= t;
  	inv[(i*4)+k]	/= t;
  }
  for(j=0; j<4; j++)
  {
  	if(j!=i)
  	{
  		t	= temp[j][i];
  		for(k=0; k<4; k++)
  		{
  			temp[j][k]	-= temp[i][k]*t;
  			inv[(j*4)+k]	-= inv[(i*4)+k]*t;
  		}
  	}
  }

}
}

Could anyone tell me if this is ok? I just need to know if my current problem is based on invalid matrix function implementation.

You can easily see for yourself if it’s OK or not. Create a random matrix, invert it, and multiply it by the original matrix. If you know your matrix math, you should know what the result is supposed to be if the matrix is correctly inevrted.

Well ok…

mat44_t m;
vec3_t v={100, 450, 30};

MatrixLoadIdentity(m);
MatrixRotateY(m, 45.0f);
MatrixTranslate(m, v);
MatrixInverse(i, m);
MatrixPostMultiply(m, i);

And m appears to be the identity matrix. Though I saw some precision errors on few numbers, they were not exactly zero, here’s the listing:

1.000000
-0.000000
-0.000000
0.000000

0.000000
1.000000
0.000000
0.000000

0.000000
0.000000
1.000000
0.000000

-0.000004
0.000000
0.000006
1.000000

It looks like it works, but to be on the safe side you should fill it with random data to make sure it works with arbitrary matrices, not just a simple rotation and a translation.

Anyways, if I remember correct, a float (I assume that’s what you use) is only guaranteed to give you about 5-6 correct digits, so -0.000004 and 0.000006 could be within that limit and should therefore be treated as correct (equal to zero) as the datatype can’t provide more precision for “better” result.