March of the Ants
I spent a little time over the Easter break playing about with the new streamlined integration of JOGL into Swing, as promoted by Chris Campbell in his blog some eighteen months back. To be honest, there really isn't an awful lot to 'play about' with. The interoperability with Java2D is just a lot more efficient (and usable) without any need to do something special. So what I really did was to brush up on my somewhat rusty, and admittedly rather limited, OpenGL skills.
For those who haven't sampled the delights of OpenGL directly, it might be worth explaining that it was originally envisioned as a kind of be-all-and-end-all for any sort of geometry based computer graphics. From video games to Computer Aided Design, OpenGL has a range of disparate functionality which can be adapted to fit. As such there's a lot of stuff which, at first glance, might cause one to think "why would I ever need that?"
Sometimes, though, cool effects can be found in the most arcane of functionality.Line stippling, an effect which adds dots and dashes to wireframe rendered polygons, is certainly useful when writing a CAD package. But why would a 'Swing Bling Merchant' (tm) need it? That was the question I asked myself when reacquainted with some of my old JOGL code.
Like a lot of people, I had worked my way through the Red Book (the Silicon Graphics comprehensive guide to OpenGL) adapting the examples in each chapter for the purposes of experimentation and learning. And as line stippling was mentioned in chapter two, I'd coded up a cute little test application in both JOGL and LWJGL to try both wrapper APIs out. But what benefit could dashed lines bring to a Swing application?
Then an interesting idea hit me (don't gasp -- I do get them every now and again, y'know!) What if I drew the polygon display list twice? Once normally, and again with the stipple mask inverted? And what if I also rotated the mask by one bit each frame? The result would be... would be... well, it would look almost like ... [dramatic drum roll] ... MARCHING ANTS!!
Marching Ants is the familiar name given to that ever-shifting black/white pattern that dances across the display whenever you draw a selection in a graphics package like Photoshop. The continual animation and the use of alternating contrasting colours ensures the selection outline remains visible no matter what the underlying image.
The idea seemed like a perfect opportunity to mix up a transparent GLJPanel with some regular Swing GUI stuff, and see just how well it performs. To wit, I began to devise a layered container which overlays marching ants onto its children. The component proved easy enough to make, and pretty soon I had a rough-n-ready MarchingAntsPane and a bit of test GUI to try it with.
//Create a new MarchingAntsPane MarchingAntsPane ants = new MarchingAntsPane(child); : // Show a given polygon ants.setPolygon(poly); : // Clear the ants ants.setPolygon(null);
The source code is available — although I must warn you that it is far from polished.
The component acts as a container, not unlike JScrollPane, wrapping any JComponent it is given with a transparent top layer onto which it can draw its ants. The logic which binds mouse actions to polygon creation/manipulation is left unimplemented on purpose, for maximum flexibility. Presumably in the majority of cases the child component will register for mouse events, then feed its ant container appropriate polygons to drawn.
I didn't stop there, oh no siree Bob! I also wrote a pure Java2D implementation which uses the more traditional approach of applying a diagonal black/white stripe across a polygon outline using a composite effect which only touches non-alpha pixels (whew!) Both components, labeled
MarchingAntsPane2 respectively, are subclasses of an abstract
MarchingAntsPane which manages the non-pixel orientated parts of the code.
The OpenGL version provides an (almost) true dashed line around its circumference, while the Java2D version looks somewhat crude by comparison, as its stripe creates long blocks of single colour for 'forward slash' orientated lines. Apart from that, the Java2D version works quite well, and has the added bonus of running without any JOGL libraries on the class/native path.
So there you go. Sometimes the most humble bits of functionality can be the most useful. And while a stippled line might not have the visual kudos of a spinning texture draped polygon, it certainly proved its worth here.