Grow vertex buffers

hello, vertex buffers have a set capacity defined when initialized, attempting to add more elements on them throws java.nio.BufferOverflowException. So here i try to “double” their size, to allow more elements. I want this for my sprite library.



i tried this with VertexBuffer.updateData(new buffer); but i get a black screen instead of my sprites.

i didn’t try VertexBuffer.setupData because it says not to use it again.



[java]

// Avoid java.nio.BufferOverflowException by resizing arrays.

private void ensureCapacity()

{

int minCapacity = sprites.size();

if (capacity >= minCapacity) return;

int newCapacity = MathUtilities.nextPowerOfTwo(minCapacity);



growBuffer(mesh, VertexBuffer.Type.Position, BufferUtils.createFloatBuffer(newCapacity3));

growBuffer(mesh, VertexBuffer.Type.Color, BufferUtils.createByteBuffer(newCapacity
4));

growBuffer(mesh, VertexBuffer.Type.Size, BufferUtils.createFloatBuffer(newCapacity));

growBuffer(mesh, VertexBuffer.Type.TexCoord, BufferUtils.createFloatBuffer(newCapacity*4));

}



private void growBuffer(Mesh mesh, VertexBuffer.Type type, Buffer data)

{

VertexBuffer vb = mesh.getBuffer(type);

vb.updateData(data);

}

[/java]

It must be a bug with VertexBuffer.updateData(), in javadoc it says that “It is allowed to specify a buffer with different capacity than the originally set buffer”.

Initial capacity : 100 sprites.

i add 30000 sprites, new capacity after grow : 32768

my screen displays 100 sprites only, instead of 30000.

I manually checked the vertex buffer contents and all contain “30000” sprites in the correct format.



[java]

// Avoid java.nio.BufferOverflowException by resizing arrays.

private void ensureCapacity()

{

int minCapacity = sprites.size();

if (capacity >= minCapacity) return;

int newCapacity = MathUtilities.nextPowerOfTwo(minCapacity);



updatePositions(BufferUtils.createFloatBuffer(newCapacity * 3));

}



private void updatePositions(FloatBuffer assignNewBuffer)

{

if (positionBufferChanged)

{

VertexBuffer pvb = mesh.getBuffer(VertexBuffer.Type.Position);

FloatBuffer positions ;

if (assignNewBuffer != null) positions = assignNewBuffer;

else positions = (FloatBuffer) pvb.getData();



positions.rewind();

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

{

Vector3f position = sprites.get(i).getPosition();

positions.put(position.x).put(position.y).put(position.z);

}

positions.flip();

pvb.updateData(positions);

}

}

[/java]

If you change the amounts of vertices, are you sure your texture coordinates are still right? Normally you only need to call updateData(data) and the new mesh is set. Obviously you need to update all other buffers (texture coords, normals etc) as well if you do that.

yes i have updated all 4 buffers, i can create a project with the full code if u want.

hasDataSizeChanged() is returning true.

do i need to call another method for new size to be accepted ?

method clearUpdateNeeded() has no documentation so i haven’t used it.

i wrote many system.out.prints.

Initial capacity : 2,

i add 5 sprites.

however i see only 2 sprites on screen.



This means that the buffers have the correct contents, however for some reason the extra sprites aren’t displayed.



[java]

Position: java.nio.DirectFloatBufferU[pos=0 lim=15 cap=24]

0: (27.88871, 7.738037, 28.987694)

1: (3.9169521, 18.192883, 5.8638706)

2: (18.052681, 6.517552, 14.187362)

3: (16.053507, 11.270653, 11.449011)

4: (28.174007, 27.362461, 11.174634)

Color: java.nio.DirectByteBuffer[pos=0 lim=20 cap=32]

0: (-1, -1, -1, -1)

1: (-1, -1, -1, -1)

2: (-1, -1, -1, -1)

3: (-1, -1, -1, -1)

4: (-1, -1, -1, -1)

Size: java.nio.DirectFloatBufferU[pos=0 lim=5 cap=8]

0: (1.0)

1: (1.0)

2: (1.0)

3: (1.0)

4: (1.0)

TexCoord: java.nio.DirectFloatBufferU[pos=0 lim=20 cap=32]

0: (0.015625, 1.0, 0.032226562, 0.98535156)

1: (0.015625, 1.0, 0.032226562, 0.98535156)

2: (0.015625, 1.0, 0.032226562, 0.98535156)

3: (0.015625, 1.0, 0.032226562, 0.98535156)

4: (0.015625, 1.0, 0.032226562, 0.98535156)

[/java]

There is no error and your mesh looks different, so the buffer is updated. Again, check your own code.

pseudo-code of what happens :

VertexBuffer vertex = new VertexBuffer(type);

vertex.setupData(BufferWith2InitialCapacity);

mesh.setBuffer(vertex);



FloatBuffer bufferWith5Sprites = BufferUtils.createFloatBuffer(5 * 3);

bufferWith5Sprites.rewind();

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

{

Vector3f position = sprites.get(i).getPosition();

bufferWith5Sprites.put(position.x).put(position.y).put(position.z);

}

bufferWith5Sprites.flip();



vertex.updateData(bufferWith5Sprites);



jme: sorry i only accept the first 2 components of your bufferWith5Sprites, i wont send the next 3 to the gpu shader, bye.

I knew it !!! i am not crazy(maybe a little bit). It was a bug with jme.

As usual i solved it by trying every possible jme method combination for hours until i found the right one.

[java]

tvb.updateData(positions);

[/java]

Changed to :

[java]

mesh.clearBuffer(Type.Position);

pvb.updateData(positions);

mesh.setBuffer(pvb);

[/java]

Uh lol, yeah, you need to update the mesh too xD That has nothing to do with the vertex buffer ^^

1 Like