Geometry in one viewport but not in another [Closed]

Hey guys!
Just to introduce myself, I have a little experience in JME, but I have never created an account on the forum.
One question I have is whether it is possible to have spatials in one Viewport but not in another?
For example, the viewport of camera 1 has geometries that are not in the viewport of camera 2 and vice versa.

Each viewport can have its own scene graph. So, yes.

If you mean that you want two viewports to be viewing the same scene but somehow filtering some geometry out of one, then no. You would have to construct two separate scene graphs for that.

2 Likes

Each viewPort can have its own scene graph, but always connected to the rootNode, right?
Because when I run this code:

        Geometry geo = new Geometry("Geo", new Box(1, 1, 1));
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.setColor("Color", ColorRGBA.Blue);
        geo.setMaterial(mat);
        
        
        Node rootNode2 = new Node("RootNode2");
        rootNode2.attachChild(geo);
        //rootNode.attachChild(rootNode2);
        
        Camera cam2 = cam.clone();
        cam2.setViewPort(0.5f, 1f, 0f, 1f);
        ViewPort view2 = getRenderManager().createMainView("View2", cam2);
        view2.setEnabled(true);
        view2.setClearFlags(true, true, true);
        view2.attachScene(rootNode2);
        view2.setBackgroundColor(ColorRGBA.Orange);

With the commented line, the following error appears:
Uncaught exception thrown in Thread[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: RootNode2

But with the line uncommented (the rootNode2 is attached to the rootNode), it runs normally.

can you see from the link:

Main.java
MiniMapState.java

where MiniMapState use rootNode in Main. So its very similar what you want to do.

And my guess is you want do something like Minimap here.

1 Like

Thank you for the link!
I realized that I no longer need to have two separate scene graphs.
But I thought that if it is necessary that the spatial parameter in method attachScene in the ViewPort class needs to be attached to the root node, then it would be interesting to put this in the documentation to help new users.

No, scene graph in the separate viewport shouldn’t be a child of the rootNode, it needs to be completely separate. This also means it doesn’t benefit from the automatic updating the engine does on rootNode, so you’ll need to call the update functions on your separate root node manually.

1 Like

Well, so I don’t know, maybe it’s a bug? Because in the few tests I did on this, it only worked if the spatial of the other viewPort was connected to the root node.

Nope, myself i use ViewPort to render own GUI in separate view, and it use separate Node for this.

probably you just miss what Grizeldi said

    viewPort.addProcessor(new SceneProcessor() {
        @Override
        public void initialize(RenderManager rm, ViewPort vp) {

        }

        @Override
        public void reshape(ViewPort vp, int i, int i1) {

        }

        @Override
        public boolean isInitialized() {
            return true;
        }

        @Override
        public void preFrame(float f) {
            separatedOwnRootNode.updateLogicalState(f); //you need this
            separatedOwnRootNode.updateGeometricState();  //and this for other things
        }

To explain further. Scene Graph Spatials are updated each frame, and each frame have stages.

For example you cant just add Geometry into Scene Graph from another Thread without: app.enqueue(() -> {

Here, when you do not call update lines for your SceneProcessor, it just think it was not proper stage for update and think you tried to incorrectly edit scene graph while draw stage/etc is not done.

Just remember when you will do multi-thread, that all you need to do is editing Scene Graph via app.enqueue() that sync code inside with main thread (so for example you load model in other thread, but attach loaded model into scene graph in app.enqueue from this thread to sync with game thread)


Minimap code i gave you, is exception for this case, because it already use same rootNode, not separated one. So all you need really is update logic for your own separated rootNode for your viewport.

2 Likes

Now I get it! It makes a lot of sense now!
It is necessary to update the logical (and geometric) state of the node, as this will not be done automatically as it is not attached to the root node. Thank you all for your help!
Can I mark the topic as resolved?

And if you manage your own viewport, there are good times and bad times to do those two update calls.

Here is an example that does it in the friendliest way:

There used to be a general example of a ViewportAppState running around on the forum but now I think if you search for you will just find 50 posts where I recommend someone find that post on the forum. So not necessarily helpful.

1 Like

I do it in the SimpleApplication in the “simpleUpdate” method.

I use the simpleUpdate to handle all my off screen buffers for guis and then my 2 main 3d and 2d gui frame buffers.

Just have to be very careful of controls and other things that might synchronize things across scene graphs.

…always best to call updateGeometricState() as late as possible and updateLogicalState() in a control-predictable way.

And lumping things into SimpleApplication is already not the best practice. But I guess it’s fine for games without main menus, loading screens, etc…

An AppState can be more reusable and easier to manage.

Sure, no need ask ofc.

If you will be interested how exactly it is done for your main thread it is here in SimpleApplication that you extend. Link here: rootNode.updateLogicalState(tpf);

1 Like

I do it this way because the entire game no matter where you are is using the off screen buffers. I do this because JME limits you to control the openGL scene size. You can only control the window size not the OpenGL graph size.

I do have tons of loading screen, menus and such…

You have control over projection but not over viewport (ortho). This is controlled by the engine and you are forced to a certain dimension.

In my own engine I used viewport to control the dimension so I control the 8-bit pixel style pixel in the game and control viewport ratio. When I don’t want the entire game to be viewport. I have several games where the viewport is a vertical style, so black bars on the side, and others where the viewport is small, and gui goes around it. It fit the 80s style format.

So in that case, every appstate uses that. So I could use another appstate to control it but it works out for me. I’ve never had issues with it yet. I’ve used it in 5 games so far.

Thanks for the alternatives.

3 Likes