Wednesday, July 29, 2009

Experiences with a different cross platform graphics library

There are periods when I don't write any code at all. These times are like the silence before the storm ... Last month, the silence broke and the storm was unleashed. I wrote code, code, code, and still managed to keep my head above in the sea of binary.
I'm currently working on three interesting hobby projects at once; a rewrite of an old skool BBS using pthreads and an SQL database backend; a cluster administration tool written entirely in Python; an OpenGL arcade game. So, there's plenty to blog about, but for now, I'll pick the game because OpenGL and games are always interesting. As you may know, I like using the SDL for developing OpenGL programs because it is a portable library. And then I ran into some post on the net where a guy said, "I always use glfw". I decided to check it out, and believe it or not, I ported it over from SDL to GLFW in just a couple of hours. GLFW is deceivingly simple. I decided it's out with SDL, and in with GLFW.

Starting out with GLFW
A first look at the website reveals that the latest stable version dates back to 2007. Hmmm ... this could mean that it's really stable, or that bugs are no longer being fixed. There is mention of an upcoming new release, though.

How to make use of GLFW? Just create a window, and make library calls. The library does not assume you use an event loop in your code. While this is surprising, it's really all for the better. I spent lots of time perfecting the event loop that SDL needs. GLFW just doesn't care. You want to know if a key has been pressed? Well, ask for it! Want to know the state of your windowed app? Call a glfwGet function to obtain it. If you really want, you can also register a callback function, for example for keyboard input events, and do things the event driven way.

Example code:

void init_events(void) {
glfwSetKeyCallback(key_event);
}

void key_event(int key, int state) {
if (state == GLFW_PRESS)
handle_keypress(key);
else
handle_keyrelease(key);
}


No library is perfect
As it says on the GLFW website, no library is perfect. I ran into little problems that had great consequences and had me hit the reset button of the computer (!) multiple times. Hello ... hitting reset is so 1989. But then again, I was programming an old skool arcade game.

I would like to detail the troubles I ran into here. Mind that they are not really big obstacles, just gotchas, things you need to know about GLFW, and maybe annoyances that might want you to favor SDL anyway, but to each his own.
  1. There seems to be no good way to toggle between full screen and windowed mode. I tried to resolve this by closing the window and recreating it, but the window manager somehow doesn't like it. It is not an OpenGL problem, nor a problem of my app — SDL can do it and GLFW can't. So stick to either windowed or full screen, not both.
  2. When you resize a window, you should reinitialize OpenGL, reload textures, etc. This may take some time. When you drag a window using the mouse, GLFW will register multiple resize events, causing your app to reinitialize multiple times and causing considerable lag. I never had this problem with SDL.
  3. The characters of keys that are pressed will be reported in uppercase, even when shift is not being held down.
  4. For text input, do not use glfwSetKeyCallback(). Use glfwSetCharCallback() instead, which does ASCII translation, etc. This will give lowercase characters, a working Shift key, etc. One thing I really don't like is that it does not translate the return key to '\n', nor does it translate backspace to '\b', and Escape is not code 27. So, I use SetCharCallBack() for the regular input, and I use SetKeyCallBack() at the same time to translate often used keys like Escape, Return, Enter, Backspace.
  5. glfwGetTime() returns a double, in seconds. This is actually great, but keep this in mind because other libraries, like SDL, work with integers and milliseconds.
  6. The library includes functions for multi-threading. Don't use them, they will be removed in a later version. Use pthreads instead.
  7. GLFW does not include functions for sound. This is intended; use OpenAL for sound.

Do you want to know more?

If you would like to get started using GLFW, I recommend reading the users guide that is available in PDF format on the website: http://glfw.sourceforge.net/documentation.html