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();
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

View File

@ -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;"
+ "}";
}
}

View File

@ -24,10 +24,11 @@ public abstract class RenderElement extends Inlist<RenderElement> {
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;