Refreshflag updateGeometricState regression

Hi,

in the current git there is a small but kinda funny bug.

Situation, create a detached node and ensure it has refreshflag != 0, in my example a BatchNode with a few blocks in it.
Have a rootnode with refreshflag == 0.
Now when attaching this child the rootnode never gets the refreshflag set to != 0.
-> This leads to updateGeometricState to skip the child, resulting in a render crash due to “Scene graph is not properly updated for rendering”

This did not happen with my last git state, so I kinda assume it is due to the latest changes in the non anymore traversing of the full scenegraph.
-> Solution is probably that the updateGeometric state takes the invalidateList into consideration, and does a full traversal for added subgraphs.

To me, I think the solution is that when a child spatial is attached then it’s flags need to be propagated up. Otherwise, I guess it would happen if some already existing child graph is added deeper in the graph, too.

…though maybe it’s already specific to root node. I haven’t actually looked at the updateGeometricState() changes in detail.

I couldn’t reproduce this on the master branch in git.

Here’s the test case created from your description:

package jme3test.scene;

import com.jme3.app.SimpleApplication;
import com.jme3.light.AmbientLight;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.Spatial;

public class TestSpatialAttach extends SimpleApplication {

    private float time = 0;
    private boolean attached = false;
    
    public static void main(String[] args) {
        TestSpatialAttach app = new TestSpatialAttach();
        app.start();
    }
    
    @Override
    public void simpleUpdate(float tpf) {
        time += tpf;
        if (time > 5 && !attached) {
            attached = true;
            Spatial model = assetManager.loadModel("Models/Boat/boat.j3o");
            model.move(0, -1, 0);
            AmbientLight al = new AmbientLight();
            model.addLight(al);
            rootNode.attachChild(model);
        }
    }
    
    @Override
    public void simpleInitApp() {
        flyCam.setDragToRotate(true);
        cam.setLocation(new Vector3f(3.4152093f, 3.6787324f, 7.3039007f));
        cam.setRotation(new Quaternion(-0.0619338f, 0.937637f, -0.2560712f, -0.22677873f));
    }
    
}

Theres a similar issue in the SDK at the moment, adding anything via the “Add Spatial” menu will cause the “not updated” exception. So something is funny there.

I know i have a simple workaround in place in my code, but I cannot find the part that was affected anymore.
I know that a Batchnode was involved, but I’m not sure if it is important to trigger the issue.
when you do the model.move it should make model to refreshflag != 0 wich should be the root cause of the problem, as far as I had identified it.
I’m pretty sure that I did not directly attach to the rootnode, but to another Node somewhere a bit down in the Hierachy.

public int attachChildAt(Spatial child, int index) {
if (child == null)
throw new NullPointerException();

    if (child.getParent() != this && child != this) {
        if (child.getParent() != null) {
            child.getParent().detachChild(child);
        }
        child.setParent(this);
        children.add(index, child);
        // XXX: Not entirely correct? Forces bound update up the
        // tree stemming from the attached child. Also forces
        // transform update down the tree-
        child.setTransformRefresh();
        child.setLightListRefresh();
        if (logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE,"Child ({0}) attached to this node ({1})",
                    new Object[]{child.getName(), getName()});
        }
        invalidateUpdateList();
    }

Looking at that method, I however still think, that the childs refresh is set. However nowhere the parent is also set to refresh. In combination with the non full traversal, a parent without refresh will never refresh the childs.
Interestngly invalidateUpdateList() does this recursively for the parents, so if the loaded model does contain any controll, stuff might just work out fine.

The TestDirectionalLightShadows has the issue.
If you press x it’s supposed to deactivate the shadowRenderer debug mode and removes some Pictures from the GUI node.
Was working fine before, now it crashes with that error.

I ran TestDirectionalLightShadow.
Press X, this added the frustum wireframe into the scene. I then pressed space which removed the pictures from the GUI node, pressed space a few more time to put the pictures back in. No crashes, everything seems to work.
Will try the SDK and report back.