Program: 70938
Project: 70938
Buggy source:
private void createVBOs(GL3 gl,RenderObject robj,GL3Object lineObject,float lineRadius,GL3Object headObject,float headRadius,float headLength){
  positionPutter=PositionBufferPutter.createDefault();
  normalPutter=NormalBufferPutter.createDefault();
  colorPutter=ColorBufferPutter.createDefault();
  texturePutter=TextureCoordBufferPutter.createDefault();
  final int POSITION_BYTES=positionPutter.bytesPerPosition();
  final int NORMAL_BYTES=normalPutter.bytesPerNormal();
  final int COLOR_BYTES=colorPutter.bytesPerColor();
  final int TEXTURE_BYTES=texturePutter.bytesPerTextureCoord();
  positionInfo=createAttributeInfoArrays(robj.numPositionSets());
  normalInfo=createAttributeInfoArrays(robj.numNormalSets());
  colorInfo=createAttributeInfoArrays(robj.numColorSets());
  textureInfo=createAttributeInfoArrays(robj.numTextureCoordSets());
  lineInfo=createAttributeInfoArrays(2);
  headInfo=createAttributeInfoArrays(2);
  staticVertexSize=0;
  staticMask=0;
  dynamicVertexSize=0;
  dynamicMask=0;
  boolean streaming=robj.isStreaming();
  nVertices=robj.numVertices();
  int numLinesTotal=0;
  for (int lg=0; lg < robj.numLineGroups(); ++lg) {
    numLinesTotal+=robj.numLines(lg);
  }
  if (robj.hasPositions()) {
    if (!streaming && robj.isPositionsDynamic()) {
      positionInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=POSITION_BYTES;
      dynamicMask|=POSITION_FLAG;
    }
 else {
      positionInfo[0].offset=staticVertexSize;
      staticVertexSize+=POSITION_BYTES;
      staticMask|=POSITION_FLAG;
    }
    positionInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < positionInfo.length; ++i) {
      positionInfo[i].offset=(i - 1) * POSITION_BYTES * 2* numLinesTotal;
      positionInfo[i].stride=POSITION_BYTES;
      positionInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasNormals()) {
    if (!streaming && robj.isNormalsDynamic()) {
      normalInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=NORMAL_BYTES;
      dynamicMask|=NORMAL_FLAG;
    }
 else {
      normalInfo[0].offset=staticVertexSize;
      staticVertexSize+=NORMAL_BYTES;
      staticMask|=NORMAL_FLAG;
    }
    normalInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < normalInfo.length; ++i) {
      normalInfo[i].offset=(i - 1) * NORMAL_BYTES * 2* numLinesTotal;
      normalInfo[i].stride=NORMAL_BYTES;
      normalInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasColors()) {
    if (!streaming && robj.isColorsDynamic()) {
      colorInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=COLOR_BYTES;
      dynamicMask|=COLOR_FLAG;
    }
 else {
      colorInfo[0].offset=staticVertexSize;
      staticVertexSize+=COLOR_BYTES;
      staticMask|=COLOR_FLAG;
    }
    colorInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < colorInfo.length; ++i) {
      colorInfo[i].offset=(i - 1) * COLOR_BYTES * 2* numLinesTotal;
      colorInfo[i].stride=COLOR_BYTES;
      colorInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasTextureCoords()) {
    if (!streaming && robj.isTextureCoordsDynamic()) {
      textureInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=TEXTURE_BYTES;
      dynamicMask|=TEXTURE_FLAG;
    }
 else {
      textureInfo[0].offset=staticVertexSize;
      staticVertexSize+=TEXTURE_BYTES;
      staticMask|=TEXTURE_FLAG;
    }
    textureInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < textureInfo.length; ++i) {
      textureInfo[i].offset=(i - 1) * TEXTURE_BYTES * 2* numLinesTotal;
      textureInfo[i].stride=TEXTURE_BYTES;
      textureInfo[i].count=2 * numLinesTotal;
    }
  }
  int vboIdx=0;
  if (staticVertexSize > 0) {
    vboIdx++;
  }
  if (robj.hasPositions()) {
    if (!streaming && robj.isPositionsDynamic()) {
      positionInfo[0].stride=dynamicVertexSize;
      positionInfo[0].vboIndex=vboIdx;
    }
 else {
      positionInfo[0].stride=staticVertexSize;
      positionInfo[0].vboIndex=0;
    }
  }
  if (robj.hasNormals()) {
    if (!streaming && robj.isNormalsDynamic()) {
      normalInfo[0].stride=dynamicVertexSize;
      normalInfo[0].vboIndex=vboIdx;
    }
 else {
      normalInfo[0].stride=staticVertexSize;
      normalInfo[0].vboIndex=0;
    }
  }
  if (robj.hasColors()) {
    if (!streaming && robj.isColorsDynamic()) {
      colorInfo[0].stride=dynamicVertexSize;
      colorInfo[0].vboIndex=vboIdx;
    }
 else {
      colorInfo[0].stride=staticVertexSize;
      colorInfo[0].vboIndex=0;
    }
  }
  if (robj.hasTextureCoords()) {
    if (!streaming && robj.isTextureCoordsDynamic()) {
      textureInfo[0].stride=dynamicVertexSize;
      textureInfo[0].vboIndex=vboIdx;
    }
 else {
      textureInfo[0].stride=staticVertexSize;
      textureInfo[0].vboIndex=0;
    }
  }
  if (!streaming && robj.isDynamic()) {
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    for (int i=1; i < positionInfo.length; ++i) {
      positionInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    for (int i=1; i < normalInfo.length; ++i) {
      normalInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    for (int i=1; i < colorInfo.length; ++i) {
      colorInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    for (int i=1; i < textureInfo.length; ++i) {
      textureInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  lineInfo[0].offset=0;
  lineInfo[0].stride=10 * Float.BYTES;
  lineInfo[0].count=1;
  lineInfo[0].vboIndex=vboIdx;
  lineInfo[1].offset=1 * Float.BYTES;
  lineInfo[1].stride=10 * Float.BYTES;
  lineInfo[1].count=1;
  lineInfo[1].vboIndex=vboIdx;
  headInfo[0].offset=5 * Float.BYTES;
  headInfo[0].stride=10 * Float.BYTES;
  headInfo[0].count=1;
  headInfo[0].vboIndex=vboIdx;
  headInfo[1].offset=6 * Float.BYTES;
  headInfo[1].stride=10 * Float.BYTES;
  headInfo[1].count=1;
  headInfo[1].vboIndex=vboIdx;
  vboIdx++;
  int nVBOs=vboIdx;
  ByteBuffer[] buffs=new ByteBuffer[nVBOs];
  vboIdx=0;
  if (staticVertexSize > 0) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * staticVertexSize);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (!streaming && robj.isDynamic()) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * dynamicVertexSize);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numPositionSets() - 1)* POSITION_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numNormalSets() - 1)* NORMAL_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numColorSets() - 1)* COLOR_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numTextureCoordSets() - 1)* TEXTURE_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  int vidx=0;
  for (int lg=0; lg < robj.numLineGroups(); ++lg) {
    List<int[]> lines=robj.getLines(lg);
    for (    int[] line : lines) {
      for (int j=0; j < 2; ++j) {
        VertexIndexSet v=robj.getVertex(line[j]);
        for (int i=0; i < positionInfo.length; ++i) {
          AttributeInfo ai=positionInfo[i];
          float[] pos=robj.getPosition(i,v.getPositionIndex());
          positionPutter.putPosition(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,pos);
        }
        for (int i=0; i < normalInfo.length; ++i) {
          AttributeInfo ai=normalInfo[i];
          float[] nrm=robj.getNormal(i,v.getNormalIndex());
          normalPutter.putNormal(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,nrm);
        }
        for (int i=0; i < colorInfo.length; ++i) {
          AttributeInfo ai=colorInfo[i];
          byte[] color=robj.getColor(i,v.getColorIndex());
          colorPutter.putColor(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,color);
        }
        for (int i=0; i < textureInfo.length; ++i) {
          AttributeInfo ai=textureInfo[i];
          float[] pos=robj.getTextureCoord(i,v.getTextureCoordIndex());
          texturePutter.putTextureCoord(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,pos);
        }
        vidx++;
      }
    }
  }
  buffs[vboIdx]=ByteBuffer.allocateDirect(10 * Float.BYTES);
  buffs[vboIdx].order(ByteOrder.nativeOrder());
  buffs[vboIdx].putFloat(lineRadius);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(1.0f);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(headRadius);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(1.0f);
  vbos=new BufferObject[nVBOs];
  vboIdx=0;
  if (staticVertexSize > 0) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(false,streaming));
    vboIdx++;
  }
  if (!streaming && robj.isDynamic()) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(true,streaming));
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isPositionsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isNormalsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isColorsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isTextureCoordsDynamic(),streaming));
    vboIdx++;
  }
  vbos[vboIdx]=new BufferObject(gl);
  buffs[vboIdx].rewind();
  vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,GL.GL_DYNAMIC_DRAW);
  vboIdx++;
}

