I'm having an issue with multithreading (yes I read the tutorial). My program works fine if I have it all in the class which contains the reference to my StandardGame, but I would like to move the MouseListener to a new thread, and have it spin off threads which activate methods on the class which contains the StandardGame.
(I'm attempting this to see if it fixes a problem I was having where the MouseListener queues up incoming events while the main thread is busy doing stuff, and then dumps them back on it when it frees up - this causes problems.)
I have tried using .lock on the StandardGame object before running my code, or even calling .setActive(false); on the gamestate before running the code which affects GL stuff, but neither works. I've also tried both in combinations with game.delayForUpdate(); and Thread.sleep.
Last but not least, yes I have game.THREAD_FRIENDLY = true;
It seems like game.lock() should work, because if i put game.delayForUpdate() immediately after it the thread will pause forever, but for some reason I still get the GL error.
Exception in thread "Thread-7" java.lang.NullPointerException
at com.jme.renderer.lwjgl.LWJGLCamera.doFrameChange(Unknown Source)
at com.jme.renderer.lwjgl.LWJGLCamera.getModelViewMatrix(Unknown Source)
at com.jme.renderer.AbstractCamera.checkViewProjection(Unknown Source)
at com.jme.renderer.AbstractCamera.getWorldCoordinates(Unknown Source)
at com.jme.system.DisplaySystem.getWorldCoordinates(Unknown Source)
at com.jme.system.DisplaySystem.getPickRay(Unknown Source)
P.S. Sorry I know I ask a lot of questions - I am just trying to understand how the basics work - after that I'm pretty self-sufficient.
I can do that, but I still don't understand why it runs fine when I keep everything in one thread, but when I move code that isn't even relevant to GL to another thread it freaks out. Unless the MouseListener is somehow related to some lwjgl functionality and messes it up. I just like to know why a problem happens so that I don't create the same problem in the future.
Just to reiterate - there is no code that is related to GL in the new classes I created - they merely call the regular GL thread - and only one of these external non-GL threads is ever touching the GL thread at a time.
JME thread use ArrayList for scenegraph tree. When at end of update, tree is sent to card in buffers. If anything changed that scenegraph didnt know about can cause problems. Some buffers are as display lists.
Maybe someone with better english could describe better
My current setup (might be a bit weird, but it works):
TestStandardGame.java - encapsulates the StandardGame object
guidevtools.java - a class extended from JPanel so I don't need to worry about displaying a GUI with JME yet
MouseWatcher.java - a class extending runnable, which encapsulates the MouseInputListener related to the StandardGame
Now, that works fine when the MouseWatcher directly calls a reference to TestStandardGame for all its operations.
What I WANT to do is have MouseWatcher create a new thread with the pertinent data for each operation, and have that thread call TestStandardGame.
Each function in TestStandardGame checks to see if there is already a command running before allowing it to continue - so there are definitely no overlapping JME calls happening here from multiple threads hitting TestStandardGame at the same time.
So yes, multiple threads may access TestStandardGame at once, but they never touch JME at the same time, so I am confused as to why that setup would give a NullPointerException in glLoadIdentity
It all depends on what is going on behind the scenes… from what you write it gives me the impression you are handling concurrency yourself, instead of through the GameStateManager/GameQueue which is already implemented for you. In principle there is nothing wrong with this, but you have to make sure that you really are making the calls in the appropriate thread, because the GL state, once corrupted, can fail at any place (like in loading an identity matrix).
The only reason I'm handling it myself is that if you fire off an event on mouse movement while the button is held down, the MouseInputListener will hand them to you one at a time if you're running in a single thread. this means if part of your code is slower than the events fire, the MouseInputListener starts to queue them up, and hand them to you one at a time. you really have no way of knowing when they were actually fired. If you have the events fire off a new thread, then you can toss out any that happen before you're ready to run core code again.
I guess you could also just have the event put them in a queue, and check that when you're ready to process again, but I just find it odd that the whole thread thing won't work properly. Doesn't seem like going from one thread to many threads should make a difference unless you're actually calling JME code with many threads at one time.