Fighting with computers

Computers are not always friendly.

Friday, August 15, 2014

Reading binary STL files in Java

I liked the source code from MaskedRetriever user on github and I assumed it would work ok. It seems it was an attempt to create a self-contained tool for 3D printing but somehow it was left at an early stage. But I liked the fact that source code was documented.

My needs were to read STL files and to slice them. As usual you need to get familiar with the different classes involved but it took me not much to get it going. I stripped most of the classes as I was not interested on 3D printing nor on having a GUI for such a tool. However, as soon as I draw the output of the slice process I noticed something was wrong.

While the proper slice looked smooth like the image below:

What I was obtaining was a bit of a mess, though the general ideal was correct. As it was my first attempt I was not sure where the error might be.
After a few tests I realized that the same code would work ok if STL file was ASCII-based but it will fail as above if a binary STL was used instead. 

I had a look at the code and I could see reading a binary STL file involved obtaining float values out of 32-bit IEEE 754 encoded values on the file. It seemed it was there when error was made in the conversion.

Googling around I realized there was a library function in Float class called intBitsToFloat that will turn the 32 bit number into the proper float value. I only needed to get that 32 bit number out of the four bytes read from the file, easy peasy ... or not?

Well, if that were C, and you have b[0..3] unsigned chars, the expression could be something like 
 b[3]<<24 | b[2]<<16 | b[1]<<8 | b[0]  

However Java language considers byte data-type as a signed 8-bit field (-128 to 127). And there is a nasty effect with the sign extension that may make you waste a fair amount of time. In summary, the C version won't work if negative values are involved, and they are most of the time (half of the time I would say). So one way of obtaining the proper 32 bit number in Java would be a bit longer : 

 (b[3]<<24)&0xff000000 | (b[2]<<16)&0xff0000 | (b[1]<<8)&0xff00 | b[0]&0xff  


Post a Comment

<< Home