floating point & fixed point again

Started by
12 comments, last by meeshoo 19 years, 6 months ago
hi there. so i've searched the internet for fixpoint tutorials, i've found some, but i'm still not ok with this subject. all my data from the exporter is floating point. now i'm building a converter to fixpoint. so, how do i do it? i've also got some integer values there. how can i convert them? i've seen in a tutorial here on gamedev that for integers shifting left 16 it's ok. on internet, i've seen shifting left just 8 positions it's ok. for floating point i've seen multipling with 256 (2^8). so in our case we will multiply by 2^16 ?. please somebody help me. thaks a lot for your patience.
Advertisement
The amount you need to shift left depends on how many bits you are using for the whole part of the number, and how many are for the fractional part. OpenGL ES uses 16.16 format, that is the first 16 bits are for the whole part, the last 16 bits are for the fractional.

I've been putting together a fixed point number class that I was planning on posting here. Here is the current version, its stable but be aware that I havn't finished fully testing it. It doesn't do any range checking, so if you multiply two numbers that are too large, you'll have problems. The HAVE_FLOATS directive is used so for PC based tools I can easily convert from floats, but for native code it will get compiled out.

#ifndef _FIXED_H_#define _FIXED_H_#define HAVE_FLOATSnamespace Math{	const int PRECISION = 16;	const int HALF_PRECISION = 8;	const int PRECISION_MASK = 0xFFFF;	class fixed	{	public:		int		mValue;	private:		fixed(int value) : mValue(value)		{		}	public:		fixed() : mValue(0)		{		}		fixed & operator = (const fixed & rhs)		{			mValue = (rhs.mValue);			return *this;		}		void FromInt(const int value)		{			mValue = (value << PRECISION);		}#ifdef HAVE_FLOATS		void FromFloat(const float value)		{			mValue = static_cast < int> (value * (1 << PRECISION));		}#endif		int ToInt()		{			return (mValue >> PRECISION);		}		float ToFloat()		{			return ((float)mValue / PRECISION_MASK);		}		friend fixed operator * (const fixed & lhs, const fixed & rhs);		friend fixed operator * (const int lhs, const fixed & rhs);		friend fixed operator * (const fixed & lhs, const int rhs);		friend fixed operator / (const fixed & lhs, const fixed & rhs);	};	fixed operator * (const fixed & lhs, const fixed & rhs)	{		return fixed((lhs.mValue >> HALF_PRECISION) * (rhs.mValue >> HALF_PRECISION));	}	fixed operator * (const int lhs, const fixed & rhs)	{		return fixed(lhs * rhs.mValue);	}	fixed operator * (const fixed & lhs, const int rhs)	{		return fixed(lhs.mValue * rhs);	}	fixed operator / (const fixed & lhs, const fixed & rhs)	{		int temp = (lhs.mValue / rhs.mValue);		return fixed(temp << PRECISION);	}}#endif


Alan
"There will come a time when you believe everything is finished. That will be the beginning." -Louis L'Amour
As you have said, the Tutorial on this site shows a one line macro for converting integers to fixed point, and the BREW site, if you choose the basic programming link or something, has a similar macro for converting floating point to fixed point.

Now, I find the rest of what you are saying to be quite interesting. First, whether it is an integer or a floating point value, the process is the same for both the macros I mentioned above, they just multiply the value by 2^16, but in the case of floating point, it takes only the non-fractional portion.

Now, when I first started working with the colors and vector values in GL ES, I found that things only worked out if I changed the macros to multiply by 2^8. I'm not certain why this is the case, as I cannot imagine that the BREW website would have the wrong macro for conversion, but perhaps someone should send a message to the OpenGL ES people, khronos or whatever.

Personally, I would stick to 2^8, otherwise all the values you send will be taken as being at minimum 256 times larger than what you intended.
There's no error. If you want to convert a value, whether it's a float or an integer, to be interpreted as a 16.16 fixed point value, you have to multiply it by 2^16. Note that if the intial value was larger than 65535, this will cause an overflow.

I think I know what's causing confusion here. If you're dealing with vertex position data or texture coordinates, an integer value of 1 is treated exactly the same way as a floating point value of 1.0. So the conversion to fixed is the same for both representations.

But with colors, it's a different story. If you represent a color as an integer value, OpenGL internally normalizes those values. So an unsigned byte value of 255 isn't equivalent to 255.0, it's equivalent to 1.0.

If you try to convert an unsigned color value to a fixed point value, you first have to convert it to a floating point value. This would mean dividing by 255. Then you'd multiply by 2^16. Note that this is equivalent (or close enough) to multiplying by 2^8. You shouldn't do this conversion anyway, though, since you can use unsigned byte colors directly as long as you pass GL_UNSIGNED_BYTE to glColorPointer.
hi. thanks a lot folks. today, before reading this, i've said to myself that all tutorials are wrong, and i have to think it up myself. so i took my pen and do some bit shifting and stuff (on the paper) and then all came to me: all tutorials were reffering to the old version of type "int" on 16 bits. so there was the problem. that's way everyone was shifitng with 8 bits for integers and multipling with 256 for floats(wich is the same, but you cannot shift float values without mess up things). so all i have to do is multiply by 65536.all ok. all libraries and classes on the internet wich implement fixed point operations are treating the fact that when you multiply 2 fixed point numbers, you also multiply the 65536 value, and so on. so you have to be carefull with that. well thank you alot guys for clearing my mind (especially with color things) and happy coding
Correct me if i'm wrong, but you don't want to have a whole class with many methods to represent a such a simple type as fixed point number.
i'm not having a class, and here and there i'm not using even macros.
what maybe wrong with this one?!!!

int tofix(float x)
{
return (int)(x * 65536);
}

i just don't have what i expect to have. i've just have some simple coordinates and the results are very unexpected.
That shld work on the emulator though it's never going to run on the phone. There is no HW support for floating point operation and you cant link with the ARM lib. The only remaining option is to use the floating point helper functions provided by BREW. Anyway since you are using fixed point I dont really get why you still need floats.

f.

Quote:Original post by meeshoo
what maybe wrong with this one?!!!

int tofix(float x)
{
return (int)(x * 65536);
}

i just don't have what i expect to have. i've just have some simple coordinates and the results are very unexpected.
hi. well, that function was not from the application, it was from a tool, a converter. i convert data to fix point from float using that function, export it to a file, then load the file using Brew SDK interfaces and it should work. i've tried it with a cube and there is nothing on my simulator when i run the programming. only black. the opengl is initialised, because i've tested by manually drawing a triangle. also the model is already scaled so it should work.

This topic is closed to new replies.

Advertisement