add FadeStep for fading BitmapTileLayer depending on map scale

add setAlpha method to TileRenderLayer to fade bitmap tiles
This commit is contained in:
Hannes Janetzek 2013-08-03 04:15:44 +02:00
parent daf43858bb
commit 2aa2683581
11 changed files with 128 additions and 41 deletions

View File

@ -340,12 +340,15 @@ public class TileManager {
return true; return true;
} }
// /** /**
// * @param tiles ... * @param tiles ...
// */ */
// public void releaseTiles(TileSet tiles) { public void releaseTiles(TileSet tileSet) {
// // unlock previously active tiles
// } for (int i = 0, n = tileSet.cnt; i < n; i++)
tileSet.tiles[i].unlock();
tileSet.cnt = 0;
}
/* package */MapTile addTile(int x, int y, int zoomLevel) { /* package */MapTile addTile(int x, int y, int zoomLevel) {
MapTile tile; MapTile tile;

View File

@ -39,16 +39,24 @@ public class TileRenderLayer extends RenderLayer {
mUploadSerial = 0; mUploadSerial = 0;
} }
boolean mFaded; private int mOverdraw = 0;
private float mAlpha = 1;
public void setFaded(boolean faded) { public void setOverdrawColor(int color) {
mFaded = faded; mOverdraw = color;
}
public void setBitmapAlpha(float alpha) {
mAlpha = alpha;
} }
@Override @Override
public void update(MapPosition pos, boolean positionChanged, Matrices m) { public void update(MapPosition pos, boolean positionChanged, Matrices m) {
//mMapPosition.copy(pos); if (mAlpha == 0){
mTileManager.releaseTiles(mDrawTiles);
return;
}
boolean tilesChanged; boolean tilesChanged;
synchronized (tilelock) { synchronized (tilelock) {
@ -74,7 +82,7 @@ public class TileRenderLayer extends RenderLayer {
BufferObject.checkBufferUsage(false); BufferObject.checkBufferUsage(false);
} }
TileRenderer.draw(tiles, tileCnt, pos, m, mFaded); TileRenderer.draw(tiles, tileCnt, pos, m, mAlpha, mOverdraw);
} }
@Override @Override
@ -327,5 +335,4 @@ public class TileRenderLayer extends RenderLayer {
} }
} }
}; };
} }

View File

