Attaching Geometries to guiNode in a class that implements SceneProcessor

I am trying to attach all of the geometries that I am generating in preFrame to a guiNode. (This seems to work so far) When I try to detach these geometries in postFrame, the program tends to crash. Is there a specific order for updatingGeometricState and detaching or where should these be placed?

I figured attaching all of the geometries to a single node might fix it but it has not.

Yes. Use a node. Take a look at the scenegraph for dummies link in the header above.

Node stuff = new Node("stuff i want grouped together");
stuff.attachChild(geom1);
stuff.attachChild(geom2);

guiNode.attachChild(stuff);

Yes, that’s what Nodes are for… attach your geometries to a node and attach that node to the GUI node.

Okay, that is what I assumed but I’m trying to do this on a separate thread and I am encountering null pointer exceptions. Is the guiNode my only method of attaching geometries to the screen or are there any other alternatives?

You can never modify the scenegraph from any thread except the render thread. If you have code in another thread that needs to alter the scenegraph, you must use app.enqueue().

No. The guiNode it a 2D scene. Much like html/css whereby the Z plane is the front-to-back order. The rootNode is your 3D scene. Usually the gui node is used for the gui (menu, hud, etc) and your game goes in the 3D scene rootNode.

Anyway. You can’t modify the scene from a seperate thread, but you can load or generate meshes from a seperate thread; e.g. using callables and futures.

Id have to see the code and stacktrace to find out why you got that exception, though, because the two are not related.

It could help to see a stack trace if yo have a crash.

So in the sceneprocessor preframe I create a Node for the collection of bounding boxes and attach the bounding box geometries to the node. The node is then attached to the guiNode. In postFrame, I detach the BoundingBox Node from the guiNode.

In preFrame:
BBNode = new Node(“BBCollection”);
for (int i = 0; i < numPed; i ++)
{

		    Geometry PDBox = new Geometry("PDBox_" + i, new WireBox(w/2,h/2,0));
			PDBox.setMaterial(matPDBox);
			BBNode.attachChild(PDBox);
			BBNode.getChild("PDBox_" + i).setLocalTranslation(100,100,0);
			BBNode.updateGeometricState();
		}
		guiNode.attachChild(BBNode);
	}

In postFrame:
guiNode.detachChild(BBNode);

In Trace:
Apr 26, 2017 9:19:30 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
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: Gui Node
at com.jme3.scene.Spatial.checkCulling(Spatial.java:354)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:669)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:662)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1019)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1086)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:260)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:152)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:192)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:233)
at java.lang.Thread.run(Unknown Source)

To fix this you have to use app.enqueue as said before. I guess there is an article about multithreading in the wiki where you can read about the enqueue function. Most likely your NPEs will be fixed too then.

Don’t forget to read the post about inserting code blocks in the forum :wink:

Edit: Why do you want to attach and detach the objects in pre and postFrame? What do you want to achieve?

I’m asking because you usually do this in the update method and when using enqueue the node will be attached in the next update call and not be available in that frame.

Thanks for your response,

I need the bounding boxes to appear on the same frame as what is being rendered to the screen. That is why i figured I would attach the Bounding Boxes in preFrame. The boundingBoxes are continuously being updated (there may be more bounding boxes in the next frame than there were in the previous and sizes are varying) which is why I need to detach them “postFrame” so to speak. Would enqueue allow me to do this?

postFrame() is too late because the scene is now prepared for rendering and you can’t modify it without updating its geometric state again… ie: doing double the work every frame.

What are you actually trying to do? It sounds pretty convoluted and may not need to be that way.

Hi pspeed,

I am trying to intercept a frame that is being rendered, draw some bounding boxes to it depending on data from processing (this needs to be on a separate thread) and then display this on the screen without delay.

Don’t add the boxes to the scene. Just draw them directly.

What do you mean by this? I create the geometry for the bounding boxes and then attach them to the guiNode, is there any other way of “drawing them directly”

This is how I understand your problem. Correct me if I’m wrong:

You have a scene. Then you want to calculate bounding boxes for this scene based on some cool algorithm you know and display them. The calculation should happen in a different thread.

My first question is: why do you need a different thread?

I assume it does not take much time to calculate the bounding boxes: you can easily do this in the update method of the render thread.

If it does need much time you have a problem because the bounding boxes will be outdated when you render them.

My second question: why do you need the preFrame method? - just do it as the last task in the update method.

Correct me if I understand your question wrong.

Hi, it actually is a quite lengthy process and it is hitting less than 10 fps which is why I wanted to do it on a separate thread. That is actually one of the constraints that I have, which is why i can’t do it in the update method.

If your bounding box calculation drops your framerate to 10 fps, even using an additional thread you will probably not be able to do much better than that if you need the boxes to be drawn with each frame, unless your fps was already very low to start with (and CPU bound).

Do you need to recompute all bounding boxes with each frame? Is there anything to stop you from calculating only the bounding boxes of things that have changed in the last frame? If you do this you may (depending on your specific requirements) be able to just attach wireframe boxes in the scene, which would be a lot more straightforward than what you’re doing now (and extremely fast to render).

If you want to render a piece of geometry separately, just call:
renderManager.renderGeometry(someGeom);

You can see an example of where I build a mesh of boxes and render them directly here:

Each drop shadow is a rectangular prism the same size/orientation as the object’s bounding box but dropped down below it. The drop-shadow part is a shader trick that renders a shadowed egg inside the volume of the box.

1 Like

Just as a hint: You could also use the bounding box by jME and not calculate it by your own. Maybe it’s faster.

Otherwise you could do something like this:
You have two nodes: One contains the scene and the other the last calculated bounding boxes. Be aware that these bounding boxes could be multiple frames older than the scene due to your complex calculations. If this is not acceptable for you your only chance is to make the calculations faster.

In the update method you do this:

if calctask is finished
  clear bounding box node
  attach new bounding boxes calculated by the finished calctask
  collect new information about the scene
  create new calctask with the information
  run this new task in a different thread

As you see the new bounding boxes are set in the update method after your task has finished. This way it won’t break.

https://jmonkeyengine.github.io/wiki/jme3/advanced/multithreading.html