From 8d350238cfea47bcd68c3b62014c8d65265087d3 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Wed, 12 Feb 2014 02:08:19 +0100 Subject: [PATCH] add heightOffset for Line- and MeshLayer --- vtm-android-app | 2 +- .../src/org/oscim/android/MapScaleBar.java | 2 +- .../org/oscim/core/MercatorProjection.java | 9 ++++- .../oscim/renderer/elements/LineLayer.java | 33 ++++++++++++++----- .../oscim/renderer/elements/MeshLayer.java | 18 ++++++++-- 5 files changed, 50 insertions(+), 14 deletions(-) diff --git a/vtm-android-app b/vtm-android-app index d6130727..329c626e 160000 --- a/vtm-android-app +++ b/vtm-android-app @@ -1 +1 @@ -Subproject commit d613072705824f130b1223ca82af2ae148835f41 +Subproject commit 329c626e1ab0799019ac06f694227deac5f4702b diff --git a/vtm-android/src/org/oscim/android/MapScaleBar.java b/vtm-android/src/org/oscim/android/MapScaleBar.java index 56a0a72c..9af443f0 100644 --- a/vtm-android/src/org/oscim/android/MapScaleBar.java +++ b/vtm-android/src/org/oscim/android/MapScaleBar.java @@ -117,7 +117,7 @@ public class MapScaleBar extends Layer implements UpdateListener { mPrevLatitude = latitude; double groundResolution = MercatorProjection - .calculateGroundResolution(latitude, mapPosition.scale); + .groundResolution(latitude, mapPosition.scale); int[] scaleBarValues; if (mImperialUnits) { diff --git a/vtm/src/org/oscim/core/MercatorProjection.java b/vtm/src/org/oscim/core/MercatorProjection.java index cb26bdc4..08c7d659 100644 --- a/vtm/src/org/oscim/core/MercatorProjection.java +++ b/vtm/src/org/oscim/core/MercatorProjection.java @@ -57,11 +57,18 @@ public final class MercatorProjection { * the map scale at which the resolution should be calculated. * @return the ground resolution at the given latitude and zoom level. */ - public static double calculateGroundResolution(double latitude, double scale) { + public static double groundResolution(double latitude, double scale) { return Math.cos(latitude * (Math.PI / 180)) * EARTH_CIRCUMFERENCE / (Tile.SIZE * scale); } + public static float groundResolution(MapPosition pos) { + double lat = MercatorProjection.toLatitude(pos.y); + return (float) (Math.cos(lat * (Math.PI / 180)) + * MercatorProjection.EARTH_CIRCUMFERENCE + / (Tile.SIZE * pos.scale)); + } + /** * Projects a longitude coordinate (in degrees) to the range [0.0,1.0] * diff --git a/vtm/src/org/oscim/renderer/elements/LineLayer.java b/vtm/src/org/oscim/renderer/elements/LineLayer.java index 0539ae57..4aa113bd 100644 --- a/vtm/src/org/oscim/renderer/elements/LineLayer.java +++ b/vtm/src/org/oscim/renderer/elements/LineLayer.java @@ -21,6 +21,7 @@ import org.oscim.backend.GLAdapter; import org.oscim.backend.canvas.Paint.Cap; import org.oscim.core.GeometryBuffer; import org.oscim.core.MapPosition; +import org.oscim.core.MercatorProjection; import org.oscim.core.Tile; import org.oscim.renderer.GLState; import org.oscim.renderer.GLUtils; @@ -57,7 +58,9 @@ public final class LineLayer extends RenderElement { public float width; public boolean roundCap; - private float mMinDist = 1 / 4f; + private float mMinDist = 1 / 8f; + + public float heightOffset; LineLayer(int layer) { super(RenderElement.LINE); @@ -77,7 +80,7 @@ public final class LineLayer extends RenderElement { * For point reduction by minimal distance. Default is 1/4. */ public void setDropDistance(float minDist) { - mMinDist = minDist < 1 / 4f ? 1 / 4f : minDist; + mMinDist = minDist < 1 / 8f ? 1 / 8f : minDist; } public void addLine(GeometryBuffer geom) { @@ -116,10 +119,8 @@ public final class LineLayer extends RenderElement { short v[] = si.vertices; int opos = si.used; - /* - * Note: just a hack to save some vertices, when there are - * more than 200 lines per type. FIXME make optional! - */ + /* Note: just a hack to save some vertices, when there are + * more than 200 lines per type. FIXME make optional! */ if (rounded && index != null) { int cnt = 0; for (int i = 0, n = index.length; i < n; i++, cnt++) { @@ -589,6 +590,7 @@ public final class LineLayer extends RenderElement { private static int[] hLineFade = new int[2]; private static int[] hLineWidth = new int[2]; private static int[] hLineMode = new int[2]; + private static int[] hLineHeight = new int[2]; public static int mTexID; static boolean init() { @@ -616,6 +618,7 @@ public final class LineLayer extends RenderElement { hLineWidth[i] = GL.glGetUniformLocation(lineProgram[i], "u_width"); hLineColor[i] = GL.glGetUniformLocation(lineProgram[i], "u_color"); hLineMode[i] = GL.glGetUniformLocation(lineProgram[i], "u_mode"); + hLineHeight[i] = GL.glGetUniformLocation(lineProgram[i], "u_height"); hLineVertexPosition[i] = GL.glGetAttribLocation(lineProgram[i], "a_pos"); } @@ -665,6 +668,7 @@ public final class LineLayer extends RenderElement { int uLineMode = hLineMode[mode]; int uLineColor = hLineColor[mode]; int uLineWidth = hLineWidth[mode]; + int uLineHeight = hLineHeight[mode]; GLState.enableVertexArrays(hLineVertexPosition[mode], -1); @@ -681,7 +685,7 @@ public final class LineLayer extends RenderElement { // scale factor to map one pixel on tile to one pixel on screen: // used with orthographic projection, (shader mode == 1) - double pixel = (mode == SHADER_PROJ) ? 0 : 1.5 / scale; + double pixel = (mode == SHADER_PROJ) ? 0.0001 : 1.5 / scale; GL.glUniform1f(uLineFade, (float) pixel); @@ -691,11 +695,21 @@ public final class LineLayer extends RenderElement { boolean blur = false; double width; + float heightOffset = 0; + GL.glUniform1f(uLineHeight, heightOffset); + RenderElement l = curLayer; for (; l != null && l.type == RenderElement.LINE; l = l.next) { LineLayer ll = (LineLayer) l; Line line = ll.line; + if (ll.heightOffset != heightOffset) { + heightOffset = ll.heightOffset; + + GL.glUniform1f(uLineHeight, heightOffset / + MercatorProjection.groundResolution(pos)); + } + if (line.fade < pos.zoomLevel) { GLUtils.setColor(uLineColor, line.color, 1); } else if (line.fade > pos.zoomLevel) { @@ -706,7 +720,7 @@ public final class LineLayer extends RenderElement { } if (mode == SHADER_PROJ && blur && line.blur == 0) { - GL.glUniform1f(uLineFade, 0); + GL.glUniform1f(uLineFade, (float) pixel); blur = false; } @@ -797,13 +811,14 @@ public final class LineLayer extends RenderElement { // xy hold position, zw extrusion vector + "attribute vec4 a_pos;" + "uniform float u_mode;" + + "uniform float u_height;" + "varying vec2 v_st;" + "void main() {" // scale extrusion to u_width pixel // just ignore the two most insignificant bits. + " vec2 dir = a_pos.zw;" - + " gl_Position = u_mvp * vec4(a_pos.xy + (u_width * dir), 0.0, 1.0);" + + " gl_Position = u_mvp * vec4(a_pos.xy + (u_width * dir), u_height, 1.0);" // last two bits hold the texture coordinates. + " v_st = abs(mod(dir, 4.0)) - 1.0;" diff --git a/vtm/src/org/oscim/renderer/elements/MeshLayer.java b/vtm/src/org/oscim/renderer/elements/MeshLayer.java index 34c78dfa..f947ba7e 100644 --- a/vtm/src/org/oscim/renderer/elements/MeshLayer.java +++ b/vtm/src/org/oscim/renderer/elements/MeshLayer.java @@ -22,6 +22,7 @@ import org.oscim.backend.GL20; import org.oscim.backend.canvas.Color; import org.oscim.core.GeometryBuffer; import org.oscim.core.MapPosition; +import org.oscim.core.MercatorProjection; import org.oscim.renderer.BufferObject; import org.oscim.renderer.GLState; import org.oscim.renderer.GLUtils; @@ -42,6 +43,7 @@ public class MeshLayer extends RenderElement { VertexItem indiceItems; public Area area; + public float heightOffset; public MeshLayer(int level) { super(RenderElement.MESH); @@ -106,6 +108,7 @@ public class MeshLayer extends RenderElement { private static int shaderProgram; private static int hMatrix; private static int hColor; + private static int hHeightOffset; private static int hVertexPosition; static boolean init() { @@ -115,6 +118,7 @@ public class MeshLayer extends RenderElement { hMatrix = GL.glGetUniformLocation(shaderProgram, "u_mvp"); hColor = GL.glGetUniformLocation(shaderProgram, "u_color"); + hHeightOffset = GL.glGetUniformLocation(shaderProgram, "u_height"); hVertexPosition = GL.glGetAttribLocation(shaderProgram, "a_pos"); return true; } @@ -130,12 +134,21 @@ public class MeshLayer extends RenderElement { m.mvp.setAsUniform(hMatrix); + float heightOffset = 0; + for (; l != null && l.type == RenderElement.MESH; l = l.next) { MeshLayer ml = (MeshLayer) l; if (ml.indicesVbo == null) continue; + if (ml.heightOffset != heightOffset) { + heightOffset = ml.heightOffset; + + GL.glUniform1f(hHeightOffset, heightOffset / + MercatorProjection.groundResolution(pos)); + } + ml.indicesVbo.bind(); if (ml.area == null) @@ -164,9 +177,10 @@ public class MeshLayer extends RenderElement { private final static String vertexShader = "" + "precision mediump float;" + "uniform mat4 u_mvp;" - + "attribute vec4 a_pos;" + + "uniform float u_height;" + + "attribute vec2 a_pos;" + "void main() {" - + " gl_Position = u_mvp * a_pos;" + + " gl_Position = u_mvp * vec4(a_pos, u_height, 1.0);" + "}"; private final static String fragmentShader = ""