I create a very simple external and stand-alone Swing GUI that runs JME Game start() and calls a doSomething() method I have implemented inside my JME Game:
public static void main(String arg[]) {
JFrame frame = new JFrame("MyJMEGame client GUI");
JButton button = new JButton("doSomething");
frame.getContentPane().add(button);
final MyJMEGame game = MyJMEGameImpl();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
OneCustomObject object = OneCustomObjet();
game.doSomething(object);
}
}
frame.setVisible(true);
game.start();
}
2) I run this main, then two windows become opened: the stand-alone Swing GUI and the JME game window.
3) Then I call a few times my doSomething(object) method to do something, whatever, inside my JME Game, like, for instance, updating state. Let's imagine that OneCustomObject it's just like that, a simple POJO transporting state.
4) Suddenly I get "strange" behaviors inside my JME Game, during rendering processes, etc. things like IndexOutOfBoundException or NullPointerException in ArrayList that internally JME Game uses (inside JME API, not mine) to process rendering meshes, vertex, whatever. And all these breaks are random! They do not happen always at the same time.
I guess there is some problem here with the AWT thread in which I launch my stand-alone Swing GUI and the JME Game I do instance and start outside it, but I call it inside my GUI. Is it right?
Any incoming help with this topic is very welcome!
Before modifying the jme Scenegraph you need to either lock it at a save place, or use the GameTaskQueue, so that the stuff happens inside the main thread.
if you can post a simple test case to reproduce the problem, it would be easier to explain what exactly happens.
Umm, you are locking the OpenGL thread itself. I believe this could lead to horrible FPS performance. Maybe using GameTaskQueue would be a better idea.
But it’s right that using GameTaskQueue leads to a better performance, as it doesn’t block the GL thread.
Anyway both solutions do not apply to BaseGame (the old way), but for StandardGame. So must I migrate my game, no other choice, but better as StandardGame is the recommended way for production impls.
All you have to do is call its update and render methods when overriding BaseGames methods…
Locking is only useful to ensure thread safety, so you don't get IndexOutOfBounds exceptions and stuff.
But you need to use GameTasks to ensure that certain things get executed inside the OpenGL thread, (all calls to GL11 Methods,like SkyBox.preloadTextures() for example) else you will get NullpointerExceptions.
i dont know all the details, but some OpenGL methods need access to the OpenGL context, which only exists in one thread because OpenGL is not designed for Multithrediness.
Thats what GameTasks are for, to inject methods who need access to the OpenGL thread into the correct Thread.
lock() only makes sure that the update/render loop is stopped, so you can safely attach new elements to the scene graph.
But thats only how i think it works
Maybe someone else with a deeper knowledge of the system can shed some more light on it.