Hi,
I’m playing around with JME and Swing. One thing that comes to mind (and I’m not sure why :P) is how you could stop the OpenGL renderer thread without exiting the application. That is, if adding the JME Canvas to a Swing/AWT component, killing or re-instantiating the simple application could be useful. So far I tried:
[java]game.stop();
game.getContext().destroy();[/java]
However my app keeps throwing
[java]jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,6,main]
java.lang.IllegalStateException: From thread Thread[LWJGL Renderer Thread,6,main]: Thread[LWJGL Renderer Thread,6,main] already has the context current[/java]
when trying to re-instantiate the 3D game.
Thanks.
why not just rootnode.detachall() and think of it like a newly started one?
No reason - but yes, that just removes all nodes. Just wondering whether it is possible to do what I described? Would have the advantage of being able to move around, re-create and re-size the canvas…
You should not make any calls to the context, that’s up to the Application class to handle.
Did you try detaching the canvas from the frame? There’s a system in place that freezes the rendering thread when the canvas is detached, and then it unfreezes when the canvas is attached back.
Hi Momoko,
Yes, I had tried that. However that doesn’t solve the issue. Freezing it will just cause the thread to pause, so creating a new instance of [java]SimpleApplication[/java] will still throw the same exception.
I thought that’s what you wanted, the render thread to pause? Isn’t it the same as freezing it?
No, I want to completely kill the OpenGL thread. ie I want to be able to destroy the existing instance of SimpleApplication and at a later stage create a new one.
What is the issue then? You call start() to start the app, then stop() to close it. See jme3test.app.TestApplication.
The issue is as I described above. After killing the application, the OpenGL thread is still running. Re-creating the instance of SimpleApplication results in
[java]jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,6,main]
java.lang.IllegalStateException: From thread Thread[LWJGL Renderer Thread,6,main]: Thread[LWJGL Renderer Thread,6,main] already has the context current[/java]
I cannot reproduce this issue. I am using jme3test.awt.TestCanvas. Calling app.stop() immediately kills the render thread.
Nov 2, 2010 10:23:49 AM com.jme3.input.lwjgl.LwjglMouseInput destroy
INFO: Mouse destroyed.
Nov 2, 2010 10:23:49 AM com.jme3.input.lwjgl.LwjglKeyInput destroy
INFO: Keyboard destroyed.
Nov 2, 2010 10:23:49 AM com.jme3.system.lwjgl.LwjglAbstractDisplay deinitInThread
INFO: Display destroyed.
Nov 2, 2010 10:23:57 AM com.jme3.system.lwjgl.LwjglCanvas$1 removeNotify
INFO: EDT: Close requested. Not re-initing.
And what happens when you re-instantiate the game? ie
[java]game.stop();
game = new MyGame();
// do swing stuff here
game.start();[/java]
Also, note that it’s not stop() that’s throwing the exception.
Sorry, I was a big vague earlier; meant to include this code:
[java] java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
game.stop();
mainPanel.removeAll();
settings = new AppSettings(true);
settings.setWidth(panelMap2D.getWidth() / 2);
settings.setHeight(768);
game = new Game3D();
game.setSettings(Main.settings);
game.createCanvas();
canvasContext = (JmeCanvasContext) Main.world.getContext();
canvasContext.setSystemListener(Main.world);
Dimension dim = new Dimension(panel.getWidth() / 2, 768);
canvasContext.getCanvas().setPreferredSize(dim);
gamePanel = new JPanel();
gamePanel.setSize(dim);
gamePanel.add(Main.canvasContext.getCanvas());
// Display Swing window including JME canvas!
game.startCanvas();
}[/java]
EDIT:
Sleeping for a few seconds before creating a new instance of the game prevents the Open GL exception from being thrown.
[java]
mainPanel.removeAll();
game.stop(true); // or stop(false) - same difference to me
// mainPanel = new JPanel();
try {
Thread.sleep(5000);
} catch (Exception e) {
}
settings = new AppSettings(true);[/java]
However after a few seconds, the application crashes with: Invalid memory access of location 0x0 rip=0x176a7ad83
Sorry I haven’t taken a look at this issue yet. It is possible that the LWJGL display isn’t properly getting destroyed.
The invalid memory access however is very strange, it definitely shouldn’t happen.
For now I added it to the issue tracker:
http://code.google.com/p/jmonkeyengine/issues/detail?id=236
I might take a look at it next week, as I am busy at the moment.
Thank you momoko - there’s no hurry Just something that I came across and thought would be useful
I found a solution:
Calling app.stop(true) instead of app.stop() fixes this issue.
When you use app.stop(), the renderer thread is told to shutdown but this can happen sometime later. If you create a new renderer thread it might have a higher priority and so it could start running before the other thread died.
When you use app.stop(true), it waits until the current render thread fully shuts down, and then you can make a new one.
I tried that before (see earlier post )…Won’t work for me (still crashes with an invalid memory exception).
[java]
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
Main.panelMap3D.removeAll();
mainPanel.removeAll();
Main.world.stop(true);
Main.settings = new AppSettings(true);
Main.settings.setWidth(panelMap2D.getWidth() / 2);
Main.settings.setHeight(768);
Main.world = new TerrainViewer3D(manager);
Main.world.setSettings(Main.settings);
Main.world.createCanvas();
Main.canvasContext = (JmeCanvasContext) Main.world.getContext();
Main.canvasContext.setSystemListener(Main.world);
Dimension dim = new Dimension(panelMap2D.getWidth() / 2, 768);
Main.canvasContext.getCanvas().setPreferredSize(dim);
Main.panelMap3D = new JPanel();
Main.panelMap3D.setSize(dim);
Main.panelMap3D.add(Main.canvasContext.getCanvas());
Main.world.startCanvas();
panelMap2D.setVisible(true);
panelMap2D.setSize(panelMap2D.getWidth() / 2, panelMap2D.getHeight());
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true);
splitPane.setRightComponent(panelMap2D);
splitPane.setLeftComponent(Main.panelMap3D);
splitPane.setDividerLocation(panelMap2D.getWidth() / 2);
splitPane.setBounds(0, 0, panelMap2D.getWidth() * 2, panelMap2D.getHeight());
splitPane.repaint();
mainPanel.add(splitPane);
}
});
[/java]
EDIT: Resolved by stopping the app prior to removing it from the canvas. Now nothing happens (I just see a blank canvas).
It successfully adds the splitPane to the parent container, I call repaint et al, but still nothing happens…
EDIT 2: After letting it run for a few minutes, the the entire app just crashes…no explanation, no exceptions…
Sorry but I don’t have any idea what is wrong. It works fine on my PC.
In one of your other threads you mentioned that a trivial operation like changing object position causes your computer to crash and require hard reboot. Sounds to me like this might be an issue with your OS/Hardware rather than jME itself.
Uff, I hope not :-s – Running it on the latest Macbook (Intel, nVidia, OS X). I’ll try running this on another machine tomorrow.
As a last favor, would you mind posting the code that you used when trying this out?
Thanks a lot for your time!