Over the last couple of weeks, I've been working on a bit of the VERA project to do with 3D visualisation of archaeological data. Now, I'm no stranger to 3D graphics, but it's been a while since I really did any, and there's been several advances* in the intervening time. There are a number of requirements for this work, but one is for some degree of platform-independence. I won't go into the details, but I'm working on the principle that Java is probably the thing to use. However, if it is the right thing to use, it's being distinctly uncooperative.
My journey started with looking for a GUI toolkit. Fortunately, Java has several: AWT, Swing and SWT being the main contenders. I've encountered AWT and Swing before (at a user level), but not SWT. However, SWT seems to be modern, uses native widgets†, and runs on most platforms. It even has an OpenGL interface since v3.2. All good – let's use SWT, then.
I then took a short detour to get a basic SWT app up and running, which was easy enough with the examples and tutorials. I also looked into Java Web Start as a deployment platform. Again, using the tutorials, it was all simple enough once you'd got through the X.509 jar-signing awkwardness.
Then the pain started...
Given that most of the work I'll be doing will be with relatively static scenes – only the camera is likely to be moving – some form of scenegraph implementation would be helpful. This would also abstract away the OpenGL stuff, and allow me to concentrate on presentation rather than getting bogged down in the details of geometry. So, let's look at the state of 3D on Java.
Java3D is the "definitive" 3D implementation for Java. However, it's very old, and reportedly rather slow (from a conversation I had with one of the 3D experts we've got here). The biggest problem for me is that, as far as I can determine, it doesn't work with SWT.
Next up – Aviatrix3D. This actually looks good: it's got a stable 2.0 release, it's been updated recently, and it claims to support SWT. The documentation is pretty good too, with examples and tutorials. The first let-down is that the basic docs on how to make it work with SWT are confusing: I spent quite a detour after reading this page, trying to get the LWJGL code to work, since using code that's "under heavy development" (for the tweaked JOGL libs) has always made me nervous. Eventually, I dropped back to using the JOGL libs anyway. Then, on the same page, they state that
You may use either your own custom Canvas, the new SWT GLCanvas or our own GLCanvas implementation.
In fact, you can do the last of these, using the
org.j3d.aviatrix3d.output.graphics.SimpleSWTSurface class, but not the second one. There is no way to use the standard SWT GLCanvas in the Aviatrix pipeline. I didn't try writing my own custom canvas – I might be mad, but I'm not entirely stupid.
The first real signs of trouble with Aviatrix started when I finally managed to get some code compiled. This test program, when run, pretty reliably threw an exception:
[java] Exception in thread "AV3D Runtime" org.eclipse.swt.SWTException: Invalid thread access [java] at org.eclipse.swt.SWT.error(SWT.java:3374) [java] at org.eclipse.swt.SWT.error(SWT.java:3297) [java] at org.eclipse.swt.SWT.error(SWT.java:3268) [java] at org.eclipse.swt.widgets.Widget.error(Widget.java:434) [java] at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:373) [java] at org.eclipse.swt.widgets.Control.getSize(Control.java:746) [java] at org.j3d.opengl.swt.internal.ri.x11.X11OnscreenGLDrawable.getWidth(X11OnscreenGLDrawable.java:148) [java] at org.j3d.aviatrix3d.output.graphics.StandardRenderingProcessor.display(StandardRenderingProcessor.java:83) [...]
A quick run through everyone's favourite debugging tool got me to the Eclipse FAQ, which says that you can only update SWT GUI widgets from the thread that created them. I asked on the Aviatrix mailing list‡, and got a detailed and almost immediate response from one of the developers. It seems that this is a known but intermittent problem that the developers haven't been able to reproduce. It also happens with SWT 3.2, which is what they use internally. On my system, it seems to happen 100% reliably, which is problematic, as I can't actually get any further while this bug exists.
Xith3D is fast, still under development, and claims to work with SWT. Only, on closer investigation, it seems to work purely as a single 3D drawing surface. This means that if I want a UI, I have to overlay it on top of the 3D surface and use the built-in Xith GUI toolkit options. There doesn't seem to be any obvious way of starting up Xith to use just a SWT GLCanvas (or equivalent) within a normal SWT interface.
jMonkeyEngine is a game engine. That's OK, I'm not proud. At this stage, I'll consider pretty much anything. As with Xith3D, however, it seems that jME just uses SWT at a very high level, for creating a single window in which to render, and any "desktop" widgets are reimplemented within jME.
From the point of view of a complete newcomer to 3D in Java, the available software has complex interrelationships, which are generally poorly defined. Most of the projects I've found seem to be reasonably well-maintained, and certainly look like they're in used by a good number of people. They just don't seem to be suitable for what I want to do. I'd like to use Aviatrix, but with a reliably-breaking bug stopping me from working, there's not much I can do with it right now. If the Aviatrix guys can help me sort out this bug, I'll be at it like a shot, but right now I can't make any progress with it.
For now, I'm seriously considering dropping back to using raw OpenGL with SWT's GLCanvas, to the extent that I've just ordered a copy of the OpenGL Red Book. This will, I'm sure, lose me productivity on what is likely to be quite a time-limited piece of work. However, I have more confidence that it will get me somewhere than any of the available scenegraph implementations out there. All in all, a frustrating week's work.
* Hardware 3D graphics cards, OpenGL, Linux, that kind of thing...
† For me, that's an aesthetic bonus, both from the appearance of the application, and from the point of view that it's not massively reinventing the wheel.
‡Not archived, so no link to the thread. Sorry.