storing positions as ints?

Started by
4 comments, last by Enigma 19 years, 6 months ago
hi, im working on a 2d online action / RPG. anyway, i've been storing my positions as floats this whole time, but now that im implementing the networking, i think it would be more efficent for me to use an unsigned short to store my position. this is half the size of a float. i just have one question, will i lose precision or something? does openGL like floats more then ints, or will i be fine using glVertex2i() instead ? do you think maybe i could keep my position stored as a float, but cast it to a unsigned short when sending it over the wire? would i lose precision here ? thanks for any help.
FTA, my 2D futuristic action MMORPG
Advertisement
Well, I'd say "of course you'll lose some precision, you're practically down-shifting". Instead, I'll completely ignore the question and talk about the presidential debate.

So, Kerry.

That was fun. Actually, I geniunely don't know this one, and that first statement's about all I really know about it. So, if someone could answer this one, I'd also be very glad.
Things change.
You will lose sub-pixel precision, which may or may not affect your game.
Quote:Original post by graveyard filla
hi,

im working on a 2d online action / RPG. anyway, i've been storing my positions as floats this whole time, but now that im implementing the networking, i think it would be more efficent for me to use an unsigned short to store my position. this is half the size of a float. i just have one question, will i lose precision or something? does openGL like floats more then ints, or will i be fine using glVertex2i() instead ? do you think maybe i could keep my position stored as a float, but cast it to a unsigned short when sending it over the wire? would i lose precision here ?

thanks for any help.



You have to look into how large your map is and how fine an increment you want/need to maintain on the client.

Another post mentioned a 2000x2000 map and a short UINT can store a value 0..65535 -- which could allow a precision of 1/16th of a world coordinate increment to be transmitted.

If that precision is enough then it is workable.


You might investigate how significant compressing the data actually is to your game. If you are only sending a few coordinate, it may not be too significant (compared to packet overhead etc..).

If you are sending huge amounts of positional updates, you might also consider sending only data for objects that moved since the last update, which can pare down the amount of data that needs to be sent. (Remember if you are using a lossy transmission
method to periodicly send the data for an object EVEN IF IT HASNT MOVED -- because it was possible that the last real update may have been lost).



compressed floats (16bit floats) its a hack-ish class i wrote a wee while back, why not transfer over the network using these and then convert back to "normal" floats for use in-game

you can get the class sourcecode here on my unfinnished website e-mail me if you have any questions.
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
As has already been said, you will lose precision if you try to use a smaller datatype. There are a couple of things you ought to do.

1. Code your program using a typedef for your world distance type. Something like typedef float world_distance_type; (or maybe wdist if you hate long identifiers). This typedef should be in a single header file, so changing the datatype involves a single source-code change.

2. Write the code and profile. Find out where the bottlenecks are.

3. If network bandwidth is one of the major bottlenecks then investigate how you can reduce the bandwidth. Eliminate redundant information, try compression etc.

4. If after all the above you still believe you need to reduce the size of the datatype for network transmission you can try another datatype. You might try a short but you can't cast a float directly to an unsigned short. You could try a half-float class. I just quickly hacked this up to demonstrate:
#include <cmath>#include <iostream>class HalfFloat{	public:		HalfFloat(const float f);		HalfFloat& operator=(const float f);		operator float() const;	private:		unsigned short value_;};HalfFloat::HalfFloat(const float f){	operator=(f);}HalfFloat& HalfFloat::operator=(const float f){	union	{		float floatValue;		unsigned int intValue;	} convertor;	convertor.floatValue = f;	if ((convertor.intValue & 0x7fffffff) == 0)	{		value_ = (convertor.intValue & 0x80000000) >> 16;	}	else if ((convertor.intValue & 0x7f800000) == 0x7f800000)	{		value_ = ((convertor.intValue & 0x80000000) >> 16) | 0x7c00 | ((convertor.intValue & 0x007fffff) >> 13);	}	else	{		unsigned int exponent = (convertor.intValue & 0x7f800000) >> 23;		if (exponent > 142)		{			value_ = ((convertor.intValue & 0x80000000) >> 16) | 0x7c00;		}		else if (exponent < 112)		{			value_ = (convertor.intValue & 0x80000000) >> 16;		}		else		{			value_ = ((convertor.intValue & 0x80000000) >> 16) | (((exponent - 112) & 0x1f) << 10) | ((convertor.intValue & 0x007fffff) >> 13);		}	}	return *this;}HalfFloat::operator float() const{	union	{		float floatValue;		unsigned int intValue;	} convertor;	if ((value_ & 0x7fff) == 0)	{		convertor.intValue = value_ << 16;	}	else if ((value_ & 0x7c00) == 0x7c00)	{		convertor.intValue = ((value_ & 0x8000) << 16) | 0x7f800000 | ((value_ & 0x03ff) << 13);	}	else if (value_ == 0x7c00)	{		convertor.intValue = 0x7f800000;	}	else if (value_ == 0xfc00)	{		convertor.intValue = 0xff800000;	}	else	{		convertor.intValue = ((value_ & 0x8000) << 16) | ((((value_ & 0x7c00) >> 10) + 112) << 23) | ((value_ & 0x03ff) << 13);	}	return convertor.floatValue;}int main(){	HalfFloat hf = 3.14159265358979323846f;	std::cout << "float: " << 3.14159265358979323846f << "\nhalf-float: " << hf << "\n\n";	hf = 192.378f;	std::cout << "float: " << 192.378f << "\nhalf-float: " << hf << "\n\n";	hf = -6147.656f;	std::cout << "float: " << -6147.656f << "\nhalf-float: " << hf << "\n\n";	hf = 123456789.0f;	std::cout << "float: " << 123456789.0f << "\nhalf-float: " << hf << "\n\n";	hf = 0;	std::cout << "float: " << 0 << "\nhalf-float: " << hf << "\n\n";	hf = -3.88e-5;	std::cout << "float: " << -3.88e-5 << "\nhalf-float: " << hf << "\n\n";	hf = 7e-45;	std::cout << "float: " << 7e-45 << "\nhalf-float: " << hf << "\n\n";	union	{		float floatValue;		unsigned int intValue;	} convertor;	convertor.intValue = 0x7fc00001;	hf = convertor.floatValue;	std::cout << "float: " << convertor.floatValue << "\nhalf-float: " << hf << "\n\n";}


Obviously this class can't represent anywhere near the same range or accuracy as a real float. Note that this class has the same layout format (by which I mean they both have a five bit exponent and ten bit mantissa) as the nVidia half datatype, so it may be possible to upload directly to OpenGL via glVertex3h{v}NV etc, but I would not count on it.

Enigma

[Edited by - Enigma on October 12, 2004 11:56:01 AM]

This topic is closed to new replies.

Advertisement