Multiple Viewports - managing node visibility

Hi guys,

I have multiple AWT panels, each with its own viewport. I attached the app’s root node onto each viewport so that they both see the same scene. Good so far…Next, I would like to be able to make certain nodes visible or invisible for each viewport. For example, I might have a nodeX whose parent is rootNode. Both viewports see nodeX since its parent is rootNode. With the press of a button, I want to toggle nodeX visibility for one viewport and not the other? I have tried different things like trying to call viewport.detachScene(nodeX) but nothing happens. Any suggestions on how can I achieve this? Thanks!!

Viewports don’t work that way. The render from their root node down no matter what.

Not really sure how best to achieve what you want to do but this isn’t the way. You may have to keep separate scene graphs.

Thanks. That’s good to know. What about guiNodes? Can I have multiple guiNodes? (one for each viewport?)

You can have as many nodes in as many viewports as you want… no matter what the type of node or viewport.

What you can’t have is a scene graph that is rendered only partially in one viewport and not another… no matter which root node or which viewport.

So, yes, you can have X number of Viewports with X number of different guiNodes. If any of those viewports share a guiNode then they will render all of the children of that guiNode. (A guiNode is not special, by the way… it’s just a plain old node with the queue bucket set to Gui.)

In this online game I play (Lord of the Rings Online) they have ‘local’ scene graphs where one person will some and NPC and another will not. JME doesn’t do that. (Like pspeed said.)

But in that case, I suspect “local” is on your machine… and then JME does do that since it’s up to you how you build your local scene graph from game objects on the server.

Spatials != game objects.

Create a node for each viewport, have both of these act in the same manner and attach to rootnode. When you want to make a node invisible for one, you detach it from the viewport where you dont want to see it?

It would imply that the things you want ot render in both are there twice, but maybe that’s ok ?

Just a suggestion

It looks like this is the way to go. Rendering twice should be fine. Unless I am cluttering the scenegraphs too much it should be fine performance-wise. It seems like it will be a little tricky to update both viewport root nodes.

So far I am thinking the following:

  • Clone the guiNode and attach one copy to each viewport. Therefore each viewport has its own guiNode
  • Attach a local rootNode to each viewport whose parent is the main root node. When the App is created and the world scene is generated each rootNode gets the same copy. Then comes the tricky part. While the app is running, if I decide to add or remove nodes from the world I will have to manage each viewport’s scenegraph by adding/removing depending on whether I want that viewport to see it or not.

I just thought that perhaps there was a way to tell the viewport not to render a specific node. This way it would be so much simpler and higher performance since I only need to maintain a single scenegraph…

Maybe there is a way to get a “hook” into “before culling and rendering” and “after rendering”.
Then you could make those visible/invisible shortly before or after the rendering takes place.
You would have to maintain a collection of the things that should be toggled and their default value of visibility.
Maybe just make a new Node class for that (“ViewportVisibilityNode” or something like that).
That Node would know for which viewport it shall be visible and for which viewport it should use default visibility.
Note that “default visibility” could use the regular system that is built into jME Spatials.
Not sure if that would work since I did not try to do this.

I think I might have found a solution. I am still testing the idea, but the initial tests look good so far. Basically, I modified RenderManager.renderSubScene(Spatial scene, ViewPort vp). I added a list of invisible nodes. When RenderManager.renderSubScene() is called it will go through this list and ignore the rendering process for the items in the list taking into account which viewport was selected. This results in these items not being rendered in the selected viewport.

The test I made:

Two viewports sharing the same scenegraph:
rootNode ← mainNode <–Geometry1 ← testNode ← Geometry2

I rotate mainNode every tick and testNode, being its child, rotates with it. If the list is empty both geometries show up in the viewport. If I add a Geometry1 to the list, it is no longer rendered to the selected viewport, but Geometry2 does show up rotating the exact same way as before because scenegraph is not affected.

This solution involves modifying the source code for Jme3, which is fine for me, however I need to generate a JAR out of this modified source. I use Eclipse and I imported the Jme3 source using gradle (I know very little about gradle):

How can I generate a new Jme3 jar with this changes that I can use in other projects? Any help would be greatly appreciated!!

gradlew dist

Got it working. Thanks!!