Hello everyone,
I just discovered JME and I saw that it can be embedded on a AWT GUI. However I’d like to do the same thing but with Qt Jambi.
I do not know how to proceed, I do not understand the principles beyound the JME embedded in AWT so I can not try to reproduce it.
Could someone can give me some hints to know where to look first?
Thanks
You might be able to create an OpenGL enabled surface in Qt, you can then grab the context handle and pass it to LWJGL/JOGL to use instead of creating a new OpenGL context.
Ok I see the logic behind this. But I don’t figure out how to pass the context to LWJGL and start the JME Canvas at the same time.
Let me explain :
[java]import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import jme.ContextedApplication;
import jme.MyJoglCanvas;
import com.sun.opengl.util.FPSAnimator;
import com.trolltech.qt.gui.*;
import com.trolltech.qt.opengl.QGLWidget;
public class GLJambiWidget extends QGLWidget{
ContextedApplication application; //A simple inherance of SImpleApplication
public static void main(String[] args) {
QApplication.initialize(args);
GLJambiWidget testGLJambiWidget = new GLJambiWidget(null);
testGLJambiWidget.show();
QApplication.exec();
}
public GLJambiWidget(QWidget parent){
super(parent);
application = new ContextedApplication() {
};
}
@Override
protected void initializeGL() {
application.start();
try {
GLContext.useContext(this);
} catch (LWJGLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
protected void glInit() {
super.glInit();
// Enable z- (depth) buffer for hidden surface removal.
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
// Enable smooth shading.
GL11.glShadeModel(GL11.GL_SMOOTH);
// Define “clear” color.
GL11.glClearColor(0f, 0f, 0f, 0f);
// We want a nice perspective.
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
}
@Override
protected void glDraw() {
super.glDraw();
}
}
[/java]
I created a QGLWidget and I pass the widget context to LWJGL by
[java]try {
GLContext.useContext(this);
} catch (LWJGLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}[/java]
However I do not figure out how to start the JME app and make it draw something directly via LWJGL. (I guess the missing thing is to be placed instead of application.start())
Could you tell me if I’m totally wrong or if it just miss me some knowledge please ? Thank you.
You will probably need to implement the JmeContext interface. When you are asked for the Renderer there, simply return a LwjglRenderer with the context properly set like shown in your code.
Thanks for your help. My gut feeling tell me that I’m not that far from the solution.
I did what you told me and implemented a JmeContext Interface (actually a Lwjgl interface), here it is:
[java]package jme;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GLContext;
import com.jme3.input.JoyInput;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.awt.AwtMouseInput;
import com.jme3.input.dummy.DummyInput;
import com.jme3.input.dummy.DummyKeyInput;
import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.input.lwjgl.LwjglJoyInput;
import com.jme3.input.lwjgl.LwjglKeyInput;
import com.jme3.input.lwjgl.LwjglMouseInput;
import com.jme3.renderer.lwjgl.LwjglRenderer;
import com.jme3.system.lwjgl.LwjglContext;
import com.jme3.system.lwjgl.LwjglDisplay;
import com.jme3.system.lwjgl.LwjglTimer;
import com.trolltech.qt.opengl.QGLWidget;
public class MyContext extends LwjglContext {
QGLWidget widget;
public MyContext(QGLWidget wid) {
widget = wid;
widget.makeCurrent();
}
@Override
public void internalCreate() {
try {
GLContext.useContext(widget);
} catch (LWJGLException e) {
e.printStackTrace();
}
super.internalCreate();
}
@Override
public void create(boolean waitFor) {
internalCreate();
listener.initialize();
}
@Override
public void destroy(boolean waitFor) {
}
@Override
public JoyInput getJoyInput() {
return (JoyInput) new DummyInput();
}
@Override
public KeyInput getKeyInput() {
return new DummyKeyInput();
}
@Override
public MouseInput getMouseInput() {
return new DummyMouseInput();
}
@Override
public Type getType() {
return Type.Display;
}
@Override
public void restart() {
}
@Override
public void setAutoFlushFrames(boolean enabled) {
}
@Override
public void setTitle(String title) {
}
}
[/java]
And I use this new “Context” with a modified application in order it to make the new context its context :
[java]
package jme;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.StatsView;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.input.FlyByCamera;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import com.jme3.system.JmeContext;
import com.jme3.system.JmeSystem;
import com.jme3.system.JmeContext.Type;
import com.jme3.system.jogl.JoglCanvas;
import com.jme3.system.lwjgl.LwjglDisplay;
import com.jme3.texture.Texture;
import com.jme3.util.BufferUtils;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.opengl.QGLWidget;
/**
*
-
@author Romain
*
/
public abstract class ContextedApplication extends SimpleApplication {
QGLWidget widget;
public ContextedApplication(QGLWidget widget) {
this.widget = widget;
}
@Override
public void simpleInitApp() {
// activate windowed input behaviour
flyCam.setDragToRotate(true);
// display a cube
Box boxshape1 = new Box(new Vector3f(-3f,1.1f,0f), 1f,1f,1f);
Geometry cube = new Geometry(“My Textured Box”, boxshape1);
Material mat_stl = new Material(assetManager, “Common/MatDefs/Misc/SimpleTextured.j3md”);
Texture tex_ml = assetManager.loadTexture(“Interface/Logo/Monkey.jpg”);
mat_stl.setTexture(“m_ColorMap”, tex_ml);
cube.setMaterial(mat_stl);
rootNode.attachChild(cube);
}
@Override
public void start(Type contextType) {
/
- The content comes from the sources
*/
if (context != null && context.isCreated()){
return;
}
if (settings == null){
settings = new AppSettings(true);
}
context = new MyContext(widget); // But I instanciate my context here
//context = new LwjglDisplay();
context.setSystemListener(this);
context.create(false);
renderer = context.getRenderer();
}
@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);
System.out.println(“I’m updating”);
}
@Override
public void simpleRender(RenderManager rm) {
super.simpleRender(rm);
System.out.println(“I’m rendering”);
}
public static void main(String[] args) {
QApplication.initialize(args);
QGLWidget widget = new QGLWidget();
ContextedApplication app = new ContextedApplication(widget) {
};
app.start();
widget.show();
QApplication.exec();
//Nothing happens except my widget showing itself.
}
}
[/java]
Everything looks to go fine, the JME engine initialize itself :
7 nov. 2010 13:55:54 com.jme3.system.lwjgl.LwjglTimer
INFO: Timer resolution: 1000 ticks per second
7 nov. 2010 13:55:54 com.jme3.renderer.lwjgl.LwjglRenderer initialize
INFO: Caps: [FrameBuffer, FrameBufferMRT, FrameBufferMultisample, OpenGL20, OpenGL21, OpenGL30, ARBprogram, GLSL100, GLSL110, GLSL120, GLSL130, GLSL140, GLSL150, VertexTextureFetch, TextureArray, TextureBuffer, FloatTexture, FloatColorBuffer, FloatDepthBuffer, PackedFloatTexture, SharedExponentTexture, PackedFloatColorBuffer, TextureCompressionLATC, MeshInstancing, VertexBufferArray]
7 nov. 2010 13:55:54 com.jme3.asset.DesktopAssetManager
INFO: DesktopAssetManager created.
7 nov. 2010 13:55:54 com.jme3.renderer.Camera
INFO: Camera created (W: 640, H: 480)
7 nov. 2010 13:55:54 com.jme3.renderer.Camera
INFO: Camera created (W: 640, H: 480)
7 nov. 2010 13:55:54 com.jme3.system.JmeSystem initialize
INFO: Running on jMonkey Engine 3 Alpha 0.6
7 nov. 2010 13:55:54 com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #1: file:/E:/jME3_10-25-2010/
7 nov. 2010 13:55:54 com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #2: D:MomhaindeveloppementEclipsetutorielsJME3GLonJME
7 nov. 2010 13:55:54 com.jme3.system.Natives extractNativeLibs
INFO: Extraction Directory #3: D:MomhaindeveloppementEclipsetutorielsJME3GLonJME
7 nov. 2010 13:55:54 com.jme3.system.JmeSystem initialize
GRAVE: Error while copying native libraries
java.io.FileNotFoundException: D:MomhaindeveloppementEclipsetutorielsJME3GLonJMElwjgl.dll (Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.(Unknown Source)
at java.io.FileOutputStream.(Unknown Source)
at com.jme3.system.Natives.extractNativeLib(Natives.java:72)
at com.jme3.system.Natives.extractNativeLibs(Natives.java:167)
at com.jme3.system.JmeSystem.initialize(JmeSystem.java:347)
at com.jme3.system.JmeSystem.newAudioRenderer(JmeSystem.java:288)
at com.jme3.app.Application.initAudio(Application.java:175)
at com.jme3.app.Application.initialize(Application.java:387)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:162)
at jme.MyContext.create(MyContext.java:45)
at jme.ContextedApplication.start(ContextedApplication.java:84)
at com.jme3.app.Application.start(Application.java:299)
at com.jme3.app.SimpleApplication.start(SimpleApplication.java:122)
at jme.ContextedApplication.main(ContextedApplication.java:107)
7 nov. 2010 13:55:54 com.jme3.audio.lwjgl.LwjglAudioRenderer initialize
INFO: Audio effect extension version: 1.0
7 nov. 2010 13:55:54 com.jme3.audio.lwjgl.LwjglAudioRenderer initialize
INFO: Audio max auxilary sends: 2
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Gui Node)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (BitmapFont) attached to this node (Statistics View)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (Statistics View) attached to this node (Gui Node)
7 nov. 2010 13:55:54 com.jme3.scene.Node attachChild
INFO: Child (My Textured Box) attached to this node (Root Node)
But it doesn't update neither render itself (it doesn't pass on the loop). Did I miss something important?
There’s an exception there:
[java]java.io.FileNotFoundException: D:MomhaindeveloppementEclipsetutorielsJME3GLonJMElwjgl.dll (Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus)[/java]
Maybe somebody can translate that?
Also, don’t forget to call the SystemListener callbacks in your context implementation. If you don’t do that, nothing will happen.
“Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus”
→ The process cannot access the file because it’s used by another process