setCamera always throws NullPointerException

Hi!



I have got following proble. Whenever I try to set a new Camera object to a renderer in an already running rendering loop, I get the Exception attached at the end of this message



I already tried to debug the code to get more information. The problem is the method switchMode in RenderRecord


public void switchMode(int mode) {
        final GL gl = GLU.getCurrentGL();

        if (!matrixValid || this.matrixMode != mode) {
            gl.glMatrixMode(mode);
            this.matrixMode = mode;
            matrixValid = true;
        }
    }



matrixValid==true and my matrixMode == 0x1701 which is GL_PROJECTION parameter in the GL11 class...
gl.glMatrixMode(mode) is called, the NullPointerException is thrown.

Does anyone know why this happens? The strange thing is that if I call renderer.setCamera(camera) at the init process, everything is ok....

Thanks a lot,
Equilibrium





java.lang.NullPointerException
       at org.lwjgl.opengl.GL11.glMatrixMode(GL11.java:1960)
       at com.jme.scene.state.lwjgl.records.RendererRecord.switchMode(RendererRecord.java:57)
       at com.jme.renderer.lwjgl.LWJGLCamera.doFrustumChange(LWJGLCamera.java:194)
       at com.jme.renderer.lwjgl.LWJGLCamera.apply(LWJGLCamera.java:156)
       at com.jme.renderer.lwjgl.LWJGLRenderer.setCamera(LWJGLRenderer.java:242)
       at at.netcrystals.praxiteles.objects.PraxitelesCamera.makeActiveCamera(PraxitelesCamera.java:233)
       at at.netcrystals.praxiteles.actions.MakeCameraActiveAction.performAction(MakeCameraActiveAction.java:17)
       at org.openide.util.actions.NodeAction$DelegateAction$1.run(NodeAction.java:589)
       at org.netbeans.modules.openide.util.ActionsBridge.implPerformAction(ActionsBridge.java:83)
       at org.netbeans.modules.openide.util.ActionsBridge.doPerformAction(ActionsBridge.java:64)
       at org.openide.util.actions.NodeAction$DelegateAction.actionPerformed(NodeAction.java:585)
       at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
       at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
       at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
       at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
       at javax.swing.AbstractButton.doClick(AbstractButton.java:357)
       at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:1223)
       at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:1264)
       at java.awt.Component.processMouseEvent(Component.java:6263)
       at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
       at java.awt.Component.processEvent(Component.java:6028)
       at java.awt.Container.processEvent(Container.java:2041)
       at java.awt.Component.dispatchEventImpl(Component.java:4630)
       at java.awt.Container.dispatchEventImpl(Container.java:2099)
       at java.awt.Component.dispatchEvent(Component.java:4460)
       at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
       at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
       at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
       at java.awt.Container.dispatchEventImpl(Container.java:2085)
       at java.awt.Window.dispatchEventImpl(Window.java:2478)
       at java.awt.Component.dispatchEvent(Component.java:4460)
       at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
       at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:125)
       at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
       at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
       at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
[catch] at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Well in that method the only thing that could be null is the "gl" variable. This would mean that GLU.getCurrentGL(); returns null. Are you maybe using GameStates and OpenGl is running on another thread? The command seems to come in via the awt eventqueue, so that is definitely not the GL thread. try calling the command like this via the GameTaskQueue:


GameTaskQueueManager.getManager () .update(new Callable<Void>() {
    public void call() {
        //do stuff here
        return null;
    }
});

Thanks for your fast answer. I don't use GameTaskQueue. Is this absolutely necessary?

Well, since you're asking I'm going to explain in detail:

Most systems like javas swing or this game engine make the use of multiple threads to efficiently use the computers ressources. Threads mean, as you probably know, that processes run concurrently and might access data at the same time.



This may lead to many problems, from simple crashes due to unexpected changes in objects by other threads to more strange things like objects with values completely out of range etc.



So to avoid this, most programs approach it the following way:

For each "set of data", like OpenGL data, audio data, Swing graphics data etc. there is a thread that manages all the data and just receives information from other threads what to change. The other threads send objects ("Callables") containing the code they want to be done to the one thread that can access the data.



So, even when you are just working with swing you have to think about that. Swing has two threads: The Event Thread (the one that sends out the calls from mouse clicks etc.) and the Render Thread (the thread that displays the graphics on screen, arranges the windows etc.).



When you assign a method to a swing button in your Java IDE , the EventThread calls the method, so everything you do there is running on the event thread, the event thead also blocks the RenderThread that is why the display does not update if you do too computation intensive things there.



If you want to do stuff to your swing objects when on the EventThread (or any other thread), you have to make your calls via the EventQueue, which makes sure that you modify your swing GUI only on the RenderThread.


        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                jTextArea.setText("Hi");
            }
        });


The problem is, it works if you dont do it like this, but if you make too many calls your Java app might actually crash or the UI just does strange things. In Swing for example, if you call JTextArea.appendText("textn") directly, the JTextArea will display the text but it will not scroll it down when it reaches the bottom, because its not being done via the RenderThread.
That is why many people have problems with Swing, they dont know that you always have to wrap your Swing modifying code like this.

So in your game, you might modify the LocalTranslation of your objects directly from a button and it works, but actually it might happen that the OpenGL thread uses the vector when the AWT EventThread has just set two of the three float values of it!

So, the short answer is: yes, you have to use a GameTaskQueue. :)

Ahhhhh



Thanks a lot. Of course, I know EventDispatcherThread problems very well. However, I didn't know that I have to call JME methods from with a ThreadQueue.



Thanks. This may be the solution to many problems…



Regards