- draw up to two parent proxies for current tile (not just one)

- nicer shader for devices not having GL_OES_standard_derivatives
- fix: check for min/max zoom position
This commit is contained in:
Hannes Janetzek
2012-06-25 02:36:30 +02:00
parent d13f1b43ad
commit 5cc678d77d
13 changed files with 280 additions and 148 deletions

View File

@@ -117,7 +117,8 @@ public class MapViewPosition {
mZoomLevel); mZoomLevel);
mLatitude = MercatorProjection.limitLatitude(mLatitude); mLatitude = MercatorProjection.limitLatitude(mLatitude);
mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal / mScale, mLongitude = MercatorProjection.pixelXToLongitude(pixelX - moveHorizontal
/ mScale,
mZoomLevel); mZoomLevel);
mLongitude = MercatorProjection.limitLongitude(mLongitude); mLongitude = MercatorProjection.limitLongitude(mLongitude);
} }
@@ -163,10 +164,14 @@ public class MapViewPosition {
if (s >= MAX_SCALE) { if (s >= MAX_SCALE) {
byte z = (byte) FloatMath.sqrt(s); byte z = (byte) FloatMath.sqrt(s);
if (z != 0 && mZoomLevel == 20)
return;
mZoomLevel += z; mZoomLevel += z;
s *= 1.0f / (1 << z); s *= 1.0f / (1 << z);
} else if (s < MIN_SCALE) { } else if (s < MIN_SCALE) {
byte z = (byte) FloatMath.sqrt(1 / s); byte z = (byte) FloatMath.sqrt(1 / s);
if (z != 0 && mZoomLevel == 1)
return;
mZoomLevel -= z; mZoomLevel -= z;
s *= 1 << z; s *= 1 << z;
} }

View File

@@ -54,7 +54,7 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback,
private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16); private static final Byte DEFAULT_START_ZOOM_LEVEL = Byte.valueOf((byte) 16);
private static final double PI180 = (Math.PI / 180) / 1000000.0; private static final double PI180 = (Math.PI / 180) / 1000000.0;
private static final double PIx4 = Math.PI * 4; private static final double PIx4 = Math.PI * 4;
private static final double STROKE_INCREASE = 1.5; private static final double STROKE_INCREASE = Math.sqrt(2);
private static final byte STROKE_MIN_ZOOM_LEVEL = 12; private static final byte STROKE_MIN_ZOOM_LEVEL = 12;
private static final byte LAYERS = 11; private static final byte LAYERS = 11;
@@ -123,12 +123,12 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback,
long dx = (x - (z >> 1)); long dx = (x - (z >> 1));
long dy = (y - (z >> 1)); long dy = (y - (z >> 1));
if (!useSphericalMercator) { if (useSphericalMercator) {
divx = 180000000.0 / (z >> 1);
divy = z / PIx4;
} else {
divx = f900913 / (z >> 1); divx = f900913 / (z >> 1);
divy = f900913 / (z >> 1); divy = f900913 / (z >> 1);
} else {
divx = 180000000.0 / (z >> 1);
divy = z / PIx4;
} }
for (int pos = 0, outPos = 0, i = 0, m = mWays.length; i < m; i++) { for (int pos = 0, outPos = 0, i = 0, m = mWays.length; i < m; i++) {

View File

@@ -24,12 +24,19 @@ class Layer {
int offset; int offset;
final int layer; final int layer;
final int color; // final int color;
final float[] colors;
Layer(int l, int c) { Layer(int l, int color) {
color = c;
layer = l; layer = l;
verticesCnt = 0; verticesCnt = 0;
colors = new float[4];
colors[0] = (color >> 16 & 0xff) / 255.0f;
colors[1] = (color >> 8 & 0xff) / 255.0f;
colors[2] = (color >> 0 & 0xff) / 255.0f;
colors[3] = (color >> 24 & 0xff) / 255.0f;
} }
float[] getNextItem() { float[] getNextItem() {

View File

@@ -21,7 +21,6 @@ import org.mapsforge.core.Tile;
class LineLayer extends Layer { class LineLayer extends Layer {
ArrayList<LineLayer> outlines; ArrayList<LineLayer> outlines;
float[] colors;
boolean isOutline; boolean isOutline;
boolean isFixed; boolean isFixed;
float width; float width;
@@ -38,15 +37,6 @@ class LineLayer extends Layer {
pool = new LinkedList<PoolItem>(); pool = new LinkedList<PoolItem>();
pool.add(curItem); pool.add(curItem);
} }
colors = new float[4];
float a = (color >> 24 & 0xff) / 255.0f;
colors[0] = (color >> 16 & 0xff) / 255.0f;
colors[1] = (color >> 8 & 0xff) / 255.0f;
colors[2] = (color >> 0 & 0xff) / 255.0f;
colors[3] = a;
} }
void addOutline(LineLayer link) { void addOutline(LineLayer link) {

View File

@@ -127,6 +127,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
private int gLineColorHandle; private int gLineColorHandle;
private int gLineMatrixHandle; private int gLineMatrixHandle;
private int gLineModeHandle; private int gLineModeHandle;
private int gLineWidthHandle;
private int gPolygonProgram; private int gPolygonProgram;
private int gPolygonVertexPositionHandle; private int gPolygonVertexPositionHandle;
@@ -163,30 +164,43 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
private void updateTileDistances() { private void updateTileDistances() {
byte zoom = mMapPosition.zoomLevel; byte zoom = mMapPosition.zoomLevel;
long x = mTileX; long x = mTileX * (Tile.TILE_SIZE); // - (Tile.TILE_SIZE >> 1);
long y = mTileY; long y = mTileY * (Tile.TILE_SIZE); // - (Tile.TILE_SIZE >> 1);
int diff; int diff;
long dx, dy; long dx, dy;
// TODO this could be optimized to consider move/zoom direction
for (int i = 0, n = mTileList.size(); i < n; i++) { for (int i = 0, n = mTileList.size(); i < n; i++) {
GLMapTile t = mTileList.get(i); GLMapTile t = mTileList.get(i);
diff = (t.zoomLevel - zoom); diff = (t.zoomLevel - zoom);
if (diff != 0) { if (diff != 0) {
if (diff > 0) { if (diff > 0) {
dx = (t.tileX << diff) - x; // tile zoom level is child of current
dy = (t.tileY << diff) - y; dx = (t.pixelX >> diff) - x;
dy = (t.pixelY >> diff) - y;
} else { } else {
dx = (t.tileX >> -diff) - x; // tile zoom level is parent of current
dy = (t.tileY >> -diff) - y; dx = (t.pixelX << -diff) - x;
dy = (t.pixelY << -diff) - y;
} }
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)); if (diff == -1) {
t.distance *= (1 + t.zoomLevel); // load parent before current layer (kind of progressive transmission :)
dy *= mAspect;
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
} else {
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
// prefer lower zoom level, i.e. it covers a larger area
t.distance *= (1 + (diff > 0 ? diff * 4 : -diff * 2));
}
} else { } else {
dx = t.tileX - x; dx = t.pixelX - x;
dy = t.tileY - y; dy = t.pixelY - y;
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)); dy *= mAspect;
t.distance = (1 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy))) * 2;
} }
// Log.d(TAG, t + " " + t.distance);
} }
} }
@@ -206,7 +220,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
if (t.zoomLevel == z + 1) { if (t.zoomLevel == z + 1) {
if (t.parent != null && t.parent.isActive && !t.parent.isDrawn) { if (t.parent != null && t.parent.isActive && !t.parent.isDrawn) {
mTileList.add(t); mTileList.add(t);
// Log.d(TAG, "EEEK removing active proxy child"); Log.d(TAG, "EEEK removing active proxy child");
continue; continue;
} }
} else if (t.zoomLevel == z - 1) { } else if (t.zoomLevel == z - 1) {
@@ -219,7 +233,31 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
} }
if (c != null) { if (c != null) {
// Log.d(TAG, "EEEK removing active proxy parent"); Log.d(TAG, "EEEK removing active proxy parent");
mTileList.add(t);
continue;
}
} else if (t.zoomLevel == z - 2) {
GLMapTile c = null, c2 = null;
for (int i = 0; i < 4; i++) {
c = t.child[i];
if (c != null) {
for (int k = 0; k < 4; k++) {
c2 = c.child[k];
if (c2 != null && c2.isActive
&& !(c2.isDrawn || c2.newData))
break;
c2 = null;
}
if (c2 != null)
break;
}
c = null;
}
if (c != null) {
Log.d(TAG, "EEEK removing active second level proxy parent");
mTileList.add(t); mTileList.add(t);
continue; continue;
} }
@@ -293,42 +331,51 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
if (tile == null) { if (tile == null) {
tile = new GLMapTile(tileX, tileY, zoomLevel); tile = new GLMapTile(tileX, tileY, zoomLevel);
TileCacheKey key = new TileCacheKey(mTileCacheKey); TileCacheKey key = new TileCacheKey(mTileCacheKey);
mTiles.put(key, tile);
// FIXME use sparse matrix or sth.
if (mTiles.put(key, tile) != null)
Log.d(TAG, "eeek collision");
mTileList.add(tile); mTileList.add(tile);
mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1)); mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1));
tile.parent = mTiles.get(mTileCacheKey); tile.parent = mTiles.get(mTileCacheKey);
int idx = (int) ((tileX & 0x01) + 2 * (tileY & 0x01));
// set this tile to be child of its parent // set this tile to be child of its parent
if (tile.parent != null) { if (tile.parent != null) {
int idx = (int) ((tileX & 0x01) + 2 * (tileY & 0x01));
tile.parent.child[idx] = tile; tile.parent.child[idx] = tile;
} }
else if (zoomLevel > 0) {
long xx = tileX << 1; tile.parent = new GLMapTile(tileX >> 1, tileY >> 1,
long yy = tileY << 1; (byte) (zoomLevel - 1));
byte z = (byte) (zoomLevel + 1); key = new TileCacheKey(mTileCacheKey);
if (mTiles.put(key, tile.parent) != null)
tile.child[0] = mTiles.get(mTileCacheKey.set(xx, yy, z)); Log.d(TAG, "eeek collision");
tile.child[1] = mTiles.get(mTileCacheKey.set(xx + 1, yy, z)); mTileList.add(tile.parent);
tile.child[2] = mTiles.get(mTileCacheKey.set(xx, yy + 1, z)); setChildren(tile.parent);
tile.child[3] = mTiles.get(mTileCacheKey.set(xx + 1, yy + 1, z));
// set this tile to be parent of its children
for (int i = 0; i < 4; i++) {
if (tile.child[i] != null)
tile.child[i].parent = tile;
} }
setChildren(tile);
} }
newTiles.tiles[tiles++] = tile; newTiles.tiles[tiles++] = tile;
if (!tile.isDrawn && !tile.isLoading) { if (!tile.isDrawn && !tile.newData && !tile.isLoading) {
MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator, MapGeneratorJob job = new MapGeneratorJob(tile, mapGenerator,
mJobParameter, mDebugSettings); mJobParameter, mDebugSettings);
mJobList.add(job); mJobList.add(job);
} }
// prefetch parent
if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData
&& !tile.parent.isLoading) {
MapGeneratorJob job = new MapGeneratorJob(tile.parent, mapGenerator,
mJobParameter, mDebugSettings);
if (!mJobList.contains(job))
mJobList.add(job);
}
} }
} }
@@ -369,6 +416,24 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
return true; return true;
} }
private void setChildren(GLMapTile tile) {
long xx = tile.tileX << 1;
long yy = tile.tileY << 1;
byte z = (byte) (tile.zoomLevel + 1);
tile.child[0] = mTiles.get(mTileCacheKey.set(xx, yy, z));
tile.child[1] = mTiles.get(mTileCacheKey.set(xx + 1, yy, z));
tile.child[2] = mTiles.get(mTileCacheKey.set(xx, yy + 1, z));
tile.child[3] = mTiles.get(mTileCacheKey.set(xx + 1, yy + 1, z));
// set this tile to be parent of its children
for (int i = 0; i < 4; i++) {
if (tile.child[i] != null)
tile.child[i].parent = tile;
}
}
/** /**
* *
*/ */
@@ -440,7 +505,9 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
return true; return true;
} }
private void fillPolygons(int[] colors, int count) { private PolygonLayer[] mFillPolys;
private void fillPolygons(int count) {
boolean blend = false; boolean blend = false;
// draw to framebuffer // draw to framebuffer
@@ -450,9 +517,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glStencilMask(0); GLES20.glStencilMask(0);
for (int c = 0; c < count; c++) { for (int c = 0; c < count; c++) {
int color = colors[c]; PolygonLayer l = mFillPolys[c];
float alpha = (color >> 24 & 0xff) / 255f;
if (alpha != 1) { float alpha = 1.0f;
if (l.fadeLevel >= mDrawZ) {
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f)
alpha = 1.0f;
if (!blend) { if (!blend) {
GLES20.glEnable(GLES20.GL_BLEND); GLES20.glEnable(GLES20.GL_BLEND);
blend = true; blend = true;
@@ -463,9 +537,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
} }
GLES20.glUniform4f(gPolygonColorHandle, GLES20.glUniform4f(gPolygonColorHandle,
(color >> 16 & 0xff) / 255f, l.colors[0], l.colors[1], l.colors[2], alpha);
(color >> 8 & 0xff) / 255f,
(color & 0xff) / 255f, alpha);
// set stencil buffer mask used to draw this layer // set stencil buffer mask used to draw this layer
GLES20.glStencilFunc(GLES20.GL_EQUAL, 0xff, 1 << c); GLES20.glStencilFunc(GLES20.GL_EQUAL, 0xff, 1 << c);
@@ -478,8 +550,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glDisable(GLES20.GL_BLEND); GLES20.glDisable(GLES20.GL_BLEND);
} }
private int[] mPolyColors;
private boolean drawPolygons(GLMapTile tile, int diff) { private boolean drawPolygons(GLMapTile tile, int diff) {
float scale, x, y, z = 1; float scale, x, y, z = 1;
@@ -514,7 +584,6 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
} }
int cnt = 0; int cnt = 0;
int[] colors = mPolyColors;
mMVPMatrix[12] = -x * (scale * mAspect); mMVPMatrix[12] = -x * (scale * mAspect);
mMVPMatrix[13] = -y * (scale); mMVPMatrix[13] = -y * (scale);
@@ -551,22 +620,11 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glStencilOp(GLES20.GL_INVERT, GLES20.GL_INVERT, GLES20.GL_INVERT); GLES20.glStencilOp(GLES20.GL_INVERT, GLES20.GL_INVERT, GLES20.GL_INVERT);
} }
colors[cnt] = l.color;
// fade out polygon layers (set in RederTheme) // fade out polygon layers (set in RederTheme)
if (l.fadeLevel > 0) { if (l.fadeLevel > 0 && l.fadeLevel > mDrawZ)
if (l.fadeLevel >= mDrawZ) { continue;
// skip layer when faded out mFillPolys[cnt] = l;
if (l.fadeLevel > mDrawZ)
continue;
// modify alpha channel
float s = (mDrawScale > 1.3f ? mDrawScale : 1.3f);
colors[cnt] = (colors[cnt] & 0xffffff)
| (byte) ((s - 1) * 0xff) << 24;
}
}
// set stencil mask to draw to // set stencil mask to draw to
GLES20.glStencilMask(1 << cnt++); GLES20.glStencilMask(1 << cnt++);
@@ -575,13 +633,13 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
// draw up to 8 layers into stencil buffer // draw up to 8 layers into stencil buffer
if (cnt == STENCIL_BITS) { if (cnt == STENCIL_BITS) {
fillPolygons(colors, cnt); fillPolygons(cnt);
cnt = 0; cnt = 0;
} }
} }
if (cnt > 0) if (cnt > 0)
fillPolygons(colors, cnt); fillPolygons(cnt);
return true; return true;
} }
@@ -644,7 +702,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
// linear scale for fixed lines // linear scale for fixed lines
float fdiv = 0.9f / (mDrawScale / z); float fdiv = 0.9f / (mDrawScale / z);
int cnt = 0; // int cnt = 0;
for (int i = 0, n = layers.length; i < n; i++) { for (int i = 0, n = layers.length; i < n; i++) {
LineLayer l = layers[i]; LineLayer l = layers[i];
@@ -654,15 +712,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
drawFixed = l.isFixed; drawFixed = l.isFixed;
if (drawFixed) { if (drawFixed) {
GLES20.glUniform2f(gLineModeHandle, 0.4f, fdiv); GLES20.glUniform2f(gLineModeHandle, 0.4f, fdiv);
// GLES20.glUniform1f(gLineWidthHandle, fdiv);
} else if (drawOutlines) { } else if (drawOutlines) {
GLES20.glUniform2f(gLineModeHandle, 0, wdiv); GLES20.glUniform2f(gLineModeHandle, 0, wdiv);
// GLES20.glUniform1i(gLineModeHandle, 1);
// GLES20.glUniform1f(gLineWidthHandle, wdiv);
} else { } else {
GLES20.glUniform2f(gLineModeHandle, 0, wdiv * 0.95f); GLES20.glUniform2f(gLineModeHandle, 0, wdiv * 0.98f);
// GLES20.glUniform1i(gLineModeHandle, 0);
// GLES20.glUniform1f(gLineWidthHandle, wdiv * 0.95f);
} }
} }
@@ -672,9 +725,16 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
for (int j = 0, m = l.outlines.size(); j < m; j++) { for (int j = 0, m = l.outlines.size(); j < m; j++) {
LineLayer o = l.outlines.get(j); LineLayer o = l.outlines.get(j);
if (mSimpleLines)
GLES20.glUniform1f(gLineWidthHandle, o.width);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
} }
} else { }
else {
if (mSimpleLines)
GLES20.glUniform1f(gLineWidthHandle, l.width);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
} }
// cnt += l.verticesCnt; // cnt += l.verticesCnt;
@@ -724,7 +784,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
if (sw + sx > mWidth) if (sw + sx > mWidth)
sw = mWidth - sx; sw = mWidth - sx;
if (sh + tile.sy > mHeight) if (sh + (sy - sh) > mHeight)
sh = mHeight - sy; sh = mHeight - sy;
if (sw <= 0 || sh <= 0) { if (sw <= 0 || sh <= 0) {
@@ -750,13 +810,26 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
tile.parent.sh = tile.sh; tile.parent.sh = tile.sh;
drawLines(tile.parent, -1); drawLines(tile.parent, -1);
} else { } else {
int drawn = 0;
// scissor coordinates already set for polygons // scissor coordinates already set for polygons
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
GLMapTile c = tile.child[i]; GLMapTile c = tile.child[i];
if (c != null && c.isDrawn && c.isVisible) if (c != null && c.isDrawn && c.isVisible) {
drawLines(c, 1); drawLines(c, 1);
drawn++;
}
} }
if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) {
p.sx = tile.sx;
p.sy = tile.sy;
p.sw = tile.sw;
p.sh = tile.sh;
drawLines(p, -2);
}
}
} }
} }
@@ -768,11 +841,26 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
tile.parent.sh = tile.sh; tile.parent.sh = tile.sh;
drawPolygons(tile.parent, -1); drawPolygons(tile.parent, -1);
} else { } else {
int drawn = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
GLMapTile c = tile.child[i]; GLMapTile c = tile.child[i];
if (c != null && c.isDrawn && setTileScissor(c, 2))
drawPolygons(c, 1);
if (c != null && c.isDrawn && setTileScissor(c, 2)) {
drawPolygons(c, 1);
drawn++;
}
}
if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) {
p.sx = tile.sx;
p.sy = tile.sy;
p.sw = tile.sw;
p.sh = tile.sh;
drawPolygons(p, -2);
}
} }
} }
} }
@@ -858,6 +946,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
return true; return true;
} }
// private long startTime = SystemClock.uptimeMillis();
@Override @Override
public void onDrawFrame(GL10 glUnused) { public void onDrawFrame(GL10 glUnused) {
long start = 0, poly_time = 0, clear_time = 0; long start = 0, poly_time = 0, clear_time = 0;
@@ -871,6 +961,18 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glStencilMask(0xFF); GLES20.glStencilMask(0xFF);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST); GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);
GLES20.glFlush();
// long endTime = SystemClock.uptimeMillis();
// long dt = endTime - startTime;
// if (dt < 33)
// try {
// Thread.sleep(33 - dt);
// } catch (InterruptedException e) {
// Log.d(TAG, "interrupt");
// return;
// }
// startTime = SystemClock.uptimeMillis();
synchronized (this) { synchronized (this) {
mDrawX = mCurX; mDrawX = mCurX;
@@ -960,7 +1062,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glEnable(GLES20.GL_STENCIL_TEST); GLES20.glEnable(GLES20.GL_STENCIL_TEST);
GLES20.glUseProgram(gPolygonProgram); GLES20.glUseProgram(gPolygonProgram);
GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) { if (tiles[i].isVisible) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
@@ -973,16 +1075,22 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
} }
GLES20.glDisable(GLES20.GL_STENCIL_TEST); GLES20.glDisable(GLES20.GL_STENCIL_TEST);
// required on GalaxyII, Android 2.3.3
GLES20.glDisableVertexAttribArray(gPolygonVertexPositionHandle);
if (timing) { if (timing) {
GLES20.glFinish(); GLES20.glFinish();
poly_time = (SystemClock.uptimeMillis() - start); poly_time = (SystemClock.uptimeMillis() - start);
} }
// GLES20.glFlush(); // GLES20.glFlush();
// Draw lines // Draw lines
GLES20.glEnable(GLES20.GL_BLEND); GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glUseProgram(gLineProgram); GLES20.glUseProgram(gLineProgram);
GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle);
GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible) { if (tiles[i].isVisible) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
@@ -999,6 +1107,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " " Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " "
+ clear_time + " " + poly_time); + clear_time + " " + poly_time);
} }
GLES20.glDisableVertexAttribArray(gLineVertexPositionHandle);
GLES20.glDisableVertexAttribArray(gLineTexturePositionHandle);
} }
@@ -1017,7 +1127,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
return; return;
STENCIL_BITS = GlConfigChooser.stencilSize; STENCIL_BITS = GlConfigChooser.stencilSize;
mPolyColors = new int[STENCIL_BITS]; mFillPolys = new PolygonLayer[STENCIL_BITS];
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
@@ -1045,6 +1155,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
mMapView.redrawTiles(); mMapView.redrawTiles();
} }
private boolean mSimpleLines = false;
@Override @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Set up the program for rendering lines // Set up the program for rendering lines
@@ -1052,6 +1164,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShader); Shaders.gLineFragmentShader);
if (gLineProgram == 0) { if (gLineProgram == 0) {
mSimpleLines = true;
Log.e(TAG, "trying simple line program."); Log.e(TAG, "trying simple line program.");
gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader, gLineProgram = GlUtils.createProgram(Shaders.gLineVertexShader,
Shaders.gLineFragmentShaderSimple); Shaders.gLineFragmentShaderSimple);
@@ -1074,6 +1187,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
gLineVertexPositionHandle = GLES20 gLineVertexPositionHandle = GLES20
.glGetAttribLocation(gLineProgram, "a_position"); .glGetAttribLocation(gLineProgram, "a_position");
gLineTexturePositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_st"); gLineTexturePositionHandle = GLES20.glGetAttribLocation(gLineProgram, "a_st");
if (mSimpleLines)
gLineWidthHandle = GLES20.glGetUniformLocation(gLineProgram, "u_width");
// Set up the program for rendering polygons // Set up the program for rendering polygons
gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader, gPolygonProgram = GlUtils.createProgram(Shaders.gPolygonVertexShader,
@@ -1095,9 +1210,11 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer {
GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle); GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_DITHER); GLES20.glDisable(GLES20.GL_DITHER);
GLES20.glClearColor(0.98f, 0.98f, 0.975f, 1.0f);
GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
GLES20.glClearStencil(0); GLES20.glClearStencil(0);
} }