@ -35,7 +35,6 @@ import org.oscim.utils.quadtree.QuadTree;
* This class is for rendering the Line- and PolygonLayers of visible MapTiles. * This class is for rendering the Line- and PolygonLayers of visible MapTiles.
* For visible tiles that do not have data available yet its parent in children * For visible tiles that do not have data available yet its parent in children
* tiles are rendered when available. * tiles are rendered when available.
*
*/ */
public class TileRenderer { public class TileRenderer {
//private final static String TAG = TileRenderer.class.getName(); //private final static String TAG = TileRenderer.class.getName();
@ -50,14 +49,28 @@ public class TileRenderer {
private static int mDrawSerial = 0; private static int mDrawSerial = 0;
private static Matrices mMatrices; private static Matrices mMatrices;
private static boolean mFaded;
private static float mFade;
private static int mOverdraw;
private static final Matrix4 mProjMatrix = new Matrix4(); private static final Matrix4 mProjMatrix = new Matrix4();
static void draw(MapTile[] tiles, int tileCnt, MapPosition pos, Matrices m, boolean fade) { /**
* Draw tiles:
*
* @param fade
* alpha value for bitmap tiles
* @param overdrawColor
* draw color on top, e.g. to darken the layer temporarily
*/
static void draw(MapTile[] tiles, int tileCnt, MapPosition pos, Matrices m, float fade,
int overdrawColor) {
mOffsetCnt = -2048; mOffsetCnt = -2048;
mMatrices = m; mMatrices = m;
mFaded = fade;
mFade = fade;
mOverdraw = overdrawColor;
mProjMatrix.copy(m.proj); mProjMatrix.copy(m.proj);
// discard depth projection from tilt, we use depth buffer // discard depth projection from tilt, we use depth buffer
@ -197,7 +210,7 @@ public class TileRenderer {
//GLState.test(false, false); //GLState.test(false, false);
switch (l.type) { switch (l.type) {
case Layer.BITMAP: case Layer.BITMAP:
l = BitmapRenderer.draw(l, 1, m); l = BitmapRenderer.draw(l, m, 1, mFade);
break; break;
default: default:
@ -205,11 +218,7 @@ public class TileRenderer {
} }
} }
// clear clip-region and could also draw 'fade-effect' PolygonRenderer.drawOver(m, mOverdraw);
if (mFaded)
PolygonRenderer.drawOver(m, true, 0x22000000);
else
PolygonRenderer.drawOver(m, false, 0);
} }
private static int drawProxyChild(MapTile tile, MapPosition pos) { private static int drawProxyChild(MapTile tile, MapPosition pos) {

View File

@ -53,4 +53,9 @@ public abstract class AbstractTileSource implements TileSource {
result = prime * result + this.port; result = prime * result + this.port;
return result; return result;
} }
@Override
public FadeStep[] getFadeSteps() {
return null;
}
} }

View File

@ -20,27 +20,63 @@ import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import org.oscim.view.MapView;
import org.oscim.backend.CanvasAdapter; import org.oscim.backend.CanvasAdapter;
import org.oscim.backend.canvas.Bitmap; import org.oscim.backend.canvas.Bitmap;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLayer; import org.oscim.layers.tile.TileLayer;
import org.oscim.layers.tile.TileLoader; import org.oscim.layers.tile.TileLoader;
import org.oscim.layers.tile.TileManager; import org.oscim.layers.tile.TileManager;
import org.oscim.layers.tile.bitmap.TileSource.FadeStep;
import org.oscim.renderer.sublayers.BitmapLayer; import org.oscim.renderer.sublayers.BitmapLayer;
import org.oscim.renderer.sublayers.Layers; import org.oscim.renderer.sublayers.Layers;
import org.oscim.utils.FastMath;
import org.oscim.view.MapView;
public class BitmapTileLayer extends TileLayer<TileLoader> { public class BitmapTileLayer extends TileLayer<TileLoader> {
private static final int TIMEOUT_CONNECT = 5000; private static final int TIMEOUT_CONNECT = 5000;
private static final int TIMEOUT_READ = 10000; private static final int TIMEOUT_READ = 10000;
protected static final String TAG = BitmapTileLayer.class.getName();
final TileSource mTileSource; final TileSource mTileSource;
private final FadeStep[] mFade;
public BitmapTileLayer(MapView mapView, TileSource tileSource) { public BitmapTileLayer(MapView mapView, TileSource tileSource) {
super(mapView, tileSource.getZoomLevelMin(), tileSource.getZoomLevelMax(), 100); super(mapView, tileSource.getZoomLevelMin(), tileSource.getZoomLevelMax(), 100);
mTileSource = tileSource; mTileSource = tileSource;
mFade = mTileSource.getFadeSteps();
}
@Override
public void onUpdate(MapPosition pos, boolean changed, boolean clear) {
super.onUpdate(pos, changed, clear);
if (mFade == null) {
mRenderLayer.setBitmapAlpha(1);
return;
}
float alpha = 0;
for (FadeStep f : mFade) {
if (pos.scale < f.scaleStart || pos.scale > f.scaleEnd)
continue;
if (f.alphaStart == f.alphaEnd) {
alpha = f.alphaStart;
break;
}
double range = f.scaleEnd / f.scaleStart;
float a = (float)((range - (pos.scale / f.scaleStart)) / range);
a = FastMath.clamp(a, 0, 1);
// interpolate alpha between start and end
alpha = a * f.alphaStart + (1 - a) * f.alphaEnd;
break;
}
mRenderLayer.setBitmapAlpha(alpha);
} }
@Override @Override
@ -61,7 +97,6 @@ public class BitmapTileLayer extends TileLayer<TileLoader> {
l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE); l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE);
tile.layers.textureLayers = l; tile.layers.textureLayers = l;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;

View File

@ -20,10 +20,11 @@ import java.net.URL;
import org.oscim.core.Tile; import org.oscim.core.Tile;
public class NaturalEarth extends AbstractTileSource { public class NaturalEarth extends AbstractTileSource {
public static final NaturalEarth INSTANCE = new NaturalEarth("city.informatik.uni-bremen.de", 80); public static final NaturalEarth INSTANCE = new NaturalEarth("city.informatik.uni-bremen.de",
80);
private static final int PARALLEL_REQUESTS_LIMIT = 4; private static final int PARALLEL_REQUESTS_LIMIT = 4;
private static final String PROTOCOL = "http"; private static final String PROTOCOL = "http";
private static final int ZOOM_LEVEL_MAX = 6; private static final int ZOOM_LEVEL_MAX = 8;
private static final int ZOOM_LEVEL_MIN = 0; private static final int ZOOM_LEVEL_MIN = 0;
public NaturalEarth(String hostName, int port) { public NaturalEarth(String hostName, int port) {
@ -38,12 +39,14 @@ public class NaturalEarth extends AbstractTileSource {
@Override @Override
public URL getTileUrl(Tile tile) throws MalformedURLException { public URL getTileUrl(Tile tile) throws MalformedURLException {
StringBuilder stringBuilder = new StringBuilder(32); StringBuilder stringBuilder = new StringBuilder(32);
stringBuilder.append("/osci/ne_image2/");
stringBuilder.append("/tiles/ne/");
//stringBuilder.append("/osci/ne_image2/");
stringBuilder.append(tile.zoomLevel); stringBuilder.append(tile.zoomLevel);
stringBuilder.append('/'); stringBuilder.append('/');
stringBuilder.append(tile.tileX); stringBuilder.append(tile.tileX);
stringBuilder.append('/'); stringBuilder.append('/');
stringBuilder.append((1 << tile.zoomLevel) - tile.tileY - 1); stringBuilder.append(tile.tileY);
stringBuilder.append(".png"); stringBuilder.append(".png");
return new URL(PROTOCOL, this.hostName, this.port, stringBuilder.toString()); return new URL(PROTOCOL, this.hostName, this.port, stringBuilder.toString());
@ -58,4 +61,14 @@ public class NaturalEarth extends AbstractTileSource {
public byte getZoomLevelMin() { public byte getZoomLevelMin() {
return ZOOM_LEVEL_MIN; return ZOOM_LEVEL_MIN;
} }
@Override
public FadeStep[] getFadeSteps() {
return new FadeStep[] {
new FadeStep(ZOOM_LEVEL_MIN, ZOOM_LEVEL_MAX - 1, 1, 0.7f),
// dont fade between zoom-min/max
// fade above zoom max + 2, interpolate 1 to 0
new FadeStep(ZOOM_LEVEL_MAX - 1, ZOOM_LEVEL_MAX + 1, 0.7f, 0)
};
}
} }

View File

@ -39,4 +39,18 @@ public interface TileSource {
* @return the minimum zoom level which this {@code TileSource} supports. * @return the minimum zoom level which this {@code TileSource} supports.
*/ */
byte getZoomLevelMin(); byte getZoomLevelMin();
FadeStep[] getFadeSteps();
public class FadeStep{
public final double scaleStart, scaleEnd;
public final float alphaStart, alphaEnd;
public FadeStep(int zoomStart, int zoomEnd, float alphaStart, float alphaEnd) {
this.scaleStart = 1 << zoomStart;
this.scaleEnd = 1 << zoomEnd;
this.alphaStart = alphaStart;
this.alphaEnd = alphaEnd;
}
}
} }

View File

@ -85,7 +85,7 @@ public abstract class BasicRenderLayer extends RenderLayer {
for (Layer l = layers.textureLayers; l != null;) { for (Layer l = layers.textureLayers; l != null;) {
switch (l.type) { switch (l.type) {
case Layer.BITMAP: case Layer.BITMAP:
l = BitmapRenderer.draw(l, 1, m); l = BitmapRenderer.draw(l, m, 1, 1);
break; break;
default: default:

View File

@ -92,6 +92,6 @@ public class BitmapRenderLayer extends BasicRenderLayer {
@Override @Override
public synchronized void render(MapPosition pos, Matrices m) { public synchronized void render(MapPosition pos, Matrices m) {
m.useScreenCoordinates(false, 8); m.useScreenCoordinates(false, 8);
BitmapRenderer.draw(layers.textureLayers, 1, m); BitmapRenderer.draw(layers.textureLayers, m, 1, 1);
} }
} }

View File

@ -39,6 +39,8 @@ public final class BitmapRenderer {
private static int hTextureScreenScale; private static int hTextureScreenScale;
private static int hTextureTexCoord; private static int hTextureTexCoord;
private static int hAlpha;
public final static int INDICES_PER_SPRITE = 6; public final static int INDICES_PER_SPRITE = 6;
final static int VERTICES_PER_SPRITE = 4; final static int VERTICES_PER_SPRITE = 4;
final static int SHORTS_PER_VERTICE = 6; final static int SHORTS_PER_VERTICE = 6;
@ -53,9 +55,10 @@ public final class BitmapRenderer {
hTextureScreenScale = GL.glGetUniformLocation(mTextureProgram, "u_swidth"); hTextureScreenScale = GL.glGetUniformLocation(mTextureProgram, "u_swidth");
hTextureVertex = GL.glGetAttribLocation(mTextureProgram, "vertex"); hTextureVertex = GL.glGetAttribLocation(mTextureProgram, "vertex");
hTextureTexCoord = GL.glGetAttribLocation(mTextureProgram, "tex_coord"); hTextureTexCoord = GL.glGetAttribLocation(mTextureProgram, "tex_coord");
hAlpha = GL.glGetUniformLocation(mTextureProgram, "u_alpha");
} }
public static Layer draw(Layer layer, float scale, Matrices m) { public static Layer draw(Layer layer, Matrices m, float scale, float alpha) {
//GLState.test(false, false); //GLState.test(false, false);
GLState.blend(true); GLState.blend(true);
@ -70,7 +73,9 @@ public final class BitmapRenderer {
else else
GL.glUniform1f(hTextureScale, 1); GL.glUniform1f(hTextureScale, 1);
GL.glUniform1f(hTextureScreenScale, 1f / GLRenderer.screenWidth); GL.glUniform1f(hTextureScreenScale, 1f / GLRenderer.screenWidth);
GL.glUniform1f(hAlpha, alpha);
m.proj.setAsUniform(hTextureProjMatrix); m.proj.setAsUniform(hTextureProjMatrix);
@ -109,9 +114,6 @@ public final class BitmapRenderer {
return layer.next; return layer.next;
} }
//private final static double TEX_COORD_DIV = 1.0 / (1024 * COORD_SCALE);
//private final static double COORD_DIV = 1.0 / GLRenderer.COORD_SCALE;
private final static String textVertexShader = "" private final static String textVertexShader = ""
+ "precision mediump float; " + "precision mediump float; "
+ "attribute vec4 vertex;" + "attribute vec4 vertex;"
@ -121,18 +123,17 @@ public final class BitmapRenderer {
+ "uniform float u_scale;" + "uniform float u_scale;"
+ "uniform float u_swidth;" + "uniform float u_swidth;"
+ "varying vec2 tex_c;" + "varying vec2 tex_c;"
//+ "const vec2 div = vec2(" + TEX_COORD_DIV + "," + TEX_COORD_DIV + ");"
//+ "const float coord_scale = " + COORD_DIV + ";"
+ "void main() {" + "void main() {"
+ " gl_Position = u_mv * vec4(vertex.xy, 0.0, 1.0);" + " gl_Position = u_mv * vec4(vertex.xy, 0.0, 1.0);"
+ " tex_c = tex_coord;" // * div;" + " tex_c = tex_coord;"
+ "}"; + "}";
private final static String textFragmentShader = "" private final static String textFragmentShader = ""
+ "precision mediump float;" + "precision mediump float;"
+ "uniform sampler2D tex;" + "uniform sampler2D tex;"
+ "uniform float u_alpha;"
+ "varying vec2 tex_c;" + "varying vec2 tex_c;"
+ "void main() {" + "void main() {"
+ " gl_FragColor = texture2D(tex, tex_c.xy);" + " gl_FragColor = texture2D(tex, tex_c.xy) * u_alpha;"
+ "}"; + "}";
} }

View File

@ -338,7 +338,7 @@ public final class PolygonRenderer {
} }
} }
public static void drawOver(Matrices m, boolean drawColor, int color) { public static void drawOver(Matrices m, int color) {
setShader(polyShader, m); setShader(polyShader, m);
/* /*
@ -346,7 +346,7 @@ public final class PolygonRenderer {
* a quad with func 'always' and op 'zero' * a quad with func 'always' and op 'zero'
*/ */
if (drawColor) { if (color != 0) {
GlUtils.setColor(hPolygonColor[0], color, 1); GlUtils.setColor(hPolygonColor[0], color, 1);
GLState.blend(true); GLState.blend(true);
} else { } else {
@ -364,7 +364,7 @@ public final class PolygonRenderer {
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4); GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, 4);
if (!drawColor) if (color == 0)
GL.glColorMask(true, true, true, true); GL.glColorMask(true, true, true, true);
} }