Matrix cannot be inverted in parallel projection

Why do I get a "matrix cannot be inverted" when doing a getWorldCoordinates with the following frustum values in parallel projection?

setFrustm(-200f, 1000f,-138f, 138f, -104f, 104f)


    public Matrix4f invert(Matrix4f store) {
        if (store == null) store = new Matrix4f();

        float fA0 = m00*m11 - m01*m10;
        float fA1 = m00*m12 - m02*m10;
        float fA2 = m00*m13 - m03*m10;
        float fA3 = m01*m12 - m02*m11;
        float fA4 = m01*m13 - m03*m11;
        float fA5 = m02*m13 - m03*m12;
        float fB0 = m20*m31 - m21*m30;
        float fB1 = m20*m32 - m22*m30;
        float fB2 = m20*m33 - m23*m30;
        float fB3 = m21*m32 - m22*m31;
        float fB4 = m21*m33 - m23*m31;
        float fB5 = m22*m33 - m23*m32;
        float fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;

        if ( FastMath.abs(fDet) <= FastMath.FLT_EPSILON )
            throw new ArithmeticException("This matrix cannot be inverted");

m00 0.007246377
m11 0.009615385
m22 -0.0016666667
m32 -0.625
the others are zero

fA0 6.96767E-5
fDet -1.16127836E-7
EPSILON: 1.1920929E-7

obviously abs(fDet) is smaller than Epsilon...but why i do not know  :)
maybe those values will make sense to someone who likes math :)

Yeah, I got that far, too.

With Epsilon being the smallest representable float value the determinant would become zero and thereby the whole matrix would become ininvertable.

I fear I will have to chzeck all the values and how they are calculated to figure out what's going on.


My guess is its because of Ortho projection and negative near/positive far value, but its just a guess. You can calculate the inverse matrix yourself directly (or better, write a fix  :D), theres descriptions on GL matrices on the net, for example this page:

There is no apparent error.

I checked the math and everything should be ok.

Also the behaviour of the value is as it is expected.

The determinant gets smaller and smaller until it is smaller than FLT_EPSILON and thereby the inversion fails because the determinant is now treated as if it is 0.

So your issue is the floating point accuracy. FLT_EPSILON should be the the smallest float where 1f+value!=1f. If the determinant is smaller than that it does not necessarily mean, that it cannot be inverted. But the result will get inaccurate, at least. But if scaling the scene instead works well for you (which I read in your other thread) it should as well be ok to use the scaled frustum. So: just replace that check with <= 0 and see if the results are fair.

That's what I tried to avoid but now that scaling introduced the physics problem I think it's easier to change one class instead of going into close combat with ode.

My suggestion was to change

if ( FastMath.abs(fDet) <= FastMath.FLT_EPSILON )
            throw new ArithmeticException("This matrix cannot be inverted");


if ( FastMath.abs(fDet) <= 0 )
            throw new ArithmeticException("This matrix cannot be inverted");

in the Matrix4f invert method. And have a look if that solves the problem for you.

I was already working on that when I did my last post.

I pulled the inversion functionality into my camera class (I wanted to avoid to modify the core classes).

Works like a charm :slight_smile:

Thanks a lot for your help, otherwise I would still be sitting there and trying to get ode to scale my vectors.

Maybe we should change that on the core then. It does not make much sense to restrict the use of the invert function if it works in most of the cases. Maybe that check against epsilon is overcautious.

Good point.

I will ask in Dev General.