Why FloatBuffer instead of float[]?
I've been using FloatBuffers in my Android code for a while (copied it from some opengles tutorial), but I cannot understand exactly what this construct is and why it is needed.
For example this code (or similar) I see in many many peoples' code and android tutorials:
float[] vertices = ...some array...
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder()); // use the device hardware's native byte order
FloatBuffer fb = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer
fb.put(vertices); // add the coordinates to the FloatBuffer
fb.position(0); // set the buffer to read the first coordinate
This seems awfully verbose and messy for something which as far as I can tell is just a fancy wrapper around of an array of floats.
Questions:
What is the justification for this type of class (ByteBuffer, FloatBuffer), as opposed to any other kind of collection or simple array of floats?
What's the idea behind creating a ByteBuffer before converting it into a FloatBuffer?
The main reason is performance: ByteBuffers and the other NIO classes enable accelerated operations when interfacing with native code (typically by avoiding the need to copy data into a temporary buffer).
This is pretty important if you are doing a lot of OpenGL rendering calls for example.
The reason for creating a ByteBuffer first is that you want to use the allocateDirect call to create a direct byte buffer, which benefits from the accelerated operations. You then create a FloatBuffer from this that shares the same memory. The FloatBuffer doesn't itself have an allocateDirect method for some reason, which is why you have to go via ByteBuffer.
We do our coding in Java on Android, but the underlying implementation of OpenGL ES is actually written in C. Before we pass our data to OpenGL, we need to convert it into a form that it’s going to understand. Java and the native system might not store their bytes in the same order, so we use a special set of buffer classes and create a ByteBuffer large enough to hold our data, and tell it to store its data using the native byte order. We then convert it into a FloatBuffer so that we can use it to hold floating-point data. Finally, we copy our array into the buffer.