Integrate JME on a Qt Jambi widget [help]

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