Scene graph is not properly updated for rendering

I will start with the error i’m getting

*******************************

SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.IllegalStateException: Scene graph is not properly updated for rendering.

State was changed after rootNode.updateGeometricState() call.

Make sure you do not modify the scene from another thread!

Problem spatial name: Game Screen RootNode

at com.jme3.scene.Spatial.checkCulling(Spatial.java:242)

at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:775)

at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:793)

at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1116)

at com.jme3.renderer.RenderManager.render(RenderManager.java:1167)

at com.jme3.app.SimpleApplication.update(SimpleApplication.java:263)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)

at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)

at java.lang.Thread.run(Thread.java:662)

BUILD SUCCESSFUL (total time: 7 seconds)

**************************************

Im running the code on Windows 7 x64=> no problems

on another pc running Win XP 32bit i get the error



the code that is causing the error:

[java]

@Override

public void initialize(AppStateManager stateManager, Application app) {

super.initialize(stateManager, app);

rootNode.attachChild(localRootNode);

guiNode.attachChild(localGuiNode);

viewPort.setBackgroundColor(backgroundColor);



DirectionalLight dl = new DirectionalLight();

dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());

localRootNode.addLight(dl);

}

[/java]

it’s an initialize method from an Appstate that’s also a nifty screen controller.

Removing the DirectionalLight also gets rid of the error, but offcours i want to be able to do something inside the scene graph in my initialize.



I guess i’m modifying the scene graph from outside the rendering thread.



Should i go multithreading as suggested here?http://hub.jmonkeyengine.org/groups/general-2/forum/topic/on-illegalstateexception-scene-graph-is-not-properly-updated-for-rendering-and-futurecallable-objects/



Also isn’t it strange i only get the error on an older pc running windows xp?

We don’t have enough information. What is localRootNode? Who managed is it? Is it a child of rootNode or its own root?



This should work as written given a few assumptions. If localRootNode is not a child of rootNode, like you are using a separate ViewPort or something then that could be the issue.

localRootNode is a Node i create in each AppState that i got, then when i attach an appstate i also do “rootNode.attachChild(localRootNode);”

for instance my GameScreenController state:

[java]

