diff --git a/src/org/oscim/renderer/LineRenderer.java b/src/org/oscim/renderer/LineRenderer.java index 47e02678..4645e8ac 100644 --- a/src/org/oscim/renderer/LineRenderer.java +++ b/src/org/oscim/renderer/LineRenderer.java @@ -25,9 +25,6 @@ import static android.opengl.GLES20.glUniformMatrix4fv; import static android.opengl.GLES20.glUseProgram; import static android.opengl.GLES20.glVertexAttribPointer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - import org.oscim.core.MapPosition; import org.oscim.generator.TileGenerator; import org.oscim.renderer.layer.Layer; @@ -84,6 +81,8 @@ public final class LineRenderer { //hLineTexturePosition[i] = glGetAttribLocation(lineProgram[i], "a_st"); } + // create lookup table as texture for 'length(0..1,0..1)' + // using mirrored wrap mode for 'length(-1..1,-1..1)' byte[] pixel = new byte[128 * 128]; for (int x = 0; x < 128; x++) { @@ -94,32 +93,11 @@ public final class LineRenderer { if (color > 255) color = 255; pixel[x + y * 128] = (byte) color; - //pixel[(127 - x) + (127 - y) * 128] = (byte) color; } } - int[] textureIds = new int[1]; - GLES20.glGenTextures(1, textureIds, 0); - mTexID = textureIds[0]; - - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID); - - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, - GLES20.GL_NEAREST); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, - GLES20.GL_NEAREST); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, - GLES20.GL_MIRRORED_REPEAT); // Set U Wrapping - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, - GLES20.GL_MIRRORED_REPEAT); // Set V Wrapping - - ByteBuffer buf = ByteBuffer.allocateDirect(128 * 128).order(ByteOrder.nativeOrder()); - buf.put(pixel); - buf.position(0); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_ALPHA, 128, 128, 0, GLES20.GL_ALPHA, - GLES20.GL_UNSIGNED_BYTE, buf); - - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); + mTexID = GlUtils.loadTexture(pixel, 128, 128, GLES20.GL_ALPHA, + GLES20.GL_MIRRORED_REPEAT, GLES20.GL_MIRRORED_REPEAT); return true; } @@ -158,9 +136,16 @@ public final class LineRenderer { glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0); + // line scale factor for non fixed lines: within a zoom- + // level lines would be scaled by the factor 2 via projection. + // though lines should only scale by sqrt(2). this is achieved + // by inverting scaling of extrusion vector with: width/sqrt(s). + // within one zoom-level: 1 <= s <= 2 + float s = scale / div; + float lineScale = (float) Math.sqrt(s * 2 / 2.2); + // scale factor to map one pixel on tile to one pixel on screen: // only works with orthographic projection - float s = scale / div; float pixel = 0; if (mode == 1) @@ -170,8 +155,6 @@ public final class LineRenderer { int lineMode = 0; glUniform1i(uLineMode, lineMode); - // line scale factor (for non fixed lines) - float lineScale = (float) Math.sqrt(s); float blurScale = pixel; boolean blur = false; // dont increase scale when max is reached @@ -199,13 +182,17 @@ public final class LineRenderer { } if (line.outline) { - // draw outline for linelayers references by this outline + // draw linelayers references by this outline for (LineLayer o = ll.outlines; o != null; o = o.outlines) { if (o.line.fixed || strokeMaxZoom) { width = (ll.width + o.width) / s; } else { width = ll.width / s + o.width / lineScale; + + // check min size for outline + if (o.line.min > 0 && o.width * lineScale < o.line.min * 2) + continue; } glUniform1f(uLineWidth, width); @@ -228,7 +215,6 @@ public final class LineRenderer { lineMode = 0; glUniform1i(uLineMode, lineMode); } - glDrawArrays(GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); } } else { @@ -239,6 +225,9 @@ public final class LineRenderer { width = ll.width / s; } else { width = ll.width / lineScale; + + if (ll.line.min > 0 && ll.width * lineScale < ll.line.min * 2) + width = (ll.width - 0.2f) / lineScale; } glUniform1f(uLineWidth, width); diff --git a/src/org/oscim/theme/renderinstruction/Line.java b/src/org/oscim/theme/renderinstruction/Line.java index 9888c626..a89f1f96 100644 --- a/src/org/oscim/theme/renderinstruction/Line.java +++ b/src/org/oscim/theme/renderinstruction/Line.java @@ -56,14 +56,15 @@ public final class Line extends RenderInstruction { boolean fixed = false; String style = null; float blur = 0; + float min = 0; if (line != null) { fixed = line.fixed; fade = line.fade; strokeLinecap = line.cap; blur = line.blur; + min = line.min; } - for (int i = 0; i < attributes.getLength(); ++i) { String name = attributes.getLocalName(i); String value = attributes.getValue(i); @@ -82,6 +83,8 @@ public final class Line extends RenderInstruction { strokeLinecap = Cap.valueOf(value.toUpperCase(Locale.ENGLISH)); } else if ("fade".equals(name)) { fade = Integer.parseInt(value); + } else if ("min".equals(name)) { + min = Float.parseFloat(value); } else if ("fixed".equals(name)) { fixed = Boolean.parseBoolean(value); } else if ("blur".equals(name)) { @@ -102,14 +105,14 @@ public final class Line extends RenderInstruction { strokeWidth = 1; return new Line(line, style, src, stroke, strokeWidth, stipple, - strokeLinecap, level, fixed, fade, blur, isOutline); + strokeLinecap, level, fixed, fade, blur, isOutline, min); } if (!isOutline) validate(strokeWidth); return new Line(style, src, stroke, strokeWidth, stipple, strokeLinecap, - level, fixed, fade, blur, isOutline); + level, fixed, fade, blur, isOutline, min); } public Line(int stroke, float width, Cap cap) { @@ -122,6 +125,7 @@ public final class Line extends RenderInstruction { this.fixed = true; this.fade = -1; this.stipple = 2; + this.min = 0; color = GlUtils.colorToFloatP(stroke); } @@ -163,6 +167,8 @@ public final class Line extends RenderInstruction { public final int stipple; + public final float min; + /** * @param style * ... @@ -186,10 +192,11 @@ public final class Line extends RenderInstruction { * ... * @param isOutline * ... + * @param min ... */ private Line(String style, String src, int stroke, float strokeWidth, int stipple, Cap strokeLinecap, int level, boolean fixed, - int fade, float blur, boolean isOutline) { + int fade, float blur, boolean isOutline, float min) { super(); this.style = style; @@ -221,6 +228,7 @@ public final class Line extends RenderInstruction { this.blur = blur; this.fade = fade; this.stipple = stipple; + this.min = min; } /** @@ -248,10 +256,11 @@ public final class Line extends RenderInstruction { * ... * @param isOutline * ... + * @param min ... */ private Line(Line line, String style, String src, int stroke, float strokeWidth, int stipple, Cap strokeLinecap, int level, boolean fixed, - int fade, float blur, boolean isOutline) { + int fade, float blur, boolean isOutline, float min) { super(); this.style = style; @@ -268,6 +277,7 @@ public final class Line extends RenderInstruction { this.cap = strokeLinecap; this.blur = blur; this.stipple = stipple; + this.min = min; } @Override diff --git a/src/org/oscim/utils/GlUtils.java b/src/org/oscim/utils/GlUtils.java index 353665e7..e3b1a4a0 100644 --- a/src/org/oscim/utils/GlUtils.java +++ b/src/org/oscim/utils/GlUtils.java @@ -14,6 +14,9 @@ */ package org.oscim.utils; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + import org.oscim.renderer.GLRenderer; import android.graphics.Bitmap; @@ -38,20 +41,23 @@ public class GlUtils { GLES20.glGenTextures(1, textures, 0); int textureID = textures[0]; - // Log.i(TAG, "new texture " + textureID + " " + textureCnt++); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); @@ -59,6 +65,37 @@ public class GlUtils { return textureID; } + public static int loadTexture(byte[] pixel, int width, int height, int format, + int wrap_s, int wrap_t) { + int[] textureIds = new int[1]; + GLES20.glGenTextures(1, textureIds, 0); + + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]); + + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_MIN_FILTER, + GLES20.GL_NEAREST); + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_MAG_FILTER, + GLES20.GL_NEAREST); + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_WRAP_S, + wrap_s); // Set U Wrapping + GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, + GLES20.GL_TEXTURE_WRAP_T, + wrap_t); // Set V Wrapping + + ByteBuffer buf = ByteBuffer.allocateDirect(width * height).order(ByteOrder.nativeOrder()); + buf.put(pixel); + buf.position(0); + + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, format, width, height, 0, format, + GLES20.GL_UNSIGNED_BYTE, buf); + + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); + return textureIds[0]; + } + /** * @param shaderType * shader type