Unusual behavior when creating multiple viewports

I’ve been playing around with adding multiple viewports for use in a strategy game to control rendering more directly. But my problem is that when I create the nodes for these new viewports and do not attach them to the rootNode from SimpleApplication and then try to manipulate spatials attached to these new nodes from my update loop without enqueing, JME throws an error “Scene graph is not properly updated for rendering”. This never happened before until I’ve tried creating these new nodes and viewports. Could this be a bug or perhaps am I not setting something up correctly? It seems pretty straight forward, as SimpleApplication doesn’t seem to be doing anything special when it creates the rootNode, but I can’t for the life of me figure out what’s different.

In the past, I’ve just done rotations and translations directly from my update loop without issue.

The pertinent code (as simple as it is) is as follows:

[java]

private Node newRootNode;
private Node newObjectsNode;

public void simpleInitApp() {

newRootNode = new Node("Base Node");
newObjectsNode = new Node("Top Node");
	
ViewPort rootViewport = renderManager.createMainView("Base Viewport", cam);
rootViewport.attachScene(newRootNode);

ViewPort topViewport = renderManager.createPostView("Top Viewport", cam);
topViewport.setClearDepth(true);
topViewport.attachScene(newObjectsNode);

}

public void simpleUpdate(float tpf) {
newRootNode.updateLogicalState(tpf);
newObjectsNode.updateLogicalState(tpf);

newRootNode.updateGeometricState();
newObjectsNode.updateGeometricState();

}
[/java]

Then when I call say setLocalTranslation on a Node attached to newObjectsNode from my update loop, the error is thrown.

If I add: rootNode.attachChild(newObjectsNode) in simpleInitApp, then the issue goes away, but does not provide what I want in the view port (a totally detached scene).

Many thanks for any ideas you might have.

when and where do you call the setLocalTranslation?

Extending nehon’s question…

The update loop goes as follows:

  1. run queued tasks
  2. collect input
  3. tickle audio
  4. AppState[].update()
  5. run simpleUpdate()
  6. rootNode, guiNode updateLogicalState ie: run controls
  7. rootNode, guiNode updateGeometricState
  8. AppState[].render()
  9. renderManager.render()
  10. run simpleRender()
  11. AppState[].postRender()

Chances are, you really want to be managing your viewports with an AppState and you really want to be updating the logical and geometric states of its root node in the AppState.render() method.

As you have it, if a control moves the spatial then you will get the error you have.

@nehon said: when and where do you call the setLocalTranslation?

I’m just doing it in simpleUpdate.

@Slowdive said: I'm just doing it in simpleUpdate.
After calling the updateGeometricState? if that's the case, the update of the scene graph must occur after any modification to the scene graph. Move the setLocalXXX before the update of the nodes and it should work.
@pspeed said: Extending nehon's question...

Chances are, you really want to be managing your viewports with an AppState and you really want to be updating the logical and geometric states of its root node in the AppState.render() method.

As you have it, if a control moves the spatial then you will get the error you have.

Understood. But it seems odd that this is not the case for the default viewport. Why is that?

Also, would you guess that if I manipulated a child of the new viewport’s rootNode, but not the rootnode itself, that I’d still get the error? (I will check it, but I suspect the answer is ‘yes’)

Lastly, it seems odd that code to determine, say how far a unit should move during a tick, should be included in the render method. I thought logically that sort of thing should be kept in the update loop?

Thanks for your input!

@nehon said: After calling the updateGeometricState? if that's the case, the update of the scene graph must occur after any modification to the scene graph. Move the setLocalXXX before the update of the nodes and it should work.

Yes I believe after updateGeometricState. I’ll confirm and give your suggestion a try. Thank you!

Ok, just to be sure you understand what’s going on :
When you go setLocalXXX on a spatial, you set the transforms of the geometry relative to its parent Node. When you do this there is an internal transform flag set saying “this spatial has been transformed”.
The engine needs the transforms of the spatial in world space to properly render it, and that’s what updateGeometricState() computes along with resetting the transform flag.
If you transform the spatial between the updateGeometricState and the render, the position of the spatial is invalid when you render it.
That’s why the engine raises the error.

1 Like

You were spot on. I guess I threw in those calls to updateGeometricState in my simple update method before I updated all my game objects. I was just trying to replicate what was happening on the rootNode in simpleApplication update method and didn’t think about the repercussion of my placement.

You guys are awesome.

Thanks again.