I’m currently working on creating a generator for quadrilateralized spheres and tried using the IndexBuffer
class. Unfortunately, it has some severe shortcomings I’d like to address.
The code I was working with in the beginning was as following:
//creating the buffer
ShortBuffer buffer = BufferUtils.createShortBuffer(indexCount);
// loops omitted for brevity
buffer.put((short) i0).put((short) (i1)).put((short) (i1 + 1));
buffer.put((short) (i0 + 1)).put((short) i0).put((short) (i1 + 1));
// setting the buffer
mesh.setBuffer(Type.Index, 3, buffer);
This obviously falls short if the number of vertices is greater than Short.MAX_VALUE
. In that case, an IntBuffer
would be appropriate. Behold, IndexBuffer
to the rescue! We can create an appropriate IndexByteBuffer
, IndexShortBuffer
or IndexIntBuffer
with it via IndexBuffer.createIndexBuffer(vertexCount, indexCount);
Or can we? The method never generates an IndexByteBuffer
. It only generates the two bigger types. This makes me wonder why an IndexByteBuffer
class exists in the first place. Consistency is king, the method should also generates IndexByteBuffer
. The wrapIndexBuffer
method does already correctly wrap ByteBuffer
into IndexByteBuffer
!
Moving on from this, after having created an IndexBuffer
with IndexBuffer.createIndexBuffer(vertexCount, indexCount);
, there is no way to set it on a mesh. This becomes obvious when looking at jme-internal code, for example found in WrappenIndexBuffer.convertToList(Mesh mesh)
, lines 110 and following:
if (outBuf instanceof IndexIntBuffer){
mesh.setBuffer(Type.Index, 3, (IntBuffer)outBuf.getBuffer());
}else{
mesh.setBuffer(Type.Index, 3, (ShortBuffer)outBuf.getBuffer());
}
This can’t be the way to set an index buffer, having to inspect the type in order to be able to do it. The Mesh
class desperately needs a new method, either setIndexBuffer
or setBuffer(type type, int components, IndexBuffer buffer)
, and this kind of introspection needs to be pushed down there. User code shouldn’t have to inspect types!
Last but not least, classes like ShortBuffer
offer fluid interfaces. You can do buffer.put(0f).put(f).put(2f);
and so on with those buffers. IndexBuffer
only offers a void
method for it. It would be very desirable if the IndexBuffer
class would offer the same interface in order to facilitate easier swapping to it!
The code I already had is presented at the top of this post. This is the code I expected to be able to get:
//creating the buffer
IndexBuffer buffer = IndexBuffer.createIndexBuffer(vertexCount, indexCount);
// loops omitted for brevity
buffer.put(i0).put(i1).put(i1 + 1);
buffer.put(i0 + 1).put(i0).put(i1 + 1);
// setting the buffer
mesh.setBuffer(Type.Index, 3, buffer);
This is the code I actually need:
// creating the buffer
IndexBuffer indexBuffer = IndexBuffer.createIndexBuffer(vertexCount, indexCount);
// loops omitted for brevity
indexBuffer.put(c++, i0);
indexBuffer.put(c++, i1);
indexBuffer.put(c++, i1+1);
indexBuffer.put(c++, i0+1);
indexBuffer.put(c++, i0);
indexBuffer.put(c++, i1+1);
//setting the buffer
if (indexBuffer instanceof IndexByteBuffer)
mesh.setBuffer(Type.Index, 3, (ByteBuffer) buffer.getBuffer());
else if (indexBuffer instanceof IndexShortBuffer)
mesh.setBuffer(Type.Index, 3, (ShortBuffer) buffer.getBuffer());
else if (indexBuffer instanceof IndexIntBuffer)
mesh.setBuffer(Type.Index, 3, (IntBuffer) buffer.getBuffer());
The code needed to swap away from a specific buffer (Byte-, Short- or IntBuffer) over to a generic IndexBuffer
is much longer and much more complicated.
In short, the three improvements I am advising are:
-
IndexBuffer.createIndexBuffer(vertexCount, indexCount);
should also return IndexByteBuffer, -
Mesh
should accept anIndexBuffer
so that user-code does not need to do type inspection and -
IndexBuffer
should offer the same fluid interface as the other buffers, especially input
, returning itself instead ofvoid
.
At the same time it could be an opportunity to swap existing JME code which still utilizes other buffers directly over to IndexBuffer
.
If these changes are wanted, I could potentially work on providing a PR for them.