Convert Irrlicht to use f64 as default.

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!

Should Irrlicht use f64 as default due to precision problems with other software?

Yes
4
22%
No
14
78%
 
Total votes: 18

hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Convert Irrlicht to use f64 as default.

Post by hach-que »

I have a bit of a problem. You see, I'm trying to get Irrlicht and Newton Physics and put it into Lua.

Problem is, Irrlicht uses f32 by default, which is of type float. It doesn't provide enough precision (5.2 gets mangled to 5.199999999999), and when you have both Lua and Newton Physics using doubles, it's impossible to do:

vector = RVector3D(5.2,2,3);
if (vector.X == 5.2)
then
print("Vector.X is 5.2");
else
print("Vector.X is not 5.2");
end

This yields Vector.X is not 5.2, simply because of the precision problem in Irrlicht.

I've tried changing the typedef of f32, but unfortunately it's used in both places where it's optional (such as values Irrlicht stores), and places where it isn't (such as fetching a value from DirectX or OpenGL).

Right now, I have 4 options:
  1. Set both Lua and Newton Physics to use float, causing precision problems in a scripting language and a physics engine, where users also expect print(5.2) to yeild 5.2, and not 5.1999999999999
  2. Store seperate values for X, Y and Z in my binding classes, using and updating them when appropriate
  3. Go through Irrlicht manually, finding out where f32 is optional and it isn't, replacing mandatory places with float.
  4. Ask people here
Since option A is unacceptable for a commercial product, option B is messy and might have syncronisation issues and option C is a huge task, I figured I'd take option D, and see what the people here can come up with.

