Remove a node from the rootNode causes Array IndexOutOfBoundsException in jme3

Hi all,

I’ve been playing with jme3 for a little while now, and found an issue where I was trying to remove a node from the rootNode from within the node’s update method. mostly it worked, but in one particular instance it always caused jme3 to throw an index out of bounds exception inside Node.updateLogicalState.

Am I doing something wrong? I thought this would be the proper place to do such things.

At any rate I ended up modifying the updateLogicalState code a tiny bit to overcome the issue, changed to this: (should I have done something else?). its not ideal because it doesn’t know what it has and hasn’t run, it just stops processing and ends if a child is removed.

what should I be doing instead?



@Override

public void updateLogicalState(float tpf){

super.updateLogicalState(tpf);

for (int i = 0, cSize = children.size(); i < cSize; i++) {

Spatial child = children.get(i);

child.updateLogicalState(tpf);

cSize = children.size(); //Added this line so that removed nodes don’t cause IndexOutOfBoundsExceptions

}

}





Cheers

Jason.

Just do not override updateGeometricState() Use a Control to modify the Spatial.

Thats what he’s doing, except that when you remove a spatial from a control.update() call you’re screwing up the above mentioned loop.

indeed, I am using control to modify the spatial.

I usually just add any object to be removed to a ‘to-be-removed’ list then in the simpleUpdate loop, remove anything in that list. It’s not really clean, and was just how my app was structured that it worked out okay.

Fixed in SVN

Please reconsider way of fixing it. In proposed solution (which just got into SVN), you are skipping one node on removal. Assuming children A,B,C, if node A will remove itself during update, node B will be skipped (as it will jump to index 0, previously occupied by A and already processed) and C will be processed afterwards.

How about inserting a flag for removal on Spatial

and remove it at the end of updateGeometricState()

I don’t think adding an extra variable to Spatial is a good idea, removal of spatials should be transparent.

Instead of iterating a “live” arraylist with all children, we can create a temp copy and iterate that instead.

could u just enforce the use of the application.enqueue mechanism (or something similar) for all such modifications? it would be consistent, and would allow you to properly control things from within the enqueue implementation. just an aside, but isn’t this project big enough to warrant a few unit tests? I’m really surprised there aren’t any.



Cheers

I’m experiencing this same frustrating issue. The offending loop is:



[java]

for (int i = 0, cSize = children.size(); i < cSize; i++) {

Spatial child = children.get(i);

child.updateLogicalState(tpf);

}

[/java]



I am also updating the rootNode from a Control. Considering any Node’s children can detached/attached during a Control’s update loop, would the correct way to implement the above loop be this?



[java]

int cSize = children.size();

for (int i = 0; i < cSize; i++) {

Spatial child = children.get(i);

child.updateLogicalState(tpf);

cSize = children.size();

}

[/java]



Also, I should mention, that my Control is detaching a child via the detachChild(Spatial) method.



I’m eager to find a real fix for this, rather than implement some sort of hack to work around the issue.



Thanks in advance.

@Pandaemonium

Do you have the latest from SVN? I think the issue might have been resolved recently. If not, I’m a liar and I am thinking of another fix that was done :slight_smile:

You should never have to call updateXXX on any Spatial and if you do you will most probably produce errors. If you call this from the OpenGL thread there should be no problems when you remove the updateLogicalState() calls.

Edit: sorry, thought that was external code there.

I’m using jMP and I believe I have it set to use the latest version of jme3.



Product Version: jMonkeyPlatform Alpha-2

Java: 1.6.0_21; Java HotSpot™ Server VM 17.0-b17

System: Windows 7 version 6.1 running on x86; Cp1252; en_US (jmonkeyplatform)



in the above, I was thinking maybe this would just be sufficient (unless I really am using an older version of jme3 somehow):



[java]

for (int i = 0; i < children.size(); i++) {

[/java]

Son of a…



My setting in jMP to use nightly build of jme3 was unchecked. Doh! I’ll update my version of jme3 and try again. Thanks all.

unless you have the version from SVN you won’t have the fix. I just checked and it is in there. I also just noticed above in this message list that Kirill said he fixed it. The fix went in on Dec 31st, and you will see it in Alpha 3.

But if you want it sooner, you can grab the nightly build: http://www.jmonkeyengine.com/nightly/jME3_12-31-2010.zip



hmm, looking at the nightlies, it seems they have stopped just before the new year… I hope the fix is in that one. And I should see why the nightlies aren’t running any more.

Actually the new nightlies are at the top of the list. So you should be able to grab the latest there.

I can now detach nodes correctly from the update() of my Control, after updating my jme3 version.



Thanks.