views:

148

answers:

3

Hi all,

I am writing a video game, Humm and Strumm, which requires a network component in its game engine. I can deal with differences in endianness easily, but I have hit a wall in attempting to deal with possible float memory formats. I know that modern computers have all a standard integer format, but I have heard that they may not all use the IEEE standard for floating-point integers. Is this true?

While certainly I could just output it as a character string into each packet, I would still have to convert to a "well-known format" of each client, regardless of the platform. The standard printf() and atod() would be inadequate.

Please note, because this game is a Free/Open Source Software program that will run on GNU/Linux, *BSD, and Microsoft Windows, I cannot use any proprietary solutions, nor any single-platform solutions.

Cheers,
Patrick

+1  A: 

Some embedded processors do not include any floating-point hardware at all. For desktop computers, I do not see any reason to worry too much, apart from details that only really annoy specialists (sqrt being incorrectly rounded on the Alpha, this kind of thing. The differences that annoy them are in the implementation of the operations, not of the format, anyway).

One variation between platforms is related to the handling of denormals. I asked a question about those a while back. Even that was not as bad as I expected.

Pascal Cuoq
Alright, thank you Pascal. It will definitely help to not have to worry as much about the binary format of floats in the game. Assuming IEEE-754 floats makes my life a whole lot easier. ^_^
Patrick Niedzielski
+4  A: 

If you properly abstract your network interface, you can have functions/objects that serialize and deserialize the float datatypes. On every system I can think of, these are the IEEE standard, so you'd just have them pass the data through unchanged (the compiler will probably even optimize it out, so you don't lose any performance). If you do encounter some system with a different format, you can conditionally-compile in some code in these functions to do bit hacks to convert from the IEEE standard to the native format. You'll only need to change it in one place. You probably will never need to do so, however, unless you get into consoles/handhelds/etc.

rmeador
This is how my system is designed at the moment. I was not sure how common it is for a non IEEE float. I'll follow your advice and keep it.Thanks!
Patrick Niedzielski
+2  A: 

I think it is safe to assume that each platform has an implementation of the IEE-754 spec that you can rely on, however, even if they all implement the same spec there is no guarantee that each platform has the exact same implementation, has the same FP control flags set, does the same optimizations, or implements the same non-standard extensions. This makes floating point determinism very hard to control and somewhat unreliable to use for this kind of thing (where you'll be communicating FP values over the network).

For more information on that; read http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/

Another problem to tackle is handling clients that don't have a floating point unit; most of the time these will be low-end CPUs, consoles or embedded devices. Make sure to take this into account if you want to target them. FP emulation can be done but tends to be very slow on these devices so you'll have to get a hang of doing fixed point calculations. Be advised though, writing elaborate classes to abstract floating point and fixed point calculations to the same code sounds like a plan; but on most devices isn't. It doesn't allow you to squeeze out the maximum precision and performance when dealing with fixed point values.

Yet another problem is handling the endianness of the floating point values because you cannot just swap bytes and stack 'm in a floating point register again (the bytes might get a different meaning, see http://www.dmh2000.com/cpp/dswap.shtml on that).

My advice would be to convert the floats to fixed point intermediate values, do an endian correction if needed and transmit that. Also, don't assume that two floating point calculations on different machines will yield the same results; they don't. However, floating point implementations other than IEEE-754 are rare. For example GPUs tended to use fixed point, but are more likely to have a subset of IEEE-754 these days because they don't want to deal with division-by-zero exceptions but they will have extensions for half-floats that fit in 16 bits.

Also realize that there are libraries out there that have already solved this problem (sending low-level data formats in a gaming context) for you. One such library is RakNet, specifically it's BitStream class is designed to send these kinds of data reliably to different platforms while keeping the overhead to a minimum; for example RakNet goes through quite some trouble not to waste any bandwidth on sending strings or vectors.

Jasper Bekkers
The determinism link you gave me is very interesting. I had been thinking of doing that with some bigger messages to make sure the clients were synchronised. As long as the positions are close enough (one unit is one metre), I think this will be fine.I don't intend to target console platforms and most embedded systems; I'm not even sure if I can do this as Free Software. As for low end processors, that is more of a concern.The byte swap issue is very unfortunate...I briefly skimmed the article, but I will have to read it later.Thank you very much for the information!
Patrick Niedzielski
There are some lesser known (handheld) consoles that allow you to publish open source software for them such as the GP2X and Open Pandora. The floating point determinism problem mainly comes up when you decided to decentralize the physics routines (eg. run them on the clients) or run replays on different machines because they tend to accumulate errors quite fast.
Jasper Bekkers