package org.osm2world.core.target.jogl;
import static javax.media.opengl.GL.GL_ARRAY_BUFFER;
import static javax.media.opengl.GL.GL_FLOAT;
import static javax.media.opengl.GL2GL3.GL_DOUBLE;
import static javax.media.opengl.fixedfunc.GLPointerFunc.GL_NORMAL_ARRAY;
import static javax.media.opengl.fixedfunc.GLPointerFunc.GL_TEXTURE_COORD_ARRAY;
import static javax.media.opengl.fixedfunc.GLPointerFunc.GL_VERTEX_ARRAY;
import static org.osm2world.core.target.jogl.JOGLTargetFixedFunction.drawPrimitive;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.util.Collection;
import javax.media.opengl.GL2;
import org.osm2world.core.math.VectorXYZ;
import org.osm2world.core.math.VectorXZ;
import org.osm2world.core.target.common.Primitive;
import org.osm2world.core.target.common.material.Material;
import org.osm2world.core.target.common.rendering.Camera;
import org.osm2world.core.target.common.rendering.Projection;
import com.jogamp.common.nio.Buffers;
/**
* Renders the contents of a {@link PrimitiveBuffer} using JOGL and the old fixed function 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 JOGLRendererVBOFixedFunction extends JOGLRendererVBO {
protected GL2 gl;
private final class VBODataDouble extends VBODataFixedFunction<DoubleBuffer> {
public VBODataDouble(GL2 gl, JOGLTextureManager textureManager, Material material, Collection<Primitive> primitives) {
super(gl, textureManager, material, primitives);
}
@Override
protected DoubleBuffer createBuffer(int numValues) {
return Buffers.newDirectDoubleBuffer(numValues);
}
@Override
protected void put(DoubleBuffer buffer, VectorXZ texCoord) {
buffer.put(texCoord.x);
buffer.put(texCoord.z);
}
@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 VBODataFixedFunction<FloatBuffer> {
public VBODataFloat(GL2 gl, JOGLTextureManager textureManager, Material material, Collection<Primitive> primitives) {
super(gl, textureManager, material, primitives);
}
@Override
protected FloatBuffer createBuffer(int numValues) {
return Buffers.newDirectFloatBuffer(numValues);
}
@Override
protected void put(FloatBuffer buffer, VectorXZ texCoord) {
buffer.put((float)texCoord.x);
buffer.put((float)texCoord.z);
}
@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;
}
}
JOGLRendererVBOFixedFunction(GL2 gl, JOGLTextureManager textureManager,
PrimitiveBuffer primitiveBuffer) {
super(textureManager);
this.gl = gl;
this.init(primitiveBuffer);
}
@Override
VBOData<?> createVBOData(JOGLTextureManager textureManager, Material material, Collection<Primitive> primitives) {
if (DOUBLE_PRECISION_RENDERING)
return new VBODataDouble(gl, textureManager, material, primitives);
else
return new VBODataFloat(gl, textureManager, material, primitives);
}
@Override
public void render(final Camera camera, final Projection projection) {
/* render static geometry */
gl.glEnableClientState(GL_VERTEX_ARRAY);
gl.glEnableClientState(GL_NORMAL_ARRAY);
for (VBOData<?> vboData : vbos) {
vboData.render();
}
gl.glDisableClientState(GL_VERTEX_ARRAY);
gl.glDisableClientState(GL_NORMAL_ARRAY);
for (int t = 0; t < JOGLTargetFixedFunction.MAX_TEXTURE_LAYERS; t++) {
gl.glClientActiveTexture(JOGLTargetFixedFunction.getGLTextureConstant(t));
gl.glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
gl.glBindBuffer(GL_ARRAY_BUFFER, 0);
/* render transparent primitives back-to-front */
sortPrimitivesBackToFront(camera, projection);
Material previousMaterial = null;
for (PrimitiveWithMaterial p : transparentPrimitives) {
if (!p.material.equals(previousMaterial)) {
JOGLTargetFixedFunction.setMaterial(gl, p.material, textureManager);
previousMaterial = p.material;
}
drawPrimitive(gl, AbstractJOGLTarget.getGLConstant(p.primitive.type),
p.primitive.vertices, p.primitive.normals,
p.primitive.texCoordLists);
}
}
@Override
public void freeResources() {
gl = null;
super.freeResources();
}
}