Java FloatBuffers don't always translate nicely to C API

Many OpenGL functions in the C API accept a pointer as a parameter, whereas the corresponding methods in JOGL use a reference to a FloatBuffer. For example, the C function (below) has two Java wrappers:


C API:

  void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *  ptr);

Corresponding Java API (wrapped in GL.java):

  public void glVertexPointer(int size, int type, int stride, java.nio.Buffer ptr);
  public void glVertexPointer(int size, int type, int stride, long ptr_buffer_offset);

The first method I use when passing the contents of a direct FloatBuffer directly to GL. The trouble with the first method, is that the stride parameter isn’t very powerful without being able to specify the starting offset in the buffer. The second method (with the buffer offset) is useful when passing an offset into a VBO and the stride works great, but with dynamic data (like an animated model) a VBO isn’t always the right choice. There are many other methods following a similar pattern (for example, I also use glTexCoordPointer and glNormalPointer a lot).

My problem is that if I interleave a FloatBuffer in T2F_N3F_V3F (texture, normal, vertex), and I don’t use a VBO, I need to jump through hoops to get the offset into the FloatBuffer. I could write something like this:


		FloatBuffer interleavedBuffer = generateT2F_N3F_V3FInterleavedBuffer();
		gl.glTexCoordPointer(2, GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, interleavedBuffer);
		interleavedBuffer.position(2);
		FloatBuffer normalSlice = interleavedBuffer.slice();
		gl.glNormalPointer(GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, normalSlice);
		group.interleavedAnimatedArray.position(5);
		FloatBuffer vertexSlice = interleavedBuffer.slice();
		gl.glVertexPointer(3, GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, vertexSlice);
		interleavedBuffer.position(0);

Yes, I can use glInterleavedArrays(GL.GL_T2F_N3F_V3F, 0, interleavedBuffer), but I am trying to make a different point. The point is, I propose yet another overload of the methods accepting a Buffer as a parameter, that would also accept an offset into the buffer. So using the glVertexPointer example from above, we would have:


  public void glVertexPointer(int size, int type, int stride, java.nio.Buffer ptr);
  public void glVertexPointer(int size, int type, int stride, java.nio.Buffer ptr, int buffer_offset);
  public void glVertexPointer(int size, int type, int stride, long ptr_buffer_offset);

The new method (the middle one, above) would more fully expose the potential of the original C API.

Thoughts?

Perhaps this isn’t my place since I’m ranked only as a JGO noob, but when I was reading through the JOGL api, they seemed to discuss there choice for the number of overloadings for various buffer related calls. I believe they stopped at the ones available so that there weren’t so many that it got confusing.

By the nature of the languages, pointers are a hard feature to correctly map to java from c/c++, and if you are so desperately in need of starting from an offset, the jogl calls that use buffers begin reading from the buffer’s current position, so it shouldn’t be that hard to set the desired position then do the gl call.

Yeah, you are right. The GLImpl is already so huge, that adding more methods would make it even more confusing. And java.nio.Buffer essentially encapsulates the position that I suggested as an additional method parameter. I saw a lot of other methods taking a float[] followed by a starting offset parameter, that it made me want the same thing for Buffers. I have found that some of my video cards really benefit from interleaved data, so I run into this a lot.

There’s no need to do the slicing since the gl…Pointer methods already take the current position of a buffer into account.

Excellent! So the snippet of code can be written like this:


		FloatBuffer interleavedBuffer = generateT2F_N3F_V3FInterleavedBuffer();
		interleavedBuffer.position(2);
		gl.glNormalPointer(GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, interleavedBuffer);
		interleavedBuffer.position(5);
		gl.glVertexPointer(3, GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, interleavedBuffer);
		interleavedBuffer.position(0);
		gl.glTexCoordPointer(2, GL.GL_FLOAT, 8 * BufferUtil.SIZEOF_FLOAT, interleavedBuffer);

I knew there was a reason I posted here.
Thank you.