public class GameScreenController extends AbstractScreenController {



private static final Logger logger = Logger.getLogger(GameScreenController.class.getName());

private Node localRootNode = new Node(“Game Screen RootNode”);

private Node localGuiNode = new Node(“Game Screen GuiNode”);





[/java]



I’m getting rootNode an ViewPort via my AbstractScreenController

[java]

public class AbstractScreenController extends AbstractAppState implements ScreenController {



@Override

public void initialize(AppStateManager stateManager, Application app) {

this.sapp = (SimpleApplication)app;

this.myStateManager = stateManager;

this.assetManager = sapp.getAssetManager();

this.rootNode = sapp.getRootNode();

this.viewPort = sapp.getViewPort();

this.guiNode = sapp.getGuiNode();

this.inputManager = sapp.getInputManager();

}

[/java]

So i’m using only 1 and the same ViewPort.

The thing is, it is working as intended, but only on my W7 x64, maybe it’s hardware related, the XP machine where i get the error is much older hardware.

When you create a new rootNode yourself that you attach to a viewPort you have to manage updating it yourself.

Ah, sorry, I missed the attach( localRootNode ) in the first post.



This shouldn’t be hardware related, really. If anything it’s just that different hardware is changing the timing.



Are you sure that you don’t have any other threads running other than the render thread?



Then again, I’ve never tried to add a light from an app state… though I don’t know why that would cause an issue.



You say that if you comment out the localRootNode.addLight() line that the problem goes away?

@normen said:
When you create a new rootNode yourself that you attach to a viewPort you have to manage updating it yourself.


Except he's not. He's using application's root node.

I’m not using multithreading , so i guess i’m running only 1 thread. Indeed if i remove the light the problem goes away.



Same thing for if i would replace the light with just 3 arrows i get the same problem:



[java]

putArrow(Vector3f.ZERO, Vector3f.UNIT_X, ColorRGBA.Red);

putArrow(Vector3f.ZERO, Vector3f.UNIT_Y, ColorRGBA.Green);

putArrow(Vector3f.ZERO, Vector3f.UNIT_Z, ColorRGBA.Blue);



public void putArrow(Vector3f pos, Vector3f dir, ColorRGBA color){

Arrow arrow = new Arrow(dir);

arrow.setLineWidth(10); // make arrow thicker

putShape(arrow, color).setLocalTranslation(pos);

}

public Geometry putShape(Mesh shape, ColorRGBA color){

Geometry g = new Geometry(“shape”, shape);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.getAdditionalRenderState().setWireframe(true);

mat.setColor(“Color”, color);

g.setMaterial(mat);

localRootNode.attachChild(g);

return g;

}

[/java]



In fact no matter what i add to the localRootNode gives me the same error

Right, no idea… You do strange things with your localRootNode like overriding updateGeometricState() or any methods at all?

I don’t do anything special,



Here’s the complete code of the Appstate:



[java]

package mygame;



import com.jme3.app.Application;

import com.jme3.app.state.AppStateManager;

import com.jme3.app.SimpleApplication;

import com.jme3.renderer.ViewPort;

import com.jme3.scene.Node;

import com.jme3.asset.AssetManager;

import com.jme3.math.ColorRGBA;

import java.util.logging.Logger;

import java.util.logging.Level;



import com.jme3.material.Material;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.math.ColorRGBA;

import com.jme3.scene.debug.Arrow;

import com.jme3.scene.Mesh;

import com.jme3.light.DirectionalLight;

import com.jme3.input.InputManager;

import com.jme3.input.KeyInput;

import com.jme3.input.MouseInput;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.AnalogListener;

import com.jme3.input.controls.KeyTrigger;

import com.jme3.input.controls.MouseAxisTrigger;

import com.jme3.input.controls.MouseButtonTrigger;





public class GameScreenController extends AbstractScreenController {



private static final Logger logger = Logger.getLogger(GameScreenController.class.getName());

private Node localRootNode = new Node(“Game Screen RootNode”);

private Node localGuiNode = new Node(“Game Screen GuiNode”);

private final ColorRGBA backgroundColor = ColorRGBA.Gray;

private GraphicalBoard board;

private boolean lctrl = false;

private Vector3f zoomlevel = new Vector3f();



public GameScreenController(){

}



@Override

public void initialize(AppStateManager stateManager, Application app) {



super.initialize(stateManager, app);

rootNode.attachChild(localRootNode);

guiNode.attachChild(localGuiNode);

viewPort.setBackgroundColor(backgroundColor);



DirectionalLight dl = new DirectionalLight();

dl.setDirection(new Vector3f(-0.1f, -1f, -1).normalizeLocal());

localRootNode.addLight(dl);

}



@Override

public void update(float tpf) {

logger.log(Level.INFO, “Updating GameScreenController”);



}



@Override

public void stateAttached(AppStateManager stateManager) {

//sapp is not yet known here, at least not first time this class is used.

//so i can’t get sapp.rootnode, guinode, vieuwport here, thats why i did put it in initialize.

}



@Override

public void stateDetached(AppStateManager stateManager) {

rootNode.detachChild(localRootNode);

guiNode.detachChild(localGuiNode);

}



@Override

public void onStartScreen() {

}



@Override

public void onEndScreen() {

super.onEndScreen();

}



public void putArrow(Vector3f pos, Vector3f dir, ColorRGBA color){

Arrow arrow = new Arrow(dir);

arrow.setLineWidth(10); // make arrow thicker

putShape(arrow, color).setLocalTranslation(pos);

}

public Geometry putShape(Mesh shape, ColorRGBA color){

Geometry g = new Geometry(“shape”, shape);

Material mat = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

mat.getAdditionalRenderState().setWireframe(true);

mat.setColor(“Color”, color);

g.setMaterial(mat);

localRootNode.attachChild(g);

return g;

}



private void initKeys() {



inputManager.addMapping(“ZoomIn”, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));

inputManager.addMapping(“ZoomOut”, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));

inputManager.addMapping(“LCTRL”, new KeyTrigger(KeyInput.KEY_LCONTROL));

inputManager.addListener(actionListener, new String[]{“LCTRL”});

inputManager.addListener(analogListener, new String[]{“ZoomIn”, “ZoomOut”});

}



private ActionListener actionListener = new ActionListener() {

public void onAction(String name, boolean keyPressed, float tpf) {



if (name.equals(“LCTRL”) && keyPressed) {

lctrl = true;

}

else{

lctrl = false;

}

}

};



private AnalogListener analogListener = new AnalogListener() {

public void onAnalog(String name, float value, float tpf) {

if (lctrl) {

zoomlevel.set(sapp.getCamera().getLocation());



if (name.equals(“ZoomIn”)) {

sapp.getCamera().setLocation(new Vector3f(zoomlevel.x, zoomlevel.y -1,zoomlevel.z - 1));

}

if (name.equals(“ZoomOut”)) {

sapp.getCamera().setLocation(new Vector3f(zoomlevel.x, zoomlevel.y + 1,zoomlevel.z + 1));

}

}



}

};



}







[/java]

Then I guess the light state isn’t properly updated, @Momoko_Fan?

I dont think it’s the light:


@mr-jor said:
I'm not using multithreading , so i guess i'm running only 1 thread. Indeed if i remove the light the problem goes away.

Same thing for if i would replace the light with just 3 arrows i get the same problem:

