GeometryBatchFactory IndexOutOfBoundsException

I’m creating a custom mesh. I used to add hundreds of Geometry into a node and then use GeometryBatchFactory.optimize(node), but I thought that that would be pretty inefficient since it would be dumping those hundreds of Geometry (since optimize() replaces them with a few geometries, right?). I didn’t seem to have any problems with that.

Now though, I’m trying to prepare all the data beforehand by storing vertex positions, normals, etc. in some ArrayLists, create one new mesh, convert the ArrayLists to Buffers and assigning corresponding ones to the mesh. But I get this:

[java]java.lang.IndexOutOfBoundsException

at java.nio.Buffer.checkIndex(Buffer.java:512)

at java.nio.DirectFloatBufferU.put(DirectFloatBufferU.java:270)

at jme3tools.optimize.GeometryBatchFactory.doTransformVerts(GeometryBatchFactory.java:38)

at jme3tools.optimize.GeometryBatchFactory.mergeGeometries(GeometryBatchFactory.java:210)

at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:324)

at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:375)

at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:359)

at SurvivalGame.SurvivalGame.optimizeChunk(SurvivalGame.java:245)

at SurvivalGame.SurvivalGame.replaceChunk(SurvivalGame.java:2116)

at SurvivalGame.SurvivalGame.updateThread(SurvivalGame.java:1025)

at SurvivalGame.SurvivalGame.access$100(SurvivalGame.java:59)

at SurvivalGame.SurvivalGame$1.run(SurvivalGame.java:228)[/java]

It seems like something’s wrong with the position buffer. Is there something I might have been doing incorrectly?

@seann999

Hmm the error does not really help at this point…indexOutOfBounds just means that the buffer is too small…like you created it with size 10 and tried to put 11 objects into it … but why exacly it occurs is dependent on your code and how you fill the buffers.



So check you arraylist sizes and buffer sizes.

@xeratos The exception occurs when I use the optimize(node) method. For applying the ArrayList to the buffer, I do this:

[java]

float[] posArray = new float[posArrayList.size() * 3];

int posIndex = 0;

Vector3f v;

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

v = posArrayList.get(i);

posArray[posIndex++] = v.getX();

posArray[posIndex++] = v.getY();

posArray[posIndex++] = v.getZ();

}



Mesh m = new Mesh();

m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(posArray));

//set other buffers (indices, texcoords, texcoords4 (for custom shader), normals)

//create new geometry with the mesh, set material

//attach geometry to node, which will later be optimized (which is when the exception is thrown)[/java]

1 Like
@seann999 said:
@xeratos The exception occurs when I use the optimize(node) method. For applying the ArrayList to the buffer, I do this:
[java]
float[] posArray = new float[posArrayList.size() * 3]; //edit arrayPos.size()
int posIndex = 0;
Vector3f v;
for (int i = 0; i < arrayPos.size(); i++) {
v = posArrayList.get(i);
posArray[posIndex++] = v.getX();
posArray[posIndex++] = v.getY();
posArray[posIndex++] = v.getZ();
}

Mesh m = new Mesh();
m.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(posArray));
//set other buffers (indices, texcoords, texcoords4 (for custom shader), normals)
//create new geometry with the mesh, set material
//attach geometry to node, which will later be optimized (which is when the exception is thrown)[/java]


its another array you get the size of

@xeratos Shoot shoot shoot, my bad. I changed variable names when posting here for readability; fixed the post.

1 Like

@seann999

ah sorry i accidently downrated the post SORRY didnt meant to. Can I redo that? --edit hehe i can just uprate the others pardon



hmm well ok so far the code looks good then…optimizing actually finds geometries with the same material and just merges them, afaik. and i dont think that it does optimization on the vertex count but i am not sure about that.



So it is hard to say what is going wrong. Do you use threads that maybe change the data while optimizing?

1 Like

Without having checked, issume its one of the following:

a) index does not mach some other buffer

b) maybe you are not setting texCoord/and normals, but they are required by optimieze()

@zzuegg said:
Without having checked, issume its one of the following:
a) index does not mach some other buffer
b) maybe you are not setting texCoord/and normals, but they are required by optimieze()


Guess it is rather 1 ... 2 I cannot confirm for me it is working without texCoord so far...didnt check normals.

@xeratos Hmm I do use multithreading. But my optimize method that uses GeometryBatchFactory.optimize(node) is synchronized, so I assume it’s okay… (I’m not too knowledgeable on multithreading)

@zzuegg I’ve debugged, it seems okay…

[java]GREATEST INDEX NUMBER: 3005

POSITION BUFFER SIZE (1 VERTEX = 1): (ORIGINAL ARRAYLIST VS. BUFFER (/3)) 3006 3006

INDEX BUFFER SIZE: 3006

TEXCOORD BUFFER SIZE (/2): 3006

TEXCOORD4 SIZE (/2): 3006

NORMAL SIZE (/3): 3006[/java]

This happens with every mesh loading, with the index number being one less than the size of the position buffer, which the sizes are the same for the other buffers.

Also, line 210 of GeometryBatchFactory (which is mentioned in the exception) looks like it deals with buffers with Type.Position.



When I build a “chunk” in my game, the bottom and right edge is omitted if data hasn’t been loaded there yet. Those edges need data from the adjacent chunk in order to load. The edge is loaded when the data is available, so (for example) when the right adjacent chunk is loaded, the right edge of the other chunk is loaded. I call it “stitching”. Anyway, when that happens, the chunk is optimized to combine the the main mesh and the stitch mesh. The weird thing is, everything seems to go fine with the main mesh. The problem occurs with stitching. Now that tells me that the problem is happening because of my fault, but I can’t find the problem-causer in my code. If I knew what kind of conditions causes the exception in GeometryBatchFactory (like as you said, the index doesn’t match a buffer), that would help.

The main chunk and the stitches are loaded almost the same exact way. Data for the mesh is initialized with the iteration (for loop) of the method “loadVoxel”, and that data is processed with “buildChunk” at the end.

With this problem, I get this:



The gaps are where the stitches are supposed to be.

Another unexpected thing that might help in finding the problem is that chunks flicker (appear and disappear) if I don’t attempt to optimize the chunk after loading stitches (combining the main mesh and the stitch mesh).

@seann999 said:
Hmm I do use multithreading. But my optimize method that uses GeometryBatchFactory.optimize(node) is synchronized, so I assume it's okay... (I'm not too knowledgeable on multithreading)


Hmm afaik that just means that not two threads optimize at the same time. But that not necessarily mean that there are changes made to the data elsewhere. Hard to know without knowing your structure. But lets say you have some threads that do the optimization stuff that is synched and you have some threads that reload data if necessary and add geometries to your node that is being optimized by a thread. Than the node suddenly has more geometries but the optimize method already allocated arrays and you get an index out of bounds.

I replaced newChunk = chunk.deepClone() to newChunk = chunk.clone(false) in my clone() method in my Chunk class. This seemed to solve most of the problem :confused: (I don’t know why). There’s occasionally some holes but that’s probably due to some logic in the code.