Why do I get ridiculous floating point values when I read a binary file?

Started by
16 comments, last by Matias Goldberg 10 years, 8 months ago

Hi,

I've developed a custom binary format exporter in Blender for my model's mesh, material and animation data. When I attempt to load the file data Integer values are read correctly in the header but when I go to read the actual per-vertex data the values are often either 0.0 or something like this monstrosity:

-6906376617984.000000

I think the problem might have something to do with the fact the values are floats. I have tried the following code to help solve the problem but it doesn't fix the problem.


float RootFile::readFloat( void )
{
uint8_t b[4];
RootDwordFloat d;

read( b, 4, 1 );
d.dword_value = ((uint32_t)b[3] << 24) |
		((uint32_t)b[2] << 16) |
		((uint32_t)b[1] << 8) |
		((uint32_t)b[0]);
return d.float_value;
}

Do you have any idea how I could solve this? Any replies are appreciated.

Advertisement

How was the float written?

EDIT:I mean, what does the documentation say the convention for byte order is? And can you post an example of four bytes from a file and what float you think they encode?

I think these are the answers to your questions but I may be wrong:

Byte order: I think the byte order is probably little endian but I can't be sure as I just used the blender python 'struct.pack' command and then 'file.write'

Sample bytes and float value: Here I will give what I think is what you are looking for with the bytes and their proper float value I took one sample from each mesh in the model:

mesh 1: 238 1 104 26 float value: 0.517633
mesh 2: 102 0 158 162 float value: 0.177884
mesh 3: 58 0 99 64 float value: -0.090596
mesh 4: 46 0 100 8 float value: -1.447870
mesh 5: 132 0 201 212 float value: 1.137005

Try using a union


union FloatInt
{
    int i;
    float f;
}

FloatInt fi;
fread(&fi.i,sizeof(FloatInt),1,fp);

Are you sure blender wrote a float and not a double?

I did actually try using a union although it may not have been clear in my code example in my first post I use the type RootDwordFloat which is the following union:

EDIT: I'm pretty sure it is not a double.


typedef union
{
        uint32_t dword_value;
	float float_value;
} RootDwordFloat;
First things first:

You have a custom binary format exporter, which I presume you've written? If so then it should be a simple matter of reversing your writes. If its not one that you've written but written by someone else, then you should read their documentation on the file format.

Endianness is important, you need to know if the values are stored in big or little endian when written. If you're doing raw writes, then chances are they're in the native endianness which is likely to be little endian.

If you're going to use a union like that, avoid bitshifting entirely, just stick your array of bytes straight in the union:


union RootFloat {
    uint8_t bytes[4];
    float value;
};
}

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Didn't get why you can't just read the value as a float, something like:


    float f;
    fread (&f, sizeof(float), 1, filePointer);

But, other approaches are printing the file offset (take a look at ftell function) to check if you are actually reading the right point of the file.

Print the byte per byte to validade if it is correct. Use this code to print byte per byte:


    float f = 0.517633;
    int i = 0;
    uint8_t* u = &f;
    for (i = 0; i < sizeof(float); ++i){
        printf("%02x ", u[i]);
    }
    printf("\n");

Here (linux 32 bits), it prints:

99 83 04 3f

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

Sorry but I am unfortunately still getting the same random values even with your simplified union load procedure. In answer to KnolanCross unfortunately I can't do that either. Naturally that was the first thing I tried.

Do you know how to use an hex editor or hexdump (if you are using linux)?

You can print the value you are expection as a binary sequence, look for it in the binary file using the hexeditor and check if you are reading the correct position. The last problem I can think of is endianess, also detectable by using a hex editor to check the binary file you created.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

I do have a hex editor and I did try that but I don't really know how to use it. Could you explain it to me?

This topic is closed to new replies.

Advertisement