[PyOpenGL-Users] Re: [wxPython-users] wxpython and thread(with OpenGl)
Brought to you by:
mcfletch
From: Mike C. F. <mcf...@ro...> - 2004-07-12 19:24:20
|
Antony Hodgson wrote: > Hi Mike, > > Thanks for your very informative reply. I'll take the liberty of > jumping in with a couple of comments that will hopefully clarify what > my student, Ali, is trying to do. > > First, we're both pretty new to dynamic 3D graphic rendering, so I'm > probably not understanding what the right way to do things is. Our > application is in computer-assisted surgery - we will ultimately have > 3D representations of complex objects such as bones (ie, thousands of > polygons) moving around in space in real time as an intraoperative > tracking system reports their positions in space. OpenGL seemed a > natural way to handle this (VTK is obviously an option as well). We > considered Inventor and Performer, but the Python bindings to those > are not as mature yet, so we were reluctant to embrace them at this > point. Okay, given your parameters, I think I can state categorically that what you *don't* want is to render in a background thread. What you want is to use a retained-mode rendering system (characterised by their use of "scenegraphs"). Your I/O thread would update the scenegraph. Most (all?) scenegraph engines already have the logic built-in to handle this kind of interaction. To elaborate slightly, when you alter the scenegraph's model of your scene, the scenegraph checks to see if the GUI thread is already rendering. If it is, the scenegraph simply sets a flag that the GUI thread will check on completion of the current rendering-pass which says, in essence "render again when you're finished", otherwise it tells the GUI thread to begin rendering. Your background thread can therefore make dozens of changes during a single rendering pass and the rendering engine will just pick them all up the next time it traverses the scenegraph. You can see what that kind of code looks like in OpenGLContext's Context base class (OpenGLContext being a pure-Python retained-mode scenegraph engine). It's not horrifically complex for simple cases, but that's all OpenGLContext will handle. More advanced scenegraph engines are designed so that they actually queue up the changes while the main GUI thread is rendering and only after the current frame has completed do they do any updates. This is the *proper* way to do the work, but it tends to make the implementations more difficult to follow, as every interaction needs to follow the Command pattern. If you can be sure that your updates (that is, the actual changing of the scenegraph data-structures) can run fast enough not to cause rendering hiccups, you would likely be best to queue up events to be rendered in the GUI thread just before the rendering simulation runs (you'll see that pattern in OpenGLContext's Context as well, it's the "normal" game-developer's pattern). This avoids "scenegraph tear" (where you've updated the scenegraph while rendering it so that part of the scene reflects one state, and part the other). Regarding size of the models. The limiter with PyOpenGL is likely to be the complexity of the scene more than the number of polygons in any given object (within the limits imposed by hardware). PyOpenGL, when using the array-drawing primitives, isn't really affected by the size of the arrays (it just passes the Numpy arrays to the C-level rendering code), but scenegraph engines have to do a lot of bookkeeping to properly render complex scenes. Even with raw PyOpenGL, though, I'd expect to have to write some C code to get acceptable performance and response times for something as intense as virtual surgery. I honestly don't think you'd get the kind of reliable performance you'd need to imagine putting a human life on the line with it. Inventor is a very mature scenegraph engine, by the way. Pivy is basically just a thin wrapper around it (little or no Python code running in the event loop), so you will likely find that it can handle almost anything you're going to throw at it (I've never used it myself, just going from conversations with the author). SGI's old Performer library (which would compile the scenegraph down into a sort of polygon soup, rather than keeping it structured) was what used to be used for this kind of work, but hardware has advanced enough that a scenegraph-based engine is likely more suitable, particularly for highly-interactive work. Not sure how well it embeds in wxPython, however. I wouldn't suggest using OnIdle for rendering. Keep to using EVT_PAINT wherever possible, the road-most-travelled is a good thing for performance in 3D graphics. Oh, for your network I/O, you might want to consider using asynchronous operations instead of a thread, if you can keep your entire app single-threaded you'll likely get the best possible performance and reliability. Twisted does, IIRC, have modules for serial-port access. HTH, Mike BTW, setting reply-to to the PyOpenGL list, as we've ventured rather away from wxPython topics. ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://members.rogers.com/mcfletch/ blog: http://zope.vex.net/~mcfletch/plumbing/ |