diff --git a/docs/Changelog.md b/docs/Changelog.md
index 408c65c50..50239eba4 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -3,6 +3,7 @@
## New since 0.12.0
- Render themes: symbols on lines with billboard / rotation [#743](https://github.com/mapsforge/vtm/pull/743)
+- Location texture renderer: rewrite and optimize [#750](https://github.com/mapsforge/vtm/pull/750)
- Android: OpenGL ES 2.0 default for performance / stability [#749](https://github.com/mapsforge/vtm/pull/749)
- `MapView.OPENGL_VERSION`
- Android: threaded system initialization
diff --git a/vtm-android-example/res/raw/marker.svg b/vtm-android-example/res/raw/marker.svg
new file mode 100755
index 000000000..bca149b58
--- /dev/null
+++ b/vtm-android-example/res/raw/marker.svg
@@ -0,0 +1,15 @@
+
+
diff --git a/vtm-android-example/src/org/oscim/android/test/LocationActivity.java b/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
index 40e2fc1c0..43c8903fb 100644
--- a/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/LocationActivity.java
@@ -24,8 +24,10 @@
import android.os.Bundle;
import org.oscim.core.MapPosition;
import org.oscim.layers.LocationLayer;
+import org.oscim.renderer.LocationCallback;
public class LocationActivity extends BitmapTileActivity implements LocationListener {
+ private Location location;
private LocationLayer locationLayer;
private LocationManager locationManager;
private final MapPosition mapPosition = new MapPosition();
@@ -37,7 +39,17 @@ public void onCreate(Bundle savedInstanceState) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationLayer = new LocationLayer(mMap);
- locationLayer.locationRenderer.setShader("location_1_reverse");
+ locationLayer.locationRenderer.setCallback(new LocationCallback() {
+ @Override
+ public boolean hasRotation() {
+ return location != null && location.hasBearing();
+ }
+
+ @Override
+ public float getRotation() {
+ return location != null && location.hasBearing() ? location.getBearing() : 0;
+ }
+ });
locationLayer.setEnabled(false);
mMap.layers().add(locationLayer);
}
@@ -66,6 +78,7 @@ public void onStop() {
@Override
public void onLocationChanged(Location location) {
+ this.location = location;
locationLayer.setEnabled(true);
locationLayer.setPosition(location.getLatitude(), location.getLongitude(), location.getAccuracy());
diff --git a/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java b/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
index 2377bad09..4ee519af2 100644
--- a/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
+++ b/vtm-android-example/src/org/oscim/android/test/LocationTextureActivity.java
@@ -25,18 +25,16 @@
import android.os.Bundle;
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.canvas.Bitmap;
-import org.oscim.backend.canvas.Color;
import org.oscim.core.MapPosition;
import org.oscim.layers.LocationTextureLayer;
-import org.oscim.renderer.atlas.TextureAtlas;
-import org.oscim.renderer.atlas.TextureRegion;
-import org.oscim.renderer.bucket.TextureItem;
+import org.oscim.renderer.LocationCallback;
import org.oscim.utils.IOUtils;
import java.io.IOException;
import java.io.InputStream;
public class LocationTextureActivity extends BitmapTileActivity implements LocationListener {
+ private Location location;
private LocationTextureLayer locationLayer;
private LocationManager locationManager;
private final MapPosition mapPosition = new MapPosition();
@@ -47,34 +45,41 @@ public void onCreate(Bundle savedInstanceState) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- // load a Bitmap/SVG from resources
InputStream is = null;
- Bitmap bmp = null;
+ Bitmap bitmapArrow = null;
try {
is = getResources().openRawResource(R.raw.arrow);
- float scale = CanvasAdapter.getScale();
- bmp = CanvasAdapter.decodeSvgBitmap(is, (int) (60 * scale), (int) (60 * scale), 100);
+ bitmapArrow = CanvasAdapter.decodeSvgBitmap(is, (int) (48 * CanvasAdapter.getScale()), (int) (48 * CanvasAdapter.getScale()), 100);
} catch (IOException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(is);
}
- // create TextureRegion from Bitmap
- TextureRegion textureRegion = new TextureRegion(new TextureItem(bmp), new TextureAtlas.Rect(0, 0, bmp.getWidth(), bmp.getHeight()));
-
- // create LocationTextureLayer with created/loaded TextureRegion
- locationLayer = new LocationTextureLayer(mMap, textureRegion);
-
- // set color of accuracy circle (Color.BLUE is default)
- locationLayer.locationRenderer.setAccuracyColor(Color.get(50, 50, 255));
-
- // set color of indicator circle (Color.RED is default)
- locationLayer.locationRenderer.setIndicatorColor(Color.MAGENTA);
+ Bitmap bitmapMarker = null;
+ try {
+ is = getResources().openRawResource(R.raw.marker);
+ bitmapMarker = CanvasAdapter.decodeSvgBitmap(is, (int) (48 * CanvasAdapter.getScale()), (int) (48 * CanvasAdapter.getScale()), 100);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ IOUtils.closeQuietly(is);
+ }
- // set billboard rendering for TextureRegion (false is default)
- locationLayer.locationRenderer.setBillboard(false);
+ locationLayer = new LocationTextureLayer(mMap);
+ locationLayer.locationRenderer.setBitmapArrow(bitmapArrow);
+ locationLayer.locationRenderer.setBitmapMarker(bitmapMarker);
+ locationLayer.locationRenderer.setCallback(new LocationCallback() {
+ @Override
+ public boolean hasRotation() {
+ return location != null && location.hasBearing();
+ }
+ @Override
+ public float getRotation() {
+ return location != null && location.hasBearing() ? location.getBearing() : 0;
+ }
+ });
locationLayer.setEnabled(false);
mMap.layers().add(locationLayer);
}
@@ -103,8 +108,9 @@ public void onStop() {
@Override
public void onLocationChanged(Location location) {
+ this.location = location;
locationLayer.setEnabled(true);
- locationLayer.setPosition(location.getLatitude(), location.getLongitude(), location.getBearing(), location.getAccuracy());
+ locationLayer.setPosition(location.getLatitude(), location.getLongitude(), location.getAccuracy());
// Follow location
mMap.getMapPosition(mapPosition);
diff --git a/vtm-app/src/org/oscim/app/location/Compass.java b/vtm-app/src/org/oscim/app/location/Compass.java
index 6d357b791..7c798e9dc 100644
--- a/vtm-app/src/org/oscim/app/location/Compass.java
+++ b/vtm-app/src/org/oscim/app/location/Compass.java
@@ -1,7 +1,7 @@
/*
* Copyright 2013 Ahmad Saleem
* Copyright 2013 Hannes Janetzek
- * Copyright 2016-2017 devemux86
+ * Copyright 2016-2019 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -24,19 +24,17 @@
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
-
import org.oscim.app.App;
import org.oscim.app.R;
import org.oscim.core.MapPosition;
import org.oscim.event.Event;
import org.oscim.layers.Layer;
import org.oscim.map.Map;
-import org.oscim.renderer.LocationRenderer;
+import org.oscim.renderer.LocationCallback;
import org.oscim.utils.FastMath;
@SuppressWarnings("deprecation")
-public class Compass extends Layer implements SensorEventListener, Map.UpdateListener,
- LocationRenderer.Callback {
+public class Compass extends Layer implements SensorEventListener, Map.UpdateListener, LocationCallback {
// static final Logger log = LoggerFactory.getLogger(Compass.class);
diff --git a/vtm/resources/assets/shaders/accuracy_1.glsl b/vtm/resources/assets/shaders/accuracy_1.glsl
new file mode 100644
index 000000000..0a5af58a4
--- /dev/null
+++ b/vtm/resources/assets/shaders/accuracy_1.glsl
@@ -0,0 +1,38 @@
+#ifdef GLES
+precision mediump float;
+#endif
+uniform mat4 u_mvp;
+uniform float u_phase;
+uniform float u_scale;
+attribute vec2 a_pos;
+varying vec2 v_tex;
+
+void main() {
+ gl_Position = u_mvp * vec4(a_pos * u_scale * u_phase, 0.0, 1.0);
+ v_tex = a_pos;
+}
+
+$$
+
+#ifdef GLES
+precision mediump float;
+#endif
+varying vec2 v_tex;
+uniform float u_scale;
+uniform int u_mode;
+uniform vec4 u_color;
+
+void main() {
+ float len = 1.0 - length(v_tex);
+ if (u_mode == -1) {
+ gl_FragColor = u_color * len;
+ } else {
+ // outer ring
+ float a = smoothstep(0.0, 2.0 / u_scale, len);
+ // inner ring
+ float b = 0.8 * smoothstep(3.0 / u_scale, 4.0 / u_scale, len);
+ // - subtract inner from outer to create the outline
+ a = a - b;
+ gl_FragColor = u_color * a;
+ }
+}
diff --git a/vtm/src/org/oscim/layers/LocationLayer.java b/vtm/src/org/oscim/layers/LocationLayer.java
index 7d89adc42..819e77dd1 100644
--- a/vtm/src/org/oscim/layers/LocationLayer.java
+++ b/vtm/src/org/oscim/layers/LocationLayer.java
@@ -1,7 +1,7 @@
/*
* Copyright 2013 Ahmad Saleem
* Copyright 2013 Hannes Janetzek
- * Copyright 2016-2017 devemux86
+ * Copyright 2016-2019 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -45,7 +45,7 @@ public void setEnabled(boolean enabled) {
locationRenderer.animate(false);
}
- public void setPosition(double latitude, double longitude, double accuracy) {
+ public void setPosition(double latitude, double longitude, float accuracy) {
double x = MercatorProjection.longitudeToX(longitude);
double y = MercatorProjection.latitudeToY(latitude);
double radius = accuracy / MercatorProjection.groundResolutionWithScale(latitude, 1);
diff --git a/vtm/src/org/oscim/layers/LocationTextureLayer.java b/vtm/src/org/oscim/layers/LocationTextureLayer.java
index 2648f4772..dce19fc01 100644
--- a/vtm/src/org/oscim/layers/LocationTextureLayer.java
+++ b/vtm/src/org/oscim/layers/LocationTextureLayer.java
@@ -1,6 +1,8 @@
/*
+ * Copyright 2013 Ahmad Saleem
+ * Copyright 2013 Hannes Janetzek
+ * Copyright 2016-2019 devemux86
* Copyright 2017-2018 Longri
- * Copyright 2018 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,19 +17,22 @@
*/
package org.oscim.layers;
+import org.oscim.backend.CanvasAdapter;
import org.oscim.core.MercatorProjection;
import org.oscim.map.Map;
import org.oscim.renderer.LocationTextureRenderer;
-import org.oscim.renderer.atlas.TextureRegion;
public class LocationTextureLayer extends Layer {
public final LocationTextureRenderer locationRenderer;
- public LocationTextureLayer(Map map, TextureRegion textureRegion) {
+ public LocationTextureLayer(Map map) {
+ this(map, CanvasAdapter.getScale());
+ }
+
+ public LocationTextureLayer(Map map, float scale) {
super(map);
- mRenderer = locationRenderer = new LocationTextureRenderer(map);
- locationRenderer.setTextureRegion(textureRegion);
+ mRenderer = locationRenderer = new LocationTextureRenderer(map, this, scale);
}
@Override
@@ -41,14 +46,11 @@ public void setEnabled(boolean enabled) {
locationRenderer.animate(false);
}
- public void setPosition(double latitude, double longitude, float bearing, float accuracy) {
+ public void setPosition(double latitude, double longitude, float accuracy) {
double x = MercatorProjection.longitudeToX(longitude);
double y = MercatorProjection.latitudeToY(latitude);
- bearing = -bearing;
- while (bearing < 0)
- bearing += 360;
double radius = accuracy / MercatorProjection.groundResolutionWithScale(latitude, 1);
- locationRenderer.setLocation(x, y, bearing, radius);
+ locationRenderer.setLocation(x, y, radius);
locationRenderer.animate(true);
}
}
diff --git a/vtm/src/org/oscim/renderer/LocationCallback.java b/vtm/src/org/oscim/renderer/LocationCallback.java
new file mode 100644
index 000000000..4119ec599
--- /dev/null
+++ b/vtm/src/org/oscim/renderer/LocationCallback.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016-2019 devemux86
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.renderer;
+
+public interface LocationCallback {
+ /**
+ * Useful with Android Location.hasBearing().
+ */
+ boolean hasRotation();
+
+ float getRotation();
+}
diff --git a/vtm/src/org/oscim/renderer/LocationRenderer.java b/vtm/src/org/oscim/renderer/LocationRenderer.java
index a8861649a..28f743b9b 100644
--- a/vtm/src/org/oscim/renderer/LocationRenderer.java
+++ b/vtm/src/org/oscim/renderer/LocationRenderer.java
@@ -20,7 +20,6 @@
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.GL;
-import org.oscim.backend.canvas.Color;
import org.oscim.core.Box;
import org.oscim.core.Point;
import org.oscim.core.Tile;
@@ -68,8 +67,8 @@ public class LocationRenderer extends LayerRenderer {
private long mAnimStart;
private boolean mCenter;
- private Callback mCallback;
- private final float[] mColors = new float[4];
+ private LocationCallback mCallback;
+ private int mColor = COLOR;
private final Point mLocation = new Point(Double.NaN, Double.NaN);
private double mRadius;
private int mShowAccuracyZoom = SHOW_ACCURACY_ZOOM;
@@ -82,19 +81,13 @@ public LocationRenderer(Map map, Layer layer, float scale) {
mMap = map;
mLayer = layer;
mScale = scale;
-
- float a = Color.aToFloat(COLOR);
- mColors[0] = a * Color.rToFloat(COLOR);
- mColors[1] = a * Color.gToFloat(COLOR);
- mColors[2] = a * Color.bToFloat(COLOR);
- mColors[3] = a;
}
public void setAnimate(boolean animate) {
mAnimate = animate;
}
- public void setCallback(Callback callback) {
+ public void setCallback(LocationCallback callback) {
mCallback = callback;
}
@@ -103,11 +96,7 @@ public void setCenter(boolean center) {
}
public void setColor(int color) {
- float a = Color.aToFloat(color);
- mColors[0] = a * Color.rToFloat(color);
- mColors[1] = a * Color.gToFloat(color);
- mColors[2] = a * Color.bToFloat(color);
- mColors[3] = a;
+ mColor = color;
}
public void setLocation(double x, double y, double radius) {
@@ -287,7 +276,7 @@ public void render(GLViewport v) {
} else
gl.uniform1i(uMode, -1); // Outside screen
- GLUtils.glUniform4fv(uColor, 1, mColors);
+ GLUtils.setColor(uColor, mColor);
gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4);
}
@@ -308,13 +297,4 @@ protected boolean init() {
return true;
}
-
- public interface Callback {
- /**
- * Usually true, can be used with e.g. Android Location.hasBearing().
- */
- boolean hasRotation();
-
- float getRotation();
- }
}
diff --git a/vtm/src/org/oscim/renderer/LocationTextureRenderer.java b/vtm/src/org/oscim/renderer/LocationTextureRenderer.java
index 1c5229785..35ac34285 100644
--- a/vtm/src/org/oscim/renderer/LocationTextureRenderer.java
+++ b/vtm/src/org/oscim/renderer/LocationTextureRenderer.java
@@ -1,6 +1,10 @@
/*
+ * Copyright 2013 Ahmad Saleem
+ * Copyright 2013 Hannes Janetzek
+ * Copyright 2016-2019 devemux86
+ * Copyright 2016 ocsike
+ * Copyright 2017 Mathieu De Brito
* Copyright 2017-2018 Longri
- * Copyright 2018-2019 devemux86
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
@@ -17,147 +21,125 @@
import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.GL;
-import org.oscim.backend.canvas.Color;
+import org.oscim.backend.canvas.Bitmap;
import org.oscim.core.Box;
import org.oscim.core.Point;
-import org.oscim.core.PointF;
import org.oscim.core.Tile;
+import org.oscim.layers.Layer;
import org.oscim.map.Map;
-import org.oscim.renderer.atlas.TextureRegion;
import org.oscim.renderer.bucket.SymbolBucket;
import org.oscim.renderer.bucket.SymbolItem;
import org.oscim.utils.FastMath;
-import org.oscim.utils.geom.GeometryUtils;
import org.oscim.utils.math.Interpolation;
-import java.util.Locale;
-
import static org.oscim.backend.GLAdapter.gl;
public class LocationTextureRenderer extends BucketRenderer {
- private static final PointF CENTER_OFFSET = new PointF(0.5f, 0.5f);
private static final long ANIM_RATE = 50;
private static final long INTERVAL = 2000;
- private static final float CIRCLE_SIZE = 30;
- private static final int SHOW_ACCURACY_ZOOM = 13;
- private static final boolean IS_MAC = System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("mac");
-
- private static final String V_SHADER = (""
- + "precision highp float;"
- + "uniform mat4 u_mvp;"
- + "uniform float u_phase;"
- + "uniform float u_scale;"
- + "attribute vec2 a_pos;"
- + "varying vec2 v_tex;"
- + "void main() {"
- + " gl_Position = u_mvp * vec4(a_pos * u_scale * u_phase, 0.0, 1.0);"
- + " v_tex = a_pos;"
- + "}").replace("precision highp float;", IS_MAC ? "" : "precision highp float;");
-
- // only circle without direction
- private static final String F_SHADER = (""
- + "precision highp float;"
- + "varying vec2 v_tex;"
- + "uniform float u_scale;"
- + "uniform float u_phase;"
- + "uniform vec4 u_fill;"
- + "void main() {"
- + " float len = 1.0 - length(v_tex);"
- /// outer ring
- + " float a = smoothstep(0.0, 2.0 / u_scale, len);"
- /// inner ring
- + " float b = 0.8 * smoothstep(3.0 / u_scale, 4.0 / u_scale, len);"
- /// center point
- + " float c = 0.5 * (1.0 - smoothstep(14.0 / u_scale, 16.0 / u_scale, 1.0 - len));"
- + " vec2 dir = normalize(v_tex);"
- /// - subtract inner from outer to create the outline
- /// - multiply by viewshed
- /// - add center point
- + " a = (a - (b + c)) + c;"
- + " gl_FragColor = u_fill * a;"
- + "}").replace("precision highp float;", IS_MAC ? "" : "precision highp float;");
-
- private final SymbolBucket symbolBucket;
- private final float[] box = new float[8];
- private final Point mapPoint = new Point();
- private final Map map;
- private boolean initialized;
- private boolean locationIsVisible;
- private int shaderProgramNumber;
+
+ public static float CIRCLE_SIZE = /*30*/0;
+ private static final int COLOR = 0xff3333cc;
+ private static final int SHOW_ACCURACY_ZOOM = 16;
+
+ private final Map mMap;
+ private final Layer mLayer;
+ protected final float mScale;
+ private final SymbolBucket mSymbolLayer;
+
+ private String mShaderFile;
+ protected int mShaderProgram;
private int hVertexPosition;
private int hMatrixPosition;
private int hScale;
private int hPhase;
- private int uFill;
- private double radius;
-
- private final Point indicatorPosition = new Point();
- private final Point screenPoint = new Point();
- private final Box boundingBox = new Box();
- private boolean runAnim;
- private boolean animate = true;
- private long animStart;
- private boolean center;
- private boolean update;
- private float bearing;
-
- // properties
- private TextureRegion textureRegion;
- private int accuracyColor = Color.BLUE;
- private int viewShedColor = Color.RED;
- private boolean billboard = false;
-
- public LocationTextureRenderer(Map map) {
- this.map = map;
- symbolBucket = new SymbolBucket();
+ private int uColor;
+ private int uMode;
+
+ private final Point mIndicatorPosition = new Point();
+
+ private final Point mScreenPoint = new Point();
+ private final Box mBBox = new Box();
+
+ private boolean mLocationIsVisible;
+
+ private boolean mRunAnim;
+ private boolean mAnimate = true;
+ private long mAnimStart;
+ private boolean mCenter;
+
+ private boolean mBillboard;
+ private Bitmap mBitmapArrow, mBitmapMarker;
+ private LocationCallback mCallback;
+ private int mColor = COLOR;
+ private final Point mLocation = new Point(Double.NaN, Double.NaN);
+ private double mRadius;
+ private int mShowAccuracyZoom = SHOW_ACCURACY_ZOOM;
+
+ public LocationTextureRenderer(Map map, Layer layer) {
+ this(map, layer, CanvasAdapter.getScale());
}
- public void setAccuracyColor(int color) {
- this.accuracyColor = color;
+ public LocationTextureRenderer(Map map, Layer layer, float scale) {
+ mMap = map;
+ mLayer = layer;
+ mScale = scale;
+
+ mSymbolLayer = new SymbolBucket();
}
public void setAnimate(boolean animate) {
- this.animate = animate;
+ mAnimate = animate;
}
public void setBillboard(boolean billboard) {
- this.billboard = billboard;
+ mBillboard = billboard;
+ }
+
+ public void setBitmapArrow(Bitmap bitmap) {
+ mBitmapArrow = bitmap;
+ }
+
+ public void setBitmapMarker(Bitmap bitmap) {
+ mBitmapMarker = bitmap;
+ }
+
+ public void setCallback(LocationCallback callback) {
+ mCallback = callback;
}
public void setCenter(boolean center) {
- this.center = center;
+ mCenter = center;
}
- public void setIndicatorColor(int color) {
- this.viewShedColor = color;
+ public void setColor(int color) {
+ mColor = color;
}
- public void setLocation(double x, double y, float bearing, double radius) {
- update = true;
- mapPoint.x = x;
- mapPoint.y = y;
- this.bearing = bearing;
- this.radius = radius;
+ public void setLocation(double x, double y, double radius) {
+ mLocation.x = x;
+ mLocation.y = y;
+ mRadius = radius;
}
- public void setTextureRegion(TextureRegion textureRegion) {
- this.textureRegion = textureRegion;
+ public void setShader(String shaderFile) {
+ mShaderFile = shaderFile;
+ mInitialized = false;
}
- public void setTextureRegion(TextureRegion textureRegion, boolean billboard) {
- this.textureRegion = textureRegion;
- this.billboard = billboard;
+ public void setShowAccuracyZoom(int showAccuracyZoom) {
+ mShowAccuracyZoom = showAccuracyZoom;
}
public void animate(boolean enable) {
- if (runAnim == enable)
+ if (mRunAnim == enable)
return;
- runAnim = enable;
+ mRunAnim = enable;
if (!enable)
return;
- if (!animate)
+ if (!mAnimate)
return;
final Runnable action = new Runnable() {
@@ -165,62 +147,70 @@ public void animate(boolean enable) {
@Override
public void run() {
- if (!runAnim)
+ if (!mRunAnim)
return;
- if (!animate)
+ if (!mAnimate)
return;
long diff = System.currentTimeMillis() - lastRun;
- map.postDelayed(this, Math.min(ANIM_RATE, diff));
- map.render();
+ mMap.postDelayed(this, Math.min(ANIM_RATE, diff));
+ mMap.render();
lastRun = System.currentTimeMillis();
}
};
- animStart = System.currentTimeMillis();
- map.postDelayed(action, ANIM_RATE);
+ mAnimStart = System.currentTimeMillis();
+ mMap.postDelayed(action, ANIM_RATE);
}
private float animPhase() {
- return (float) ((MapRenderer.frametime - animStart) % INTERVAL) / INTERVAL;
+ return (float) ((MapRenderer.frametime - mAnimStart) % INTERVAL) / INTERVAL;
}
@Override
public synchronized void update(GLViewport v) {
- if (!v.changed() && !update)
- return;
- // accuracy
- if (!initialized) {
+ if (!mInitialized) {
init();
- initialized = true;
+ mInitialized = true;
+ }
+
+ if (!mLayer.isEnabled()) {
+ setReady(false);
+ return;
}
+
+ /*if (!v.changed() && isReady())
+ return;*/
+
setReady(true);
- int width = map.getWidth();
- int height = map.getHeight();
+ int width = mMap.getWidth();
+ int height = mMap.getHeight();
double x, y;
- if (center) {
- x = (width >> 1) + width * map.viewport().getMapViewCenterX();
- y = (height >> 1) + height * map.viewport().getMapViewCenterY();
+ if (mCenter) {
+ x = (width >> 1) + width * mMap.viewport().getMapViewCenterX();
+ y = (height >> 1) + height * mMap.viewport().getMapViewCenterY();
} else {
- v.getBBox(boundingBox, 0);
+ // clamp location to a position that can be
+ // safely translated to screen coordinates
+ v.getBBox(mBBox, 0);
- x = mapPoint.x;
- y = mapPoint.y;
+ x = mLocation.x;
+ y = mLocation.y;
- if (!boundingBox.contains(mapPoint)) {
- x = FastMath.clamp(x, boundingBox.xmin, boundingBox.xmax);
- y = FastMath.clamp(y, boundingBox.ymin, boundingBox.ymax);
+ if (!mBBox.contains(mLocation)) {
+ x = FastMath.clamp(x, mBBox.xmin, mBBox.xmax);
+ y = FastMath.clamp(y, mBBox.ymin, mBBox.ymax);
}
// get position of Location in pixel relative to
// screen center
- v.toScreenPoint(x, y, screenPoint);
+ v.toScreenPoint(x, y, mScreenPoint);
- x = screenPoint.x + width / 2;
- y = screenPoint.y + height / 2;
+ x = mScreenPoint.x + (width >> 1);
+ y = mScreenPoint.y + (height >> 1);
}
// clip position to screen boundaries
@@ -240,112 +230,130 @@ else if (y < 5)
else
visible++;
- locationIsVisible = (visible == 2);
+ mLocationIsVisible = (visible == 2);
- if (locationIsVisible)
- animate(false);
- else
- animate(true);
// set location indicator position
- v.fromScreenPoint(x, y, indicatorPosition);
+ v.fromScreenPoint(x, y, mIndicatorPosition);
- // Texture
- mMapPosition.copy(v.pos);
+ /* Texture */
- double mx = v.pos.x;
- double my = v.pos.y;
- double scale = Tile.SIZE * v.pos.scale;
- map.viewport().getMapExtents(box, 100);
- long flip = (long) (Tile.SIZE * v.pos.scale) >> 1;
+ buckets.clear();
- /* check visibility */
- float symbolX = (float) ((mapPoint.x - mx) * scale);
- float symbolY = (float) ((mapPoint.y - my) * scale);
+ if (mBitmapArrow == null || mBitmapMarker == null)
+ return;
- if (symbolX > flip)
- symbolX -= (flip << 1);
- else if (symbolX < -flip)
- symbolX += (flip << 1);
- buckets.clear();
- if (!GeometryUtils.pointInPoly(symbolX, symbolY, box, 8, 0))
+ if (!mLocationIsVisible)
return;
+ float itx, ity;
+ if (mCenter) {
+ itx = 0;
+ ity = 0;
+ } else {
+ double mx = v.pos.x;
+ double my = v.pos.y;
+ double scale = Tile.SIZE * v.pos.scale;
+
+ long flip = (long) (Tile.SIZE * v.pos.scale) >> 1;
+
+ itx = (float) ((mLocation.x - mx) * scale);
+ ity = (float) ((mLocation.y - my) * scale);
+
+ if (itx > flip)
+ itx -= (flip << 1);
+ else if (itx < -flip)
+ itx += (flip << 1);
+ }
+
+ mMapPosition.copy(v.pos);
mMapPosition.bearing = -mMapPosition.bearing;
- if (textureRegion == null)
- return;
- SymbolItem symbolItem = SymbolItem.pool.get();
- symbolItem.set(symbolX, symbolY, textureRegion, this.bearing, this.billboard);
- symbolItem.offset = CENTER_OFFSET;
- symbolBucket.pushSymbol(symbolItem);
- buckets.set(symbolBucket);
+ SymbolItem s = SymbolItem.pool.get();
+ if (mCallback != null && mCallback.hasRotation())
+ s.set(itx, ity, mBitmapArrow, mCallback.getRotation(), mBillboard);
+ else
+ s.set(itx, ity, mBitmapMarker, mBillboard);
+ mSymbolLayer.pushSymbol(s);
+
+ buckets.set(mSymbolLayer);
buckets.prepare();
- buckets.compile(true);
+
compile();
- update = false;
}
@Override
- public void render(GLViewport v) {
- renderAccuracyCircle(v);
- super.render(v);
- }
-
- private void init() {
- int shader = GLShader.createProgram(V_SHADER, F_SHADER);
- if (shader == 0)
- return;
-
- shaderProgramNumber = shader;
- hVertexPosition = gl.getAttribLocation(shader, "a_pos");
- hMatrixPosition = gl.getUniformLocation(shader, "u_mvp");
- hPhase = gl.getUniformLocation(shader, "u_phase");
- hScale = gl.getUniformLocation(shader, "u_scale");
- uFill = gl.getUniformLocation(shader, "u_fill");
- }
+ public synchronized void render(GLViewport v) {
- private void renderAccuracyCircle(GLViewport v) {
- GLState.useProgram(shaderProgramNumber);
+ GLState.useProgram(mShaderProgram);
GLState.blend(true);
GLState.test(false, false);
GLState.enableVertexArrays(hVertexPosition, GLState.DISABLED);
MapRenderer.bindQuadVertexVBO(hVertexPosition/*, true*/);
- float radius = 10;
+ float radius = CIRCLE_SIZE * mScale;
+
boolean viewShed = false;
- if (!locationIsVisible)
- radius = CIRCLE_SIZE * CanvasAdapter.getScale();
- else {
- if (v.pos.zoomLevel >= SHOW_ACCURACY_ZOOM)
- radius = (float) (this.radius * v.pos.scale);
- radius = Math.max(2, radius);
+ if (!mLocationIsVisible /* || pos.zoomLevel < SHOW_ACCURACY_ZOOM */) {
+ animate(true);
+ } else {
+ if (v.pos.zoomLevel >= mShowAccuracyZoom)
+ radius = (float) (mRadius * v.pos.scale);
+ radius = Math.max(CIRCLE_SIZE * mScale, radius);
+
viewShed = true;
+ animate(false);
}
gl.uniform1f(hScale, radius);
- double x = indicatorPosition.x - v.pos.x;
- double y = indicatorPosition.y - v.pos.y;
+ double x = mIndicatorPosition.x - v.pos.x;
+ double y = mIndicatorPosition.y - v.pos.y;
double tileScale = Tile.SIZE * v.pos.scale;
v.mvp.setTransScale((float) (x * tileScale), (float) (y * tileScale), 1);
v.mvp.multiplyMM(v.viewproj, v.mvp);
v.mvp.setAsUniform(hMatrixPosition);
- if (!viewShed && animate) {
+ if (!viewShed && mAnimate) {
float phase = Math.abs(animPhase() - 0.5f) * 2;
//phase = Interpolation.fade.apply(phase);
phase = Interpolation.swing.apply(phase);
+
gl.uniform1f(hPhase, 0.8f + phase * 0.2f);
- } else
+ } else {
gl.uniform1f(hPhase, 1);
+ }
- if (viewShed && locationIsVisible)
- GLUtils.setColor(uFill, accuracyColor, 1);
- else
- GLUtils.setColor(uFill, viewShedColor, 1);
+ if (viewShed && mLocationIsVisible) {
+ if (mCallback != null && mCallback.hasRotation())
+ gl.uniform1i(uMode, 1); // With bearing
+ else
+ gl.uniform1i(uMode, 0); // Without bearing
+ } else
+ gl.uniform1i(uMode, -1); // Outside screen
+
+ GLUtils.setColor(uColor, mColor);
gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4);
- gl.flush();
+
+ /* Texture */
+
+ super.render(v);
+ }
+
+ protected boolean init() {
+ int program = GLShader.loadShader(mShaderFile != null ? mShaderFile : "accuracy_1");
+ if (program == 0)
+ return false;
+
+ mShaderProgram = program;
+ hVertexPosition = gl.getAttribLocation(program, "a_pos");
+ hMatrixPosition = gl.getUniformLocation(program, "u_mvp");
+ hPhase = gl.getUniformLocation(program, "u_phase");
+ hScale = gl.getUniformLocation(program, "u_scale");
+ uColor = gl.getUniformLocation(program, "u_color");
+ uMode = gl.getUniformLocation(program, "u_mode");
+
+ return true;
}
}