Question about Scene graph is not properly updated for rendering error with multiple ViewPort

Hi everyone, I’m trying to have a custom camera and viewport for render the item in the hands of the player, so i create a new camera and a viewport in simpleInitApp.

        Camera fpsCam = new Camera(settings.getWidth(), settings.getHeight());
        Node fpsRoot=new Node("FPSRoot");
        ViewPort fpsView= renderManager.createPreView("FPSView",fpsCam);
        Node fpsCamNode = new CameraNode("fpsCamera",fpsCam);
        fpsRoot.attachChild(fpsCamNode);
        fpsView.attachScene(fpsRoot);

But with only this code i get this error:

Uncaught exception thrown in Thread[#21,jME3 Main,5,main]
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: FPSRoot

Now, the solution i founded is to add:

        fpsRoot.updateLogicalState(tpf);
        fpsRoot.updateGeometricState();

to the simpleUpdate function.

Why this? I’m doing this in the correct way? There is a better way to do that?
Also the SDK tell me about the 2 line in simpleUpdate that:
updating is not needed in JM3, check your update order if you need to call this

What I do in my game is to add the secondary root to the main scene graph under a node that’s hidden with the cull hint.
Something like this:

Node hiddenNode = new Node("hidden");
rootNode.attachChild(rootNode);
hiddenNode.setCullHint(CullHint.Always);

Node fpsRoot = new Node("FPSRoot");
hiddenNode.attachChild(fpsRoot);

This worked well for me so far although it felt a bit strange when I did it so it might not be completely correct. :man_shrugging:

When you create a viewport with its own root that is separate from the regular scene graph, you have to manage that root. You don’t get the automatic handling the JME provides for the main viewport. (JME can’t possibly know when the best time to update that secondary viewport’s root is.)

There used to be a sample ViewportState or ViewportAppState that ran around on the forums but I think if you search for it now you might only find references to it… and not the actual thread.

Best advice: create an AppState (BaseAppState subclass). In initialize() create your viewport and set it up. In cleanup(), clean it up.

Then have something like:

    @Override
    public void update( float tpf ) {
        if( vpRoot != null ) {
            vpRoot.updateLogicalState(tpf);
        }
    }
    
    @Override
    public void render( RenderManager rm ) {
        if( vpRoot != null ) {
            vpRoot.updateGeometricState();
        }
    }

Then attach that app state. This will play happiest with the rest of JME.

6 Likes

Yeah, that worked!!! Thank you!

1 Like