After the model compiler comes the texture compiler. Decompressing a PNG file on Android is possible, but the loading code is simpler if the texture is already available in a format that we can feed directly to OpenGL. So I devised the GLT (GL Texture) format, and wrote a program called
gltc to convert PNG files to GLT.
The GLT writing part was easy. The PNG loading part I’d already written for the water game, which was lucky, because this was the hairy bit. “What do you mean,” you ask, “surely there’s a library to do that for you?
libpng or something?” Well, yes there is. But it has the most arcane interface ever.
You see, normal C libraries report errors by returning an error code from their functions. If it returns
0, you know that something went wrong. Normal C++ libraries, on the other hand, report errors by throwing exceptions. You can either ignore these and let your program crash, or decide which ones to catch at which point. Very nice.
libpng, however, does neither of these things. Instead, it relies on a C mechanism that should never have been:
longjmp. You specify your error handler with a call to
setjmp, and in the case of an error,
libpng performs a
longjmp to that location.
These two functions,
longjmp, are dangerous. A slight mistake can result in stack corruption and undefined behaviour. Nesting of
setjmp handlers is not possible, so you’re forced to put all your code into one big function, or at least do all your error handling at one level. Even more dangerous is the combination with C++ exceptions, that do their own unwinding of the stack.
End of rant. I had working PNG loading code, so I just reused it in
gltc. The result is that we now have textured models in the game!
Keep in mind that these graphics are temporary, more of a proof-of-concept than a final thing. Also, never mind that frame rate: the emulator slows it down a lot. On the real phone it runs much better, and there are many obvious optimizations (e.g. vertex buffer objects) that remain to be done.