Nasty design constraints when using AWTGLCanvas

I started a topic http://www.java-gaming.org/index.php/topic,19099.0.html in the newbies forum which pointed me towards AWTGLCanvas. Having had a play with this canvas class I’ve got a couple of further questions which are probably best raised in this forum:

First a little background: I’m designing and implementing an engine that is OpenGL agnostic, i.e. it handles the generic side of a 3D application: models, texture blending, vector maths, etc. The engine defines a set of interfaces that a specific OpenGL library implements to handle rendering, lighting, texturing, etc. I’ve got two implementations, one for JOGL (largely incomplete) and another for LWJGL (largely done :)).

The LWJGL implementation initially used the Display class to create the window and Keyboard/Mouse to handle input. Once I started on the JOGL version I realised that I’d been re-inventing the wheel to some extent - it would much nicer to use standard Java APIs for creating the frame and keyboard/mouse handling, which is why I ended up looking at AWTGLCanvas.

But having altered the LWJGL library to use AWTGLCanvas I’ve realised that it’s screwing the engine architecture and I don’t like it.

Like most applications, the engine sets everything up then starts a rendering loop that redraws the scene, updates the game and swaps the buffers:

  • open the display
  • init the application (build the scene-graph, load models, texture images, etc)
  • setup input devices handlers
  • rendering loop:
    1. update context (timing, etc)
    2. render scene
    3. swap buffers
    4. update game

But this approach won’t work with the AWTGLCanvas. I (perhaps naively) expected I could just leave the engine as it is and change step 3 above to invoke repaint() on the canvas. Oh no - null-pointers all over the place. It appears that the LWJGL context is only created in the paint() method ( :-!) of the canvas, and is not valid outside of that method. Why? You don’t need to be concerned with this context notion when using the Display approach, the GL APIs are globally available.

This forces me to sub-class the canvas, put the initialisation code in initGL() and the scene code in paintGL(), or at least call back to the engine to do it. I can understand why this is as it is, the developer followed the AWT/SWING paradigm. It’s bad design but that’s the way the AWT/SWING developers decided to do things - deal with it you might say.

But I’m not giving in just yet, so:

  1. Is what I’ve written above correct? i.e. the GL APIs are not available outside of this loop.

  2. If so, why? It works when you use the Display approach.

  3. Is there anyway I can get access to the GL APIs outside of the painting loop such that my engine remains largely as it is? Or am I going to have to start the rendering loop and then wait for the initialisation and painting ‘callbacks’ from the canvas?

  4. As a small aside - should I be using AWTGLCanvas and standard Java APIs for display modes, input devices, etc. in a real-world LWJGL application anyway, or should I be using the Display/Keyboard/Mouse approach? What is the general approach used out there?

I hope this makes some sense. Cheers in advance for any suggestions.

Hi, there is also another approach introduced in LWJGL 2.0rc1. It allows to embed Display in Canvas, see the Display.setParent method, there is also example in LWJGL sources in src/org/lwjgl/test/opengl/awt/DisplayParentTest.java. It works exactly like Display including input handling :slight_smile: The only drawback is that you can have only one Display at once.

Yep, AFAIK we’re deprecating AWTGLCanvas in favour of Display.setParent().

Cas :slight_smile:

OK that sounds a nicer approach, I’ll give it a whirl.

Ta ;D

But the AWTGLCanvas allows for multiple instances at a time, while Display.setParent() doesn’t. That’s great for editors and similar applications that offer multiple viewports. People are actually using this feature. Deprecating it isn’t a good idea IMHO.

Ah maybe I jumped the gun a bit there then. Forgot about that. setParent() is just so cool :slight_smile:

Cas :slight_smile:

From what I’ve seen so far (and bear in mind I’m quite new to this - hence this thread) both have their place. The new setParent() should make integration of a ‘real-world’ application/game with AWT/SWING much nicer, whereas AWTGLCanvas is ideal for demos, editors, etc. and has the benefit supporting multiple instances.

For anyone that’s interested in my conclusions…

Display.setParent() works sweet - it means that for both the ‘real-world’ case (using the Display approach, generally full-screen) and the AWT/SWING case (using AWTGLCanvas, windowed for editors, demos, etc) I’ve only had to make minimal changes to the architecture of my engine, which is nice :slight_smile:

Cheers for all the advice.

  • chris