Wednesday, 5 August 2009

Map projections with Pyglet

In 2001, I wrote code to generate fractal-based landscapes and wanted to visualise what it produced using map projections. The projection I was most familiar with was the mercator projection, and while it showed that the generation was working, it wasn't ideal for visualisation due to the distortion present within it. So I played around with other projections and eventually settled on an orthographic projection. The end result was an animated gif of around a megabyte in size that showed a generated planet rotating. Unfortunately, at some point in time, the code was lost.

With a bit of time to spare to create some similar code, this time I decided on using the mollweide projection. Pygame has always been a little too complicated, sure there is documentation, but more often than not when I try and use a feature there will be an non-obvious little detail that prevents it from working correctly if at all. So this time, I decided to use Pyglet.

I've used Pyglet in the past, and had a simple script that used OpenGL to display a grid and move around it on the XZ plane. Unpromisingly, this script no longer worked and the grid wouldn't display. It turns out that Pyglet has changed the way their window events work. My resize event was being called:

@window.event
def on_resize(width, height):
# Override the default on_resize handler to create a 3D projection
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, width / float(height), 0.1, 1000.0)
glMatrixMode(GL_MODELVIEW)
But it turns out that now if you do not return pyglet.event.EVENT_HANDLED from this event, Pyglet decides to assert some default behaviour. Some helpful bloke from the Pyglet mailing list pointed me in the right direction with this.

During the period where I was unaware that this non-backwards compatible change had occurred I tried two different examples from the Pyglet documentation. Both errored due to bugs in the current release of Pyglet (1.1.3). It seems that Pyglet isn't in a stable state at the moment, and given that 1.1.3 is a maintenance release or something, I am not sure it ever is. I tracked down bug reports for the problems and noted they were considered to be fixed in the trunk, both at different points in time months before 1.1.3 was released. It would be nice to be able to see a list of all the known bugs with the current release (especially since any I encounter already seem to be fixed) so that I as a user do not have to waste my time unexpectedly experiencing them, tracking down the problem and trying to report them. The best approach with regard to Pyglet when I experience a bug seems to be ignoring the bug reporting system and just looking to see if a fix has been made in the trunk and manually patching it into my own code.

I mentioned something above about PyGame. I'd also like to say that sure there is documentation for Pyglet, but more often than not when I try and use a feature there will be an non-obvious little detail that prevents it from working correctly if at all.

In any case, eventually I reached the point where I had written code to do a mollweide projection and had it displaying in the PyGame window, looking the following way.



I am also saving out the images I generate, in order to take not of different approaches and mistakes made during the process of development. By itself Pyglet can only save out PNG images, so this was what it saved out to a PNG file.



Now one picture is a little bright and the other is a little dark. The PNG images saved by Pyglet have darker colours. I initially tried to compensate by continually brightening the map colours. The brighter image, which is identical to what is displayed by Pyglet, was saved out as a JPG image after I had installed PIL. If PIL is present, than Pyglet can handle a wider range of image formats.

No comments:

Post a Comment