[java]
putArrow(Vector3f.ZERO, Vector3f.UNIT_X, ColorRGBA.Red);
putArrow(Vector3f.ZERO, Vector3f.UNIT_Y, ColorRGBA.Green);
putArrow(Vector3f.ZERO, Vector3f.UNIT_Z, ColorRGBA.Blue);

public void putArrow(Vector3f pos, Vector3f dir, ColorRGBA color){
Arrow arrow = new Arrow(dir);
arrow.setLineWidth(10); // make arrow thicker
putShape(arrow, color).setLocalTranslation(pos);
}
public Geometry putShape(Mesh shape, ColorRGBA color){
Geometry g = new Geometry("shape", shape);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.getAdditionalRenderState().setWireframe(true);
mat.setColor("Color", color);
g.setMaterial(mat);
localRootNode.attachChild(g);
return g;
}
[/java]

In fact no matter what i add to the localRootNode gives me the same error

Where are you calling putArrow()? From initialize()?



Ok… and now just so that I’m not making bad assumptions… which version of JME are you running? Beta or a recent stable update?



Also, can we see where you create this state and attach it? And pass it to nifty?



Normally this stuff should work. I do it all the time… so something is amiss in your code somewhere and I don’t see it in what’s provided.

What are your rootNode or guiNode variables?

I guess they come from your AbstractScreenController, but they don’t seem to be initialized with the SimpleApplication rootNode or guiNode.

Only those are automatically updated, so if you have your own rootNode and guiNode you need to call updateLogicalState and updateGeometricState on them on each update (in the abstract controller).

An easier way would be to feed the appState with the SimpleApplication’s rootNode and guiNode in the constructor.

@nehon said:
What are your rootNode or guiNode variables?
I guess they come from your AbstractScreenController, but they don't seem to be initialized with the SimpleApplication rootNode or guiNode.
Only those are automatically updated, so if you have your own rootNode and guiNode you need to call updateLogicalState and updateGeometricState on them on each update (in the abstract controller).
An easier way would be to feed the appState with the SimpleApplication's rootNode and guiNode in the constructor.


See a previous post from the original poster...

[java]
public class AbstractScreenController extends AbstractAppState implements ScreenController {

@Override
public void initialize(AppStateManager stateManager, Application app) {
this.sapp = (SimpleApplication)app;
this.myStateManager = stateManager;
this.assetManager = sapp.getAssetManager();
this.rootNode = sapp.getRootNode();
this.viewPort = sapp.getViewPort();
this.guiNode = sapp.getGuiNode();
this.inputManager = sapp.getInputManager();
}[/java]

I've made the assumption that he's just using the default root node and gui node that SimpleApplication provides and hasn't created his own in some weird way.

But that's worth verifying.

oh ok my bad

@pspeed

I would indeed call putarrow from initialize(), just as a test, i replaced the lights with putarrow, and got the same error.

The xp pc where i get the error is running beta, my other W7x64 pc where i dont get the error with the same code is running a more recent version. Problem is that update from inside JMP isn’t working anymore here at work.



I’ll try to copy the installation on my w7 machine(home) to this xp machine (at work) . I dont see another way to update



To answer your last question: Im creating and attaching the state inside a method in my AbstractScreenController

[java]

public void gotogame() {

GameScreenController gameScreenController = (GameScreenController) nifty.getScreen(“game”).getScreenController();

myStateManager.attach(gameScreenController);

nifty.gotoScreen(“game”);

}

[/java]

My Nifty itself is created inside my simpleInitApp()

[java]

@Override

public void simpleInitApp() {



NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, viewPort);

Nifty nifty = niftyDisplay.getNifty();

nifty.addXml(“Interface/screens/screenOptions.xml”);

nifty.addXml(“Interface/screens/screenGame.xml”);

nifty.addXml(“Interface/screens/screenStart.xml”);

nifty.gotoScreen(“start”);

StartScreenController startScreenController = (StartScreenController) nifty.getScreen(“start”).getScreenController();//

stateManager.attach(startScreenController);

guiViewPort.addProcessor(niftyDisplay);

inputManager.setCursorVisible(true);

flyCam.setEnabled(false);

}

[/java]



@nehon



I’m indeed using the rootNode and guiNode from my SimpleApplication via the initialize of my AbstractScreenController

So you maybe have an alpha version of the SDK installed? They don’t update anymore.

Its the standard beta installation:



Product Version: jMonkeyEngine SDK 3.0beta

Java: 1.6.0_29; Java HotSpot™ Server VM 20.4-b02

System: Windows XP version 5.1 running on x86; Cp1252; nl_BE

Please try making a test case for this issue, while doing it you’ll probably find out whats going wrong.

As a stab in the dark, please try making sure your beta is updated to the latest stable release. I fixed some things with how AppStates are managed that may come into play here. Actually, I’m 90% sure of it as some things are now clicking in my memory.



Update to the latest stable and see if that fixes your problems.