Jump to content
  • Advertisement
Sign in to follow this  
lucky6969b

About the stability of matrix inverses in DirectX9

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!