View File

@@ -45,10 +45,10 @@ class PolygonLayers {
PolygonLayer getLayer(int layer, int color, int fade) { PolygonLayer getLayer(int layer, int color, int fade) {
PolygonLayer l = layers.get(layer); PolygonLayer l = layers.get(layer);
if (l != null) { if (l != null) {
if (color == l.color) // if (color == l.color)
return l; return l;
return getLayer(layer + 1, color, fade); // return getLayer(layer + 1, color, fade);
} }
l = new PolygonLayer(layer, color, fade); l = new PolygonLayer(layer, color, fade);

View File

@@ -30,14 +30,13 @@ class Shaders {
final static String gLineFragmentShader = "" final static String gLineFragmentShader = ""
+ "#extension GL_OES_standard_derivatives : enable\n" + "#extension GL_OES_standard_derivatives : enable\n"
+ "precision mediump float;" + "precision mediump float;"
+ "uniform vec2 u_mode;" + "uniform lowp vec2 u_mode;"
+ "uniform vec4 u_color;" + "uniform vec4 u_color;"
+ "const float zero = 0.0;" + "const lowp float zero = 0.0;"
+ "const float fuzzf = 1.5;" + "const float fuzzf = 1.8;"
// + "const vec4 blank = vec4(0.0,0.0,0.0,0.0);"
+ "varying vec2 v_st;" + "varying vec2 v_st;"
+ "void main() {" + "void main() {"
+ " lowp vec4 color = u_color;" + " gl_FragColor = u_color;"
+ " lowp float len;" + " lowp float len;"
+ " lowp float fuzz;" + " lowp float fuzz;"
+ " lowp float width = u_mode[1];" + " lowp float width = u_mode[1];"
@@ -48,14 +47,12 @@ class Shaders {
+ " fuzz = max(fwidth(v_st.s), fwidth(v_st.t)) * fuzzf;" + " fuzz = max(fwidth(v_st.s), fwidth(v_st.t)) * fuzzf;"
+ " len = width - length(v_st);" + " len = width - length(v_st);"
+ " } " + " } "
+ " lowp float min_fuzz = -fuzz * u_mode[0];" // + " if (len < min_fuzz)"
+ " if (len < min_fuzz)" // + " discard;"
+ " discard;" // + " alpha = zero;"
// + " color = blank;" + " if (len < fuzz) {"
+ " else {" + " lowp float min_fuzz = -fuzz * u_mode[0];"
+ " if (len < fuzz)" + " gl_FragColor.a = u_color.a * smoothstep(min_fuzz, fuzz, len);"
+ " color.a *= smoothstep(min_fuzz, fuzz, len);"
+ " gl_FragColor = color;"
+ " }" + " }"
+ "}"; + "}";
@@ -144,19 +141,19 @@ class Shaders {
final static String gLineFragmentShaderSimple = "" final static String gLineFragmentShaderSimple = ""
+ "precision mediump float;" + "precision mediump float;"
+ "uniform vec4 u_color;" + "uniform vec4 u_color;"
+ "uniform vec2 u_mode;"
+ "uniform float u_width;" + "uniform float u_width;"
+ "varying vec2 v_st;" + "varying vec2 v_st;"
+ "void main() {" + "void main() {"
+ " vec4 color = u_color;" + " gl_FragColor = u_color;"
+ " float width = u_width * u_mode[1];"
+ " float len;" + " float len;"
+ " if (v_st.t == 0.0) " + " if (v_st.t == 0.0) "
+ " len = abs(v_st.s);" + " len = abs(v_st.s);"
+ " else " + " else "
+ " len = length(v_st);" + " len = length(v_st);"
+ " if (len > 0.4) {" + " gl_FragColor.a = smoothstep(width, width - u_mode[1], width * len);"
+ " color = u_color * (smoothstep(0.2, 1.0, (u_width + 0.3) - len));"
+ "}"
+ " gl_FragColor = color;"
+ "}"; + "}";
final static String gPolygonVertexShader = "" final static String gPolygonVertexShader = ""

View File

@@ -31,12 +31,15 @@ public final class MapDatabaseFactory {
* @return a new MapGenerator instance. * @return a new MapGenerator instance.
*/ */
public static IMapDatabase createMapDatabase(AttributeSet attributeSet) { public static IMapDatabase createMapDatabase(AttributeSet attributeSet) {
String mapDatabaseName = attributeSet.getAttributeValue(null, MAP_DATABASE_ATTRIBUTE_NAME); String mapDatabaseName = attributeSet.getAttributeValue(null,
MAP_DATABASE_ATTRIBUTE_NAME);
if (mapDatabaseName == null) { if (mapDatabaseName == null) {
return new org.mapsforge.database.mapfile.MapDatabase(); return new org.mapsforge.database.postgis.MapDatabase();
} }
MapDatabaseInternal mapDatabaseInternal = MapDatabaseInternal.valueOf(mapDatabaseName); MapDatabaseInternal mapDatabaseInternal = MapDatabaseInternal
.valueOf(mapDatabaseName);
return MapDatabaseFactory.createMapDatabase(mapDatabaseInternal); return MapDatabaseFactory.createMapDatabase(mapDatabaseInternal);
} }

View File

@@ -359,7 +359,9 @@
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10"> <rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9"> <rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
<line stroke="#eeee4a" stroke-width="1.3" stroke-linecap="butt" <!-- <line stroke="#eeee4a" stroke-width="1.3" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="1.2" stroke-linecap="butt"
fixed="true" /> fixed="true" />
</rule> </rule>
@@ -369,7 +371,9 @@
</rule> </rule>
<rule e="way" k="*" v="primary" zoom-min="8"> <rule e="way" k="*" v="primary" zoom-min="8">
<line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt" <!-- <line stroke="#eeee4a" stroke-width="1.4" stroke-linecap="butt"
fixed="true" /> -->
<line stroke="#f2df6d" stroke-width="1.4" stroke-linecap="butt"
fixed="true" /> fixed="true" />
</rule> </rule>

View File

@@ -29,7 +29,7 @@ public class GlConfigChooser implements GLSurfaceView.EGLConfigChooser {
EGL10.EGL_GREEN_SIZE, 6, EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5, EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_ALPHA_SIZE, 0, EGL10.EGL_ALPHA_SIZE, 0,
// EGL10.EGL_DEPTH_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0,
// Requires that setEGLContextClientVersion(2) is called on the view. // Requires that setEGLContextClientVersion(2) is called on the view.
EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */, EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */,
// EGL10.EGL_SAMPLE_BUFFERS, 1 /* true */, // EGL10.EGL_SAMPLE_BUFFERS, 1 /* true */,
@@ -50,7 +50,7 @@ public class GlConfigChooser implements GLSurfaceView.EGLConfigChooser {
EGL10.EGL_GREEN_SIZE, 6, EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5, EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_ALPHA_SIZE, 0, EGL10.EGL_ALPHA_SIZE, 0,
// EGL10.EGL_DEPTH_SIZE, 8, EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */, EGL10.EGL_RENDERABLE_TYPE, 4 /* EGL_OPENGL_ES2_BIT */,
EGL10.EGL_STENCIL_SIZE, 4, EGL10.EGL_STENCIL_SIZE, 4,
EGL10.EGL_NONE }; EGL10.EGL_NONE };
@@ -78,18 +78,21 @@ public class GlConfigChooser implements GLSurfaceView.EGLConfigChooser {
// configurations are considered to be "better" and returned first. // configurations are considered to be "better" and returned first.
// You need to explicitly filter the data returned by eglChooseConfig! // You need to explicitly filter the data returned by eglChooseConfig!
// for (int i = 0; i < configs.length; ++i) { for (int i = 0; i < configs.length; ++i) {
// Log.i(TAG, printConfig(egl, display, configs[i])); Log.i(TAG, printConfig(egl, display, configs[i]));
// } }
//
// int index = -1; // int index = -1;
// for (int i = 0; i < configs.length; ++i) { // for (int i = 0; i < configs.length; ++i) {
// if (findConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE, 0) == 8 && // // if (findConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE, 0) == 8
// findConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE, 0) == 0) { // // &&
// index = i; // // findConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE, 0) == 0) {
// break; // // index = i;
// } // // break;
// else if (findConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE, 0) == 5 && // // }
// // else
// if (findConfigAttrib(egl, display, configs[i], EGL10.EGL_RED_SIZE, 0) == 5
// &&
// findConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE, 0) == 0) { // findConfigAttrib(egl, display, configs[i], EGL10.EGL_ALPHA_SIZE, 0) == 0) {
// index = i; // index = i;
// break; // break;
@@ -123,24 +126,26 @@ public class GlConfigChooser implements GLSurfaceView.EGLConfigChooser {
int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0); int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
/* /*
* EGL_CONFIG_CAVEAT value * EGL_CONFIG_CAVEAT value #define EGL_NONE 0x3038 #define EGL_SLOW_CONFIG 0x3050 #define
* #define EGL_NONE 0x3038 * EGL_NON_CONFORMANT_CONFIG 0x3051
* #define EGL_SLOW_CONFIG 0x3050
* #define EGL_NON_CONFORMANT_CONFIG 0x3051
*/ */
return String.format("EGLConfig rgba=%d%d%d%d depth=%d stencil=%d", new Integer(r), new Integer(g), return String.format("EGLConfig rgba=%d%d%d%d depth=%d stencil=%d",
new Integer(r), new Integer(g),
new Integer(b), new Integer(a), new Integer(d), new Integer(s)) new Integer(b), new Integer(a), new Integer(d), new Integer(s))
+ " native=" + " native="
+ findConfigAttrib(egl, display, config, EGL10.EGL_NATIVE_RENDERABLE, 0) + findConfigAttrib(egl, display, config, EGL10.EGL_NATIVE_RENDERABLE, 0)
+ " buffer=" + " buffer="
+ findConfigAttrib(egl, display, config, EGL10.EGL_BUFFER_SIZE, 0) + findConfigAttrib(egl, display, config, EGL10.EGL_BUFFER_SIZE, 0)
+ String.format(" caveat=0x%04x", + String.format(
new Integer(findConfigAttrib(egl, display, config, EGL10.EGL_CONFIG_CAVEAT, 0))); " caveat=0x%04x",
new Integer(findConfigAttrib(egl, display, config,
EGL10.EGL_CONFIG_CAVEAT, 0)));
} }
private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) { private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config,
int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) { if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0]; return mValue[0];
} }

View File

@@ -302,7 +302,8 @@ public class MapDatabase implements IMapDatabase {
public FileOpenResult openFile(File mapFile) { public FileOpenResult openFile(File mapFile) {
try { try {
if (mapFile == null) { if (mapFile == null) {
throw new IllegalArgumentException("mapFile must not be null"); // throw new IllegalArgumentException("mapFile must not be null");
return new FileOpenResult("no file!");
} }
// make sure to close any previously opened file first // make sure to close any previously opened file first

View File

@@ -53,7 +53,8 @@ public class MapDatabase implements IMapDatabase {
private final MapFileInfo mMapInfo = private final MapFileInfo mMapInfo =
new MapFileInfo(new BoundingBox(-180, -85, 180, 85), new MapFileInfo(new BoundingBox(-180, -85, 180, 85),
new Byte((byte) 14), new GeoPoint(53.11, 8.85), SphericalMercator.NAME, new Byte((byte) 14), new GeoPoint(53.11, 8.85),
SphericalMercator.NAME,
0, 0, 0, "de", "yo!", "hannes"); 0, 0, 0, "de", "yo!", "hannes");
// new MapFileInfo(new BoundingBox(-180, -90, 180, 90), // new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
// new Byte((byte) 0), null, "Mercator", // new Byte((byte) 0), null, "Mercator",
@@ -62,7 +63,8 @@ public class MapDatabase implements IMapDatabase {
private boolean mOpenFile = false; private boolean mOpenFile = false;
private Connection connection = null; private Connection connection = null;
private static HashMap<Entry<String, String>, Tag> tagHash = new HashMap<Entry<String, String>, Tag>(100); private static HashMap<Entry<String, String>, Tag> tagHash = new HashMap<Entry<String, String>, Tag>(
100);
private PreparedStatement prepQuery = null; private PreparedStatement prepQuery = null;
private boolean connect() { private boolean connect() {
@@ -77,7 +79,7 @@ public class MapDatabase implements IMapDatabase {
Properties dbOpts = new Properties(); Properties dbOpts = new Properties();
dbOpts.setProperty("user", "osm"); dbOpts.setProperty("user", "osm");
dbOpts.setProperty("password", "osm"); dbOpts.setProperty("password", "osm");
dbOpts.setProperty("socketTimeout", "15000"); dbOpts.setProperty("socketTimeout", "30");
dbOpts.setProperty("tcpKeepAlive", "true"); dbOpts.setProperty("tcpKeepAlive", "true");
try { try {
@@ -113,6 +115,7 @@ public class MapDatabase implements IMapDatabase {
prepQuery.setLong(1, tile.pixelX); prepQuery.setLong(1, tile.pixelX);
prepQuery.setLong(2, tile.pixelY); prepQuery.setLong(2, tile.pixelY);
prepQuery.setInt(3, tile.zoomLevel); prepQuery.setInt(3, tile.zoomLevel);
System.out.println("" + prepQuery.toString());
prepQuery.execute(); prepQuery.execute();
r = prepQuery.getResultSet(); r = prepQuery.getResultSet();
} catch (SQLException e) { } catch (SQLException e) {
@@ -181,13 +184,13 @@ public class MapDatabase implements IMapDatabase {
} catch (SQLException e) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
try { // try {
connection.close(); // connection.close();
} catch (SQLException e1) { // } catch (SQLException e1) {
e1.printStackTrace(); // e1.printStackTrace();
} finally { // } finally {
connection = null; connection = null;
} // }
} }
} }

View File

@@ -41,7 +41,7 @@ class MyLocationListener implements LocationListener {
// this.advancedMapViewer.itemizedOverlay.requestRedraw(); // this.advancedMapViewer.itemizedOverlay.requestRedraw();
if (this.centerAtFirstFix || this.advancedMapViewer.isSnapToLocationEnabled()) { if (this.centerAtFirstFix || this.advancedMapViewer.isSnapToLocationEnabled()) {
this.centerAtFirstFix = false; this.centerAtFirstFix = false;
this.advancedMapViewer.mapController.setCenter(point); this.advancedMapViewer.mMapController.setCenter(point);
} }
} }