# About the stability of matrix inverses in DirectX9

This topic is 641 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

D3DXMatrixInverse(&worldInv, NULL, &l_transform->getWorldMatrix());

When I calculate the above math using matrix inverses,
even though the world matrix is at identity,
the outcome is still a bit off from standard 1.0,
looks like some floating point errors....
0.9999 on the diagonal or something

How do I eliminate those instabilities? does the determinant play a role in there?
Thanks
Jack

##### Share on other sites

How do I eliminate those instabilities? does the determinant play a role in there?

There's something you're supposed to never do, due to floating point inaccuracies.  Unfortunately, i don't recall exactly what it was, transpose, inverse - don't think its determinant. think it was inverse.

The workaround is you don't use it, you use something else.  i know - rather vague.

I just don't remember my Linear well enough.  Transpose swaps elements (?), determinant results in a scalar (?), and invert has rounding errors (?).  something like that...

Alvaro or somebody will know what the answer is.

##### Share on other sites
I don't know how D3D implements the inverse. I think every implementation of matrix inverse I have worked with would give you the identity matrix exactly as the inverse of the identity matrix.

However, your code should probably be robust enough to withstand this difference. What are you using the inverse of the world matrix for?

##### Share on other sites

Ok, now you've got me curious...

I know i heard somewhere that one of them had issues.  One that i don't use.

Let me do some googling.

well, i found this, but that's not where i heard about it....

https://www.johndcook.com/blog/2010/01/19/dont-invert-that-matrix/

not finding much else.

Edited by Norman Barrows

##### Share on other sites

In computer science 1 == 0.9999 because you never compare two floating point value unless you use an epsilon isequal( float a, float b) { return abs(a-b) < epsilon; }.

What is important is to not accumulate rounding error over time, this is the only metric that matters, and if in an application you care about precision that much, you move to fixed point math, but this is not what you want here.

##### Share on other sites

Hi there, I am hashing the local position, that is, I had multiple objects in my scene,

when I query the navigation system, I give the world position to it and the object's world matrix,

I multiply the position to the inverse of the world matrix give me the base of the hash, however,

the ground is extremely thin and sensitive, when it is off by 0.1, the hash gives me back a null pointer.

Edited by lucky6969b

##### Share on other sites
You can just quantize the position, if you rely on floating point value to match, you fall exactly in the case i describe, equality of floating points need an epsilon

##### Share on other sites

Looks like dx9 probably uses Gaussian elimination to invert a matrix.  And that means floating point division, and that means rounding errors.

As you can see, using a floating point value as a hash key is probably not a good idea.

##### Share on other sites
Direct3D 9 changes the floating-point mode to single-precision and round-to-nearest unless you specify D3DCREATE_FPU_PRESERVE in IDirect3D9::CreateDevice().
By passing this flag and setting your own floating-point mode in the compiler options you may get different results here.

But as mentioned you should never write code that relies on that level of precision as it will never be robust.

L. Spiro Edited by L. Spiro

##### Share on other sites

In computer science 1.0 == 0.9999 because you never compare two floating point value unless you use an epsilon isequal( float a, float b) { return abs(a-b) < epsilon; }.

That is entirely dependent on the size/precision of the floating point numbers being used.

With the following code:

int _tmain(int argc, _TCHAR* argv[])
{
float test = 1.0f;
if( test == 0.99999999f )
{
printf( "Test One!");
}

if( test == 0.9999f )
{
printf( "Test Two!");
}

return 0;
}


Will output:

  Test One!

The second 'if' statement will fail to execute the contained code.

You can definitely use an epsilon to mitigate the problem, but you have to keep in mind that the epsilon needs to scale with the floating point numbers you use... the larger the 'real' component of the float, the larger the required epsilon.

Edited by Orangeatang

1. 1
2. 2
Rutin
22
3. 3
4. 4
khawk
14
5. 5

• 13
• 26
• 10
• 11
• 44
• ### Forum Statistics

• Total Topics
633743
• Total Posts
3013643
×