package org.osm2world.core.target.jogl;
import static javax.media.opengl.GL.GL_FLOAT;
import static javax.media.opengl.GL2GL3.GL_DOUBLE;
import java.awt.Color;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.media.opengl.GL3;
import org.osm2world.core.math.VectorXYZ;
import com.jogamp.common.nio.Buffers;
/**
* Renders the a bunch of {@link NonAreaPrimitive} objects using JOGL and the new shader based OpengGL pipeline.
* Uses vertex buffer objects (VBO) to speed up the process.
*
* If you don't need the renderer anymore, it's recommended to manually call
* {@link #freeResources()} to delete the VBOs and other resources.
*/
public class JOGLRendererVBONonAreaShader {
protected static final boolean DOUBLE_PRECISION_RENDERING = false;
protected GL3 gl;
private NonAreaShader shader;
protected List<VBODataNonAreaShader<?>> vbos = new ArrayList<VBODataNonAreaShader<?>>();
private final class VBODataDouble extends VBODataNonAreaShader<DoubleBuffer> {
public VBODataDouble(GL3 gl, NonAreaPrimitive primitive) {
super(gl, shader, primitive);
}
@Override
protected DoubleBuffer createBuffer(int numValues) {
return Buffers.newDirectDoubleBuffer(numValues);
}
@Override
protected void put(DoubleBuffer buffer, Color color) {
buffer.put(color.getRed()/255d);
buffer.put(color.getGreen()/255d);
buffer.put(color.getBlue()/255d);
buffer.put(color.getAlpha()/255d);
}
@Override
protected void put(DoubleBuffer buffer, VectorXYZ v) {
buffer.put(v.x);
buffer.put(v.y);
buffer.put(-v.z);
}
@Override
protected int valueTypeSize() {
return Buffers.SIZEOF_DOUBLE;
}
@Override
protected int glValueType() {
return GL_DOUBLE;
}
}
private final class VBODataFloat extends VBODataNonAreaShader<FloatBuffer> {
public VBODataFloat(GL3 gl, NonAreaPrimitive primitive) {
super(gl, shader, primitive);
}
@Override
protected FloatBuffer createBuffer(int numValues) {
return Buffers.newDirectFloatBuffer(numValues);
}
@Override
protected void put(FloatBuffer buffer, Color color) {
buffer.put(color.getRed()/255f);
buffer.put(color.getGreen()/255f);
buffer.put(color.getBlue()/255f);
buffer.put(color.getAlpha()/255f);
}
@Override
protected void put(FloatBuffer buffer, VectorXYZ v) {
buffer.put((float)v.x);
buffer.put((float)v.y);
buffer.put((float)-v.z);
}
@Override
protected int valueTypeSize() {
return Buffers.SIZEOF_FLOAT;
}
@Override
protected int glValueType() {
return GL_FLOAT;
}
}
/**
* Creates vertex buffer objects for all primitives.
* @param shader the shader used for rendering
* @param primitives the primitives to render
*/
public JOGLRendererVBONonAreaShader(GL3 gl, NonAreaShader shader, Collection<NonAreaPrimitive> primitives) {
this.gl = gl;
this.shader = shader;
for (NonAreaPrimitive nonAreaPrimitive : primitives) {
VBODataNonAreaShader<?> vbo;
if (DOUBLE_PRECISION_RENDERING)
vbo = new VBODataDouble(gl, nonAreaPrimitive);
else
vbo = new VBODataFloat(gl, nonAreaPrimitive);
vbos.add(vbo);
}
}
/**
* Renders all VBOs for the {@link NonAreaPrimitive} objects.
*/
public void render() {
gl.glEnableVertexAttribArray(shader.getVertexPositionID());
gl.glEnableVertexAttribArray(shader.getVertexColorID());
// render non area primitives
for (VBODataNonAreaShader<?> vbo : vbos) {
vbo.render();
}
gl.glDisableVertexAttribArray(shader.getVertexPositionID());
gl.glDisableVertexAttribArray(shader.getVertexColorID());
}
}