start of MeshLayer for 2D Meshes w/ tessellation

This commit is contained in:
Hannes Janetzek 2013-09-25 02:56:25 +02:00
parent 836f6a60e0
commit c519a4f34b
3 changed files with 165 additions and 66 deletions

View File

@ -32,9 +32,13 @@ public class ElementLayers {
PolygonLayer.Renderer.init(); PolygonLayer.Renderer.init();
TextureLayer.Renderer.init(); TextureLayer.Renderer.init();
BitmapLayer.Renderer.init(); BitmapLayer.Renderer.init();
MeshLayer.Renderer.init();
TextureItem.init(gl, 0); TextureItem.init(gl, 0);
} }
// FIXME use one ArrayList for these!
// mixed Polygon- and LineLayer // mixed Polygon- and LineLayer
public RenderElement baseLayers; public RenderElement baseLayers;
// Text- and SymbolLayer // Text- and SymbolLayer
@ -87,6 +91,14 @@ public class ElementLayers {
return (LineLayer) getLayer(level, RenderElement.LINE); 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 * Get or add the PolygonLayer for a level. Levels are ordered from
* bottom (0) to top * bottom (0) to top
@ -115,6 +127,12 @@ public class ElementLayers {
RenderElement l = baseLayers; RenderElement l = baseLayers;
RenderElement renderElement = null; 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) { if (mCurLayer != null && mCurLayer.level == level) {
renderElement = mCurLayer; renderElement = mCurLayer;
} else { } else {
@ -146,9 +164,8 @@ public class ElementLayers {
renderElement = new PolygonLayer(level); renderElement = new PolygonLayer(level);
else if (type == RenderElement.TEXLINE) else if (type == RenderElement.TEXLINE)
renderElement = new LineTexLayer(level); renderElement = new LineTexLayer(level);
else else if (type == RenderElement.MESH)
// TODO throw execption renderElement = new MeshLayer(level);
return null;
if (l == null) { if (l == null) {
// insert at start // insert at start
@ -177,6 +194,7 @@ public class ElementLayers {
private final static int[] VERTEX_SHORT_CNT = { private final static int[] VERTEX_SHORT_CNT = {
4, // LINE_VERTEX_SHORTS 4, // LINE_VERTEX_SHORTS
2, // POLY_VERTEX_SHORTS 2, // POLY_VERTEX_SHORTS
2, // MESH_VERTEX_SHORTS
6, // TEXLINE_VERTEX_SHORTS 6, // TEXLINE_VERTEX_SHORTS
}; };
@ -212,6 +230,7 @@ public class ElementLayers {
size += addLayerItems(sbuf, baseLayers, RenderElement.LINE, 0); size += addLayerItems(sbuf, baseLayers, RenderElement.LINE, 0);
texLineOffset = size * SHORT_BYTES; texLineOffset = size * SHORT_BYTES;
for (RenderElement l = baseLayers; l != null; l = l.next) { for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == RenderElement.TEXLINE) { if (l.type == RenderElement.TEXLINE) {
addPoolItems(l, sbuf); 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) { for (RenderElement l = textureLayers; l != null; l = l.next) {
TextureLayer tl = (TextureLayer) l; //TextureLayer tl = (TextureLayer) l;
tl.compile(sbuf); l.compile(sbuf);
} }
// extrusion layers are compiled by extrusion overlay // extrusion layers are compiled by extrusion overlay

View File

@ -15,91 +15,165 @@
package org.oscim.renderer.elements; package org.oscim.renderer.elements;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.Arrays;
import org.oscim.backend.GL20;
import org.oscim.backend.Log; import org.oscim.backend.Log;
import org.oscim.backend.canvas.Color;
import org.oscim.core.GeometryBuffer; 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 { public class MeshLayer extends RenderElement {
GeometryBuffer mGeom = new GeometryBuffer(10, 10); private static final String TAG = MeshLayer.class.getName();
public MeshLayer() { BufferObject indicesVbo;
GeometryBuffer e = mGeom; int numIndices;
int size = Tile.SIZE; VertexItem indiceItems;
float x1 = -1; public MeshLayer(int level) {
float y1 = -1; super(RenderElement.MESH);
float x2 = size + 1; this.level = level;
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 void addMesh(GeometryBuffer geom) { public void addMesh(GeometryBuffer geom) {
int numRings = 2; if (vertexItems == null) {
vertexItems = VertexItem.pool.get();
long ctx = tessellate(geom.points, 0, geom.index, 0, numRings); indiceItems = VertexItem.pool.get();
short[] coordinates = new short[100];
while (tessGetCoordinates(ctx, coordinates, 2) > 0) {
Log.d("..", Arrays.toString(coordinates));
} }
while (tessGetIndices(ctx, coordinates) > 0) { numIndices += Tessellator.tessellate(geom, MapRenderer.COORD_SCALE,
Log.d("..", Arrays.toString(coordinates)); 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 @Override
protected void compile(ShortBuffer sbuf) { 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 @Override
protected void clear() { protected void clear() {
BufferObject.release(indicesVbo);
VertexItem.pool.releaseAll(indiceItems);
VertexItem.pool.releaseAll(vertexItems);
indiceItems = null;
vertexItems = null;
indicesVbo = null;
} }
/** public static class Renderer {
* @param points an array of x,y coordinates private static int shaderProgram;
* @param pos position in points array private static int hMatrix;
* @param index geom indices private static int hColor;
* @param ipos position in index array private static int hVertexPosition;
* @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 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;"
+ "}";
}
} }

View File

@ -24,10 +24,11 @@ public abstract class RenderElement extends Inlist<RenderElement> {
public final static byte LINE = 0; public final static byte LINE = 0;
public final static byte POLYGON = 1; public final static byte POLYGON = 1;
public final static byte TEXLINE = 2; public static final byte MESH = 2;
public final static byte SYMBOL = 3; public final static byte TEXLINE = 3;
public final static byte BITMAP = 4; public final static byte SYMBOL = 4;
public final static byte EXTRUSION = 5; public final static byte BITMAP = 5;
public final static byte EXTRUSION = 6;
protected RenderElement(byte type) { protected RenderElement(byte type) {
this.type = type; this.type = type;