Fixed version (ground truth):
private void createVBOs(GL3 gl,RenderObject robj,GL3Object lineObject,float lineRadius,GL3Object headObject,float headRadius,float headLength){
  positionPutter=PositionBufferPutter.createDefault();
  normalPutter=NormalBufferPutter.createDefault();
  colorPutter=ColorBufferPutter.createDefault();
  texturePutter=TextureCoordBufferPutter.createDefault();
  final int POSITION_BYTES=positionPutter.bytesPerPosition();
  final int NORMAL_BYTES=normalPutter.bytesPerNormal();
  final int COLOR_BYTES=colorPutter.bytesPerColor();
  final int TEXTURE_BYTES=texturePutter.bytesPerTextureCoord();
  positionInfo=createAttributeInfoArrays(robj.numPositionSets());
  normalInfo=createAttributeInfoArrays(robj.numNormalSets());
  colorInfo=createAttributeInfoArrays(robj.numColorSets());
  textureInfo=createAttributeInfoArrays(robj.numTextureCoordSets());
  lineInfo=createAttributeInfoArrays(2);
  headInfo=createAttributeInfoArrays(2);
  staticVertexSize=0;
  staticMask=0;
  dynamicVertexSize=0;
  dynamicMask=0;
  boolean streaming=robj.isStreaming();
  nVertices=robj.numVertices();
  int numLinesTotal=0;
  for (int lg=0; lg < robj.numLineGroups(); ++lg) {
    numLinesTotal+=robj.numLines(lg);
  }
  if (robj.hasPositions()) {
    if (!streaming && robj.isPositionsDynamic()) {
      positionInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=POSITION_BYTES;
      dynamicMask|=POSITION_FLAG;
    }
 else {
      positionInfo[0].offset=staticVertexSize;
      staticVertexSize+=POSITION_BYTES;
      staticMask|=POSITION_FLAG;
    }
    positionInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < positionInfo.length; ++i) {
      positionInfo[i].offset=(i - 1) * POSITION_BYTES * 2* numLinesTotal;
      positionInfo[i].stride=POSITION_BYTES;
      positionInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasNormals()) {
    if (!streaming && robj.isNormalsDynamic()) {
      normalInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=NORMAL_BYTES;
      dynamicMask|=NORMAL_FLAG;
    }
 else {
      normalInfo[0].offset=staticVertexSize;
      staticVertexSize+=NORMAL_BYTES;
      staticMask|=NORMAL_FLAG;
    }
    normalInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < normalInfo.length; ++i) {
      normalInfo[i].offset=(i - 1) * NORMAL_BYTES * 2* numLinesTotal;
      normalInfo[i].stride=NORMAL_BYTES;
      normalInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasColors()) {
    if (!streaming && robj.isColorsDynamic()) {
      colorInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=COLOR_BYTES;
      dynamicMask|=COLOR_FLAG;
    }
 else {
      colorInfo[0].offset=staticVertexSize;
      staticVertexSize+=COLOR_BYTES;
      staticMask|=COLOR_FLAG;
    }
    colorInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < colorInfo.length; ++i) {
      colorInfo[i].offset=(i - 1) * COLOR_BYTES * 2* numLinesTotal;
      colorInfo[i].stride=COLOR_BYTES;
      colorInfo[i].count=2 * numLinesTotal;
    }
  }
  if (robj.hasTextureCoords()) {
    if (!streaming && robj.isTextureCoordsDynamic()) {
      textureInfo[0].offset=dynamicVertexSize;
      dynamicVertexSize+=TEXTURE_BYTES;
      dynamicMask|=TEXTURE_FLAG;
    }
 else {
      textureInfo[0].offset=staticVertexSize;
      staticVertexSize+=TEXTURE_BYTES;
      staticMask|=TEXTURE_FLAG;
    }
    textureInfo[0].count=2 * numLinesTotal;
    for (int i=1; i < textureInfo.length; ++i) {
      textureInfo[i].offset=(i - 1) * TEXTURE_BYTES * 2* numLinesTotal;
      textureInfo[i].stride=TEXTURE_BYTES;
      textureInfo[i].count=2 * numLinesTotal;
    }
  }
  int vboIdx=0;
  if (staticVertexSize > 0) {
    vboIdx++;
  }
  if (robj.hasPositions()) {
    if (!streaming && robj.isPositionsDynamic()) {
      positionInfo[0].stride=dynamicVertexSize;
      positionInfo[0].vboIndex=vboIdx;
    }
 else {
      positionInfo[0].stride=staticVertexSize;
      positionInfo[0].vboIndex=0;
    }
  }
  if (robj.hasNormals()) {
    if (!streaming && robj.isNormalsDynamic()) {
      normalInfo[0].stride=dynamicVertexSize;
      normalInfo[0].vboIndex=vboIdx;
    }
 else {
      normalInfo[0].stride=staticVertexSize;
      normalInfo[0].vboIndex=0;
    }
  }
  if (robj.hasColors()) {
    if (!streaming && robj.isColorsDynamic()) {
      colorInfo[0].stride=dynamicVertexSize;
      colorInfo[0].vboIndex=vboIdx;
    }
 else {
      colorInfo[0].stride=staticVertexSize;
      colorInfo[0].vboIndex=0;
    }
  }
  if (robj.hasTextureCoords()) {
    if (!streaming && robj.isTextureCoordsDynamic()) {
      textureInfo[0].stride=dynamicVertexSize;
      textureInfo[0].vboIndex=vboIdx;
    }
 else {
      textureInfo[0].stride=staticVertexSize;
      textureInfo[0].vboIndex=0;
    }
  }
  if (!streaming && robj.isDynamic()) {
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    for (int i=1; i < positionInfo.length; ++i) {
      positionInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    for (int i=1; i < normalInfo.length; ++i) {
      normalInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    for (int i=1; i < colorInfo.length; ++i) {
      colorInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    for (int i=1; i < textureInfo.length; ++i) {
      textureInfo[i].vboIndex=vboIdx;
    }
    vboIdx++;
  }
  lineInfo[0].offset=0;
  lineInfo[0].stride=10 * GLSupport.FLOAT_SIZE;
  lineInfo[0].count=1;
  lineInfo[0].vboIndex=vboIdx;
  lineInfo[1].offset=1 * GLSupport.FLOAT_SIZE;
  lineInfo[1].stride=10 * GLSupport.FLOAT_SIZE;
  lineInfo[1].count=1;
  lineInfo[1].vboIndex=vboIdx;
  headInfo[0].offset=5 * GLSupport.FLOAT_SIZE;
  headInfo[0].stride=10 * GLSupport.FLOAT_SIZE;
  headInfo[0].count=1;
  headInfo[0].vboIndex=vboIdx;
  headInfo[1].offset=6 * GLSupport.FLOAT_SIZE;
  headInfo[1].stride=10 * GLSupport.FLOAT_SIZE;
  headInfo[1].count=1;
  headInfo[1].vboIndex=vboIdx;
  vboIdx++;
  int nVBOs=vboIdx;
  ByteBuffer[] buffs=new ByteBuffer[nVBOs];
  vboIdx=0;
  if (staticVertexSize > 0) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * staticVertexSize);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (!streaming && robj.isDynamic()) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * dynamicVertexSize);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numPositionSets() - 1)* POSITION_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numNormalSets() - 1)* NORMAL_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numColorSets() - 1)* COLOR_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    buffs[vboIdx]=ByteBuffer.allocateDirect(2 * numLinesTotal * (robj.numTextureCoordSets() - 1)* TEXTURE_BYTES);
    buffs[vboIdx].order(ByteOrder.nativeOrder());
    vboIdx++;
  }
  int vidx=0;
  for (int lg=0; lg < robj.numLineGroups(); ++lg) {
    List<int[]> lines=robj.getLines(lg);
    for (    int[] line : lines) {
      for (int j=0; j < 2; ++j) {
        VertexIndexSet v=robj.getVertex(line[j]);
        for (int i=0; i < positionInfo.length; ++i) {
          AttributeInfo ai=positionInfo[i];
          float[] pos=robj.getPosition(i,v.getPositionIndex());
          positionPutter.putPosition(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,pos);
        }
        for (int i=0; i < normalInfo.length; ++i) {
          AttributeInfo ai=normalInfo[i];
          float[] nrm=robj.getNormal(i,v.getNormalIndex());
          normalPutter.putNormal(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,nrm);
        }
        for (int i=0; i < colorInfo.length; ++i) {
          AttributeInfo ai=colorInfo[i];
          byte[] color=robj.getColor(i,v.getColorIndex());
          colorPutter.putColor(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,color);
        }
        for (int i=0; i < textureInfo.length; ++i) {
          AttributeInfo ai=textureInfo[i];
          float[] pos=robj.getTextureCoord(i,v.getTextureCoordIndex());
          texturePutter.putTextureCoord(buffs[ai.vboIndex],ai.offset + vidx * ai.stride,pos);
        }
        vidx++;
      }
    }
  }
  buffs[vboIdx]=ByteBuffer.allocateDirect(10 * GLSupport.FLOAT_SIZE);
  buffs[vboIdx].order(ByteOrder.nativeOrder());
  buffs[vboIdx].putFloat(lineRadius);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(1.0f);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(headRadius);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(0.0f);
  buffs[vboIdx].putFloat(headLength);
  buffs[vboIdx].putFloat(1.0f);
  vbos=new BufferObject[nVBOs];
  vboIdx=0;
  if (staticVertexSize > 0) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(false,streaming));
    vboIdx++;
  }
  if (!streaming && robj.isDynamic()) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(true,streaming));
    vboIdx++;
  }
  if (robj.numPositionSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isPositionsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numNormalSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isNormalsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numColorSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isColorsDynamic(),streaming));
    vboIdx++;
  }
  if (robj.numTextureCoordSets() > 1) {
    vbos[vboIdx]=new BufferObject(gl);
    buffs[vboIdx].rewind();
    vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,getBufferUsage(robj.isTextureCoordsDynamic(),streaming));
    vboIdx++;
  }
  vbos[vboIdx]=new BufferObject(gl);
  buffs[vboIdx].rewind();
  vbos[vboIdx].fill(gl,buffs[vboIdx],GL.GL_ARRAY_BUFFER,GL.GL_DYNAMIC_DRAW);
  vboIdx++;
}