Skip to main content
GameDev.net gamedev.net
🔒 Locked

unpack my vert

Started by castor Apr 28, 2001 at 9:23 PM 4 replies 700+ views
Original Post
castor
castor
i pack 3 floats to an int: int result =( int( f1 * 8.0f ) & 0x7ff ) | ( ( int( f2 * 8.0f ) & 0x7ff ) << 11 ) | ( ( int( f3 * 4.0f ) & 0x3ff ) << 22 ) ; ...later, i want to get my floats back from the int var. it works, but only if each of all 3 floats are >= 0. if they are e.g. -23.34,-45,-345 - or 23,-45,11 ... it won`t work. the packing method is not mine, so i really need help here. thanks
castor
castor
because the unreal model format has packed vertices (3 floats ) to single int. i just want to know how unpack negative values.
Diodor
Diodor
The problem is with the number format. Lets take 16 bits ints for example. Notice that if you add / substract 1 from each of this numbers and ignore the carry, you obtain the correct result (0 - 1 = -1, -1 - 1 = -2, -1 + 1 = 0, 1 + 1 = 2, etc).

0000000000000010 = 2
0000000000000001 = 1
0000000000000000 = 0
1111111111111111 = -1
1111111111111110 = -2

If you pack a negative 16 bits int into an 8 bit one, this is what you get:
00000010 = 2
11111111 = -1
11111110 = -2

So, if you unpack back to 16 bits like this
0000000000000010 = 2, correct, but
0000000011111111 = 255, incorrect
0000000011111110 = 254

The correct way to unpack is to check the most significant byte and expand it through the extra 8 bits of the 16 bit integer.

????????00000010 => 0000000000000010
????????11111111 => 1111111111111111

I dont know how to do that easily, so I cheated a bit and let the C compiler do the work


typedef struct
{
int f1 : 11;
int f2 : 11;
int f3 : 10;
} smart;

void unpack (int pack3, float* f)
{
smart* s = (smart*)&pack3
f[0] = s->f1 / 8.0f;
f[1] = s->f2 / 8.0f;
f[2] = s->f3 / 4.0f;
}

castor
castor
thanks a lot! its really great and it works perfect.

now i would like to understand it, bc. i don
t want to copy&paste others code without knowing what`s going on.


typedef struct{
int f1 : 11;
int f2 : 11;
int f3 : 10;
} smart;

does that mean that : f1 is 11 bits, f2 is 11 bits and f3 is 10 bits of size?
then you cast a whole 32bit int into that type and get the single components ?
Diodor
Diodor
quote:

does that mean that : f1 is 11 bits, f2 is 11 bits and f3 is 10 bits of size?
then you cast a whole 32bit int into that type and get the single components ?



Yes, you''re right. The casting is just formal, the actual 32 bits of the initial int stay the same. Only I let the compiler know that the first 11 bits of the initial int make an int, the next 11 another, and the next 10 yet another one. This works for negative numbers too because now the compiler is aware that these struct components are signed ints, so it can correctly fill up with zeros or ones when converting from 10/11 bits to 32 bits.

Btw, you can notice that sizeof(smart) is only 4, equal to sizeof(int).

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.