From c519a4f34b4c9329e2af5385f65e08180db50bdf Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Wed, 25 Sep 2013 02:56:25 +0200 Subject: [PATCH] start of MeshLayer for 2D Meshes w/ tessellation --- .../renderer/elements/ElementLayers.java | 34 +++- .../oscim/renderer/elements/MeshLayer.java | 188 ++++++++++++------ .../renderer/elements/RenderElement.java | 9 +- 3 files changed, 165 insertions(+), 66 deletions(-) diff --git a/vtm/src/org/oscim/renderer/elements/ElementLayers.java b/vtm/src/org/oscim/renderer/elements/ElementLayers.java index 71982976..1cff6960 100644 --- a/vtm/src/org/oscim/renderer/elements/ElementLayers.java +++ b/vtm/src/org/oscim/renderer/elements/ElementLayers.java @@ -32,9 +32,13 @@ public class ElementLayers { PolygonLayer.Renderer.init(); TextureLayer.Renderer.init(); BitmapLayer.Renderer.init(); + MeshLayer.Renderer.init(); + TextureItem.init(gl, 0); } + // FIXME use one ArrayList for these! + // mixed Polygon- and LineLayer public RenderElement baseLayers; // Text- and SymbolLayer @@ -87,6 +91,14 @@ public class ElementLayers { return (LineLayer) getLayer(level, RenderElement.LINE); } + /** + * Get or add the MeshLayer for a level. Levels are ordered from + * bottom (0) to top + */ + public MeshLayer getMeshLayer(int level) { + return (MeshLayer) getLayer(level, RenderElement.MESH); + } + /** * Get or add the PolygonLayer for a level. Levels are ordered from * bottom (0) to top @@ -115,6 +127,12 @@ public class ElementLayers { RenderElement l = baseLayers; RenderElement renderElement = null; + if (!(type == RenderElement.LINE + || type == RenderElement.POLYGON + || type == RenderElement.TEXLINE + || type == RenderElement.MESH)) + throw new IllegalArgumentException("invalid layer type"); + if (mCurLayer != null && mCurLayer.level == level) { renderElement = mCurLayer; } else { @@ -146,9 +164,8 @@ public class ElementLayers { renderElement = new PolygonLayer(level); else if (type == RenderElement.TEXLINE) renderElement = new LineTexLayer(level); - else - // TODO throw execption - return null; + else if (type == RenderElement.MESH) + renderElement = new MeshLayer(level); if (l == null) { // insert at start @@ -177,6 +194,7 @@ public class ElementLayers { private final static int[] VERTEX_SHORT_CNT = { 4, // LINE_VERTEX_SHORTS 2, // POLY_VERTEX_SHORTS + 2, // MESH_VERTEX_SHORTS 6, // TEXLINE_VERTEX_SHORTS }; @@ -212,6 +230,7 @@ public class ElementLayers { size += addLayerItems(sbuf, baseLayers, RenderElement.LINE, 0); texLineOffset = size * SHORT_BYTES; + for (RenderElement l = baseLayers; l != null; l = l.next) { if (l.type == RenderElement.TEXLINE) { addPoolItems(l, sbuf); @@ -221,9 +240,14 @@ public class ElementLayers { } } + for (RenderElement l = baseLayers; l != null; l = l.next) { + if (l.type == RenderElement.MESH) + l.compile(sbuf); + } + for (RenderElement l = textureLayers; l != null; l = l.next) { - TextureLayer tl = (TextureLayer) l; - tl.compile(sbuf); + //TextureLayer tl = (TextureLayer) l; + l.compile(sbuf); } // extrusion layers are compiled by extrusion overlay diff --git a/vtm/src/org/oscim/renderer/elements/MeshLayer.java b/vtm/src/org/oscim/renderer/elements/MeshLayer.java index 35b4a3f1..d67d8bd3 100644 --- a/vtm/src/org/oscim/renderer/elements/MeshLayer.java +++ b/vtm/src/org/oscim/renderer/elements/MeshLayer.java @@ -15,91 +15,165 @@ package org.oscim.renderer.elements; import java.nio.ShortBuffer; -import java.util.Arrays; +import org.oscim.backend.GL20; import org.oscim.backend.Log; +import org.oscim.backend.canvas.Color; import org.oscim.core.GeometryBuffer; -import org.oscim.core.Tile; +import org.oscim.core.MapPosition; +import org.oscim.renderer.BufferObject; +import org.oscim.renderer.GLState; +import org.oscim.renderer.GLUtils; +import org.oscim.renderer.MapRenderer; +import org.oscim.renderer.MapRenderer.Matrices; +import org.oscim.utils.Tessellator; +import org.oscim.utils.pool.Inlist; public class MeshLayer extends RenderElement { - GeometryBuffer mGeom = new GeometryBuffer(10, 10); + private static final String TAG = MeshLayer.class.getName(); - public MeshLayer() { - GeometryBuffer e = mGeom; + BufferObject indicesVbo; + int numIndices; - int size = Tile.SIZE; + VertexItem indiceItems; - float x1 = -1; - float y1 = -1; - float x2 = size + 1; - float y2 = size + 1; - - // always clear geometry before starting - // a different type. - e.clear(); - e.startPolygon(); - e.addPoint(x1, y1); - e.addPoint(x2, y1); - e.addPoint(x2, y2); - e.addPoint(x1, y2); - - y1 = 5; - y2 = size - 5; - x1 = 5; - x2 = size - 5; - - e.startHole(); - e.addPoint(x1, y1); - e.addPoint(x2, y1); - e.addPoint(x2, y2); - e.addPoint(x1, y2); - - addMesh(e); + public MeshLayer(int level) { + super(RenderElement.MESH); + this.level = level; } public void addMesh(GeometryBuffer geom) { - int numRings = 2; - - long ctx = tessellate(geom.points, 0, geom.index, 0, numRings); - - short[] coordinates = new short[100]; - - while (tessGetCoordinates(ctx, coordinates, 2) > 0) { - Log.d("..", Arrays.toString(coordinates)); + if (vertexItems == null) { + vertexItems = VertexItem.pool.get(); + indiceItems = VertexItem.pool.get(); } - while (tessGetIndices(ctx, coordinates) > 0) { - Log.d("..", Arrays.toString(coordinates)); - } + numIndices += Tessellator.tessellate(geom, MapRenderer.COORD_SCALE, + Inlist.last(vertexItems), + Inlist.last(indiceItems), + verticesCnt); - tessFinish(ctx); + verticesCnt = vertexItems.getSize() / 2; + + Log.d(TAG, "-> " + verticesCnt + " " + numIndices); + + if (numIndices <= 0) { + vertexItems.release(); + vertexItems = null; + + indiceItems.release(); + indiceItems = null; + } } @Override protected void compile(ShortBuffer sbuf) { + if (indiceItems == null) { + return; + } + Log.d(TAG, "compile"); + // add vertices to shared VBO + ElementLayers.addPoolItems(this, sbuf); + + int cnt = indiceItems.getSize(); + + Log.d(TAG, "check " + cnt + ":" + numIndices); + + if (cnt != numIndices) { + numIndices = cnt; + } + + // add indices to indicesVbo + sbuf = MapRenderer.getShortBuffer(numIndices); + + for (VertexItem it = indiceItems; it != null; it = it.next) + sbuf.put(it.vertices, 0, it.used); + + VertexItem.pool.releaseAll(indiceItems); + indiceItems = null; + + sbuf.flip(); + + indicesVbo = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); + indicesVbo.loadBufferData(sbuf, sbuf.limit() * 2); } @Override protected void clear() { + BufferObject.release(indicesVbo); + VertexItem.pool.releaseAll(indiceItems); + VertexItem.pool.releaseAll(vertexItems); + indiceItems = null; + vertexItems = null; + indicesVbo = null; } - /** - * @param points an array of x,y coordinates - * @param pos position in points array - * @param index geom indices - * @param ipos position in index array - * @param numRings number of rings in polygon == outer(1) + inner rings - * @return number of triangles in io buffer - */ - public static native int tessellate(float[] points, int pos, - short[] index, int ipos, int numRings); + public static class Renderer { + private static int shaderProgram; + private static int hMatrix; + private static int hColor; + private static int hVertexPosition; - public static native void tessFinish(long ctx); + static boolean init() { + shaderProgram = GLUtils.createProgram(vertexShader, fragmentShader); + if (shaderProgram == 0) + return false; - public static native int tessGetCoordinates(long ctx, short[] coordinates, float scale); + hMatrix = GL.glGetUniformLocation(shaderProgram, "u_mvp"); + hColor = GL.glGetUniformLocation(shaderProgram, "u_color"); + hVertexPosition = GL.glGetAttribLocation(shaderProgram, "a_pos"); + return true; + } - public static native int tessGetIndices(long ctx, short[] indices); + public static RenderElement draw(MapPosition pos, RenderElement layer, + Matrices m) { + GLState.blend(true); + + RenderElement l = layer; + + GLState.useProgram(shaderProgram); + + GLState.enableVertexArrays(hVertexPosition, -1); + + //m.viewproj.setAsUniform(hMatrix); + //m.useScreenCoordinates(true, 1f); + m.mvp.setAsUniform(hMatrix); + + GLUtils.setColor(hColor, Color.BLUE, 0.4f); + + for (; l != null && l.type == RenderElement.MESH; l = l.next) { + MeshLayer ml = (MeshLayer) l; + + ml.indicesVbo.bind(); + + GL.glVertexAttribPointer(hVertexPosition, 2, GL20.GL_SHORT, + false, 0, ml.offset); + + GL.glDrawElements(GL20.GL_TRIANGLES, ml.numIndices, + GL20.GL_UNSIGNED_SHORT, 0); + } + + GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); + + return l; + } + + private final static String vertexShader = "" + + "precision mediump float;" + + "uniform mat4 u_mvp;" + + "attribute vec4 a_pos;" + + "void main() {" + + " gl_Position = u_mvp * a_pos;" + + "}"; + + private final static String fragmentShader = "" + + "precision mediump float;" + + "uniform vec4 u_color;" + + "void main() {" + + " gl_FragColor = u_color;" + + "}"; + } } diff --git a/vtm/src/org/oscim/renderer/elements/RenderElement.java b/vtm/src/org/oscim/renderer/elements/RenderElement.java index bb81b326..d5676bcf 100644 --- a/vtm/src/org/oscim/renderer/elements/RenderElement.java +++ b/vtm/src/org/oscim/renderer/elements/RenderElement.java @@ -24,10 +24,11 @@ public abstract class RenderElement extends Inlist { public final static byte LINE = 0; public final static byte POLYGON = 1; - public final static byte TEXLINE = 2; - public final static byte SYMBOL = 3; - public final static byte BITMAP = 4; - public final static byte EXTRUSION = 5; + public static final byte MESH = 2; + public final static byte TEXLINE = 3; + public final static byte SYMBOL = 4; + public final static byte BITMAP = 5; + public final static byte EXTRUSION = 6; protected RenderElement(byte type) { this.type = type;