BatchNode Exception

I get this exception with a BatchNode:
[java]
java.lang.IndexOutOfBoundsException
at java.nio.Buffer.checkBounds(Buffer.java:535)
at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:229)
at com.jme3.scene.BatchNode.doTransforms(BatchNode.java:593)
at com.jme3.scene.BatchNode.updateSubBatch(BatchNode.java:163)
at com.jme3.scene.Geometry.updateWorldTransforms(Geometry.java:296)
at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:702)
at com.jme3.scene.BatchNode.updateGeometricState(BatchNode.java:120)
at com.jme3.scene.Node.updateGeometricState(Node.java:175)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:247)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:662)
[/java]
This happens only when I use its batch() method.
I looked around at the source, but all I got so far was well… something to do with indices being out of bounds and buffers :stuck_out_tongue:
Anyone got an idea why this happens?
P.S.: I just saw this, but what’s a “support request”?

I’ve had this trouble a while ago. But I was not able to reproduce it in a simple test-case.

Well i can reproduce it with certain models i try to batch, i assume that the might have an invalid index or similar.

Could one of you give me a test case with the problematic models?
There might be something wrong inddeed.

I will do when i’m home, however due to licenses (as it is bought) I can at max send it directly to you. Can you pm me your mail?

Well, I got something… Uh, I had mostly no idea what I was doing but here’s what I got:
In the doTransforms method in BatchNode, the line
[java]
bufPos.get(tmpFloat, 0, length);
[/java]
is involved in leading to the exception (see above, 4th line).
Buffer.checkBounds(…) (the 2nd line in the exception) uses bitwise operators. Unfortunately, I don’t really know bitwise operators, but I can guess what the method’s basically doing from it’s name.
tmpFloat.length is involved, so I guessed it was something having to do with it being too small or a negative index.
I checked tmpFloat.length immediately before the exception occurs, and saw that its length was 0. Now it made sense to me that it would throw an IndexOutOfBoundsException.
The integer variable maxVertCount is involved in determining tmpFloat’s length (maxVertCount * 3 or 4).
So that means maxVertCount would have to be 0 for tmpFloat.length to be 0.
As far as I saw, maxVertCount is initialized with 0 but is supposed to change in the method BatchNode.doBatch(), where maxVertCount is reset to 0, something happens to maxVertCount, and then in the same method tmpFloat is initialized with length maxVertCount * 3 or 4.
So I thought that maybe maxVertCount is set incorrectly?
The thing that changes maxVertCount’s value was in BatchNode.mergeGeometries(…) called within BatchNode.doBatch(). This is part of mergeGeometries(…)’ code that changes its value:
[java]
if (maxVertCount < geom.getVertexCount()) {
maxVertCount = geom.getVertexCount();
}
[/java]
Uuuuuuuuuuuuuuuhhhhhhhhhhhhhhhh… so yeah, that’s all I got so far. I might be all wrong, but I really do want to solve this, since my laptop can’t handle so many “objects”. :amused:

heheh you’re right, that’s the issue, the question is why maxVertcount is not properly initialized, something must be early exiting in the mergeGeometries method, something “unusual” with the buffers of the mesh i presume.
That’s why i need a test case and a failing model.

Oh oh oh I think I caught something!.. I was trying to create a test case by modifying TestBatchNodeTower and noticed that unlike my program, it uses batchNode.batch() only once during initialization. My program calls it whenever more objects are added to the node (that’s proper usage, right?) in simpleUpdate(…).
So, in TestBatchNodeTower, if I call batch() in simpleUpdate(…), a similar exception happened!
[java]
java.lang.IndexOutOfBoundsException
at java.nio.Buffer.checkBounds(Buffer.java:535)
at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:229)
at com.jme3.scene.MyBatchNode.doTransforms(MyBatchNode.java:609)
at com.jme3.scene.MyBatchNode.updateSubBatch(MyBatchNode.java:169)
at com.jme3.scene.Geometry.updateWorldTransforms(Geometry.java:296)
at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:702)
at com.jme3.scene.MyBatchNode.updateGeometricState(MyBatchNode.java:126)
at com.jme3.scene.MyBatchNode.batch(MyBatchNode.java:190)
at SurvivalGame.BatchNodeTest.simpleUpdate(BatchNodeTest.java:268)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:242)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:662)
[/java]
Which means at least for me, the exception may not be caused by weird models but by calling batch() in simpleUpdate(…).
Still don’t know a fix, though…