(In case you are wondering, it is not possible to use the vector's equals function, due to Lua being the one comparing numbers, not Irrlicht)
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

To solve the equal issue:

Code: Select all

bool f32Equal( f32 f1, f32 f2, f32 tol = std::numeric_limits<f32>::epsilon() )
{
     return ( ( f2 - f1 ) <= tol ? true : false );
}
I'm sure that Irrlicht has a similar comparing function for floating-point values, but I don't remember the name, so there's one I wrote of the top of my head.

On another note, it would be best if Irrlicht included a configuration flag, and decided the size. Something like:

Code: Select all

#ifdef _IRR_COMPILE_DOUBLE_PRECISION_
typedef f64 Real;
#else
typedef f32 Real;
#endif
Then you don't have to worry about whether it is optional or not, you cast either way.

So that's probably your best bet. Do something like a compiler flag, then wherever their is an occurence of f32 just use Real. And when assigning anything other than a Real to a Real then you just cast no matter what to avoid problems.
TheQuestion = 2B || !2B
hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Post by hach-que »

That won't work. I cannot apply a function to the equals sign while comparing numbers in Lua.

I need to somehow change the types of all the Irrlicht functions, but unfortunately, for whatever reason, the "portability" idea for f32 seems to have gone out the window when it was used for retrieving floats from DirectX and OpenGL. If OpenGL and DirectX are ALWAYS going to need to use a float variable to store the data, then Irrlicht should not use f32 for it. Why? Because it means you can't just change the typedef of f32 to increase precision of the engine.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

hach-que wrote:That won't work. I cannot apply a function to the equals sign while comparing numbers in Lua.
There's absolutely no way to overload the equality operator for Lua? That seems funny because AngelScript supports it.
hach-que wrote: If OpenGL and DirectX are ALWAYS going to need to use a float variable to store the data, then Irrlicht should not use f32 for it. Why? Because it means you can't just change the typedef of f32 to increase precision of the engine.
Exactly, that's why you make the Real type definition. Then you keep the things that absolutely need to be f32 as f32. Otherwise, you change it to real.

It doesn't make much sense that how Irrlicht provides the data to OpenGL/DX should affect you as an end-user. If you do it with the Real way as shown above you can have everything input and output with Real to the END-USER, but cast from Real to f32 when needed in the engine, etc.
TheQuestion = 2B || !2B
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Yes, it is bad to use operator== on floats. That isn't the only problem with your code. You compare a float to a double literal. If you insist on comparing floats this way, you should use 5.2f. If you don't, the operand on the right is of type double, and the one on the left is of type float. Even if they started out with the same initial values, the comparison can fail...

Code: Select all

// this may work for some values of `d'
const f64 d = 111.1234;
const f32 f = d;
printf ("%s\n", (f == d) ? "same" : "different");
That said, you should try the SIrrlichtCreationParameters::HighPrecision flag. When using DirectX, the default is to use low precision for performance...

Travis
night_hawk
Posts: 153
Joined: Mon Mar 03, 2008 8:42 am
Location: Suceava - Romania
Contact:

Post by night_hawk »

I'm going to throw my own xp with floats and doubles here...
I lost a competition thanks to floats. While the answer was, for example, 12145.2142141, my app gave 12145.2001254, which, obviously, is bad. Of course, should I have used double, all would have been well. It's not a big difference, but it can make a difference in some cases.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

night_hawk wrote:I'm going to throw my own xp with floats and doubles here...
I lost a competition thanks to floats. While the answer was, for example, 12145.2142141, my app gave 12145.2001254, which, obviously, is bad. Of course, should I have used double, all would have been well. It's not a big difference, but it can make a difference in some cases.
You can't place blame on the IEEE floating point format. It sounds like you forgot or didn't understand how floating point numbers work. They get less accurate the further you get from zero, and a standard 32-bit float only offers about 6 digits of precision.

Travis
night_hawk
Posts: 153
Joined: Mon Mar 03, 2008 8:42 am
Location: Suceava - Romania
Contact:

Post by night_hawk »

I'm not blaming anyone other than myself, but I'm pointing out that it could be bad for others. Giving the option to choose between float and double could save some trouble.
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

Halifax wrote: On another note, it would be best if Irrlicht included a configuration flag, and decided the size. Something like:

Code: Select all

#ifdef _IRR_COMPILE_DOUBLE_PRECISION_
typedef f64 Real;
#else
typedef f32 Real;
#endif
Then you don't have to worry about whether it is optional or not, you cast either way.

So that's probably your best bet. Do something like a compiler flag, then wherever their is an occurence of f32 just use Real. And when assigning anything other than a Real to a Real then you just cast no matter what to avoid problems.
How about suggesting it for Irrlicht? For v1.6? 2.0?.. (In a proper thread of course)
Cause it sounds pretty nice.
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Post by hach-que »

The Real idea won't work without heavily modifying Irrlicht (and trust me, I just tried to modify the whole thing to use f64 where optional, and it didn't work out too well).

Vector3D doesn't store the X, Y, Z values as Real, it stores them as floats (or f32). If I create a vector3d as vector3d<irr::f64>, that doesn't work, because I cannot pass that to functions, and I get a cannot convert error from the compiler. Since functions such as getPosition (GUI Elements), as well as various others always return vector3df, it's literally impossible to use double precision with Irrlicht vectors for anything other that user code.

I'm going to have to modify Lua, but you can understand why I'm not happy having such a precision problem in commercial software (I mean my software is commercial, not Irrlicht :P ).
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Did you try using createDeviceEx() and the SIrrlichtCreationParameters::HighPrecisionFPU flag as I suggested earlier?

Travis
hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Post by hach-que »

Last time I checked, that cannot change the return type of getPosition.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

hach-que wrote:Last time I checked, that cannot change the return type of getPosition.
I never said anything about that. If you're using one of the direct3d drivers, all of your floating point math will be less precise by default. If you use that flag, you will get some precision for free.

That said, I don't understand why you can't just use a function in lua to tell you if two floats are the same or are similar.
hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Post by hach-que »

It's not so much comparing the floats anymore, as I did manage to change Lua to do that. It's that when you use:

print(5.2);

it outputs 5.19999999999999 on the command line.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

And where's Lua's print statement related to Irrlicht?
Post Reply