add mesh-only mode to ExtrusionRenderer/Layer

This commit is contained in:
Hannes Janetzek 2014-03-08 01:21:46 +01:00
parent eb41496c5a
commit 8064dda6ac
2 changed files with 128 additions and 125 deletions

View File

@ -20,7 +20,6 @@ import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY;
import org.oscim.backend.GL20;
import org.oscim.backend.canvas.Color;
import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileRenderer;
@ -45,6 +44,14 @@ public class ExtrusionRenderer extends LayerRenderer {
mTileLayer = tileRenderLayer;
mTileSet = new TileSet();
mTileZoom = tileZoom;
mMode = 0;
}
public ExtrusionRenderer(TileRenderer tileRenderLayer, int tileZoom, boolean mesh) {
mTileLayer = tileRenderLayer;
mTileSet = new TileSet();
mTileZoom = tileZoom;
mMode = mesh ? 1 : 0;
}
private static int[] shaderProgram = new int[2];
@ -61,18 +68,18 @@ public class ExtrusionRenderer extends LayerRenderer {
private MapTile[] mTiles;
private int mTileCnt;
private final static int SHADER = 0;
private final int mMode;
private boolean initShader() {
initialized = true;
for (int i = 0; i <= SHADER; i++) {
for (int i = 0; i < 2; i++) {
if (i == 0) {
shaderProgram[i] = GLShader.createProgram(extrusionVertexShader,
extrusionFragmentShader);
} else {
shaderProgram[i] = GLShader.createProgram(extrusionVertexShader,
extrusionFragmentShaderZ);
shaderProgram[i] = GLShader.createProgram(extrusionVertexShader2,
extrusionFragmentShader);
}
if (shaderProgram[i] == 0) {
@ -105,13 +112,6 @@ public class ExtrusionRenderer extends LayerRenderer {
return;
}
// if (mUpdateColors) {
// synchronized (this) {
// System.arraycopy(mNewColors, 0, mColor, 0, 16);
// mUpdateColors = false;
// }
// }
int activeTiles = 0;
mTileLayer.getVisibleTiles(mTileSet);
MapTile[] tiles = mTileSet.tiles;
@ -131,17 +131,7 @@ public class ExtrusionRenderer extends LayerRenderer {
ExtrusionLayer el;
if (zoom == mTileZoom) {
for (int i = 0; i < mTileSet.cnt; i++) {
el = getLayer(tiles[i]);
if (el == null)
continue;
if (!el.compiled) {
int numShorts = el.sumVertices * 8;
el.compile(MapRenderer.getShortBuffer(numShorts));
GLUtils.checkGlError("...");
}
if (el.compiled)
if (compileLayers(getLayer(tiles[i])))
mTiles[activeTiles++] = tiles[i];
}
} else if (zoom == mTileZoom + 1) {
@ -159,13 +149,7 @@ public class ExtrusionRenderer extends LayerRenderer {
if (el == null)
continue;
if (!el.compiled) {
int numShorts = el.sumVertices * 8;
el.compile(MapRenderer.getShortBuffer(numShorts));
GLUtils.checkGlError("...");
}
if (el.compiled)
if (compileLayers(el))
mTiles[activeTiles++] = t;
}
} else if (zoom == mTileZoom - 1) {
@ -187,24 +171,6 @@ public class ExtrusionRenderer extends LayerRenderer {
}
}
// // check if proxy children are ready
// for (int i = 0; i < mTileSet.cnt; i++) {
// MapTile t = tiles[i];
// for (byte j = 0; j < 4; j++) {
// if (!t.hasProxy(1 << j))
// continue;
//
// MapTile c = t.rel.get(j);
// el = getLayer(c);
//
// if (el == null || !el.compiled)
// continue;
//
// mTiles[activeTiles++] = c;
// }
// }
// }
mTileCnt = activeTiles;
//log.debug("" + activeTiles + " " + zoom);
@ -214,6 +180,26 @@ public class ExtrusionRenderer extends LayerRenderer {
mTileLayer.releaseTiles(mTileSet);
}
private boolean compileLayers(ExtrusionLayer el) {
if (el == null)
return false;
if (el.compiled)
return true;
boolean compiled = false;
for (; el != null; el = (ExtrusionLayer) el.next) {
if (!el.compiled) {
int numShorts = el.sumVertices * 8;
el.compile(MapRenderer.getShortBuffer(numShorts));
GLUtils.checkGlError("...");
}
compiled |= el.compiled;
}
return compiled;
}
private static ExtrusionLayer getLayer(MapTile t) {
ElementLayers layers = t.getLayers();
if (layers == null || !t.state(READY | NEW_DATA))
@ -233,15 +219,15 @@ public class ExtrusionRenderer extends LayerRenderer {
MapTile[] tiles = mTiles;
int uExtAlpha = hAlpha[SHADER];
int uExtColor = hColor[SHADER];
int uExtVertexPosition = hVertexPosition[SHADER];
int uExtLightPosition = hLightPosition[SHADER];
int uExtMatrix = hMatrix[SHADER];
int uExtMode = hMode[SHADER];
int uExtAlpha = hAlpha[mMode];
int uExtColor = hColor[mMode];
int uExtVertexPosition = hVertexPosition[mMode];
int uExtLightPosition = hLightPosition[mMode];
int uExtMatrix = hMatrix[mMode];
int uExtMode = hMode[mMode];
if (debug) {
GLState.useProgram(shaderProgram[SHADER]);
GLState.useProgram(shaderProgram[mMode]);
GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition);
GL.glUniform1i(uExtMode, 0);
@ -266,12 +252,14 @@ public class ExtrusionRenderer extends LayerRenderer {
GL20.GL_UNSIGNED_BYTE, false, 8, 6);
GL.glDrawElements(GL20.GL_TRIANGLES,
(el.numIndices[0] + el.numIndices[1] + el.numIndices[2]),
(el.numIndices[0] + el.numIndices[1]
+ el.numIndices[2]),
GL20.GL_UNSIGNED_SHORT, 0);
GL.glDrawElements(GL20.GL_LINES, el.numIndices[3],
GL20.GL_UNSIGNED_SHORT,
(el.numIndices[0] + el.numIndices[1] + el.numIndices[2]) * 2);
(el.numIndices[0] + el.numIndices[1]
+ el.numIndices[2]) * 2);
// just a temporary reference!
tiles[i] = null;
@ -286,7 +274,7 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.test(true, false);
GLState.useProgram(shaderProgram[SHADER]);
GLState.useProgram(shaderProgram[mMode]);
GLState.enableVertexArrays(uExtVertexPosition, -1);
GLState.blend(false);
@ -319,7 +307,8 @@ public class ExtrusionRenderer extends LayerRenderer {
GL20.GL_SHORT, false, 8, 0);
GL.glDrawElements(GL20.GL_TRIANGLES,
(el.numIndices[0] + el.numIndices[1] + el.numIndices[2]),
(el.numIndices[0] + el.numIndices[1]
+ el.numIndices[2]),
GL20.GL_UNSIGNED_SHORT, 0);
}
}
@ -340,12 +329,15 @@ public class ExtrusionRenderer extends LayerRenderer {
ExtrusionLayer el = t.getLayers().getExtrusionLayers();
for (; el != null; el = (ExtrusionLayer) el.next) {
if (el.vboIndices == null)
continue;
if (el.colors == null) {
currentColor = mColor;
GLUtils.glUniform4fv(uExtColor, 4, currentColor);
GLUtils.glUniform4fv(uExtColor, mMode == 0 ? 4 : 1, currentColor);
} else if (currentColor != el.colors) {
currentColor = el.colors;
GLUtils.glUniform4fv(uExtColor, 4, currentColor);
GLUtils.glUniform4fv(uExtColor, mMode == 0 ? 4 : 1, currentColor);
}
int d = 1;
@ -440,41 +432,6 @@ public class ExtrusionRenderer extends LayerRenderer {
v.mvp.addDepthOffset(delta);
}
public synchronized void setColors(float[] colors) {
System.arraycopy(colors, 0, mNewColors, 0, 16);
mUpdateColors = true;
}
public synchronized void setColors(int sides, int top, int lines) {
fillColors(sides, top, lines);
mUpdateColors = true;
}
private void fillColors(int sides, int top, int lines) {
mNewColors[0] = Color.rToFloat(top);
mNewColors[1] = Color.gToFloat(top);
mNewColors[2] = Color.bToFloat(top);
mNewColors[3] = Color.aToFloat(top);
mNewColors[4] = Color.rToFloat(sides);
mNewColors[5] = Color.gToFloat(sides);
mNewColors[6] = Color.bToFloat(sides);
mNewColors[7] = Color.aToFloat(sides);
mNewColors[8] = Color.rToFloat(sides);
mNewColors[9] = Color.gToFloat(sides);
mNewColors[10] = Color.bToFloat(sides);
mNewColors[11] = Color.aToFloat(sides);
mNewColors[12] = Color.rToFloat(lines);
mNewColors[13] = Color.gToFloat(lines);
mNewColors[14] = Color.bToFloat(lines);
mNewColors[15] = Color.aToFloat(lines);
}
private volatile boolean mUpdateColors;
private final float[] mNewColors = new float[16];
private final float _a = 0.88f;
private final float _r = 0xe9;
private final float _g = 0xe8;
@ -575,17 +532,43 @@ public class ExtrusionRenderer extends LayerRenderer {
+ " color = vec4(l, l, l-0.02, 1.0);"
+ "}}}";
// vec3 decode(vec2 enc)
// {
// vec2 fenc = enc * 4.0 - 2.0;
// float f = dot(fenc, fenc);
// float g = sqrt(1.0 - f / 4.0);
//
// vec3 n;
// n.xy = fenc * g;
// n.z = 1.0 - f / 2.0;
// return n;
// }
final static String extrusionVertexShader2 = ""
+ "uniform mat4 u_mvp;"
+ "uniform vec4 u_color;"
+ "uniform float u_alpha;"
+ "attribute vec4 a_pos;"
+ "attribute vec2 a_light;"
+ "varying vec4 color;"
+ "varying float depth;"
+ "void main() {"
// change height by u_alpha
+ " vec4 pos = a_pos;"
+ " pos.z *= u_alpha;"
+ " gl_Position = u_mvp * pos;"
// normalize face x/y direction
+ " vec2 enc = (a_light / 255.0);"
+ " vec2 fenc = enc * 4.0 - 2.0;"
+ " float f = dot(fenc, fenc);"
+ " float g = sqrt(1.0 - f / 4.0);"
+ " vec3 r_norm;"
+ " r_norm.xy = fenc * g;"
+ " r_norm.z = 1.0 - f / 2.0;"
// normal points up or down (1,-1)
////+ " float dir = 1.0 - (2.0 * abs(mod(a_light.x,2.0)));"
// recreate face normal vector
///+ " vec3 r_norm = vec3(n.xy, dir * (1.0 - length(n.xy)));"
+ " vec3 light = normalize(vec3(-0.2,0.2,1.0));"
+ " float l = (1.0 + dot(r_norm, light)) / 2.0;"
/** ambient */
//+ " l = 0.2 + l * 0.8;"
/** extreme fake-ssao by height */
+ " l = l + (clamp(a_pos.z / 8192.0, 0.0, 0.1) - 0.05);"
+ " color = u_color * l;" //vec4(l, l, l-0.02, 1.0);"
+ "}";
final static String extrusionFragmentShader = ""
+ "precision mediump float;"
@ -594,13 +577,13 @@ public class ExtrusionRenderer extends LayerRenderer {
+ " gl_FragColor = color;"
+ "}";
final static String extrusionFragmentShaderZ = ""
+ "precision mediump float;"
+ "varying float depth;"
+ "void main() {"
+ "float d = depth * 0.2;"
+ "if (d < 0.0)"
+ " d = -d;"
+ " gl_FragColor = vec4(1.0 - d, 1.0 - d, 1.0 - d, 1.0 - d);"
+ "}";
//final static String extrusionFragmentShaderZ = ""
// + "precision mediump float;"
// + "varying float depth;"
// + "void main() {"
// + "float d = depth * 0.2;"
// + "if (d < 0.0)"
// + " d = -d;"
// + " gl_FragColor = vec4(1.0 - d, 1.0 - d, 1.0 - d, 1.0 - d);"
// + "}";
}

View File

@ -20,6 +20,7 @@ import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Color;
import org.oscim.core.GeometryBuffer;
import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement;
@ -33,11 +34,6 @@ import org.oscim.utils.pool.Inlist;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Hannes Janetzek
* FIXME check if polygon has self intersections or 0/180 degree
* angles! or bad things might happen in Triangle
*/
public class ExtrusionLayer extends RenderElement {
static final Logger log = LoggerFactory.getLogger(ExtrusionLayer.class);
@ -48,10 +44,11 @@ public class ExtrusionLayer extends RenderElement {
private final VertexItem mCurIndices[];
private LineClipper mClipper;
/** 16 floats rgba for top, even-side, odd-sides and outline */
public final float[] colors;
public final int color;
// indices for:
// 0. even sides, 1. odd sides, 2. roof, 3. roof outline
/** indices for: 0. even sides, 1. odd sides, 2. roof, 3. roof outline */
public int numIndices[] = { 0, 0, 0, 0, 0 };
public int sumIndices = 0;
public int sumVertices = 0;
@ -65,7 +62,7 @@ public class ExtrusionLayer extends RenderElement {
private final static int IND_OUTLINE = 3;
private final static int IND_MESH = 4;
private static final int NORMAL_DIR_MASK = 0xFFFFFFFE;
//private static final int NORMAL_DIR_MASK = 0xFFFFFFFE;
public boolean compiled = false;
private final float mGroundResolution;
@ -76,6 +73,7 @@ public class ExtrusionLayer extends RenderElement {
super(RenderElement.EXTRUSION);
this.level = level;
this.colors = colors;
this.color = 0;
mGroundResolution = groundResolution;
mVertices = mCurVertices = VertexItem.pool.get();
@ -88,6 +86,29 @@ public class ExtrusionLayer extends RenderElement {
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE);
}
/**
* ExtrusionLayer for Mesh elements only.
*/
public ExtrusionLayer(int level, float groundResolution, int color) {
super(RenderElement.EXTRUSION);
this.level = level;
this.color = color;
this.colors = new float[4];
float a = Color.aToFloat(color);
colors[0] = a * Color.rToFloat(color);
colors[1] = a * Color.gToFloat(color);
colors[2] = a * Color.bToFloat(color);
colors[3] = a;
mGroundResolution = groundResolution;
mVertices = mCurVertices = VertexItem.pool.get();
mIndices = new VertexItem[5];
mCurIndices = new VertexItem[5];
mIndices[4] = mCurIndices[4] = VertexItem.pool.get();
}
public void add(MapElement element) {
if (element.type != GeometryType.TRIS)
return;
@ -156,7 +177,6 @@ public class ExtrusionLayer extends RenderElement {
double len = Math.sqrt(cx * cx + cy * cy + cz * cz);
// packing the normal in two bytes
//(cx / len) / p + 0.5
double p = Math.sqrt((cz / len) * 8.0 + 8.0);
int mx = FastMath.clamp(127 + (int) ((cx / len / p) * 128), 0, 255);
int my = FastMath.clamp(127 + (int) ((cy / len / p) * 128), 0, 255);