- switched to using shorts instead of float/half-float

- fixed flickering caused by stencil/scissor combination on nexus
- added blending option for areas in rendertheme
This commit is contained in:
Hannes Janetzek 2012-08-18 04:34:03 +02:00
parent 7f573f0ac4
commit 1cf0c02dd2
21 changed files with 855 additions and 802 deletions

View File

@ -188,7 +188,10 @@ public class MapView extends GLSurfaceView {
mMapWorkers[i].start();
}
setRenderTheme(InternalRenderTheme.OSMARENDER);
if (!setRenderTheme(InternalRenderTheme.OSMARENDER)) {
Log.d(TAG, "EEEK could parse theme");
// FIXME show init error dialog
}
setEGLConfigChooser(new GlConfigChooser());
setEGLContextClientVersion(2);
@ -496,14 +499,15 @@ public class MapView extends GLSurfaceView {
* @throws IllegalArgumentException
* if the supplied internalRenderTheme is null.
*/
public void setRenderTheme(InternalRenderTheme internalRenderTheme) {
public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) {
if (internalRenderTheme == null) {
throw new IllegalArgumentException("render theme must not be null");
}
setRenderTheme((Theme) internalRenderTheme);
boolean ret = setRenderTheme((Theme) internalRenderTheme);
clearAndRedrawMapView();
return ret;
}
/**

View File

@ -1,40 +0,0 @@
/*
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General 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 License for more details.
*
* You should have received a copy of the GNU Lesser General License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
class Layer {
PoolItem pool;
protected PoolItem curItem;
int verticesCnt;
int offset;
final int layer;
Layer(int l) {
layer = l;
verticesCnt = 0;
}
float[] getNextPoolItem() {
curItem.used = PoolItem.SIZE;
curItem.next = VertexPool.get();
curItem = curItem.next;
return curItem.vertices;
}
}

View File

@ -15,11 +15,13 @@
package org.mapsforge.android.glrenderer;
import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.core.Tile;
import android.util.FloatMath;
class LineLayer extends Layer {
class LineLayer {
private static final float SCALE_FACTOR = 16;
Line line;
LineLayer next;
@ -28,14 +30,21 @@ class LineLayer extends Layer {
float width;
boolean isOutline;
ShortItem pool;
protected ShortItem curItem;
int verticesCnt;
int offset;
final int layer;
LineLayer(int layer, Line line, boolean outline) {
super(layer);
this.layer = layer;
this.line = line;
this.isOutline = outline;
if (!outline) {
curItem = VertexPool.get();
curItem = ShortPool.get();
pool = curItem;
}
}
@ -49,6 +58,15 @@ class LineLayer extends Layer {
outlines = link;
}
short[] getNextItem() {
curItem.used = ShortItem.SIZE;
curItem.next = ShortPool.get();
curItem = curItem.next;
return curItem.vertices;
}
/*
* line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj
*/
@ -57,7 +75,7 @@ class LineLayer extends Layer {
float a;
int pointPos = pos;
boolean rounded = capRound;
width = w;
width = w;// * SCALE_FACTOR;
if (w < 0.5)
rounded = false;
@ -66,19 +84,19 @@ class LineLayer extends Layer {
int MAX = PoolItem.SIZE;
float[] curVertices = curItem.vertices;
short[] curVertices = curItem.vertices;
int vertexPos = curItem.used;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
x = pointArray[pointPos++];
y = pointArray[pointPos++];
x = pointArray[pointPos++];// * SCALE_FACTOR;
y = pointArray[pointPos++];// * SCALE_FACTOR;
nextX = pointArray[pointPos++];
nextY = pointArray[pointPos++];
nextX = pointArray[pointPos++];// * SCALE_FACTOR;
nextY = pointArray[pointPos++];// * SCALE_FACTOR;
// Calculate triangle corners for the given width
vx = nextX - x;
@ -86,8 +104,8 @@ class LineLayer extends Layer {
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
vx = (vx / a);
vy = (vy / a);
ux = -vy;
uy = vx;
@ -98,58 +116,59 @@ class LineLayer extends Layer {
float vxw = vx * w;
float vyw = vy * w;
boolean outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
&& (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
// boolean outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
// && (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
boolean outside = false;
if (rounded && !outside) {
// Add the first point twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x + uxw - vxw;
curVertices[vertexPos++] = y + uyw - vyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 1;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x + uxw - vxw;
curVertices[vertexPos++] = y + uyw - vyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 1;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 1;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
// Start of line
curVertices[vertexPos++] = x + uxw;
curVertices[vertexPos++] = y + uyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw;
curVertices[vertexPos++] = y - uyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
} else {
// outside means line is probably clipped
@ -163,30 +182,30 @@ class LineLayer extends Layer {
verticesCnt -= 2;
}
// Add the first point twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x + uxw - vxw;
curVertices[vertexPos++] = y + uyw - vyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x + uxw - vxw;
curVertices[vertexPos++] = y + uyw - vyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
}
prevX = x;
@ -203,15 +222,15 @@ class LineLayer extends Layer {
vx = prevX - x;
vy = prevY - y;
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
vx = (vx / a);
vy = (vy / a);
// Unit vector pointing forward to next node
wx = nextX - x;
wy = nextY - y;
a = FloatMath.sqrt(wx * wx + wy * wy);
wx = (float) (wx / a);
wy = (float) (wy / a);
wx = (wx / a);
wy = (wy / a);
// Sum of these two vectors points
ux = vx + wx;
@ -223,8 +242,8 @@ class LineLayer extends Layer {
ux = -wy;
uy = wx;
} else {
ux = (float) (ux / a);
uy = (float) (uy / a);
ux = (ux / a);
uy = (uy / a);
if (ux > 2 || uy > 2 || ux < -2 || uy < -2) {
ux = -wy;
@ -250,24 +269,24 @@ class LineLayer extends Layer {
uyw = uy * w;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x + uxw;
curVertices[vertexPos++] = y + uyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw;
curVertices[vertexPos++] = y - uyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
prevX = x;
prevY = y;
@ -280,8 +299,8 @@ class LineLayer extends Layer {
a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a);
vy = (float) (vy / a);
vx = (vx / a);
vy = (vy / a);
ux = vy;
uy = -vx;
@ -292,69 +311,61 @@ class LineLayer extends Layer {
vxw = vx * w;
vyw = vy * w;
outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
&& (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
// if (vertexPos == MAX) {
// curItem.used = vertexPos;
// curItem = LayerPool.get();
// pool.add(curItem);
// curVertices = curItem.vertices;
// vertexPos = 0;
// }
// outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE)
// && (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
if (rounded && !outside) {
curVertices[vertexPos++] = x + uxw;
curVertices[vertexPos++] = y + uyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw;
curVertices[vertexPos++] = y - uyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
// For rounded line edges
curVertices[vertexPos++] = x + uxw - vxw;
curVertices[vertexPos++] = y + uyw - vyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = -1;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
// Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = -1;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = -1;
} else {
if (!outside) {
@ -365,31 +376,31 @@ class LineLayer extends Layer {
verticesCnt -= 2;
}
curVertices[vertexPos++] = x + uxw;
curVertices[vertexPos++] = y + uyw;
curVertices[vertexPos++] = -1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
// Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
if (vertexPos == MAX) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
vertexPos = 0;
}
curVertices[vertexPos++] = x - uxw - vxw;
curVertices[vertexPos++] = y - uyw - vyw;
curVertices[vertexPos++] = 1.0f;
curVertices[vertexPos++] = 0.0f;
curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0;
}

View File

@ -16,57 +16,113 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
class LineLayers {
private static int NUM_VERTEX_FLOATS = 4;
static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
int size = 0;
for (LineLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
ByteOrder.nativeOrder());
fbuf = bbuf.asFloatBuffer();
} else {
fbuf.clear();
}
int pos = 0;
PoolItem last = null, items = null;
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
VertexPool.add(items);
fbuf.flip();
return fbuf;
}
// static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
// FloatBuffer fbuf = buf;
// int size = 0;
//
// for (LineLayer l = layers; l != null; l = l.next)
// size += l.verticesCnt;
//
// size *= NUM_VERTEX_FLOATS;
//
// if (buf == null || buf.capacity() < size) {
// ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
// ByteOrder.nativeOrder());
// fbuf = bbuf.asFloatBuffer();
// } else {
// fbuf.clear();
// }
// int pos = 0;
//
// PoolItem last = null, items = null;
//
// for (LineLayer l = layers; l != null; l = l.next) {
// if (l.isOutline)
// continue;
//
// for (PoolItem item = l.pool; item != null; item = item.next) {
// fbuf.put(item.vertices, 0, item.used);
// last = item;
// }
// l.offset = pos;
// pos += l.verticesCnt;
//
// if (last != null) {
// last.next = items;
// items = l.pool;
// }
//
// l.pool = null;
// }
//
// VertexPool.add(items);
//
// fbuf.flip();
//
// return fbuf;
// }
//
// static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
// int size = 0;
// ShortBuffer sbuf = buf;
//
// for (LineLayer l = layers; l != null; l = l.next)
// size += l.verticesCnt;
//
// size *= NUM_VERTEX_FLOATS;
//
// if (buf == null || buf.capacity() < size) {
// ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
// ByteOrder.nativeOrder());
// sbuf = bbuf.asShortBuffer();
// } else {
// sbuf.clear();
// }
// int pos = 0;
//
// short[] data = new short[PoolItem.SIZE];
//
// PoolItem last = null, items = null;
//
// for (LineLayer l = layers; l != null; l = l.next) {
// if (l.isOutline)
// continue;
//
// for (PoolItem item = l.pool; item != null; item = item.next) {
// PoolItem.toHalfFloat(item, data);
// sbuf.put(data, 0, item.used);
// last = item;
// }
//
// l.offset = pos;
// pos += l.verticesCnt;
//
// if (last != null) {
// last.next = items;
// items = l.pool;
// }
//
// l.pool = null;
// }
//
// VertexPool.add(items);
//
// sbuf.flip();
//
// return sbuf;
// }
//
// static void clear(LineLayer layer) {
// for (LineLayer l = layer; l != null; l = l.next) {
// if (l.pool != null)
// VertexPool.add(l.pool);
// }
// }
static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
int size = 0;
@ -86,17 +142,18 @@ class LineLayers {
}
int pos = 0;
short[] data = new short[PoolItem.SIZE];
// short[] data = new short[PoolItem.SIZE];
PoolItem last = null, items = null;
ShortItem last = null, items = null;
for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline)
continue;
for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
for (ShortItem item = l.pool; item != null; item = item.next) {
// PoolItem.toHalfFloat(item, data);
// sbuf.put(data, 0, item.used);
sbuf.put(item.vertices, 0, item.used);
last = item;
}
@ -111,7 +168,7 @@ class LineLayers {
l.pool = null;
}
VertexPool.add(items);
ShortPool.add(items);
sbuf.flip();
@ -121,7 +178,7 @@ class LineLayers {
static void clear(LineLayer layer) {
for (LineLayer l = layer; l != null; l = l.next) {
if (l.pool != null)
VertexPool.add(l.pool);
ShortPool.add(l.pool);
}
}
}

View File

@ -49,6 +49,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private static final byte STROKE_MIN_ZOOM_LEVEL = 12;
private static final byte LAYERS = 11;
private static final double f900913 = 20037508.342789244;
// 134217728
// 2147483648.000
private static RenderTheme renderTheme;
@ -77,7 +79,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
*/
public MapGenerator() {
Log.d(TAG, "init DatabaseRenderer");
VertexPool.init();
}
private float mPoiX = 256;
@ -143,12 +144,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private boolean mProjectedResult;
private float mSimplify;
private boolean projectToTile(boolean area) {
private boolean projectToTile() {
if (mProjected)
return mProjectedResult;
// float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
float[] coords = mWayNodes;
long x = mCurrentTile.x;
@ -186,17 +185,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
lat = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
}
// if (area && i == 0) {
// if (lon < minx)
// minx = lon;
// if (lon > maxx)
// maxx = lon;
// if (lat < miny)
// miny = lat;
// if (lat > maxy)
// maxy = lat;
// }
if (cnt != 0) {
// drop small distance intermediate nodes
@ -214,15 +202,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
cnt += 2;
}
// if (area) {
// // Log.d(TAG, "area:" + (maxx - minx) * (maxy - miny));
// if ((maxx - minx) * (maxy - miny) < 2000 / mCurrentTile.zoomLevel) {
// mProjected = true;
// mProjectedResult = false;
// return false;
// }
// }
mWays[i] = (short) cnt;
}
mProjected = true;
@ -239,19 +218,12 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
boolean changed) {
boolean closed) {
// Log.d(TAG, "render way: " + layer);
mTagName = null;
mProjected = false;
mDrawingLayer = getValidLayer(layer) * mLevels;
// int len = wayLength[0];
// boolean closed = (wayNodes[0] == wayNodes[len - 2] &&
// wayNodes[1] == wayNodes[len - 1]);
boolean closed = changed;
mSimplify = 0.5f;
if (closed) {
@ -272,15 +244,12 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
// mRenderInstructions[i].renderWay(this, tags);
// }
// prevClosed = closed;
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0),
closed, true);
if (mRenderInstructions == null && mDebugDrawUnmatched)
debugUnmatched(closed, tags);
// firstMatch = false;
}
private void debugUnmatched(boolean closed, Tag[] tags) {
@ -312,9 +281,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mLabels = new ArrayList<TextItem>();
mLabels.add(new TextItem(mWayNodes[0], mWayNodes[1], mTagName.value, caption));
}
// if (caption.textKey == mTagEmptyName.key)
// mLabels.add(new TextItem(mPoiX, mPoiY, mTagName.value, caption));
}
@Override
@ -350,55 +316,41 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
private int countLines;
private int countNodes;
@Override
public void renderWay(Line line) {
projectToTile(false);
projectToTile();
LineLayer outlineLayer = null;
LineLayer lineLayer = null;
int numLayer = mDrawingLayer + line.level;
// LineLayer l = mLineLayers;
//
// for (; l != null; l = l.next)
// if (l.next == null || l.next.layer > numLayer)
// break;
//
// if (l == null || l == mLineLayers) {
// // insert at start
// lineLayer = new LineLayer(numLayer, line, false);
// lineLayer.next = mLineLayers;
// mLineLayers = lineLayer;
// } else if (l.layer == numLayer) {
// lineLayer = l;
// } else {
// // insert between current and next layer
// lineLayer = new LineLayer(numLayer, line, false);
// lineLayer.next = l.next;
// l.next = lineLayer;
// }
LineLayer l = mLineLayers;
// FIXME simplify this...
if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) {
lineLayer = mCurLineLayer;
} else if (mLineLayers == null || mLineLayers.layer > numLayer) {
} else if (l == null || l.layer > numLayer) {
// insert new layer at start
lineLayer = new LineLayer(numLayer, line, false);
lineLayer.next = mLineLayers;
lineLayer.next = l;
mLineLayers = lineLayer;
} else {
for (LineLayer l = mLineLayers; l != null; l = l.next) {
while (l != null) {
// found layer
if (l.layer == numLayer) {
lineLayer = l;
break;
}
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) {
lineLayer = new LineLayer(numLayer, line, false);
// insert new layer between current and next layer
lineLayer.next = l.next;
l.next = lineLayer;
}
l = l.next;
}
}
@ -421,9 +373,11 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
int length = mWays[i];
// need at least two points
if (length >= 4)
if (length >= 4) {
lineLayer.addLine(mWayNodes, pos, length, w, line.round);
countLines++;
countNodes += length;
}
pos += length;
}
@ -437,23 +391,26 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
numLayer = mDrawingLayer + outline.level;
if (mLineLayers == null || mLineLayers.layer > numLayer) {
l = mLineLayers;
if (l == null || l.layer > numLayer) {
// insert new layer at start
outlineLayer = new LineLayer(numLayer, outline, true);
outlineLayer.next = mLineLayers;
outlineLayer.next = l;
mLineLayers = outlineLayer;
} else {
for (LineLayer l = mLineLayers; l != null; l = l.next) {
while (l != null) {
if (l.layer == numLayer) {
outlineLayer = l;
break;
}
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) {
outlineLayer = new LineLayer(numLayer, outline, true);
// insert new layer between current and next layer
outlineLayer.next = l.next;
l.next = outlineLayer;
}
l = l.next;
}
}
@ -467,33 +424,36 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (!mDebugDrawPolygons)
return;
// if (!projectToTile(mCurrentTile.zoomLevel < 14))
if (!projectToTile(false))
if (!projectToTile())
return;
int numLayer = mDrawingLayer + area.level;
PolygonLayer layer = null;
PolygonLayer l = mPolyLayers;
if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
layer = mCurPolyLayer;
} else if (mPolyLayers == null || mPolyLayers.layer > numLayer) {
} else if (l == null || l.layer > numLayer) {
// insert new layer at start
layer = new PolygonLayer(numLayer, area);
layer.next = mPolyLayers;
layer.next = l;
mPolyLayers = layer;
} else {
for (PolygonLayer l = mPolyLayers; l != null; l = l.next) {
if (l.layer >= numLayer) {
while (l != null) {
if (l.layer == numLayer) {
layer = l;
break;
}
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) {
layer = new PolygonLayer(numLayer, area);
// insert new layer between current and next layer
layer.next = l.next;
l.next = layer;
}
l = l.next;
}
}
if (layer == null)
@ -536,9 +496,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
if (!(mapGeneratorJob.tile instanceof GLMapTile))
return false;
if (mMapDatabase == null)
return false;
@ -547,7 +504,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
if (mCurrentTile.isLoading || mCurrentTile.isDrawn)
if (mCurrentTile.isLoading || mCurrentTile.isReady)
return false;
mCurrentTile.isLoading = true;
@ -561,7 +518,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mLabels = null;
// firstMatch = true;
countLines = 0;
countNodes = 0;
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
* (Math.PI / 180))); // / 1.5f;
@ -576,7 +534,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
}
if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
mTagName = new Tag("name", mCurrentTile.toString(), false);
mTagName = new Tag("name", countLines + " " + countNodes + " "
+ mCurrentTile.toString(), false);
mPoiX = 10;
mPoiY = 10;
MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0);

View File

@ -21,8 +21,6 @@ import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_DITHER;
import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
import static android.opengl.GLES20.GL_EQUAL;
import static android.opengl.GLES20.GL_EXTENSIONS;
import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_NEVER;
import static android.opengl.GLES20.GL_ONE;
@ -50,7 +48,6 @@ import static android.opengl.GLES20.glEnableVertexAttribArray;
import static android.opengl.GLES20.glFinish;
import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetString;
import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glScissor;
import static android.opengl.GLES20.glStencilFunc;
@ -65,7 +62,6 @@ import static android.opengl.GLES20.glUseProgram;
import static android.opengl.GLES20.glVertexAttribPointer;
import static android.opengl.GLES20.glViewport;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Collections;
@ -102,14 +98,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static final String TAG = "MapRenderer";
private static final int MB = 1024 * 1024;
// private boolean mTriangulate = false;
private static int CACHE_TILES_MAX = 250;
private static int CACHE_TILES = CACHE_TILES_MAX;
private static int LIMIT_BUFFERS = 20 * MB;
private static final int OES_HALF_FLOAT = 0x8D61;
private static final int FLOAT_BYTES = 4;
// private static final int OES_HALF_FLOAT = 0x8D61;
// private static final int FLOAT_BYTES = 4;
private static final int SHORT_BYTES = 2;
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
@ -118,16 +112,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static int STENCIL_BITS = 8;
private final MapView mMapView;
private final ArrayList<MapGeneratorJob> mJobList;
private final ArrayList<VertexBufferObject> mVBOs;
private final TileCacheKey mTileCacheKey;
private final HashMap<TileCacheKey, GLMapTile> mTiles;
private final ArrayList<GLMapTile> mTileList;
private final TileDistanceSort mTileDistanceSort;
private static ArrayList<MapGeneratorJob> mJobList;
private static ArrayList<VertexBufferObject> mVBOs;
private static TileCacheKey mTileCacheKey;
private static HashMap<TileCacheKey, GLMapTile> mTiles;
private static ArrayList<GLMapTile> mTileList;
private static TileDistanceSort mTileDistanceSort;
private DebugSettings mDebugSettings;
private JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition;
private static DebugSettings mDebugSettings;
private static JobParameters mJobParameter;
private static MapPosition mMapPosition, mPrevMapPosition;
private static int mWidth, mHeight;
private static float mAspect;
@ -141,7 +135,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static long mTileX, mTileY;
private static int rotateBuffers = 2;
private static FloatBuffer floatBuffer[];
private static ShortBuffer shortBuffer[];
static boolean useHalfFloat = false;
@ -171,7 +164,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// nextTiles is swapped with curTiles in onDrawFrame in GL thread.
private static TilesData newTiles, nextTiles, curTiles;
private boolean mInitial;
private static boolean mInitial;
// shader handles
private static int lineProgram;
@ -198,7 +191,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
*/
public MapRenderer(MapView mapView) {
Log.d(TAG, "init MapRenderer");
mMapView = mapView;
if (mInitial)
return;
mDebugSettings = mapView.getDebugSettings();
mVBOs = new ArrayList<VertexBufferObject>();
@ -214,7 +212,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = false;
}
private void updateTileDistances() {
private static void updateTileDistances() {
int h = (Tile.TILE_SIZE >> 1);
byte zoom = mMapPosition.zoomLevel;
long x = mTileX * (Tile.TILE_SIZE) + h;
@ -222,57 +220,57 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
int diff;
long dx, dy;
// TODO this could be optimized to consider move/zoom direction
// TODO this could need some fixing..
// and be optimized to consider move/zoom direction
for (int i = 0, n = mTileList.size(); i < n; i++) {
GLMapTile t = mTileList.get(i);
diff = (t.zoomLevel - zoom);
if (diff != 0) {
if (diff > 0) {
if (diff == 0) {
dx = (t.pixelX + h) - x;
dy = (t.pixelY + h) - y;
dy *= mAspect;
t.distance = (1 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)));
} else if (diff > 0) {
// tile zoom level is child of current
dx = ((t.pixelX + h) >> diff) - x;
dy = ((t.pixelY + h) >> diff) - y;
dy *= mAspect;
t.distance = 2 * ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
} else {
// tile zoom level is parent of current
dx = ((t.pixelX + h) << -diff) - x;
dy = ((t.pixelY + h) << -diff) - y;
}
if (diff == -1) {
dy *= mAspect;
t.distance = 2 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
} else {
// load parent before current layer (kind of progressive transmission :)
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));
// prefer lower zoom level, it covers a larger area
t.distance /= -diff;
}
} else {
dx = (t.pixelX + h) - x;
dy = (t.pixelY + h) - y;
dy *= mAspect;
t.distance = (1 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)));// * 2;
}
// Log.d(TAG, t + " " + t.distance);
// Log.d(TAG, diff + " " + (float) t.distance / Tile.TILE_SIZE + " " + t);
}
}
private void limitCache(int remove) {
private static void limitCache(int remove) {
byte z = mMapPosition.zoomLevel;
for (int j = mTileList.size() - 1, cnt = 0; cnt < remove && j > 0; j--, cnt++) {
GLMapTile t = mTileList.remove(j);
if (t.isActive) {
Log.d(TAG, "EEEK removing active tile");
// Log.d(TAG, "EEEK removing active tile");
mTileList.add(t);
continue;
}
// check if this tile is used as proxy for not yet drawn active tile
if (t.isDrawn || t.newData || t.isLoading) {
// TODO to be simplified...
if (t.isReady || t.newData || t.isLoading) {
if (t.zoomLevel == z + 1) {
if (t.parent != null && t.parent.isActive
&& !(t.parent.isDrawn || t.parent.newData)) {
&& !(t.parent.isReady || t.parent.newData)) {
mTileList.add(t);
Log.d(TAG, "EEEK removing active proxy child");
continue;
@ -281,7 +279,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile c = null;
for (int i = 0; i < 4; i++) {
c = t.child[i];
if (c != null && c.isActive && !(c.isDrawn || c.newData))
if (c != null && c.isActive && !(c.isReady || c.newData))
break;
c = null;
}
@ -299,7 +297,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int k = 0; k < 4; k++) {
c2 = c.child[k];
if (c2 != null && c2.isActive
&& !(c2.isDrawn || c2.newData))
&& !(c2.isReady || c2.newData))
break;
c2 = null;
@ -344,6 +342,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
t.polygonVBO = null;
}
}
if (t.newData) {
// Log.d(TAG, ">>>> clear unsused data ! " + t + "<<<<");
LineLayers.clear(t.lineLayers);
PolygonLayers.clear(t.polygonLayers);
}
}
}
@ -425,14 +428,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
newTiles.tiles[tiles++] = tile;
if (!tile.isDrawn && !tile.newData && !tile.isLoading) {
if (!tile.isReady && !tile.newData && !tile.isLoading) {
MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
mDebugSettings);
mJobList.add(job);
}
// prefetch parent
// if (tile.parent != null && !tile.parent.isDrawn && !tile.parent.newData
// if (tile.parent != null && !tile.parent.isReady && !tile.parent.newData
// && !tile.parent.isLoading) {
// MapGeneratorJob job = new MapGeneratorJob(tile.parent, mJobParameter,
// mDebugSettings);
@ -484,7 +487,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return true;
}
private void setChildren(GLMapTile tile) {
private static void setChildren(GLMapTile tile) {
long xx = tile.tileX << 1;
long yy = tile.tileY << 1;
@ -597,23 +600,42 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
float alpha = 1.0f;
if (l.area.fade >= mDrawZ) {
if (l.area.fade >= mDrawZ || l.area.color[3] != 1.0) {
alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f)
alpha = 1.0f;
alpha *= l.area.color[3];
if (!blend) {
glEnable(GL_BLEND);
blend = true;
}
} else if (blend) {
glUniform4f(hPolygonColor,
l.area.color[0], l.area.color[1], l.area.color[2], alpha);
} else if (l.area.blend == mDrawZ) {
alpha = mDrawScale - 1.0f;
if (alpha > 1.0f)
alpha = 1.0f;
else if (alpha < 0)
alpha = 0;
glUniform4f(hPolygonColor,
l.area.color[0] * (1 - alpha) + l.area.blendColor[0] * alpha,
l.area.color[1] * (1 - alpha) + l.area.blendColor[1] * alpha,
l.area.color[2] * (1 - alpha) + l.area.blendColor[2] * alpha, 1);
} else {
if (blend) {
glDisable(GL_BLEND);
blend = false;
}
glUniform4f(hPolygonColor,
l.area.color[0], l.area.color[1], l.area.color[2], alpha);
if (l.area.blend <= mDrawZ && l.area.blend > 0)
glUniform4fv(hPolygonColor, 1, l.area.blendColor, 0);
else
glUniform4fv(hPolygonColor, 1, l.area.color, 0);
}
// set stencil buffer mask used to draw this layer
glStencilFunc(GL_EQUAL, 0xff, 1 << c);
@ -632,26 +654,22 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tile.polygonLayers == null)
return true;
glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
// Nexus doesnt like using changing scissor in combination with stencil...
// glScissor(tile.sx, tile.sy, tile.sw, tile.sh);
if (mLastBoundVBO != tile.polygonVBO.id) {
mLastBoundVBO = tile.polygonVBO.id;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) {
glVertexAttribPointer(hPolygonVertexPosition, 2,
OES_HALF_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
} else {
glVertexAttribPointer(hPolygonVertexPosition, 2,
GL_FLOAT, false, 0,
GLES20.GL_SHORT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
}
}
setMatrix(tile, diff);
glUniformMatrix4fv(hPolygonMatrix, 1, false, mMVPMatrix, 0);
boolean firstPass = true;
// boolean firstPass = true;
for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) {
// fade out polygon layers (set in RederTheme)
@ -665,10 +683,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// never pass the test, i.e. always apply first stencil op (sfail)
glStencilFunc(GL_NEVER, 0, 0xff);
if (firstPass)
firstPass = false;
else {
GLES20.glFlush();
// if (firstPass)
// firstPass = false;
// else {
// GLES20.glFlush();
// clear stencilbuffer
glStencilMask(0xFF);
@ -677,7 +695,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
// }
// stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
@ -720,19 +738,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mLastBoundVBO = tile.lineVBO.id;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) {
glVertexAttribPointer(hLineVertexPosition, 2, OES_HALF_FLOAT,
glVertexAttribPointer(hLineVertexPosition, 2, GLES20.GL_SHORT,
false, 8, LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(hLineTexturePosition, 2, OES_HALF_FLOAT,
glVertexAttribPointer(hLineTexturePosition, 2, GLES20.GL_SHORT,
false, 8, LINE_VERTICES_DATA_TEX_OFFSET >> 1);
} else {
glVertexAttribPointer(hLineVertexPosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_POS_OFFSET);
glVertexAttribPointer(hLineTexturePosition, 2, GL_FLOAT,
false, 16, LINE_VERTICES_DATA_TEX_OFFSET);
}
}
if (diff != 0)
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff);
@ -888,7 +899,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private boolean uploadTileData(GLMapTile tile) {
ShortBuffer sbuf = null;
FloatBuffer fbuf = null;
// double start = SystemClock.uptimeMillis();
@ -914,68 +924,42 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
int size = 0;
if (useHalfFloat) {
sbuf = LineLayers.compileLayerData(tile.lineLayers,
shortBuffer[uploadCnt * 2]);
size = sbuf.remaining();
shortBuffer[uploadCnt * 2] = sbuf;
} else {
fbuf = LineLayers.compileLayerData(tile.lineLayers,
floatBuffer[uploadCnt * 2]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2] = fbuf;
}
if (size > 0) {
mBufferMemoryUsage -= tile.lineVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
// Nexus doesnt like this either
// glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW);
if (useHalfFloat) {
tile.lineVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
sbuf, GL_DYNAMIC_DRAW);
} else {
tile.lineVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.lineVBO.size;
} else {
tile.lineLayers = null;
}
if (useHalfFloat) {
sbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
shortBuffer[uploadCnt * 2 + 1]);
size = sbuf.remaining();
shortBuffer[uploadCnt * 2 + 1] = sbuf;
} else {
fbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
floatBuffer[uploadCnt * 2 + 1]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2 + 1] = fbuf;
}
// Upload polygon data to vertex buffer object
if (size > 0) {
mBufferMemoryUsage -= tile.polygonVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
// glBufferData(GL_ARRAY_BUFFER, 0, null,
// GL_DYNAMIC_DRAW);
if (useHalfFloat) {
tile.polygonVBO.size = size * SHORT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
sbuf, GL_DYNAMIC_DRAW);
} else {
tile.polygonVBO.size = size * FLOAT_BYTES;
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
fbuf, GL_DYNAMIC_DRAW);
}
mBufferMemoryUsage += tile.polygonVBO.size;
} else {
@ -983,7 +967,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
tile.newData = false;
tile.isDrawn = true;
tile.isReady = true;
tile.isLoading = false;
// double compile = SystemClock.uptimeMillis();
@ -1007,8 +991,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (timing)
start = SystemClock.uptimeMillis();
glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// glStencilMask(0xFF);
// glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
synchronized (this) {
mDrawX = mCurX;
@ -1072,7 +1057,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
continue;
}
if (!tile.isDrawn) {
if (!tile.isReady) {
if (tile.parent != null) {
if (tile.parent.newData)
uploadTileData(tile.parent);
@ -1099,8 +1084,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (timing)
clear_time = (SystemClock.uptimeMillis() - start);
glEnable(GL_SCISSOR_TEST);
// glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, mWidth, mHeight);
glUseProgram(polygonProgram);
glEnableVertexAttribArray(hPolygonVertexPosition);
@ -1112,7 +1097,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tiles[i].isVisible) {
GLMapTile tile = tiles[i];
if (tile.isDrawn)
if (tile.isReady)
drawPolygons(tile, 0);
else
drawProxyPolygons(tile);
@ -1129,6 +1114,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
poly_time = (SystemClock.uptimeMillis() - start);
}
// glEnable(GL_SCISSOR_TEST);
// Draw lines
glEnable(GL_BLEND);
glUseProgram(lineProgram);
@ -1140,7 +1127,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tiles[i].isVisible) {
GLMapTile tile = tiles[i];
if (tile.isDrawn)
if (tile.isReady)
drawLines(tile, 0);
else
drawProxyLines(tile);
@ -1150,10 +1137,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glDisableVertexAttribArray(hLineVertexPosition);
glDisableVertexAttribArray(hLineTexturePosition);
glDisable(GL_SCISSOR_TEST);
glScissor(0, 0, mWidth, mHeight);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
mTextRenderer.beginDraw();
mTextRenderer.beginDraw(mDrawScale);
for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null)
continue;
@ -1243,16 +1231,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
}
String ext = glGetString(GL_EXTENSIONS);
// String ext = glGetString(GL_EXTENSIONS);
if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
useHalfFloat = true;
// if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
// useHalfFloat = true;
shortBuffer = new ShortBuffer[rotateBuffers * 2];
}
else {
floatBuffer = new FloatBuffer[rotateBuffers * 2];
}
Log.d(TAG, "Extensions: " + ext);
// }
// else {
// floatBuffer = new FloatBuffer[rotateBuffers * 2];
// }
// Log.d(TAG, "Extensions: " + ext);
hLineMatrix = glGetUniformLocation(lineProgram, "u_center");
hLineMode = glGetUniformLocation(lineProgram, "u_mode");
@ -1289,13 +1277,15 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glDisable(GL_DITHER);
glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
GlUtils.checkGlError("onSurfaceCreated");
}
private void drawProxyLines(GLMapTile tile) {
if (tile.parent != null && tile.parent.isDrawn) {
if (tile.parent != null && tile.parent.isReady) {
tile.parent.sx = tile.sx;
tile.parent.sy = tile.sy;
tile.parent.sw = tile.sw;
@ -1306,7 +1296,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// scissor coordinates already set for polygons
for (int i = 0; i < 4; i++) {
GLMapTile c = tile.child[i];
if (c != null && c.isDrawn && c.isVisible) {
if (c != null && c.isReady && c.isVisible) {
drawLines(c, 1);
drawn++;
}
@ -1314,7 +1304,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) {
if (p != null && p.isReady) {
p.sx = tile.sx;
p.sy = tile.sy;
p.sw = tile.sw;
@ -1326,7 +1316,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
private void drawProxyPolygons(GLMapTile tile) {
if (tile.parent != null && tile.parent.isDrawn) {
if (tile.parent != null && tile.parent.isReady) {
tile.parent.sx = tile.sx;
tile.parent.sy = tile.sy;
tile.parent.sw = tile.sw;
@ -1338,7 +1328,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int i = 0; i < 4; i++) {
GLMapTile c = tile.child[i];
if (c != null && c.isDrawn && setTileScissor(c, 2)) {
if (c != null && c.isReady && setTileScissor(c, 2)) {
drawPolygons(c, 1);
drawn++;
}
@ -1346,7 +1336,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) {
if (p != null && p.isReady) {
p.sx = tile.sx;
p.sy = tile.sy;
p.sw = tile.sw;

View File

@ -16,21 +16,37 @@ package org.mapsforge.android.glrenderer;
import org.mapsforge.android.rendertheme.renderinstruction.Area;
class PolygonLayer extends Layer {
class PolygonLayer {
PolygonLayer next;
Area area;
private static final float SCALE_FACTOR = 16.0f;
private boolean first = true;
private float originX;
private float originY;
ShortItem pool;
protected ShortItem curItem;
int verticesCnt;
int offset;
final int layer;
PolygonLayer(int layer, Area area) {
super(layer);
this.layer = layer;
this.area = area;
curItem = VertexPool.get();
curItem = ShortPool.get();
pool = curItem;
}
short[] getNextItem() {
curItem.used = ShortItem.SIZE;
curItem.next = ShortPool.get();
curItem = curItem.next;
return curItem.vertices;
}
void addPolygon(float[] points, int pos, int length) {
verticesCnt += length / 2 + 2;
@ -41,43 +57,48 @@ class PolygonLayer extends Layer {
originY = points[pos + 1];
}
float[] curVertices = curItem.vertices;
short[] curVertices = curItem.vertices;
int outPos = curItem.used;
if (outPos == PoolItem.SIZE) {
curVertices = getNextPoolItem();
if (outPos == ShortItem.SIZE) {
curVertices = getNextItem();
outPos = 0;
}
curVertices[outPos++] = originX; // Tile.TILE_SIZE >> 1;
curVertices[outPos++] = originY; // Tile.TILE_SIZE >> 1;
curVertices[outPos++] = (short) (originX * SCALE_FACTOR);
curVertices[outPos++] = (short) (originY * SCALE_FACTOR);
int remaining = length;
int inPos = pos;
while (remaining > 0) {
if (outPos == PoolItem.SIZE) {
curVertices = getNextPoolItem();
if (outPos == ShortItem.SIZE) {
curVertices = getNextItem();
outPos = 0;
}
int len = remaining;
if (len > (PoolItem.SIZE) - outPos)
len = (PoolItem.SIZE) - outPos;
if (len > (ShortItem.SIZE) - outPos)
len = (ShortItem.SIZE) - outPos;
for (int i = 0; i < len; i++)
curVertices[outPos++] = (short) (points[inPos++] * SCALE_FACTOR);
// System.arraycopy(points, inPos, curVertices, outPos, len);
// outPos += len;
// inPos += len;
System.arraycopy(points, inPos, curVertices, outPos, len);
outPos += len;
inPos += len;
remaining -= len;
}
if (outPos == PoolItem.SIZE) {
curVertices = getNextPoolItem();
curVertices = getNextItem();
outPos = 0;
}
curVertices[outPos++] = points[pos + 0];
curVertices[outPos++] = points[pos + 1];
curVertices[outPos++] = (short) (points[pos + 0] * SCALE_FACTOR);
curVertices[outPos++] = (short) (points[pos + 1] * SCALE_FACTOR);
curItem.used = outPos;
}

View File

@ -16,68 +16,137 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.mapsforge.android.utils.FastMath;
import org.mapsforge.core.Tile;
class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2;
static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
-2, Tile.TILE_SIZE + 1, -2 };
// static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
// Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
// -2, Tile.TILE_SIZE + 1, -2 };
private static short[] mByteFillCoords = null;
// private static short[] mByteFillCoords = null;
static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf;
int size = 4;
// static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
// FloatBuffer fbuf = buf;
// int size = 4;
//
// for (PolygonLayer l = layers; l != null; l = l.next)
// size += l.verticesCnt;
//
// size *= NUM_VERTEX_FLOATS;
//
// if (buf == null || buf.capacity() < size) {
// ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
// ByteOrder.nativeOrder());
// // Log.d("GLMap", "allocate buffer " + size);
// fbuf = bbuf.asFloatBuffer();
// } else {
// fbuf.clear();
// }
//
// fbuf.put(mFillCoords, 0, 8);
// int pos = 4;
//
// PoolItem last = null, items = null;
//
// for (PolygonLayer l = layers; l != null; l = l.next) {
//
// for (PoolItem item = l.pool; item != null; item = item.next) {
// fbuf.put(item.vertices, 0, item.used);
// last = item;
// }
// l.offset = pos;
// pos += l.verticesCnt;
//
// if (last != null) {
// last.next = items;
// items = l.pool;
// }
//
// l.pool = null;
// }
//
// VertexPool.add(items);
//
// fbuf.flip();
//
// return fbuf;
// }
//
// static final short[] tmpItem = new short[PoolItem.SIZE];
for (PolygonLayer l = layers; l != null; l = l.next)
size += l.verticesCnt;
// static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
// ShortBuffer sbuf = buf;
// int size = 4;
//
// for (PolygonLayer l = layers; l != null; l = l.next)
// size += l.verticesCnt;
//
// size *= NUM_VERTEX_FLOATS;
//
// if (buf == null || buf.capacity() < size) {
// ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order(
// ByteOrder.nativeOrder());
// sbuf = bbuf.asShortBuffer();
// } else {
// sbuf.clear();
// }
//
// short[] data = tmpItem;
//
// if (mByteFillCoords == null) {
// mByteFillCoords = new short[8];
// FastMath.convertFloatToHalf(mFillCoords[0], mByteFillCoords, 0);
// FastMath.convertFloatToHalf(mFillCoords[1], mByteFillCoords, 1);
// FastMath.convertFloatToHalf(mFillCoords[2], mByteFillCoords, 2);
// FastMath.convertFloatToHalf(mFillCoords[3], mByteFillCoords, 3);
// FastMath.convertFloatToHalf(mFillCoords[4], mByteFillCoords, 4);
// FastMath.convertFloatToHalf(mFillCoords[5], mByteFillCoords, 5);
// FastMath.convertFloatToHalf(mFillCoords[6], mByteFillCoords, 6);
// FastMath.convertFloatToHalf(mFillCoords[7], mByteFillCoords, 7);
// }
//
// sbuf.put(mByteFillCoords, 0, 8);
// int pos = 4;
//
// PoolItem last = null, items = null;
//
// for (PolygonLayer l = layers; l != null; l = l.next) {
//
// for (PoolItem item = l.pool; item != null; item = item.next) {
// PoolItem.toHalfFloat(item, data);
// sbuf.put(data, 0, item.used);
// last = item;
// }
//
// l.offset = pos;
// pos += l.verticesCnt;
//
// if (last != null) {
// last.next = items;
// items = l.pool;
// }
//
// l.pool = null;
// }
//
// VertexPool.add(items);
//
// sbuf.flip();
//
// return sbuf;
// }
//
// static void clear(PolygonLayer layers) {
// for (PolygonLayer l = layers; l != null; l = l.next) {
// if (l.pool != null)
// VertexPool.add(l.pool);
// }
// }
size *= NUM_VERTEX_FLOATS;
if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
ByteOrder.nativeOrder());
// Log.d("GLMap", "allocate buffer " + size);
fbuf = bbuf.asFloatBuffer();
} else {
fbuf.clear();
}
fbuf.put(mFillCoords, 0, 8);
int pos = 4;
PoolItem last = null, items = null;
for (PolygonLayer l = layers; l != null; l = l.next) {
for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used);
last = item;
}
l.offset = pos;
pos += l.verticesCnt;
if (last != null) {
last.next = items;
items = l.pool;
}
l.pool = null;
}
VertexPool.add(items);
fbuf.flip();
return fbuf;
}
static final short[] tmpItem = new short[PoolItem.SIZE];
private static short[] mFillCoords;
static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
ShortBuffer sbuf = buf;
@ -96,30 +165,29 @@ class PolygonLayers {
sbuf.clear();
}
short[] data = tmpItem;
if (mByteFillCoords == null) {
mByteFillCoords = new short[8];
FastMath.convertFloatToHalf(mFillCoords[0], mByteFillCoords, 0);
FastMath.convertFloatToHalf(mFillCoords[1], mByteFillCoords, 1);
FastMath.convertFloatToHalf(mFillCoords[2], mByteFillCoords, 2);
FastMath.convertFloatToHalf(mFillCoords[3], mByteFillCoords, 3);
FastMath.convertFloatToHalf(mFillCoords[4], mByteFillCoords, 4);
FastMath.convertFloatToHalf(mFillCoords[5], mByteFillCoords, 5);
FastMath.convertFloatToHalf(mFillCoords[6], mByteFillCoords, 6);
FastMath.convertFloatToHalf(mFillCoords[7], mByteFillCoords, 7);
if (mFillCoords == null) {
short min = (-2) << 4;
short max = (short) ((Tile.TILE_SIZE + 1) << 4);
mFillCoords = new short[8];
mFillCoords[0] = min;
mFillCoords[1] = max;
mFillCoords[2] = max;
mFillCoords[3] = max;
mFillCoords[4] = min;
mFillCoords[5] = min;
mFillCoords[6] = max;
mFillCoords[7] = min;
}
sbuf.put(mByteFillCoords, 0, 8);
sbuf.put(mFillCoords, 0, 8);
int pos = 4;
PoolItem last = null, items = null;
ShortItem last = null, items = null;
for (PolygonLayer l = layers; l != null; l = l.next) {
for (PoolItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used);
for (ShortItem item = l.pool; item != null; item = item.next) {
sbuf.put(item.vertices, 0, item.used);
last = item;
}
@ -134,7 +202,7 @@ class PolygonLayers {
l.pool = null;
}
VertexPool.add(items);
ShortPool.add(items);
sbuf.flip();
@ -144,7 +212,7 @@ class PolygonLayers {
static void clear(PolygonLayer layers) {
for (PolygonLayer l = layers; l != null; l = l.next) {
if (l.pool != null)
VertexPool.add(l.pool);
ShortPool.add(l.pool);
}
}
}

View File

@ -1,95 +0,0 @@
/*
* Copyright 2012 Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General 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 License for more details.
*
* You should have received a copy of the GNU Lesser General License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
// TODO use byte[] for half-float, not converting on compilation (in glThread)
class PoolItem {
final float[] vertices;
int used;
PoolItem next;
PoolItem() {
vertices = new float[SIZE];
used = 0;
}
static int SIZE = 128;
private static final float FLOAT_HALF_PREC = 5.96046E-8f;
private static final float FLOAT_HALF_MAX = 65504f;
private static ByteBuffer byteBuffer = ByteBuffer.allocate(SIZE * 4);
private static IntBuffer intBuffer = byteBuffer.asIntBuffer();
private static FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
private static int[] intArray = new int[SIZE];
static void toHalfFloat(PoolItem item, short[] data) {
floatBuffer.position(0);
floatBuffer.put(item.vertices, 0, item.used);
intBuffer.position(0);
intBuffer.get(intArray, 0, item.used);
int out = 0;
for (int j = 0; j < item.used; j++) {
float flt = item.vertices[j];
int f = intArray[j];
if (f == 0x0000000) {
// == 0
data[out++] = (short) 0x0000;
} else if (f == 0x80000000) {
// == -0
data[out++] = (short) 0x8000;
} else if (f == 0x3f800000) {
// == 1
data[out++] = (short) 0x3c00;
} else if (f == 0xbf800000) {
// == -1
data[out++] = (short) 0xbc00;
} else if (flt > FLOAT_HALF_MAX) {
if (flt == Float.POSITIVE_INFINITY) {
data[out++] = (short) 0x7c00;
} else {
data[out++] = (short) 0x7bff;
}
} else if (flt < -FLOAT_HALF_MAX) {
if (flt == Float.NEGATIVE_INFINITY) {
data[out++] = (short) 0xfc00;
} else {
data[out++] = (short) 0xfbff;
}
} else if (flt > 0f && flt < FLOAT_HALF_PREC) {
data[out++] = (short) 0x0001;
} else if (flt < 0f && flt > -FLOAT_HALF_PREC) {
data[out++] = (short) 0x8001;
} else {
// maybe just ignore and set 0? -- we'll see. when this happens
if (f == 0x7fc00000)
throw new UnsupportedOperationException(
"NaN to half conversion not supported!");
data[out++] = (short) (((f >> 16) & 0x8000)
| ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00)
| ((f >> 13) & 0x03ff));
}
}
}
}

View File

@ -22,10 +22,12 @@ class Shaders {
+ "attribute vec4 a_position;"
+ "attribute vec2 a_st;"
+ "varying vec2 v_st;"
+ "const vec4 scale = vec4(1.0/16.0, 1.0/16.0, 0.0, 1.0);"
+ "void main() {"
// + " gl_Position = u_center * vec4(a_position.x, a_position.y, 0.0, 1.0);"
// + " v_st = a_position.zw;"
+ " gl_Position = u_center * a_position;"
+ " gl_Position = u_center * (scale * a_position);"
// + " gl_Position = u_center * a_position;"
+ " v_st = a_st;"
+ "}";
@ -165,8 +167,9 @@ class Shaders {
+ "precision mediump float; \n"
+ "uniform mat4 u_center;\n"
+ "attribute vec4 a_position;"
+ "const vec4 scale = vec4(1.0/16.0, 1.0/16.0, 0.0, 1.0);"
+ "void main() {"
+ " gl_Position = u_center * a_position;"
+ " gl_Position = u_center * (scale * a_position);"
+ "}";
final static String gPolygonFragmentShader = ""

View File

@ -0,0 +1,28 @@
/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* 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 <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
public class ShortItem {
final short[] vertices;
int used;
ShortItem next;
ShortItem() {
vertices = new short[SIZE];
used = 0;
}
static int SIZE = 128;
}

View File

@ -1,43 +1,39 @@
/*
* Copyright 2012 Hannes Janetzek
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General License as published by the Free Software
* 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 License for more details.
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General License along with
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.glrenderer;
import android.annotation.SuppressLint;
class VertexPool {
public class ShortPool {
private static final int POOL_LIMIT = 8192;
@SuppressLint("UseValueOf")
private static final Boolean lock = new Boolean(true);
static private PoolItem pool = null;
static private ShortItem pool = null;
static private int count = 0;
static void init() {
}
static PoolItem get() {
static ShortItem get() {
synchronized (lock) {
if (count == 0)
return new PoolItem();
return new ShortItem();
count--;
PoolItem it = pool;
ShortItem it = pool;
pool = pool.next;
it.used = 0;
it.next = null;
@ -45,12 +41,12 @@ class VertexPool {
}
}
static void add(PoolItem items) {
static void add(ShortItem items) {
if (items == null)
return;
synchronized (lock) {
PoolItem last = items;
ShortItem last = items;
// limit pool items
while (count < POOL_LIMIT) {
@ -62,7 +58,7 @@ class VertexPool {
}
// clear references
PoolItem tmp2, tmp = last.next;
ShortItem tmp2, tmp = last.next;
while (tmp != null) {
tmp2 = tmp;
tmp = tmp.next;

View File

@ -16,7 +16,6 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.mapsforge.android.utils.GlUtils;
@ -42,7 +41,7 @@ public class TextRenderer {
private int mBitmapFormat;
private int mBitmapType;
private ByteBuffer mByteBuffer;
private FloatBuffer mFloatBuffer;
private ShortBuffer mShortBuffer;
private TextTexture[] mTextures;
private int mIndicesVBO;
@ -50,30 +49,31 @@ public class TextRenderer {
final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite
final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite
final static int FLOATS_PER_VERTICE = 4;
final static int SHORTS_PER_VERTICE = 6;
private static int mTextProgram;
static int mTextUVPMatrixLocation;
static int mTextVertexLocation;
static int mTextTextureCoordLocation;
static int mTextUColorLocation;
static int hTextUVPMatrix;
static int hTextVertex;
static int hTextScale;
static int hTextTextureCoord;
static int hTextUColor;
static Paint mPaint = new Paint(Color.BLACK);
boolean debug = false;
float[] debugVertices = {
short[] debugVertices = {
0, 0,
0, 1,
0, TEXTURE_HEIGHT,
0, TEXTURE_HEIGHT - 1,
0, 0,
TEXTURE_WIDTH - 1, 0,
1, 1,
TEXTURE_WIDTH, TEXTURE_HEIGHT,
TEXTURE_WIDTH - 1, TEXTURE_HEIGHT - 1,
1, 0,
TEXTURE_WIDTH, 0,
};
@ -87,20 +87,21 @@ public class TextRenderer {
mTextProgram = GlUtils.createProgram(textVertexShader, textFragmentShader);
mTextUVPMatrixLocation = GLES20.glGetUniformLocation(mTextProgram, "mvp");
mTextUColorLocation = GLES20.glGetUniformLocation(mTextProgram, "col");
mTextVertexLocation = GLES20.glGetAttribLocation(mTextProgram, "vertex");
mTextTextureCoordLocation = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
hTextUVPMatrix = GLES20.glGetUniformLocation(mTextProgram, "mvp");
hTextUColor = GLES20.glGetUniformLocation(mTextProgram, "col");
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
// mVertexBuffer = new float[];
int bufferSize = numTextures
* MAX_LABELS * VERTICES_PER_SPRITE
* FLOATS_PER_VERTICE * (Float.SIZE / 8);
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
mByteBuffer = ByteBuffer.allocateDirect(bufferSize)
.order(ByteOrder.nativeOrder());
mFloatBuffer = mByteBuffer.asFloatBuffer();
mShortBuffer = mByteBuffer.asShortBuffer();
int[] textureIds = new int[numTextures];
TextTexture[] textures = new TextTexture[numTextures];
@ -184,20 +185,14 @@ public class TextRenderer {
if (tex.tile != null)
tex.tile.texture = null;
// if (debug)
// mBitmap.eraseColor(0xaa0000aa);
// else
mBitmap.eraseColor(Color.TRANSPARENT);
int pos = 0;
float[] buf = tex.vertices;
float xx = mFontPadX;
float yy = 0;
float width, height;
short[] buf = tex.vertices;
float y = 0;
float x = 0;
float x = mFontPadX;
float width, height;
int max = tile.labels.size();
if (max > MAX_LABELS)
@ -214,8 +209,9 @@ public class TextRenderer {
mCanvas.drawLine(debugVertices[12], debugVertices[13], debugVertices[8],
debugVertices[9], mPaint);
}
int advanceY = 0;
// int advanceX = 0;
for (int i = 0; i < max; i++) {
TextItem t = tile.labels.get(i);
@ -225,18 +221,23 @@ public class TextRenderer {
if (height > advanceY)
advanceY = (int) height;
if (xx + width > TEXTURE_WIDTH) {
xx = mFontPadX;
if (x + width > TEXTURE_WIDTH) {
x = mFontPadX;
y += advanceY;
advanceY = (int) height;
}
yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
float yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
if (yy > TEXTURE_HEIGHT) {
Log.d(TAG, "reached max labels");
continue;
}
if (t.caption.stroke != null)
mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.stroke);
mCanvas.drawText(t.text, x + t.width / 2, yy, t.caption.stroke);
mCanvas.drawText(t.text, xx + t.width / 2, yy, t.caption.paint);
mCanvas.drawText(t.text, x + t.width / 2, yy, t.caption.paint);
// Log.d(TAG, "draw: " + t.text + " at:" + (xx + t.width / 2) + " " + yy + " w:"
// + t.width + " " + cellHeight);
@ -246,44 +247,57 @@ public class TextRenderer {
float halfWidth = width / 2.0f;
float halfHeight = height / 2.0f;
float x1 = t.x - halfWidth;
float y1 = t.y - halfHeight;
float x2 = t.x + halfWidth;
float y2 = t.y + halfHeight;
float u1 = xx / TEXTURE_WIDTH;
float v1 = y / TEXTURE_HEIGHT;
float u2 = u1 + (width / TEXTURE_WIDTH);
float v2 = v1 + (height / TEXTURE_HEIGHT);
// short x1 = (short) (2.0f * (t.x - halfWidth));
// short y1 = (short) (2.0f * (t.y - halfHeight));
// short x2 = (short) (2.0f * (t.x + halfWidth));
// short y2 = (short) (2.0f * (t.y + halfHeight));
short x1 = (short) (2.0f * (-halfWidth));
short y1 = (short) (2.0f * (-halfHeight));
short x2 = (short) (2.0f * (halfWidth));
short y2 = (short) (2.0f * (halfHeight));
short u1 = (short) (2.0f * x);
short v1 = (short) (2.0f * y);
short u2 = (short) (2.0f * (x + width));
short v2 = (short) (2.0f * (y + height));
short tx = (short) (2.0f * t.x);
short ty = (short) (2.0f * t.y);
buf[pos++] = tx;
buf[pos++] = ty;
buf[pos++] = x1;
buf[pos++] = y1;
buf[pos++] = u1;
buf[pos++] = v2;
buf[pos++] = tx;
buf[pos++] = ty;
buf[pos++] = x2;
buf[pos++] = y1;
buf[pos++] = u2;
buf[pos++] = v2;
buf[pos++] = tx;
buf[pos++] = ty;
buf[pos++] = x2;
buf[pos++] = y2;
buf[pos++] = u2;
buf[pos++] = v1;
buf[pos++] = tx;
buf[pos++] = ty;
buf[pos++] = x1;
buf[pos++] = y2;
buf[pos++] = u1;
buf[pos++] = v1;
// yy += cellHeight;
// x += width;
x += width;
xx += width;
// y += cellHeight;
if (y > TEXTURE_HEIGHT) {
Log.d(TAG, "reached max labels");
Log.d(TAG, "reached max labels: texture is full");
break;
}
}
@ -309,42 +323,42 @@ public class TextRenderer {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
mFloatBuffer.clear();
mShortBuffer.clear();
for (int i = 0; i < mTextures.length; i++) {
tex = mTextures[i];
if (tex.tile == null || !tex.tile.isActive)
continue;
mFloatBuffer.put(tex.vertices, 0, tex.length);
mShortBuffer.put(tex.vertices, 0, tex.length);
tex.offset = offset;
offset += tex.length;
}
mFloatBuffer.flip();
mShortBuffer.flip();
// Log.d(TAG, "compileTextures" + mFloatBuffer.remaining() + " " + offset);
// TODO use sub-bufferdata function
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, offset * (Float.SIZE / 8),
mFloatBuffer, GLES20.GL_DYNAMIC_DRAW);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, offset * (Short.SIZE / 8),
mShortBuffer, GLES20.GL_DYNAMIC_DRAW);
}
void beginDraw() {
void beginDraw(float scale) {
GLES20.glUseProgram(mTextProgram);
GLES20.glEnableVertexAttribArray(mTextTextureCoordLocation);
GLES20.glEnableVertexAttribArray(mTextVertexLocation);
GLES20.glEnableVertexAttribArray(hTextTextureCoord);
GLES20.glEnableVertexAttribArray(hTextVertex);
GLES20.glUniform1f(hTextScale, scale);
if (debug) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mFloatBuffer.clear();
mFloatBuffer.put(debugVertices, 0, 16);
mFloatBuffer.flip();
GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
GLES20.GL_FLOAT, false, 16, mFloatBuffer);
mFloatBuffer.position(2);
GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, 16, mFloatBuffer);
mShortBuffer.clear();
mShortBuffer.put(debugVertices, 0, 16);
mShortBuffer.flip();
GLES20.glVertexAttribPointer(hTextVertex, 2,
GLES20.GL_SHORT, false, 8, mShortBuffer);
mShortBuffer.position(2);
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
GLES20.GL_SHORT, false, 8, mShortBuffer);
} else {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
@ -353,31 +367,32 @@ public class TextRenderer {
void endDraw() {
GLES20.glDisableVertexAttribArray(mTextTextureCoordLocation);
GLES20.glDisableVertexAttribArray(mTextVertexLocation);
GLES20.glDisableVertexAttribArray(hTextTextureCoord);
GLES20.glDisableVertexAttribArray(hTextVertex);
}
void drawTile(GLMapTile tile, float[] matrix) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
GlUtils.checkGlError("bind");
GLES20.glUniformMatrix4fv(mTextUVPMatrixLocation, 1, false, matrix, 0);
GlUtils.checkGlError("matrix");
GLES20.glUniformMatrix4fv(hTextUVPMatrix, 1, false, matrix, 0);
if (debug) {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
} else {
GLES20.glVertexAttribPointer(mTextVertexLocation, 2,
GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4);
GLES20.glVertexAttribPointer(hTextVertex, 4,
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
GLES20.glVertexAttribPointer(mTextTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, 16, tile.texture.offset * 4 + 8);
// GLES20.glVertexAttribPointer(hTextVertexOffset, 2,
// GLES20.GL_SHORT, false, 8, tile.texture.offset * (Short.SIZE / 8) + 4);
//
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
+ 8);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 16) *
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
}
}
@ -385,12 +400,18 @@ public class TextRenderer {
private static String textVertexShader = ""
+ "precision highp float; "
+ "attribute vec4 vertex;"
// + "attribute vec4 offset;"
+ "attribute vec2 tex_coord;"
+ "uniform mat4 mvp;"
+ "uniform float scale;"
+ "varying vec2 tex_c;"
+ "const vec2 div = vec2(1.0/1024.0,1.0/512.0);"
+ "const vec4 dp = vec4(0.5,0.5,0.5,0.5);"
+ "void main() {"
+ " gl_Position = mvp * vertex;"
+ " tex_c = tex_coord;"
+ " vec4 s = dp * vertex;"
+ " gl_Position = mvp * vec4(s.x + (s.z / scale), s.y + (s.w / scale), 0.0, 1.0);"
// + " gl_Position = vec4(pos.x + s.z, pos.y + s.w, 0.0, 1.0);"
+ " tex_c = tex_coord * div;"
+ "}";
private static String textFragmentShader = ""
@ -399,7 +420,7 @@ public class TextRenderer {
+ "uniform vec4 col;"
+ "varying vec2 tex_c;"
+ "void main() {"
+ " gl_FragColor = texture2D(tex, tex_c);"
+ " gl_FragColor = texture2D(tex, tex_c.xy);"
+ "}";
}

View File

@ -16,7 +16,7 @@ package org.mapsforge.android.glrenderer;
public class TextTexture {
final float[] vertices;
final short[] vertices;
final int id;
int length;
int offset;
@ -25,7 +25,9 @@ public class TextTexture {
String[] text;
TextTexture(int textureID) {
vertices = new float[TextRenderer.MAX_LABELS * 16];
vertices = new short[TextRenderer.MAX_LABELS *
TextRenderer.VERTICES_PER_SPRITE *
TextRenderer.SHORTS_PER_VERTICE];
id = textureID;
}

View File

@ -21,9 +21,9 @@ import org.mapsforge.core.Tile;
*/
public class MapTile extends Tile {
/**
* tile is loaded and ready for drawing. (set and used by render thread).
* tile is loaded and ready for drawing. (set and used by render thread after uploading data to gl).
*/
public boolean isDrawn;
public boolean isReady;
/**
* tile is removed from JobQueue and loading in DatabaseRenderer. set by MapWorker.

View File

@ -147,28 +147,15 @@
</rule>
<rule e="way" k="natural|" v="*">
<rule e="way" k="*" v="wood">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
<rule e="way" k="natural" v="wood">
<area fill="#ebefe5" fade="7" blend="11" blend-fill="#d3dec8"/>
</rule>
<rule e="way" k="landuse" v="*">
<rule e="way" k="*" v="forest">
<rule e="way" k="*" v="*" zoom-max="12">
<area fill="#ebefe5" fade="7" />
</rule>
<rule e="way" k="*" v="*" zoom-min="11">
<area fill="#d3dec8" fade="12" />
</rule>
</rule>
<rule e="way" k="landuse" v="forest">
<area fill="#ebefe5" fade="7" blend="11" blend-fill="#d3dec8"/>
</rule>
<!-- keep grass above forest:wood and leisure:park! -->
<rule e="way" k="landuse" v="grass">
<area fill="#ebf2d2" fade="10" />
@ -481,6 +468,19 @@
</rule>
</rule>
<!-- different colors :) -->
<!-- <rule e="way" k="*" v="residential">
<line stroke="#00ff00" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="road">
<line stroke="#ff00ff" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="living_street">
<line stroke="#ffff00" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule>
<rule e="way" k="*" v="unclassified">
<line stroke="#00ffff" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule> -->
</rule>
@ -683,11 +683,11 @@
<rule e="way" k="debug" v="area">
<line stroke="#ff0000" stroke-width="1.2" fixed="true" stroke-linecap="butt" />
<area fill="#880000ff"/>
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
<caption k="name" font-size="15" fill="#ff0000" stroke="#444444" stroke-width="2.0"/>
</rule>
<rule e="way" k="debug" v="way">
<line stroke="#00ffff" stroke-width="1.5" fixed="true" stroke-linecap="butt" />
<caption k="name" font-size="15" fill="#ffffff" stroke="#000000" stroke-width="2.0"/>
<caption k="name" font-size="15" fill="#00ffff" stroke="#444444" stroke-width="2.0"/>
</rule>
</rule>
@ -723,7 +723,7 @@
<!-- place -->
<rule e="node" k="place" v="*">
<rule e="node" k="*" v="suburb|town|village" zoom-max="14">
<caption k="name" font-style="bold" font-size="15" fill="#000000"
<caption k="name" font-size="14" fill="#000000"
stroke="#ffffff" stroke-width="2.0" />
</rule>
<rule e="node" k="*" v="island" zoom-min="10">

View File

@ -86,12 +86,16 @@
<xs:attribute name="src" type="tns:src" use="optional" />
<xs:attribute name="fill" type="tns:color" use="optional"
default="#000000" />
<xs:attribute name="stroke" type="tns:color" use="optional"
<xs:attribute name="stroke" type="tns:color" u se="optional"
default="#00000000" />
<xs:attribute name="stroke-width" type="tns:nonNegativeFloat"
use="optional" default="0" />
<xs:attribute name="fade" type="xs:integer" use="optional"
default="-1" />
<xs:attribute name="blend" type="xs:integer" use="optional"
default="-1" />
<xs:attribute name="blend-fill" type="tns:color" use="optional"
default="#000000" />
</xs:complexType>
<xs:complexType name="caption">

View File

@ -49,6 +49,9 @@ public final class Area implements RenderInstruction {
int stroke = Color.TRANSPARENT;
float strokeWidth = 0;
int fade = -1;
int blend = -1;
int blendFill = Color.BLACK;
for (int i = 0; i < attributes.getLength(); ++i) {
String name = attributes.getLocalName(i);
String value = attributes.getValue(i);
@ -63,13 +66,17 @@ public final class Area implements RenderInstruction {
strokeWidth = Float.parseFloat(value);
} else if ("fade".equals(name)) {
fade = Integer.parseInt(value);
} else if ("blend".equals(name)) {
blend = Integer.parseInt(value);
} else if ("blend-fill".equals(name)) {
blendFill = Color.parseColor(value);
} else {
RenderThemeHandler.logUnknownAttribute(elementName, name, value, i);
}
}
validate(strokeWidth);
return new Area(src, fill, stroke, strokeWidth, fade, level);
return new Area(src, fill, stroke, strokeWidth, fade, level, blend, blendFill);
}
private static void validate(float strokeWidth) {
@ -79,32 +86,8 @@ public final class Area implements RenderInstruction {
}
}
/**
*
*/
public final int level;
/**
*
*/
public final Paint paintFill;
/**
*
*/
public final Paint paintOutline;
/**
*
*/
public final float strokeWidth;
/**
*
*/
public final float color[];
/**
*
*/
public final int fade;
private Area(String src, int fill, int stroke, float strokeWidth, int fade, int level)
private Area(String src, int fill, int stroke, float strokeWidth, int fade,
int level, int blend, int blendFill)
throws IOException {
super();
@ -129,12 +112,24 @@ public final class Area implements RenderInstruction {
paintOutline.setColor(stroke);
paintOutline.setStrokeCap(Cap.ROUND);
}
color = new float[4];
color[0] = (fill >> 16 & 0xff) / 255.0f;
color[1] = (fill >> 8 & 0xff) / 255.0f;
color[2] = (fill >> 0 & 0xff) / 255.0f;
color[3] = (fill >> 24 & 0xff) / 255.0f;
if (blend > 0) {
blendColor = new float[4];
blendColor[0] = (blendFill >> 16 & 0xff) / 255.0f;
blendColor[1] = (blendFill >> 8 & 0xff) / 255.0f;
blendColor[2] = (blendFill >> 0 & 0xff) / 255.0f;
blendColor[3] = (blendFill >> 24 & 0xff) / 255.0f;
} else {
blendColor = null;
}
this.blend = blend;
this.strokeWidth = strokeWidth;
this.fade = fade;
this.level = level;
@ -168,4 +163,33 @@ public final class Area implements RenderInstruction {
public void scaleTextSize(float scaleFactor) {
// do nothing
}
/**
*
*/
public final int level;
/**
*
*/
public final Paint paintFill;
/**
*
*/
public final Paint paintOutline;
/**
*
*/
public final float strokeWidth;
/**
*
*/
public final float color[];
/**
*
*/
public final int fade;
public final float blendColor[];
public final int blend;
}

View File

@ -39,7 +39,6 @@ public class GLMapTile extends MapTile {
public GLMapTile(long tileX, long tileY, byte zoomLevel) {
super(tileX, tileY, zoomLevel);
mScale = 1;
isDrawn = false;
mTextureID = -1;
}

View File

@ -212,7 +212,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
newTiles[tiles++] = tile;
if (!tile.isDrawn || (tile.getScale() != scale)) {
if (!tile.isReady || (tile.getScale() != scale)) {
tile.isLoading = true;
// approximation for TileScheduler
if (tileY < tileTop || tileY > tileBottom || tileX < tileLeft
@ -455,7 +455,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
}
tile.setScale(mMapGeneratorJob.getScale());
tile.isDrawn = true;
tile.isReady = true;
tile.isLoading = false;
mMapGeneratorJob = null;

View File

@ -59,7 +59,7 @@ public class MapDatabase implements IMapDatabase {
private static final MapFileInfo mMapInfo =
new MapFileInfo(new BoundingBox(-180, -90, 180, 90),
new Byte((byte) 14), new GeoPoint(53.11, 8.85),
new Byte((byte) 4), new GeoPoint(53.11, 8.85),
WebMercator.NAME, 0, 0, 0, "de", "comment", "author");
private boolean mOpenFile = false;
@ -343,7 +343,8 @@ public class MapDatabase implements IMapDatabase {
}
if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) {
Log.d(TAG, "..." + index + " " + tags + " " + indexCnt + " " + coordCnt + " "
Log.d(TAG, "..." + index + " " + (tags != null ? tags[0] : "...") + " "
+ indexCnt + " " + coordCnt + " "
+ tagCnt);
return false;
}