This is the implementation of GeomBatch.setSolidColor():

   public void setSolidColor(ColorRGBA color) {
      if (colorBuf == null)
         colorBuf = BufferUtils.createColorBuffer(vertQuantity);

      for (int x = 0, cLength = colorBuf.remaining(); x < cLength; x += 4) {

There are at least two things wrong with this.

First, colors that come in as byte-based RGBA (or BGRA) colors should not be turned into floats -- that takes up four times the memory! (And memory is speed).

Second, if the object has a solid color, then it is more efficient to just call glColor() than to bind an entire color buffer. Especially if you try to animate the color of the object using this function! The documentation says nothing about this.

Actually, on some ATI hardware, they don't support glColor(), and synthesize it in the driver, but on most hardware, glColor() is a lot faster than passing the data by an array.

Actually, looking at the code, it seems as if the arrays are being passed separately. There is a limit over which the graphics card fetch will start running slower (or the driver will re-pack the data) when you have more vertex streams. That limit used to be 1, but I think on NVIDIA it's up to 4 these days. Spending some effort to interlace the data, and/or at least support pre-interlaced data, would be useful from a performance point of view. Perhaps the lock functions do this? The documentation is silent on this subject...

Anyway, there you have it: some suggestions for the future, if you want to run faster with more complex geometry.

You're right about the color array part; OpenGL can indeed accept byte-based color array data, and I don't think there would be much of a noticeable quality loss since textures and the colorbuffer use 24 bit color depth anyway.

For your second point, there's a function called setDefaultColor which uses a single glColor call to set the color of geometry, like you said. And interlaced geometry data, I agree that it might be a good idea to use it, but since much of jME code is centered around managing the arrays separately I think it would be very difficult to implement without having to rewrite a lot of code.

Hah, the setDefaultColor()/setSolidColor() difference actually documented! Silly me, not checking that when I found it in the source.

I think you could, at least, interlace when upload to VBO happens, and possibly when compiling to display lists.

It would be swell if I could get a Direct buffer that points to the VBO array, by the way. That would avoid copying each time something dynamic is rendered.