[SOLVED] Problem implementing Drawable (Using LWJGL with QTJambi)

Started by Ummon, February 16, 2010, 16:06:57

Previous topic - Next topic

Ummon

Hello,
I am currently playing around with OpenGL and want to use LWJGL in conjunction with QTJambi to create a very basic 3D Editor thingy. QTJambi has the QGLWidget which integrates an OpenGL Context into a QT Widget (basic window object). So what I need is basically the connection of that Widget to the LWJGL output so it is displayed in my QT GUI which should be accomplished by extending the QGLWidget or possibly the basic QWidget and implementing the LWJGL interface Drawable. This would be just like the AWTGLCanvas Class which extends the java.awt.Canvas, my Problem however is that the Drawable interface method getContext has a return type of org.lwjgl.opengl.Context which does not seem to exist.  ???
I am probably not seeing the obvious but neither the online API nor my LWJGL version seem to have something about this class. I hope somebody can clarify what I overlooked or if I am completely off with where I try to make the connection.

Matzon

the Drawable getContext method is package protected - as is the final class Context
I do not know if it makes sense to make them public

Ummon

So I cannot implement that interface? Then is there another way to get the rendered output from LWJGL to show in a specific Container?
From what I can see the standard LWJGL Display can be made a child of a java.awt.Canvas which should allow for a gui to be built around it using Java AWT. And I suppose i could somehow create a class that extends the AWT Canvas and displays in a QWidget but not without some messy programming. Is integration in different UI frameworks just not something LWJGL is made for or am I completely missing something here.
Please, help me out.

spasi

Drawable and Context exist so that LWJGL can provide different implementations of GL contexts, they are not meant to be used outside the library.

What you probably want to use is GLContext.useContext. This method takes a plain Object as its single argument, which is supposed to be a GL context that has been created outside LWJGL. After a call to useContext you can use the LWJGL API to submit GL rendering calls, with the limitation that the external context has to have been created and made current in the same thread that called GLContext.useContext (that's a GL/driver limitation, not LWJGL limitation). Something like:

QGLWidget widget = ...create widget...

widget.makeCurrent(); // Imaginary call, you need to be sure the widget's GL context is made current before useContext.

GLContext.useContext(widget);

...
GL11.glFoo(...);
GL11.glBar(...);
...

widget.update(); // I assume there must be a way to swapBuffers or something.


This is all assuming QGLWidget creates and manages its own GL context (sounds like it from your description). If you need to hack your own context in there, then I guess you'll have to checkout LWJGL, implement your own Drawable and use that custom build in your project.

Ummon

Ok, that should work. QGLWidget.makeCurrent() is already implemented but I can't test it because the actual creation of the context QGLContext.create() is causing problems. As soon as I get that to work I will post my results or more questions. ;)
Thanks spasi.

Ummon

Ah, now it works. It was a little bit unclear in the QGLWidget documentation that the Context is really created automatically and that the QGLContext.create() is something that has to be called from the context object constructor so it will only be used if you need to extend the QGLContext class.
Anyway for completeness sake I will post my code of the LWJGL Widget using the code from the basic rendering tutorial.

Code: LWJGLWidget
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;

import com.trolltech.qt.gui.QWidget;
import com.trolltech.qt.opengl.QGLFormat;
import com.trolltech.qt.opengl.QGLWidget;

public class LWJGLWidget extends QGLWidget {

	private static float angle = 0;

	public LWJGLWidget(QWidget parent) {
		super(new QGLFormat(), parent);
	}

	public LWJGLWidget(QGLFormat format, QWidget parent) {
		super(format, parent);
	}

	protected void initializeGL() {
		if (this.context().isValid()) {
			this.makeCurrent();
			try {
				GLContext.useContext(this.context());
			} catch (LWJGLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	protected void resizeGL(int w, int h) {
		// setup viewport, projection etc.:
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GL11.glOrtho(0.0, this.width(), 0.0, this.height(), -1.0, 1.0);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();
		GL11.glViewport(0, 0, this.width(), this.height());
	}

	protected void paintGL() {
		angle += 2.0f % 360;
		// clear the screen
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);

		// center square according to screen size
		GL11.glPushMatrix();
		GL11.glTranslatef(this.width() / 2, this.height() / 2, 0.0f);

		// rotate square according to angle
		GL11.glRotatef(angle, 0, 0, 1.0f);

		// render the square
		GL11.glBegin(GL11.GL_QUADS);
		GL11.glVertex2i(-50, -50);
		GL11.glVertex2i(50, -50);
		GL11.glVertex2i(50, 50);
		GL11.glVertex2i(-50, 50);
		GL11.glEnd();

		GL11.glPopMatrix();
	}
}


Basically just call makeCurrent() and useContext() in the initializeGL() method (useContext() with the QGLWidget.context()) and use the methods QGLWidget.paintGL() and QGLWidget.resizeGL() as described in the QGLWidget API to do the rendering and configure the viewport.

Thanks again spasi for providing the admittedly quite simple solution.