ROUNDING_ERROR_f32 too big? (f64 too?)

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

ROUNDING_ERROR_f32 too big? (f64 too?)

Post by MasterD »

I want to know, why the rounding error in irrlicht is given as
const f32 ROUNDING_ERROR_f32 = 0.000001f;
instead of e.g.
const f32 ROUNDING_ERROR_f32 = std::numeric_limits<f32>::epsilon()

Will it get to instable with a too precise rounding error?

The reason is the following:

I have a animated character mesh. For some reasons (like: "I don't own Studio Max") I need to take what is at hand and scale this mesh by a uniform factor of 0.01. For some time now I wondered why it is not possible to select this character based on a triangle selector. Now I now, that this is due to the above given indifferences. The reason: the inverse matrix of the character cannot be constructed, as the calculation of the determinant (variable "d") in matrix4x4::getInverse is treated as zero, although it needn't to, in this case.

Some numbers:
Absolute transformation:

Code: Select all

0.0099999998 0.00000000   0.00000000   3.9448023   
0.00000000   0.0099999998 0.00000000   -0.056485906
0.00000000   0.00000000   0.0099999998 -0.045391038
0.00000000   0.00000000   0.00000000   1.0000000   
Determinant: 9.9999988e-007
Treated as
zero, with ROUNDING_ERROR_f32=1.0e-6F
non-zero, with std::numeric_limits<float>::epsilon()= 1.192092896e-7F(on my machine, but x86 is pretty standard)

Inverse:

Code: Select all

100.00001 0.0000000 0.0000000 -394.48026
0.0000000 100.00001 0.0000000 5.6485910 
0.0000000 0.0000000 100.00001 4.5391040 
0.0000000 0.0000000 0.0000000 1.0000000 
Looks not unstable, imho, but possibly an edge case?
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Yes I agree this is an issue epsilons. A better way instead of using a fixed value was discussed here: http://ompf.org/forum/viewtopic.php?f=11&t=1578&start=0

It's a little hack-ish but should work for almost any values.

PS: Lubeck is a beautiful place, didn't know you are from there.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

An interesting approach, also it looks a bit hack-ish, indeed. However, when determining if a given value is zero, this approach won't succeed.

I think I'm gonna try an even more rigorous approach*. In CMatrix4 I'm going to compare the determinant against numeric_limits<float>::min, to decide if the inverse may be constructed or not. But testing this is postponed to the weekend.
(*Edit: not the scaled epsilon approach, but the numeric_limits epsilon approach)

Interestingly, another open source 3D engine (*cough*ogre*cough*) is not checking the determinant at all when constructing the inverse. It seems that they rely on the fact (?) that a matrix used in a 3D engine always has an inverse (because of the homogeneous coordinates, i think).

PS: yep, Lübeck is a nice place, but I've been there only for the last 6 months and counting...
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

I've not tracked it down to the root, but I think that there is some windows.h included in matrix4.h without #define NO_MIN_MAX as std::numeric_limits<thecakeisalie>::min() wont work in this template.

... It seems there is some other included macro defining "min" as something, since only "#undef min" succeeds when using

Code: Select all

f32 d = ...;
if( d < std::numeric_limits<T>::min())
in matrix4.h:1251something

Edit:
Maybe in Irrlicht.cpp and/or in os.cpp it should state:

Code: Select all

#ifdef _IRR_WINDOWS_
	#define NO_MIN_MAX
	#include <windows.h>

---
Edit:Edit:
Well, that wasnt the error... somewhere else there is some macro defined...
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

If there is a function macro named min() you can prevent the preprocessor from expanding it by using an additional set of parens.

Code: Select all

f32 d = ...;
if( d < std::numeric_limits<T>::(min)())
Travis
MasterD
Posts: 153
Joined: Sun Feb 15, 2004 4:17 pm
Location: Lübeck, Germany
Contact:

Post by MasterD »

This hack you proposed worked with (std::numeric_limits<T>::min)(). Thanks for that, vitek, I didn't knew you could fool the preprocessor in that way.

I've now managed to raycast my animated characters. There was some precission problems involved, as I tried to raycast a ray of 10km length. Shortening this resolved the problem. _But_ only with the proposed fix for the matrix4.

Therefore I say that matrix4 check for the determinant should be changed. Either to a check against std::numeric_limits<T>::min() or removed completely. Since disregarding my 10.000 units raycasts, any SceneNode which is scaled to 1% is not able to be raycast.
YASS - Yet another Space Shooter
under Devolpment, see http://yass-engine.de
burningreggae
Posts: 66
Joined: Wed Oct 04, 2006 2:07 pm

Post by burningreggae »

I initialized the rounding_error_values with fixed values instead of float epsilion.

i used this value (1e-06) for beeing compatible with the fixed point implementation. ( mainly in burningvideo and collision)

but the collision detection still underflows or still uses to much 1/0 division;-)

so please feel free to decrease the default value, for more precision range.
but please don't check in std:: , or stl:: namespaces...;-)

burningreggae drum
burningreggae
robmar
Posts: 1125
Joined: Sun Aug 14, 2011 11:30 pm

Re: ROUNDING_ERROR_f32 too big? (f64 too?)

Post by robmar »

I´m also seeing the failed getInverse matrix return when using a parralax node for a reflected water simulation, but only when in D3D mode. In opengl it works fine.

In D3D, the texture mapped to the plane node gets repeated in the four quadrants of the plane. Strangely, adding any object to the scene using my Gooch shader usually fixes the problem... so far unexplained...
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: ROUNDING_ERROR_f32 too big? (f64 too?)

Post by CuteAlien »

Not the same problem. I rewrote getInverse recently (not knowing about this thread, run into it when debugging another reported bug). There's other places where the rounding error define is still used when it shouldn't be used, but that's rather tricky case-by-case stuff, so will take a while to fix all that.

No idea at all if your problem is the same as like usual nothing can be known without test-cases to reproduce problems. There are valid situations for getInverse to fail, but if you get different results for the same matrix in opengl and dx it's likely a floating-point precision thing. DX uses by default a lower (but but faster) precision. You can influence that behaviour also in Irrlicht by setting HighPrecisionFPU in the parameters to createDeviceEx to true. So if it works then you know at least it's some precision trouble - how ever you want to handle it.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
burningreggae
Posts: 66
Joined: Wed Oct 04, 2006 2:07 pm

Re: ROUNDING_ERROR_f32 too big? (f64 too?)

Post by burningreggae »

what is the shortest mathematical joke?
epsilon is zero...
burningreggae
Post Reply