[SOLVED] Problems when modifying the scene from another thread

Hi , i was getting a problem while modifying my scene from another thread :

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: Root Node
	at com.jme3.scene.Spatial.checkCulling(Spatial.java:361)
	at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:717)
	at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:710)
	at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1096)
	at com.jme3.renderer.RenderManager.render(RenderManager.java:1158)
	at com.jme3.app.SimpleApplication.update(SimpleApplication.java:272)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:153)
	at com.jme3.system.lwjgl.LwjglCanvas.runLoop(LwjglCanvas.java:229)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:234)
	at java.base/java.lang.Thread.run(Thread.java:834)

code:


package Store;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.bullet.BulletAppState;
import com.jme3.input.ChaseCamera;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.LightScatteringFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

/**
 *
 * @author twisted
 */
public class VehicleSelectorStage extends SimpleApplication {
    private BulletAppState bulletAppState;
    private Node vehicle;
    private String selectedSpaceShip;
    
    /**
     * create a new Instance of stage view
     * @param selectedSpaceShip default spaceship
     */
    public VehicleSelectorStage(String selectedSpaceShip){
        this.selectedSpaceShip=selectedSpaceShip;
    }
    
    
    // this part here .............................................................................................
    /** change the vehicle view on the stage
     * @param selectedSpaceShip vehicle directory
     */
    public void changeVehicle(String selectedSpaceShip) {
      try{
           Thread.sleep(150);
           vehicle=(Node) rootNode.getChild("Vehicle");
           vehicle.detachAllChildren();
           vehicle.attachChild(assetManager.loadModel(selectedSpaceShip));
      }catch(InterruptedException e){
          System.err.println(e.getMessage());
      }
    }
    @Override
    public void simpleInitApp() {
        /**
         * Attach physcis state
         */
        bulletAppState=new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.setDebugEnabled(false);
        /**
         * Light up the world
         */
        rootNode.addLight(new AmbientLight(ColorRGBA.White));  

        /**
         * load the stage scene & the stage Vehicles
         */
        rootNode.attachChild(assetManager.loadModel("Scenes/Vehicle Selector Stage/VehicleSelectorStage.j3o"));
        vehicle=(Node) rootNode.getChild("Vehicle");
        vehicle.detachAllChildren();
        vehicle.attachChild(assetManager.loadModel(selectedSpaceShip));
        /**
         * Setting up the camera
         */
        ChaseCamera vehicleStageCamera=new ChaseCamera(cam, vehicle);
        vehicleStageCamera.setDefaultDistance(-20);
        vehicleStageCamera.setChasingSensitivity(0.05f);
        vehicleStageCamera.setSmoothMotion(true);
        
        vehicleStageCamera.registerWithInput(inputManager);
        vehicleStageCamera.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.AXIS_X));        
        /**
         * Set-up Stage Effects(FIlter effect)
         */
      
        FilterPostProcessor stagefilter=new FilterPostProcessor(assetManager);
        LightScatteringFilter stagelight = new LightScatteringFilter(rootNode.getChild("stage").getLocalTranslation());
        stagelight.setLightDensity(10f);
        stagefilter.addFilter(stagelight);
        viewPort.addProcessor(stagefilter); 
        
        DirectionalLight stageDirectLight = new DirectionalLight();
        stageDirectLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
        stageDirectLight.setColor(ColorRGBA.Blue);
        rootNode.addLight(stageDirectLight); 

        
    } 
    
}

& i am calling the changeVehicle(dirString) method from a button Listener inside a JFrame

1 Like

You can’t modify your scenegraph from another thread (swing runs on its own thread).
But you can call

yourApplication.enqueue(()->{
 changeVehicle(...)
}) 

to enqueue the action to your update loop

3 Likes

@RiccardoBlb thank you ! yeh to run the application from swing i start a new thread

Swing is always on its own thread… regardless of what you do.

Moral of the story: don’t update the scene graph from another thread. :slight_smile:

2 Likes