Tuesday, July 10, 2007

PyOpenGL is Dead to Me (Where Are All the 3d Graphics Python Enthusiasts?)

Right now, displaying a plot permanently blocks the main thread; in other words, you can't do:
p = Plot( x**2, [x, -5, 5, 10] ) #never returns
p.append(x**3) #execution never gets here!
I've tried desperately to get this to work using threading, but GLUT is not meant to be used in this way. GLUT basically forces the user to put all application logic into event callback functions which are called by the non-reentrant glutMainLoop. This won't work for either of my use cases, which are graphing from interactively from the console and embedding plotting functionality in larger applications/scripts.

The bottom line is that GLUT is not meant for real-world OpenGL applications, it's meant for learning OpenGL and and tangentially for writing simple demos and games. TOGL, a Tk Widget for OpenGL rendering which is also supported in PyOpenGL (though I couldn't get it to work right in less than an hour), suffers from essentially the same problem (Tk.mainloop is non-reentrant). As far as I can tell, these are really the only two interfaces which are available out-of-the-box in PyOpenGL.

So imagine my hope when I learned that another implementation of GLUT called Freeglut has a workaround for the inflexible event model problem. Tantalizingly, PyOpenGL 3.0 (a rewrite which uses ctypes instead of SWIG) supports Freeglut, as well as Python 2.5 (not currently supported by any functional version of PyOpenGL). I spent most of yesterday trying to get PyOpenGL 3.0 to work on Windows. Unfortunately, it just doesn't work yet, and PyOpenGL development is painfully slow.

