alright, then riddle me this.
(all in column-major order)
The projection matrix I created is:
0.074978 0.000000 0.000000 0.000000 0.000000 0.099970 0.000000 0.000000 0.000000 0.000000 -1.000100 -1.000000 0.000000 0.000000 -0.200010 0.000000
It's inverse I calculated is:
13.337285 0.000000 0.000000 0.000000 0.000000 10.002963 0.000000 0.000000 0.000000 0.000000 0.000000 -4.999750 0.000000 0.000000 -1.000000 20001000.000000
an multiplying those matrices together should be identy, but instead I get:
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.000000 0.000000 -20000994.000000 1.000000
All code related to this is shown below. I've been up and down and all the methods, as far as I can tell, look correct.
[source lang="cpp"]// Mat4f class is a 4x4 matrix of floats.
// Mat4f::data is a float[16], and is column-major
// returns float& intentionally, method is private
inline float& Mat4f::M( const int col, const int row ) {
assert( col < dim && row < dim && col >= 0 && row >= 0);
return data[row+col*4];
}
void Mat4f::Multiply( const Mat4f& mat, Mat4f& out ) const {
assert ( &mat != &out );
int r,c;
for ( c=0; c<4; c++ ) {
for ( r=0; r<4; r++ ) {
out.M(c,r) =
M(r,0) * mat.M(0,c) +
M(r,1) * mat.M(1,c) +
M(r,2) * mat.M(2,c) +
M(r,3) * mat.M(3,c);
}
}
}
// calculation from: http://www.glprogramming.com/red/images/Image23.gif
void my_glFrustum( float l, float r, float b, float t, float n, float f, Mat4f& out ) {
float n2 = n * 2.0f;
out.data[0]=n2/(r-l);
out.data[1]=0.0f;
out.data[2]=0.0f;
out.data[3]=0.0f;
out.data[4]=0.0f;
out.data[5]=n2/(t-b);
out.data[6]=0.0f;
out.data[7]=0.0f;
out.data[8]=(r+l)/(r-l);
out.data[9]=(t+b)/(t-b);
out.data[10]=-(f+n)/(f-n);
out.data[11]=-1.0f;
out.data[12]=0.0f;
out.data[13]=0.0f;
out.data[14]=-(n2*f)/(f-n);
out.data[15]=0.0f;
}
// calculation from: http://www.glprogramming.com/red/images/Image23.gif
void my_glFrustum_inv( float l, float r, float b, float t, float n, float f, Mat4f& out ) {
float n2 = n * 2.0f;
out.data[0]=(r-l)/n2;
out.data[1]=0.0f;
out.data[2]=0.0f;
out.data[3]=0.0f;
out.data[4]=0.0f;
out.data[5]=(t-b)/n2;
out.data[6]=0.0f;
out.data[7]=0.0f;
out.data[8]=0.0f;
out.data[9]=0.0f;
out.data[10]=0.0f;
out.data[11]=-(f-n)/(n2*f);
out.data[12]=(r+l)/n2;
out.data[13]=(t+b)/n2;
out.data[14]=-1.0f;
out.data[15]=(f+n)/n2*f;
}
void my_gluPerspective( float fov, float x,float y,float near,float far, Mat4f& out, bool invert = false );
void my_gluPerspective( float fov, float x,float y,float near,float far, Mat4f& out, bool invert ) {
// inspired by
http://www.cse.unsw....e/frustsrc.html
float aspect = x / y;
float t = 1.0f/tanf(fov * 3.141f / 360.0f);
if ( invert ) {
my_glFrustum_inv(-t * aspect, t * aspect, -t, t, near, far, out);
} else {
my_glFrustum(-t * aspect, t * aspect, -t, t, near, far, out);
}
}
inline void my_gluPerspective_inv( float fov, float x,float y,float near,float far, Mat4f& out ) {
my_gluPerspective( fov, x, y, near, far, out, true );
}
int main ( void ) {
Mat4f should_be_identity;
Mat4f projection;
Mat4f projection_inverse;
my_gluPerspective(90,800,600,0.1f,2000,projection);
my_gluPerspective_inv(90,800,600,0.1f,2000,projection_inverse);
projection.Multiply(projection_inverse, should_be_identity);
for ( int i=0; i<16; i++ )
printf("%f ", should_be_identity.data
);
/*
expected output:
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.000000 0.000000 0.000000 1.000000
actual output:
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.000000 0.000000 -20000994.000000 1.000000
*/
return 0;
}
[/source]