wip: use HairLine for PolygonLayer outlines

This commit is contained in:
Hannes Janetzek 2014-09-10 20:39:03 +02:00
parent 7bf2544a83
commit e830252c85
4 changed files with 102 additions and 77 deletions

View File

@ -81,15 +81,7 @@ public class ThemeStylerActivity extends BaseMapActivity implements OnSeekBarCha
s.set(areaBuilder.set(s) s.set(areaBuilder.set(s)
.color(modColor(s.color, areaColor)) .color(modColor(s.color, areaColor))
.blendColor(modColor(s.blendColor, areaColor)) .blendColor(modColor(s.blendColor, areaColor))
.build()); .strokeColor(modColor(s.strokeColor, areaColor))
if (s.outline == null)
continue;
s.outline.set(lineBuilder.set(s.outline)
.color(modColor(s.outline.color, areaColor))
.stippleColor(modColor(s.outline.stippleColor,
areaColor))
.build()); .build());
} }
} }

View File

@ -17,16 +17,21 @@
package org.oscim.renderer.elements; package org.oscim.renderer.elements;
import static org.oscim.backend.GL20.GL_ALWAYS; import static org.oscim.backend.GL20.GL_ALWAYS;
import static org.oscim.backend.GL20.GL_ELEMENT_ARRAY_BUFFER;
import static org.oscim.backend.GL20.GL_EQUAL; import static org.oscim.backend.GL20.GL_EQUAL;
import static org.oscim.backend.GL20.GL_INVERT; import static org.oscim.backend.GL20.GL_INVERT;
import static org.oscim.backend.GL20.GL_KEEP; import static org.oscim.backend.GL20.GL_KEEP;
import static org.oscim.backend.GL20.GL_LINES;
import static org.oscim.backend.GL20.GL_REPLACE; import static org.oscim.backend.GL20.GL_REPLACE;
import static org.oscim.backend.GL20.GL_SHORT; import static org.oscim.backend.GL20.GL_SHORT;
import static org.oscim.backend.GL20.GL_TRIANGLE_FAN; import static org.oscim.backend.GL20.GL_TRIANGLE_FAN;
import static org.oscim.backend.GL20.GL_TRIANGLE_STRIP; import static org.oscim.backend.GL20.GL_TRIANGLE_STRIP;
import static org.oscim.backend.GL20.GL_UNSIGNED_SHORT;
import static org.oscim.backend.GL20.GL_ZERO; import static org.oscim.backend.GL20.GL_ZERO;
import static org.oscim.utils.FastMath.clamp; import static org.oscim.utils.FastMath.clamp;
import java.nio.ShortBuffer;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLMatrix; import org.oscim.renderer.GLMatrix;
@ -43,7 +48,8 @@ import org.slf4j.LoggerFactory;
/** /**
* Special Renderer for drawing tile polygons using the stencil buffer method * Special Renderer for drawing tile polygons using the stencil buffer method
*/ */
public final class PolygonLayer extends RenderElement { public final class PolygonLayer extends IndexedRenderElement {
static final Logger log = LoggerFactory.getLogger(PolygonLayer.class); static final Logger log = LoggerFactory.getLogger(PolygonLayer.class);
public final static int CLIP_STENCIL = 1; public final static int CLIP_STENCIL = 1;
@ -68,6 +74,10 @@ public final class PolygonLayer extends RenderElement {
public void addPolygon(float[] points, short[] index) { public void addPolygon(float[] points, short[] index) {
short center = (short) ((Tile.SIZE >> 1) * S); short center = (short) ((Tile.SIZE >> 1) * S);
short id = (short) numVertices;
boolean outline = area.strokeWidth > 0;
for (int i = 0, pos = 0, n = index.length; i < n; i++) { for (int i = 0, pos = 0, n = index.length; i < n; i++) {
int length = index[i]; int length = index[i];
if (length < 0) if (length < 0)
@ -79,21 +89,45 @@ public final class PolygonLayer extends RenderElement {
continue; continue;
} }
numVertices += length / 2 + 2; //numVertices += length / 2 + 2;
vertexItems.add(center, center); vertexItems.add(center, center);
id++;
int inPos = pos; int inPos = pos;
for (int j = 0; j < length; j += 2) { for (int j = 0; j < length; j += 2) {
vertexItems.add((short) (points[inPos++] * S), vertexItems.add((short) (points[inPos++] * S),
(short) (points[inPos++] * S)); (short) (points[inPos++] * S));
if (outline) {
indiceItems.add(id++);
numIndices++;
indiceItems.add(id);
numIndices++;
} else {
id++;
}
} }
vertexItems.add((short) (points[pos + 0] * S), vertexItems.add((short) (points[pos + 0] * S),
(short) (points[pos + 1] * S)); (short) (points[pos + 1] * S));
id++;
pos += length; pos += length;
} }
numVertices = id;
}
@Override
protected void compile(ShortBuffer sbuf) {
if (area.strokeWidth == 0) {
/* add vertices to shared VBO */
compileVertexItems(sbuf);
return;
}
/* compile with indexed outline */
super.compile(sbuf);
} }
static class Shader extends GLShader { static class Shader extends GLShader {
@ -121,7 +155,7 @@ public final class PolygonLayer extends RenderElement {
private static final float FADE_START = 1.3f; private static final float FADE_START = 1.3f;
private static AreaStyle[] mAreaFills; private static PolygonLayer[] mAreaFills;
private static Shader polyShader; private static Shader polyShader;
private static Shader texShader; private static Shader texShader;
@ -130,7 +164,7 @@ public final class PolygonLayer extends RenderElement {
polyShader = new Shader("base_shader"); polyShader = new Shader("base_shader");
texShader = new Shader("polygon_layer_tex"); texShader = new Shader("polygon_layer_tex");
mAreaFills = new AreaStyle[STENCIL_BITS]; mAreaFills = new PolygonLayer[STENCIL_BITS];
return true; return true;
} }
@ -143,15 +177,19 @@ public final class PolygonLayer extends RenderElement {
/* do not modify stencil buffer */ /* do not modify stencil buffer */
GL.glStencilMask(0x00); GL.glStencilMask(0x00);
//int shader = polyShader; Shader s;
Shader s = setShader(polyShader, v.mvp, false); for (int i = start; i < end; i++) {
PolygonLayer l = mAreaFills[i];
AreaStyle a = l.area.current();
for (int c = start; c < end; c++) { boolean useTexture = enableTexture && a.texture != null;
AreaStyle a = mAreaFills[c].current(); if (useTexture)
if (enableTexture && a.texture != null) {
s = setShader(texShader, v.mvp, false); s = setShader(texShader, v.mvp, false);
else
s = setShader(polyShader, v.mvp, false);
if (useTexture) {
float num = clamp((Tile.SIZE / a.texture.width) >> 1, 1, Tile.SIZE); float num = clamp((Tile.SIZE / a.texture.width) >> 1, 1, Tile.SIZE);
float transition = Interpolation.exp5.apply(clamp(scale - 1, 0, 1)); float transition = Interpolation.exp5.apply(clamp(scale - 1, 0, 1));
GL.glUniform2f(s.uScale, transition, div / num); GL.glUniform2f(s.uScale, transition, div / num);
@ -184,10 +222,8 @@ public final class PolygonLayer extends RenderElement {
GLUtils.setColor(s.uColor, a.blendColor, 1); GLUtils.setColor(s.uColor, a.blendColor, 1);
} else { } else {
if (a.color < 0xff000000) /* test if color contains alpha */
GLState.blend(true); GLState.blend((a.color & OPAQUE) != OPAQUE);
else
GLState.blend(false);
GLUtils.setColor(s.uColor, a.color, 1); GLUtils.setColor(s.uColor, a.color, 1);
} }
@ -195,14 +231,37 @@ public final class PolygonLayer extends RenderElement {
/* set stencil buffer mask used to draw this layer /* set stencil buffer mask used to draw this layer
* also check that clip bit is set to avoid overdraw * also check that clip bit is set to avoid overdraw
* of other tiles */ * of other tiles */
GL.glStencilFunc(GL_EQUAL, 0xff, CLIP_BIT | 1 << c); GL.glStencilFunc(GL_EQUAL, 0xff, CLIP_BIT | 1 << i);
/* draw tile fill coordinates */ /* draw tile fill coordinates */
GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable texture shader */ if (l.indicesVbo == null)
if (s != polyShader) continue;
s = setShader(polyShader, v.mvp, false);
GL.glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT);
GLState.blend(true);
//GLState.testDepth(false);
HairLineLayer.Renderer.shader.set(v);
l.indicesVbo.bind();
GLUtils.setColor(HairLineLayer.Renderer.shader.uColor, l.area.strokeColor, 1);
GL.glVertexAttribPointer(HairLineLayer.Renderer.shader.aPos, 2, GL_SHORT,
false, 0, l.offset << 2);
GL.glDrawElements(GL_LINES, l.numIndices,
GL_UNSIGNED_SHORT, 0);
GL.glLineWidth(1);
GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
///* disable texture shader */
//if (s != polyShader)
//s = setShader(polyShader, v, false);
} }
} }
@ -280,7 +339,7 @@ public final class PolygonLayer extends RenderElement {
start = cur = 0; start = cur = 0;
} }
mAreaFills[cur] = pl.area.current(); mAreaFills[cur] = pl;
/* set stencil mask to draw to */ /* set stencil mask to draw to */
GL.glStencilMask(1 << cur++); GL.glStencilMask(1 << cur++);

View File

@ -472,8 +472,7 @@ public class XmlThemeBuilder extends DefaultHandler {
} }
} }
AreaStyle area = createArea(style, localName, attributes, mLevels); AreaStyle area = createArea(style, localName, attributes, mLevels++);
mLevels += 2;
if (isStyle) { if (isStyle) {
mStyles.put(AREA_STYLE + area.style, area); mStyles.put(AREA_STYLE + area.style, area);
@ -509,12 +508,12 @@ public class XmlThemeBuilder extends DefaultHandler {
b.color(value); b.color(value);
else if ("stroke".equals(name)) else if ("stroke".equals(name))
b.outlineColor(value); b.strokeColor(value);
else if ("stroke-width".equals(name)) { else if ("stroke-width".equals(name)) {
float strokeWidth = Float.parseFloat(value); float strokeWidth = Float.parseFloat(value);
validateNonNegative("stroke-width", strokeWidth); validateNonNegative("stroke-width", strokeWidth);
b.outlineWidth = strokeWidth; b.strokeWidth = strokeWidth;
} else if ("fade".equals(name)) } else if ("fade".equals(name))
b.fadeScale = Integer.parseInt(value); b.fadeScale = Integer.parseInt(value);

View File

@ -46,7 +46,8 @@ public class AreaStyle extends RenderStyle {
public final TextureItem texture; public final TextureItem texture;
/** Outline */ /** Outline */
public final LineStyle outline; public final int strokeColor;
public final float strokeWidth;
public AreaStyle(int color) { public AreaStyle(int color) {
this(0, color); this(0, color);
@ -60,7 +61,8 @@ public class AreaStyle extends RenderStyle {
this.blendScale = -1; this.blendScale = -1;
this.color = color; this.color = color;
this.texture = null; this.texture = null;
this.outline = null; this.strokeColor = color;
this.strokeWidth = 1;
} }
public AreaStyle(AreaBuilder b) { public AreaStyle(AreaBuilder b) {
@ -72,23 +74,8 @@ public class AreaStyle extends RenderStyle {
this.color = b.color; this.color = b.color;
this.texture = b.texture; this.texture = b.texture;
if (b.outline != null && this.strokeColor = b.strokeColor;
b.outlineColor == b.outline.color && this.strokeWidth = b.strokeWidth;
b.outlineWidth == b.outline.width) {
this.outline = b.outline;
} else if (b.outlineColor != Color.TRANSPARENT) {
this.outline = new LineStyle(-1, b.outlineColor, b.outlineWidth);
} else {
this.outline = null;
}
}
@Override
public void update() {
super.update();
if (outline != null)
outline.update();
} }
@Override @Override
@ -99,22 +86,18 @@ public class AreaStyle extends RenderStyle {
@Override @Override
public void renderWay(Callback renderCallback) { public void renderWay(Callback renderCallback) {
renderCallback.renderArea(this, level); renderCallback.renderArea(this, level);
if (outline != null)
renderCallback.renderWay(outline, level + 1);
} }
public static class AreaBuilder implements StyleBuilder { public static class AreaBuilder implements StyleBuilder {
public int level; public int level;
public String style; public String style;
public LineStyle outline;
public int color; public int color;
public int fadeScale; public int fadeScale;
public int blendColor; public int blendColor;
public int blendScale; public int blendScale;
public int outlineColor; public int strokeColor;
public float outlineWidth; public float strokeWidth;
public TextureItem texture; public TextureItem texture;
@ -129,14 +112,8 @@ public class AreaStyle extends RenderStyle {
this.blendScale = area.blendScale; this.blendScale = area.blendScale;
this.color = area.color; this.color = area.color;
this.texture = area.texture; this.texture = area.texture;
this.outline = area.outline; this.strokeColor = area.strokeColor;
if (area.outline != null) { this.strokeWidth = area.strokeWidth;
this.outlineColor = outline.color;
this.outlineWidth = outline.width;
} else {
outlineColor = Color.TRANSPARENT;
outlineWidth = 1;
}
return this; return this;
} }
@ -152,23 +129,23 @@ public class AreaStyle extends RenderStyle {
} }
public AreaBuilder outline(int color, float width) { public AreaBuilder outline(int color, float width) {
this.outlineColor = color; this.strokeColor = color;
this.outlineWidth = width; this.strokeWidth = width;
return this; return this;
} }
public AreaBuilder outlineColor(int color) { public AreaBuilder strokeColor(int color) {
this.outlineColor = color; this.strokeColor = color;
return this; return this;
} }
public AreaBuilder outlineColor(String color) { public AreaBuilder strokeColor(String color) {
this.outlineColor = parseColor(color); this.strokeColor = parseColor(color);
return this; return this;
} }
public AreaBuilder outlineWidth(float width) { public AreaBuilder strokeWidth(float width) {
this.outlineWidth = width; this.strokeWidth = width;
return this; return this;
} }
@ -209,10 +186,8 @@ public class AreaStyle extends RenderStyle {
public AreaBuilder reset() { public AreaBuilder reset() {
color = Color.BLACK; color = Color.BLACK;
strokeColor = Color.BLACK;
outlineColor = Color.TRANSPARENT; strokeWidth = 0;
outlineWidth = 1;
fadeScale = -1; fadeScale = -1;
blendScale = -1; blendScale = -1;
blendColor = Color.TRANSPARENT; blendColor = Color.TRANSPARENT;