As far as I can tell, PyOpenGL 3.0 has only one core developer, and he doesn't seem to have much time to work on it (search for 'OpenGL' on his blog, most of the results are from 2004 and 2005). I don't blame him personally, I'm just utterly shocked that Python doesn't have an actively maintained OpenGL interface library (next year's SoC?). A lag time of more than two years in producing a build for Python 2.5 on Windows is unacceptable in my view, given the size of the Python community and the traditional strength of its library support. [/Rant]

Today, I investigated a variety of new approaches (vaguely in reverse order of my preference):
  • Using Visual Python (annoyingly high-level, hideous website ;-)
  • Using PyOGRE (huge, probably unacceptable overhead)
  • Using the DirectX binding for Python on Windows, and PyOpenGL 3.0 elsewhere (disgusting platform dependency, PyOpenGL 3.0 is quite unstable and not expected to improve anytime soon)
  • Fixing PyOpenGL to work on Windows (probably a monumental task worthy of its own SoC project)
  • Creating my own limited ctypes wrapper for OpenGL (jury still out)
  • Hacking PyOpenGL 2.0 to work with Freeglut (possibly feasible?)
  • Creating a C or C++ Python rendering extension (how Visual Python works under the hood; has hacker sex appeal)
  • Writing my own event loop with PyOpenGL 2.0, but without using GLUT (after exhaustive searching I couldn't find any examples or mention of this, but I want to keep looking. You'd think this would be the most reasonable option)
I don't particularly like any of these, though several might work. Anything good which I missed?

Post script: I'm particularly interested in hearing about anything not listed here, though I'd still like to know if there is a gem on there which I have overlooked.


Deep said...

I once toyed a little with visual python for making movies of molecular dynamics simulations, and I was quite happy about it, because it was simple hackable, and they had a script that allowed me to export everything (almost faultlessly) to powray.

I haven't looked deeply into the code, so I don't know if visual python will make it simpler for you to complete your GSOC project, but if you could somehow extend visual python into a 3D plotting program, while keeping the existing hackability, then the result could become quite versatile and thus cool.

Niels L Ellegaard

PS: I only tried a small number of plotting libraries, but I just wanted to convey my joy over visual python.

Fabian said...

Hi Brian. Don't know if it helps, but PySoy (http://www.pysoy.org/) offers OpenGL bindings and is actively mantained.


kinetik said...

Look at Pyglet (http://www.pyglet.org/).

dan said...

Is pygame not acceptable here? It's an SDL wrapper so it's a lot less intrusive on your event loop.

Also kinetik mentioned Pyglet - from what I remember this contains a small cross-platform windowing system, all from Python c-types code. Very neat, and could be just what you want in terms of hackability.

I do agree with your comments about the state of OpenGL on Python. While I'm thankful it's there and that it's good enough for most simple projects, you inevitably end up having to write extensions when you start dealing with textures, arrays, newer extensions and the like.

Brian Jorgensen said...

Okay, so that's one vote for VPython. The main drawback is that it requires compilation of native code, so if I want to extend it at all that adds new complexity to building SymPy from source. I'll look at it in more depth today.

PySoy deserves a closer look as well. Although it has a lot of things I don't need (networking comes to mind), it is still much simpler than, say, OGRE. It also uses native code (which I'm not completely against; a ctypes solution just seems more Pythonic and easier to extend/support/maintain).

Pyglet looks really interesting! The event model seems to be exactly what I'm looking for. Also, the OpenGL interface looks like it might even be compatible with my existing code. Niice. Thanks for that one.

PyGame is good, and it's not off the table, but it focuses on the 2d side and has a less-documented 3d interface. Correct me if I'm wrong.

Thanks guys!

Will McGugan said...

You're post puzzles me! I've found PyOpenGL (3) to work very well with both PyGame and wxWindows. And I've never experience any problem using it on Windows.

Exactly what kind of problems have you been having?

Brian Jorgensen said...

Will: you might be exactly the person I wanted to attract to this post!

I can't get any release >= 3 to run the most basic GLUT examples. The first exception is:

AttributeError: 'NoneType' object has no attribute 'glutDestroyWindow'

I don't use this function currently, so I commented it out, hoping it was a bug that had gone unnoticed since the primary developer does not focus much on Windows (at least yet).

The second problem is that __glutInitWithExit, and therefore glutInit, ends up as a NullFunction.

I did not find any helpful google results, and judging from the sf forums and relevant blog posts, the waiting line for PyOpenGL support seemed prohibitively long.

Disclaimer: I'm not very clear on the architecture of PyOpenGL 3. I traced it as deeply as I felt comfortable, and my trail ended at wglGetProcAddress returning a lot of null pointers (though not all, and they mostly seemed to be extensions related to shader programs, etc). I have glut32.dll and opengl32.dll in System32 as well as in my Python path.

Aside from these difficulties, another thing that worries me is the unstability and slow development on PyOpenGL 3. I don't want to depend on a library that a beginner could not set up easily.

I also tried to use Togl, but I get the error:

TclError: invalid command name "togl"

I haven't tried it with wxWindows or PyGame. In your opinion, are they compatible with the event model I've described?

Will McGugan said...

I can't help you with glut or Togl I'm afraid. It could be that that the glut bindings just aren't implemented, or there are other issues on your system. But I wouldn't use glut since other toolkits give you all glut can do and more. I can vouch for PyGame though, setting up an OpenGL display is a one liner.

I wouldn't say that PyOpenGL is unstable. Its a virtually complete binding to OpenGL, and OpenGL isn't going to change any time soon. I concur that it would be more reassuring if there was more than one developer working on it, but Mike Fletcher knows what he is doing. :-)

OpenGL is intentionally low-level, if you want an event based model you could use wxWindows (which can have multiple OpenGL windows) or perhaps a socket based solution that launches PyGame instances.

Please don't give up on PyOpenGL just yet. ;)

Ondrej Certik said...

Hi, as Will said, I would try to use pyopengl and possibly some higher interface, like pygame. Pygame works very nice on linux, and I guess it shouldn't be difficult to install it on windows.

Adam Griffiths said...

I'm working on a project that may be of interest to you.


It's not a fully featured 'engine' but it's a well written (if I might say so) framework with which to build applications.
With a bit of magic, it may provide what you need.

In the future I will probably build high level APIs, but I aim to keep PyGLy simple and flexible.