Easy 2D/3D Mixing in Swing
When You're A Jet...
A couple weeks back, I had the privilege of speaking to the Java Programming Club at Monta Vista High School in Cupertino, CA. I'm still amazed at the turnout: about 25 students showed up, all with varying levels of experience with Java, and all apparently willing to endure my so-so demos on their lunch hour. The thing that grabs me though is, if they have a Java club, does that imply that they have other similarly specialized programming clubs too? Do the Ruby, Haskell, Java, and Lisp clubs all confront each other just outside school grounds when they have a score to settle, Ã¡ la Sharks v. Jets?
Anyway, I'd like to thank their president, Anshul Bhagi, for inviting me. It was fun! I promised to post the (rather scattershot) slides from my talk, which mainly revolved around JDK 6 (the new SplashScreen API, 2D/3D mixing in Swing apps, how to get involved, etc). I asked the students if anyone had tried out JDK 6 snapshots, and was surprised to find that none of them had. All the more reason to pose a challenge to the students... By the end of this school year, I'd like to see at least two of them contribute fixes to the JDK 7 project. I know we've had a number of contributions for JDK 6 from the university level, but none that I'm aware of at the high school level, so I think that would be pretty cool.
It's A Bit Of A Pain
To get the students interested in doing some basic 2D and 3D graphics programming, I showed a couple of existing 2D/3D mixing demos, like Aerith. The great thing about demos like Aerith and its precursor Twinkle is that they're polished and they even behave like "real apps" (bells and whistles included), so ooh/aah factor is never an issue. But of course, we all know that the road to real-app-hood often involves thousands of lines of code, so if you're trying to learn from their source code, it's often difficult to locate the essence of the demo. Twinkle's cool and all, but the source code can be daunting to a newcomer (no fault of Romain's).
Quite frequently I hear from developers who are familiar with Swing and Java2D, but haven't the foggiest idea where to begin when it comes to using JOGL in their application. It's especially difficult for developers who have no 3D graphics programming experience to be thrown into the world of OpenGL so abruptly. This time around, I decided to develop my own demo from scratch (with only a few, sparse, documented classes) to help show how to use some complementary technologies in the same application:
- Mixing Java2D and JOGL in a Swing application
- Using Chet's Timing Framework (can we just start calling this CTF?) to control 2D and 3D elements
- Leveraging the new SplashScreen API in JDK 6
Hans thinks we're incapable of writing a 2D/3D demo that goes outside the realm of photo viewers, and you know what, he's probably right (at least for this week). So, mea culpa, I wrote yet another photo-centric demo, but this time I stripped out all that pesky application logic. All that's left is a minimal demo that I hope is easy to understand for beginners. Here's a screenshot of "PhotoCube" (click to enlarge):
Or, why not run it yourself (the app itself is unsigned and requires JDK 6):
With OpenGL-based Java2D pipeline enabled
(should be faster than the other option)
With OpenGL-based Java2D pipeline disabled
(useful for comparing performance between the two,
or if you have trouble with the first link)
And finally, here's the source code (NetBeans project included).
The core functionality can be found in the DemoPanel class. The timingframework-specific code is isolated to the
DemoPanel.initTimers() method. You'll note that I've demonstrated a couple different ways to use the timingframework API to animate various rendering elements, some simple and some complex. It's unfortunate that the code is so verbose; it's certainly better than doing it by hand, but there's still plenty of room for simplifying the API. Chet and others are looking into ways to reduce the amount of code needed to write common animations, and some tools support is possible, so I would expect this to become much simpler in the near future.
(As an aside, one thing I'd like to see is something like a RepaintingObjectModifier, because so often in Swing applications all you want to say is, for example, "animate the location property of this JComponent from here to there, and call repaint() upon each timing event". Right now you have to override ObjectModifier or TimingTarget to get this common behavior, which just adds to the verbosity.)
The 2D/3D mixing code is also in that class, look for the
render2DForeground() methods. This code is illustrating how you can override those 3 or 4 methods provided by the CompositeGLJPanel class (also included in the source code) to easily include both Java2D and JOGL rendering elements in your user interface. I'd really like to see something like CompositeGLJPanel included as a convenience class in one of the JOGL utility packages; GLJPanel itself can be really scary beast to someone just learning this stuff for the first time. CompositeGLJPanel lowers the barrier a bit and handles a lot of the common boilerplate code needed by simple applications. Let me know if you have any suggestions or ideas for improvement.
Finally, check out the PhotoCube class, where I demonstrate the nifty TextureIO utility classes. (They're not part of the official JSR-231 spec, but rather are part of the com.sun.opengl.* packages that ship with the JOGL 1.0.0 distribution.) These classes work just like my other favorite API, Image I/O, and really make it easy to load an image from disk (or any other location) into an OpenGL texture. From there, you can use the Texture class, a simple wrapper object for OpenGL textures, which again provides an easier and slightly more object-oriented approach to dealing with OpenGL (a decidedly non-OO library). Enjoy...
Okay, I swear, I'm really done now, once again proving that I'm incapable of short-and-sweet...
In my ears: Faust, "IV"
In my eyes: Kenzaburo Oe, "The Silent Cry"