package org.osm2world.core.target.jogl; import static javax.media.opengl.GL.GL_ARRAY_BUFFER; import static javax.media.opengl.GL.GL_STATIC_DRAW; import java.awt.Color; import java.nio.Buffer; import javax.media.opengl.GL3; import org.osm2world.core.math.VectorXYZ; /** * class that keeps a VBO id along with associated information for {@link NonAreaPrimitive} objects. */ abstract class VBODataNonAreaShader<BufferT extends Buffer> { /** array with one element containing the VBO id */ protected final int[] id; /** number of vertices in the vbo */ protected final int vertexCount; /** size of each value in the vbo */ protected final int valueTypeSize; /** gl constant for the value type in the vbo */ protected final int glValueType; /** create a buffer to store the vbo data for upload to graphics memory */ protected abstract BufferT createBuffer(int numValues); /** add vertex color to the vbo buffer */ protected abstract void put(BufferT buffer, Color color); /** add 3d vertex data to the vbo buffer */ protected abstract void put(BufferT buffer, VectorXYZ v); /** returns the size of each value in the vbo */ protected abstract int valueTypeSize(); /** returns the gl constant for the value type in the vbo */ protected abstract int glValueType(); protected GL3 gl; private NonAreaShader shader; /** the OpenGL constant for the type of the {@link NonAreaPrimitive} */ private int primitiveType; /** width of the {@link NonAreaPrimitive} */ private int width; /** * Creates a new vertex buffer object, adds all primitives to the buffer and uploads it to graphics memory. */ public VBODataNonAreaShader(GL3 gl, NonAreaShader shader, NonAreaPrimitive nonAreaPrimitive) { this.gl = gl; this.shader = shader; primitiveType= AbstractJOGLTarget.getGLConstant(nonAreaPrimitive.type); width = nonAreaPrimitive.width; valueTypeSize = valueTypeSize(); glValueType = glValueType(); vertexCount = nonAreaPrimitive.vs.size(); /* create the buffer */ id = new int[1]; gl.glGenBuffers(1, id, 0); /* collect the data for the buffer */ BufferT valueBuffer = createBuffer( vertexCount * getValuesPerVertex()); /* put the values into the buffer, in the right order */ for (int i = 0; i < nonAreaPrimitive.vs.size(); i++) { put(valueBuffer, nonAreaPrimitive.vs.get(i)); put(valueBuffer, nonAreaPrimitive.color); } valueBuffer.rewind(); /* write the data into the buffer */ gl.glBindBuffer(GL_ARRAY_BUFFER, id[0]); gl.glBufferData( GL_ARRAY_BUFFER, valueBuffer.capacity() * valueTypeSize, valueBuffer, GL_STATIC_DRAW); } /** * Bind and render this vertex buffer object. */ public void render() { gl.glBindBuffer(GL_ARRAY_BUFFER, id[0]); setPointerLayout(); gl.glLineWidth(width); gl.glDrawArrays(primitiveType, 0, vertexCount); } private void setPointerLayout() { int stride = valueTypeSize * getValuesPerVertex(); int offset = 0; gl.glVertexAttribPointer(shader.getVertexPositionID(), 3, glValueType(), false, stride, offset); gl.glVertexAttribPointer(shader.getVertexColorID(), 4, glValueType(), false, stride, offset + valueTypeSize() * 3); } /** * Returns the number of values for each vertex in the vertex buffer layout. */ private int getValuesPerVertex() { // 3 for vertex position, 4 for vertex color return 7; } }