@seann999 said: Oh oh oh I think I caught something!... I was trying to create a test case by modifying TestBatchNodeTower and noticed that unlike my program, it uses batchNode.batch() only once during initialization. My program calls it whenever more objects are added to the node (that's proper usage, right?) in simpleUpdate(...). So, in TestBatchNodeTower, if I call batch() in simpleUpdate(...), a similar exception happened! [java] java.lang.IndexOutOfBoundsException at java.nio.Buffer.checkBounds(Buffer.java:535) at java.nio.DirectFloatBufferU.get(DirectFloatBufferU.java:229) at com.jme3.scene.MyBatchNode.doTransforms(MyBatchNode.java:609) at com.jme3.scene.MyBatchNode.updateSubBatch(MyBatchNode.java:169) at com.jme3.scene.Geometry.updateWorldTransforms(Geometry.java:296) at com.jme3.scene.Spatial.updateGeometricState(Spatial.java:702) at com.jme3.scene.MyBatchNode.updateGeometricState(MyBatchNode.java:126) at com.jme3.scene.MyBatchNode.batch(MyBatchNode.java:190) at SurvivalGame.BatchNodeTest.simpleUpdate(BatchNodeTest.java:268) at com.jme3.app.SimpleApplication.update(SimpleApplication.java:242) at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151) at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185) at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228) at java.lang.Thread.run(Thread.java:662) [/java] Which means at least for me, the exception may not be caused by weird models but by calling batch() in simpleUpdate(...). Still don't know a fix, though...
Ho cool nice find! Proper usage is to batch only once, once you have all the geometries added to the batch. But the other way should work without failing even if it's not the optimal way of doing it.

I’ll test that with the batched tower test thanks

Okay, I don’t know half of what I’m saying here, but I also found this:
As mentioned before, when doBatch() is called, maxVertCount is reset to 0. Then maxVertCount is supposed to become equal to the amount of vertices of the geometry with the highest amount in the BatchNode. The geometry with the highest amount of vertices is searched by going through Map matMap. matMap is filled up with method gatherGeomerties(Map map, Spatial n, boolean rebatch). However, in that method, if the spatial is a geometry, it has to pass this condition:
[java]
!g.isBatched() || rebatch
[/java]
to be entered into matMap.
I’m guessing that if the geometry has been previously batched and needsFullRebatch is false, the geometry will not pass. Which I think is what happened in my case for all geometries when I called batchNode.batch() in simpleUpdate(). Which means matMap will have a size of 0, without any geometries. Which means maxVertCount will not be changed from 0 since matMap is empty anyway. Which means tmpFloat will have length 0. Which triggers the IndexOutOfBoundsException.
This is a guess.
Uuuuuuuuuuuuuuuhhhhhhhhhhhhhhhh…. yes no maybe so?

yeah, that’s it. Actually I should remove this maxVertCount and just allocate the temp array on demand by chunks…
This temp array is here to speed up the buffer writing process (gives a good perf boost). maxVertCount is the number of vertex of the “biggest” geometry (the one with the higher number of vertice). It’s the maximum amount of vertices that will be moved during an update call at once.

Wow nice, btw did you receive the mail with the model (even tho it may not be necessary anymore now)?

@Empire Phoenix said: Wow nice, btw did you receive the mail with the model (even tho it may not be necessary anymore now)?
mhh nope I didn't Even checked my spam folder and nothing