- 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(); 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()); setEGLConfigChooser(new GlConfigChooser());
setEGLContextClientVersion(2); setEGLContextClientVersion(2);
@ -496,14 +499,15 @@ public class MapView extends GLSurfaceView {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* if the supplied internalRenderTheme is null. * if the supplied internalRenderTheme is null.
*/ */
public void setRenderTheme(InternalRenderTheme internalRenderTheme) { public boolean setRenderTheme(InternalRenderTheme internalRenderTheme) {
if (internalRenderTheme == null) { if (internalRenderTheme == null) {
throw new IllegalArgumentException("render theme must not be null"); throw new IllegalArgumentException("render theme must not be null");
} }
setRenderTheme((Theme) internalRenderTheme); boolean ret = setRenderTheme((Theme) internalRenderTheme);
clearAndRedrawMapView(); 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; package org.mapsforge.android.glrenderer;
import org.mapsforge.android.rendertheme.renderinstruction.Line; import org.mapsforge.android.rendertheme.renderinstruction.Line;
import org.mapsforge.core.Tile;
import android.util.FloatMath; import android.util.FloatMath;
class LineLayer extends Layer { class LineLayer {
private static final float SCALE_FACTOR = 16;
Line line; Line line;
LineLayer next; LineLayer next;
@ -28,14 +30,21 @@ class LineLayer extends Layer {
float width; float width;
boolean isOutline; boolean isOutline;
ShortItem pool;
protected ShortItem curItem;
int verticesCnt;
int offset;
final int layer;
LineLayer(int layer, Line line, boolean outline) { LineLayer(int layer, Line line, boolean outline) {
super(layer); this.layer = layer;
this.line = line; this.line = line;
this.isOutline = outline; this.isOutline = outline;
if (!outline) { if (!outline) {
curItem = VertexPool.get(); curItem = ShortPool.get();
pool = curItem; pool = curItem;
} }
} }
@ -49,6 +58,15 @@ class LineLayer extends Layer {
outlines = link; 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 * 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; float a;
int pointPos = pos; int pointPos = pos;
boolean rounded = capRound; boolean rounded = capRound;
width = w; width = w;// * SCALE_FACTOR;
if (w < 0.5) if (w < 0.5)
rounded = false; rounded = false;
@ -66,19 +84,19 @@ class LineLayer extends Layer {
int MAX = PoolItem.SIZE; int MAX = PoolItem.SIZE;
float[] curVertices = curItem.vertices; short[] curVertices = curItem.vertices;
int vertexPos = curItem.used; int vertexPos = curItem.used;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
x = pointArray[pointPos++]; x = pointArray[pointPos++];// * SCALE_FACTOR;
y = pointArray[pointPos++]; y = pointArray[pointPos++];// * SCALE_FACTOR;
nextX = pointArray[pointPos++]; nextX = pointArray[pointPos++];// * SCALE_FACTOR;
nextY = pointArray[pointPos++]; nextY = pointArray[pointPos++];// * SCALE_FACTOR;
// Calculate triangle corners for the given width // Calculate triangle corners for the given width
vx = nextX - x; vx = nextX - x;
@ -86,8 +104,8 @@ class LineLayer extends Layer {
a = FloatMath.sqrt(vx * vx + vy * vy); a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a); vx = (vx / a);
vy = (float) (vy / a); vy = (vy / a);
ux = -vy; ux = -vy;
uy = vx; uy = vx;
@ -98,58 +116,59 @@ class LineLayer extends Layer {
float vxw = vx * w; float vxw = vx * w;
float vyw = vy * w; float vyw = vy * w;
boolean outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= 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); // && (x - vxw <= 0 || x - vxw >= Tile.TILE_SIZE || y - vyw <= 0 || y - vyw >= Tile.TILE_SIZE);
boolean outside = false;
if (rounded && !outside) { if (rounded && !outside) {
// Add the first point twice to be able to draw with GL_TRIANGLE_STRIP // Add the first point twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x + uxw - vxw; curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw - vyw; curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x + uxw - vxw; curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw - vyw; curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
// Start of line // Start of line
curVertices[vertexPos++] = x + uxw; curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw; curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw; curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw; curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
} else { } else {
// outside means line is probably clipped // outside means line is probably clipped
@ -163,30 +182,30 @@ class LineLayer extends Layer {
verticesCnt -= 2; verticesCnt -= 2;
} }
// Add the first point twice to be able to draw with GL_TRIANGLE_STRIP // Add the first point twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x + uxw - vxw; curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw - vyw; curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x + uxw - vxw; curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw - vyw; curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
} }
prevX = x; prevX = x;
@ -203,15 +222,15 @@ class LineLayer extends Layer {
vx = prevX - x; vx = prevX - x;
vy = prevY - y; vy = prevY - y;
a = FloatMath.sqrt(vx * vx + vy * vy); a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a); vx = (vx / a);
vy = (float) (vy / a); vy = (vy / a);
// Unit vector pointing forward to next node // Unit vector pointing forward to next node
wx = nextX - x; wx = nextX - x;
wy = nextY - y; wy = nextY - y;
a = FloatMath.sqrt(wx * wx + wy * wy); a = FloatMath.sqrt(wx * wx + wy * wy);
wx = (float) (wx / a); wx = (wx / a);
wy = (float) (wy / a); wy = (wy / a);
// Sum of these two vectors points // Sum of these two vectors points
ux = vx + wx; ux = vx + wx;
@ -223,8 +242,8 @@ class LineLayer extends Layer {
ux = -wy; ux = -wy;
uy = wx; uy = wx;
} else { } else {
ux = (float) (ux / a); ux = (ux / a);
uy = (float) (uy / a); uy = (uy / a);
if (ux > 2 || uy > 2 || ux < -2 || uy < -2) { if (ux > 2 || uy > 2 || ux < -2 || uy < -2) {
ux = -wy; ux = -wy;
@ -250,24 +269,24 @@ class LineLayer extends Layer {
uyw = uy * w; uyw = uy * w;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x + uxw; curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw; curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw; curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw; curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
prevX = x; prevX = x;
prevY = y; prevY = y;
@ -280,8 +299,8 @@ class LineLayer extends Layer {
a = FloatMath.sqrt(vx * vx + vy * vy); a = FloatMath.sqrt(vx * vx + vy * vy);
vx = (float) (vx / a); vx = (vx / a);
vy = (float) (vy / a); vy = (vy / a);
ux = vy; ux = vy;
uy = -vx; uy = -vx;
@ -292,69 +311,61 @@ class LineLayer extends Layer {
vxw = vx * w; vxw = vx * w;
vyw = vy * w; vyw = vy * w;
outside = (x <= 0 || x >= Tile.TILE_SIZE || y <= 0 || y >= Tile.TILE_SIZE) // 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); // && (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;
// }
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
if (rounded && !outside) { if (rounded && !outside) {
curVertices[vertexPos++] = x + uxw; curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw; curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw; curVertices[vertexPos++] = (short) ((x - uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw; curVertices[vertexPos++] = (short) ((y - uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
// For rounded line edges // For rounded line edges
curVertices[vertexPos++] = x + uxw - vxw; curVertices[vertexPos++] = (short) ((x + uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw - vyw; curVertices[vertexPos++] = (short) ((y + uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
// Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP // Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
} else { } else {
if (!outside) { if (!outside) {
@ -365,31 +376,31 @@ class LineLayer extends Layer {
verticesCnt -= 2; verticesCnt -= 2;
} }
curVertices[vertexPos++] = x + uxw; curVertices[vertexPos++] = (short) ((x + uxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y + uyw; curVertices[vertexPos++] = (short) ((y + uyw) * SCALE_FACTOR);
curVertices[vertexPos++] = -1.0f; curVertices[vertexPos++] = -1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
// Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP // Add the last vertex twice to be able to draw with GL_TRIANGLE_STRIP
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
if (vertexPos == MAX) { if (vertexPos == MAX) {
curVertices = getNextPoolItem(); curVertices = getNextItem();
vertexPos = 0; vertexPos = 0;
} }
curVertices[vertexPos++] = x - uxw - vxw; curVertices[vertexPos++] = (short) ((x - uxw - vxw) * SCALE_FACTOR);
curVertices[vertexPos++] = y - uyw - vyw; curVertices[vertexPos++] = (short) ((y - uyw - vyw) * SCALE_FACTOR);
curVertices[vertexPos++] = 1.0f; curVertices[vertexPos++] = 1;
curVertices[vertexPos++] = 0.0f; curVertices[vertexPos++] = 0;
} }

View File

@ -16,57 +16,113 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
class LineLayers { class LineLayers {
private static int NUM_VERTEX_FLOATS = 4; private static int NUM_VERTEX_FLOATS = 4;
static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) { // static FloatBuffer compileLayerData(LineLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf; // FloatBuffer fbuf = buf;
int size = 0; // int size = 0;
//
for (LineLayer l = layers; l != null; l = l.next) // for (LineLayer l = layers; l != null; l = l.next)
size += l.verticesCnt; // size += l.verticesCnt;
//
size *= NUM_VERTEX_FLOATS; // size *= NUM_VERTEX_FLOATS;
//
if (buf == null || buf.capacity() < size) { // if (buf == null || buf.capacity() < size) {
ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order( // ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order(
ByteOrder.nativeOrder()); // ByteOrder.nativeOrder());
fbuf = bbuf.asFloatBuffer(); // fbuf = bbuf.asFloatBuffer();
} else { // } else {
fbuf.clear(); // fbuf.clear();
} // }
int pos = 0; // int pos = 0;
//
PoolItem last = null, items = null; // PoolItem last = null, items = null;
//
for (LineLayer l = layers; l != null; l = l.next) { // for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline) // if (l.isOutline)
continue; // continue;
//
for (PoolItem item = l.pool; item != null; item = item.next) { // for (PoolItem item = l.pool; item != null; item = item.next) {
fbuf.put(item.vertices, 0, item.used); // fbuf.put(item.vertices, 0, item.used);
last = item; // last = item;
} // }
l.offset = pos; // l.offset = pos;
pos += l.verticesCnt; // pos += l.verticesCnt;
//
if (last != null) { // if (last != null) {
last.next = items; // last.next = items;
items = l.pool; // items = l.pool;
} // }
//
l.pool = null; // l.pool = null;
} // }
//
VertexPool.add(items); // VertexPool.add(items);
//
fbuf.flip(); // fbuf.flip();
//
return fbuf; // 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) { static ShortBuffer compileLayerData(LineLayer layers, ShortBuffer buf) {
int size = 0; int size = 0;
@ -86,17 +142,18 @@ class LineLayers {
} }
int pos = 0; 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) { for (LineLayer l = layers; l != null; l = l.next) {
if (l.isOutline) if (l.isOutline)
continue; continue;
for (PoolItem item = l.pool; item != null; item = item.next) { for (ShortItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data); // PoolItem.toHalfFloat(item, data);
sbuf.put(data, 0, item.used); // sbuf.put(data, 0, item.used);
sbuf.put(item.vertices, 0, item.used);
last = item; last = item;
} }
@ -111,7 +168,7 @@ class LineLayers {
l.pool = null; l.pool = null;
} }
VertexPool.add(items); ShortPool.add(items);
sbuf.flip(); sbuf.flip();
@ -121,7 +178,7 @@ class LineLayers {
static void clear(LineLayer layer) { static void clear(LineLayer layer) {
for (LineLayer l = layer; l != null; l = l.next) { for (LineLayer l = layer; l != null; l = l.next) {
if (l.pool != null) 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 STROKE_MIN_ZOOM_LEVEL = 12;
private static final byte LAYERS = 11; private static final byte LAYERS = 11;
private static final double f900913 = 20037508.342789244; private static final double f900913 = 20037508.342789244;
// 134217728
// 2147483648.000
private static RenderTheme renderTheme; private static RenderTheme renderTheme;
@ -77,7 +79,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
*/ */
public MapGenerator() { public MapGenerator() {
Log.d(TAG, "init DatabaseRenderer"); Log.d(TAG, "init DatabaseRenderer");
VertexPool.init();
} }
private float mPoiX = 256; private float mPoiX = 256;
@ -143,12 +144,10 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
private boolean mProjectedResult; private boolean mProjectedResult;
private float mSimplify; private float mSimplify;
private boolean projectToTile(boolean area) { private boolean projectToTile() {
if (mProjected) if (mProjected)
return mProjectedResult; return mProjectedResult;
// float minx = Float.MAX_VALUE, miny = Float.MAX_VALUE, maxx = Float.MIN_VALUE, maxy = Float.MIN_VALUE;
float[] coords = mWayNodes; float[] coords = mWayNodes;
long x = mCurrentTile.x; 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); 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) { if (cnt != 0) {
// drop small distance intermediate nodes // drop small distance intermediate nodes
@ -214,15 +202,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
cnt += 2; 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; mWays[i] = (short) cnt;
} }
mProjected = true; mProjected = true;
@ -239,19 +218,12 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override @Override
public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength, public void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
boolean changed) { boolean closed) {
// Log.d(TAG, "render way: " + layer);
mTagName = null; mTagName = null;
mProjected = false; mProjected = false;
mDrawingLayer = getValidLayer(layer) * mLevels; 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; mSimplify = 0.5f;
if (closed) { if (closed) {
@ -272,15 +244,12 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
// mRenderInstructions[i].renderWay(this, tags); // mRenderInstructions[i].renderWay(this, tags);
// } // }
// prevClosed = closed;
mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags, mRenderInstructions = MapGenerator.renderTheme.matchWay(this, tags,
(byte) (mCurrentTile.zoomLevel + 0), (byte) (mCurrentTile.zoomLevel + 0),
closed, true); closed, true);
if (mRenderInstructions == null && mDebugDrawUnmatched) if (mRenderInstructions == null && mDebugDrawUnmatched)
debugUnmatched(closed, tags); debugUnmatched(closed, tags);
// firstMatch = false;
} }
private void debugUnmatched(boolean closed, Tag[] tags) { private void debugUnmatched(boolean closed, Tag[] tags) {
@ -312,9 +281,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mLabels = new ArrayList<TextItem>(); mLabels = new ArrayList<TextItem>();
mLabels.add(new TextItem(mWayNodes[0], mWayNodes[1], mTagName.value, caption)); 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 @Override
@ -350,55 +316,41 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
} }
private int countLines;
private int countNodes;
@Override @Override
public void renderWay(Line line) { public void renderWay(Line line) {
projectToTile(false); projectToTile();
LineLayer outlineLayer = null; LineLayer outlineLayer = null;
LineLayer lineLayer = null; LineLayer lineLayer = null;
int numLayer = mDrawingLayer + line.level; int numLayer = mDrawingLayer + line.level;
// LineLayer l = mLineLayers; 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;
// }
// FIXME simplify this...
if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) { if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) {
lineLayer = mCurLineLayer; lineLayer = mCurLineLayer;
} else if (mLineLayers == null || mLineLayers.layer > numLayer) { } else if (l == null || l.layer > numLayer) {
// insert new layer at start // insert new layer at start
lineLayer = new LineLayer(numLayer, line, false); lineLayer = new LineLayer(numLayer, line, false);
lineLayer.next = mLineLayers; lineLayer.next = l;
mLineLayers = lineLayer; mLineLayers = lineLayer;
} else { } else {
for (LineLayer l = mLineLayers; l != null; l = l.next) { while (l != null) {
// found layer
if (l.layer == numLayer) { if (l.layer == numLayer) {
lineLayer = l; lineLayer = l;
break; break;
} }
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) { if (l.next == null || l.next.layer > numLayer) {
lineLayer = new LineLayer(numLayer, line, false); lineLayer = new LineLayer(numLayer, line, false);
// insert new layer between current and next layer
lineLayer.next = l.next; lineLayer.next = l.next;
l.next = lineLayer; l.next = lineLayer;
} }
l = l.next;
} }
} }
@ -421,9 +373,11 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
int length = mWays[i]; int length = mWays[i];
// need at least two points // need at least two points
if (length >= 4) if (length >= 4) {
lineLayer.addLine(mWayNodes, pos, length, w, line.round); lineLayer.addLine(mWayNodes, pos, length, w, line.round);
countLines++;
countNodes += length;
}
pos += length; pos += length;
} }
@ -437,23 +391,26 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
numLayer = mDrawingLayer + outline.level; numLayer = mDrawingLayer + outline.level;
if (mLineLayers == null || mLineLayers.layer > numLayer) { l = mLineLayers;
if (l == null || l.layer > numLayer) {
// insert new layer at start // insert new layer at start
outlineLayer = new LineLayer(numLayer, outline, true); outlineLayer = new LineLayer(numLayer, outline, true);
outlineLayer.next = mLineLayers; outlineLayer.next = l;
mLineLayers = outlineLayer; mLineLayers = outlineLayer;
} else { } else {
for (LineLayer l = mLineLayers; l != null; l = l.next) { while (l != null) {
if (l.layer == numLayer) { if (l.layer == numLayer) {
outlineLayer = l; outlineLayer = l;
break; break;
} }
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) { if (l.next == null || l.next.layer > numLayer) {
outlineLayer = new LineLayer(numLayer, outline, true); outlineLayer = new LineLayer(numLayer, outline, true);
// insert new layer between current and next layer
outlineLayer.next = l.next; outlineLayer.next = l.next;
l.next = outlineLayer; l.next = outlineLayer;
} }
l = l.next;
} }
} }
@ -467,33 +424,36 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
if (!mDebugDrawPolygons) if (!mDebugDrawPolygons)
return; return;
// if (!projectToTile(mCurrentTile.zoomLevel < 14)) if (!projectToTile())
if (!projectToTile(false))
return; return;
int numLayer = mDrawingLayer + area.level; int numLayer = mDrawingLayer + area.level;
PolygonLayer layer = null; PolygonLayer layer = null;
PolygonLayer l = mPolyLayers;
if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) { if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
layer = mCurPolyLayer; layer = mCurPolyLayer;
} else if (mPolyLayers == null || mPolyLayers.layer > numLayer) { } else if (l == null || l.layer > numLayer) {
// insert new layer at start // insert new layer at start
layer = new PolygonLayer(numLayer, area); layer = new PolygonLayer(numLayer, area);
layer.next = mPolyLayers; layer.next = l;
mPolyLayers = layer; mPolyLayers = layer;
} else { } else {
for (PolygonLayer l = mPolyLayers; l != null; l = l.next) { while (l != null) {
if (l.layer >= numLayer) {
if (l.layer == numLayer) {
layer = l; layer = l;
break; break;
} }
// insert new layer between current and next layer
if (l.next == null || l.next.layer > numLayer) { if (l.next == null || l.next.layer > numLayer) {
layer = new PolygonLayer(numLayer, area); layer = new PolygonLayer(numLayer, area);
// insert new layer between current and next layer
layer.next = l.next; layer.next = l.next;
l.next = layer; l.next = layer;
} }
l = l.next;
} }
} }
if (layer == null) if (layer == null)
@ -536,9 +496,6 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
@Override @Override
public boolean executeJob(MapGeneratorJob mapGeneratorJob) { public boolean executeJob(MapGeneratorJob mapGeneratorJob) {
if (!(mapGeneratorJob.tile instanceof GLMapTile))
return false;
if (mMapDatabase == null) if (mMapDatabase == null)
return false; return false;
@ -547,7 +504,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mCurrentTile = (GLMapTile) mapGeneratorJob.tile; mCurrentTile = (GLMapTile) mapGeneratorJob.tile;
mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons; mDebugDrawPolygons = !mapGeneratorJob.debugSettings.mDisablePolygons;
mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted; mDebugDrawUnmatched = mapGeneratorJob.debugSettings.mDrawUnmatchted;
if (mCurrentTile.isLoading || mCurrentTile.isDrawn) if (mCurrentTile.isLoading || mCurrentTile.isReady)
return false; return false;
mCurrentTile.isLoading = true; mCurrentTile.isLoading = true;
@ -561,7 +518,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
mLabels = null; mLabels = null;
// firstMatch = true; // firstMatch = true;
countLines = 0;
countNodes = 0;
mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection mProjectionScaleFactor = (float) (1.0 / Math.cos(MercatorProjection
.pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel) .pixelYToLatitude(mCurrentTile.pixelY, mCurrentTile.zoomLevel)
* (Math.PI / 180))); // / 1.5f; * (Math.PI / 180))); // / 1.5f;
@ -576,7 +534,8 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
} }
if (mapGeneratorJob.debugSettings.mDrawTileFrames) { if (mapGeneratorJob.debugSettings.mDrawTileFrames) {
mTagName = new Tag("name", mCurrentTile.toString(), false); mTagName = new Tag("name", countLines + " " + countNodes + " "
+ mCurrentTile.toString(), false);
mPoiX = 10; mPoiX = 10;
mPoiY = 10; mPoiY = 10;
MapGenerator.renderTheme.matchNode(this, debugTagWay, (byte) 0); 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_DITHER;
import static android.opengl.GLES20.GL_DYNAMIC_DRAW; import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
import static android.opengl.GLES20.GL_EQUAL; 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_INVERT;
import static android.opengl.GLES20.GL_NEVER; import static android.opengl.GLES20.GL_NEVER;
import static android.opengl.GLES20.GL_ONE; 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.glFinish;
import static android.opengl.GLES20.glGenBuffers; import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glGetAttribLocation; import static android.opengl.GLES20.glGetAttribLocation;
import static android.opengl.GLES20.glGetString;
import static android.opengl.GLES20.glGetUniformLocation; import static android.opengl.GLES20.glGetUniformLocation;
import static android.opengl.GLES20.glScissor; import static android.opengl.GLES20.glScissor;
import static android.opengl.GLES20.glStencilFunc; 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.glVertexAttribPointer;
import static android.opengl.GLES20.glViewport; import static android.opengl.GLES20.glViewport;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; 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 String TAG = "MapRenderer";
private static final int MB = 1024 * 1024; private static final int MB = 1024 * 1024;
// private boolean mTriangulate = false;
private static int CACHE_TILES_MAX = 250; private static int CACHE_TILES_MAX = 250;
private static int CACHE_TILES = CACHE_TILES_MAX; private static int CACHE_TILES = CACHE_TILES_MAX;
private static int LIMIT_BUFFERS = 20 * MB; private static int LIMIT_BUFFERS = 20 * MB;
private static final int OES_HALF_FLOAT = 0x8D61; // private static final int OES_HALF_FLOAT = 0x8D61;
private static final int FLOAT_BYTES = 4; // private static final int FLOAT_BYTES = 4;
private static final int SHORT_BYTES = 2; private static final int SHORT_BYTES = 2;
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0; private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
private static final int LINE_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 static int STENCIL_BITS = 8;
private final MapView mMapView; private final MapView mMapView;
private final ArrayList<MapGeneratorJob> mJobList; private static ArrayList<MapGeneratorJob> mJobList;
private final ArrayList<VertexBufferObject> mVBOs; private static ArrayList<VertexBufferObject> mVBOs;
private final TileCacheKey mTileCacheKey; private static TileCacheKey mTileCacheKey;
private final HashMap<TileCacheKey, GLMapTile> mTiles; private static HashMap<TileCacheKey, GLMapTile> mTiles;
private final ArrayList<GLMapTile> mTileList; private static ArrayList<GLMapTile> mTileList;
private final TileDistanceSort mTileDistanceSort; private static TileDistanceSort mTileDistanceSort;
private DebugSettings mDebugSettings; private static DebugSettings mDebugSettings;
private JobParameters mJobParameter; private static JobParameters mJobParameter;
private MapPosition mMapPosition, mPrevMapPosition; private static MapPosition mMapPosition, mPrevMapPosition;
private static int mWidth, mHeight; private static int mWidth, mHeight;
private static float mAspect; private static float mAspect;
@ -141,7 +135,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static long mTileX, mTileY; private static long mTileX, mTileY;
private static int rotateBuffers = 2; private static int rotateBuffers = 2;
private static FloatBuffer floatBuffer[];
private static ShortBuffer shortBuffer[]; private static ShortBuffer shortBuffer[];
static boolean useHalfFloat = false; 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. // nextTiles is swapped with curTiles in onDrawFrame in GL thread.
private static TilesData newTiles, nextTiles, curTiles; private static TilesData newTiles, nextTiles, curTiles;
private boolean mInitial; private static boolean mInitial;
// shader handles // shader handles
private static int lineProgram; private static int lineProgram;
@ -198,7 +191,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
*/ */
public MapRenderer(MapView mapView) { public MapRenderer(MapView mapView) {
Log.d(TAG, "init MapRenderer"); Log.d(TAG, "init MapRenderer");
mMapView = mapView; mMapView = mapView;
if (mInitial)
return;
mDebugSettings = mapView.getDebugSettings(); mDebugSettings = mapView.getDebugSettings();
mVBOs = new ArrayList<VertexBufferObject>(); mVBOs = new ArrayList<VertexBufferObject>();
@ -214,7 +212,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = false; mUpdateTiles = false;
} }
private void updateTileDistances() { private static void updateTileDistances() {
int h = (Tile.TILE_SIZE >> 1); int h = (Tile.TILE_SIZE >> 1);
byte zoom = mMapPosition.zoomLevel; byte zoom = mMapPosition.zoomLevel;
long x = mTileX * (Tile.TILE_SIZE) + h; long x = mTileX * (Tile.TILE_SIZE) + h;
@ -222,57 +220,57 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
int diff; int diff;
long dx, dy; 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++) { 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) {
// tile zoom level is child of current
dx = ((t.pixelX + h) >> diff) - x;
dy = ((t.pixelY + h) >> diff) - y;
} 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));
}
} else {
dx = (t.pixelX + h) - x; dx = (t.pixelX + h) - x;
dy = (t.pixelY + h) - y; dy = (t.pixelY + h) - y;
dy *= mAspect; dy *= mAspect;
t.distance = (1 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)));// * 2; 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;
dy *= mAspect;
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
// prefer lower zoom level, it covers a larger area
t.distance /= -diff;
} }
// 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; byte z = mMapPosition.zoomLevel;
for (int j = mTileList.size() - 1, cnt = 0; cnt < remove && j > 0; j--, cnt++) { for (int j = mTileList.size() - 1, cnt = 0; cnt < remove && j > 0; j--, cnt++) {
GLMapTile t = mTileList.remove(j); GLMapTile t = mTileList.remove(j);
if (t.isActive) { if (t.isActive) {
Log.d(TAG, "EEEK removing active tile"); // Log.d(TAG, "EEEK removing active tile");
mTileList.add(t); mTileList.add(t);
continue; continue;
} }
// check if this tile is used as proxy for not yet drawn active tile // 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.zoomLevel == z + 1) {
if (t.parent != null && t.parent.isActive if (t.parent != null && t.parent.isActive
&& !(t.parent.isDrawn || t.parent.newData)) { && !(t.parent.isReady || t.parent.newData)) {
mTileList.add(t); mTileList.add(t);
Log.d(TAG, "EEEK removing active proxy child"); Log.d(TAG, "EEEK removing active proxy child");
continue; continue;
@ -281,7 +279,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
GLMapTile c = null; GLMapTile c = null;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
c = t.child[i]; c = t.child[i];
if (c != null && c.isActive && !(c.isDrawn || c.newData)) if (c != null && c.isActive && !(c.isReady || c.newData))
break; break;
c = null; c = null;
} }
@ -299,7 +297,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int k = 0; k < 4; k++) { for (int k = 0; k < 4; k++) {
c2 = c.child[k]; c2 = c.child[k];
if (c2 != null && c2.isActive if (c2 != null && c2.isActive
&& !(c2.isDrawn || c2.newData)) && !(c2.isReady || c2.newData))
break; break;
c2 = null; c2 = null;
@ -344,6 +342,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
t.polygonVBO = null; 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; newTiles.tiles[tiles++] = tile;
if (!tile.isDrawn && !tile.newData && !tile.isLoading) { if (!tile.isReady && !tile.newData && !tile.isLoading) {
MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter, MapGeneratorJob job = new MapGeneratorJob(tile, mJobParameter,
mDebugSettings); mDebugSettings);
mJobList.add(job); mJobList.add(job);
} }
// prefetch parent // 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) { // && !tile.parent.isLoading) {
// MapGeneratorJob job = new MapGeneratorJob(tile.parent, mJobParameter, // MapGeneratorJob job = new MapGeneratorJob(tile.parent, mJobParameter,
// mDebugSettings); // mDebugSettings);
@ -484,7 +487,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return true; return true;
} }
private void setChildren(GLMapTile tile) { private static void setChildren(GLMapTile tile) {
long xx = tile.tileX << 1; long xx = tile.tileX << 1;
long yy = tile.tileY << 1; long yy = tile.tileY << 1;
@ -597,23 +600,42 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
float alpha = 1.0f; 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; alpha = (mDrawScale > 1.3f ? mDrawScale : 1.3f) - alpha;
if (alpha > 1.0f) if (alpha > 1.0f)
alpha = 1.0f; alpha = 1.0f;
alpha *= l.area.color[3];
if (!blend) { if (!blend) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
blend = true; blend = true;
} }
} else if (blend) { glUniform4f(hPolygonColor,
glDisable(GL_BLEND); l.area.color[0], l.area.color[1], l.area.color[2], alpha);
blend = false;
}
glUniform4f(hPolygonColor, } else if (l.area.blend == mDrawZ) {
l.area.color[0], l.area.color[1], l.area.color[2], alpha); 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;
}
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 // set stencil buffer mask used to draw this layer
glStencilFunc(GL_EQUAL, 0xff, 1 << c); glStencilFunc(GL_EQUAL, 0xff, 1 << c);
@ -632,26 +654,22 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tile.polygonLayers == null) if (tile.polygonLayers == null)
return true; 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) { if (mLastBoundVBO != tile.polygonVBO.id) {
mLastBoundVBO = tile.polygonVBO.id; mLastBoundVBO = tile.polygonVBO.id;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
if (useHalfFloat) { glVertexAttribPointer(hPolygonVertexPosition, 2,
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_SHORT, false, 0,
OES_HALF_FLOAT, false, 0, POLYGON_VERTICES_DATA_POS_OFFSET);
POLYGON_VERTICES_DATA_POS_OFFSET);
} else {
glVertexAttribPointer(hPolygonVertexPosition, 2,
GL_FLOAT, false, 0,
POLYGON_VERTICES_DATA_POS_OFFSET);
}
} }
setMatrix(tile, diff); setMatrix(tile, diff);
glUniformMatrix4fv(hPolygonMatrix, 1, false, mMVPMatrix, 0); glUniformMatrix4fv(hPolygonMatrix, 1, false, mMVPMatrix, 0);
boolean firstPass = true; // boolean firstPass = true;
for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) { for (PolygonLayer l = tile.polygonLayers; l != null; l = l.next) {
// fade out polygon layers (set in RederTheme) // fade out polygon layers (set in RederTheme)
@ -665,19 +683,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// never pass the test, i.e. always apply first stencil op (sfail) // never pass the test, i.e. always apply first stencil op (sfail)
glStencilFunc(GL_NEVER, 0, 0xff); glStencilFunc(GL_NEVER, 0, 0xff);
if (firstPass) // if (firstPass)
firstPass = false; // firstPass = false;
else { // else {
GLES20.glFlush(); // GLES20.glFlush();
// clear stencilbuffer // clear stencilbuffer
glStencilMask(0xFF); glStencilMask(0xFF);
// glClear(GL_STENCIL_BUFFER_BIT); // glClear(GL_STENCIL_BUFFER_BIT);
// clear stencilbuffer (tile region) // clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} // }
// stencil op for stencil method polygon drawing // stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
@ -720,19 +738,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mLastBoundVBO = tile.lineVBO.id; mLastBoundVBO = tile.lineVBO.id;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
if (useHalfFloat) { glVertexAttribPointer(hLineVertexPosition, 2, GLES20.GL_SHORT,
glVertexAttribPointer(hLineVertexPosition, 2, OES_HALF_FLOAT, false, 8, LINE_VERTICES_DATA_POS_OFFSET);
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); 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) if (diff != 0)
z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); 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) { private boolean uploadTileData(GLMapTile tile) {
ShortBuffer sbuf = null; ShortBuffer sbuf = null;
FloatBuffer fbuf = null;
// double start = SystemClock.uptimeMillis(); // double start = SystemClock.uptimeMillis();
@ -914,68 +924,42 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
int size = 0; int size = 0;
if (useHalfFloat) { sbuf = LineLayers.compileLayerData(tile.lineLayers,
sbuf = LineLayers.compileLayerData(tile.lineLayers, shortBuffer[uploadCnt * 2]);
shortBuffer[uploadCnt * 2]); size = sbuf.remaining();
size = sbuf.remaining(); shortBuffer[uploadCnt * 2] = sbuf;
shortBuffer[uploadCnt * 2] = sbuf;
} else {
fbuf = LineLayers.compileLayerData(tile.lineLayers,
floatBuffer[uploadCnt * 2]);
size = fbuf.remaining();
floatBuffer[uploadCnt * 2] = fbuf;
}
if (size > 0) { if (size > 0) {
mBufferMemoryUsage -= tile.lineVBO.size; mBufferMemoryUsage -= tile.lineVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.lineVBO.id);
// Nexus doesnt like this either
// glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW); // glBufferData(GL_ARRAY_BUFFER, 0, null, GL_DYNAMIC_DRAW);
if (useHalfFloat) { tile.lineVBO.size = size * SHORT_BYTES;
tile.lineVBO.size = size * SHORT_BYTES; glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size,
glBufferData(GL_ARRAY_BUFFER, tile.lineVBO.size, sbuf, GL_DYNAMIC_DRAW);
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; mBufferMemoryUsage += tile.lineVBO.size;
} else { } else {
tile.lineLayers = null; tile.lineLayers = null;
} }
if (useHalfFloat) { sbuf = PolygonLayers.compileLayerData(tile.polygonLayers,
sbuf = PolygonLayers.compileLayerData(tile.polygonLayers, shortBuffer[uploadCnt * 2 + 1]);
shortBuffer[uploadCnt * 2 + 1]); size = sbuf.remaining();
size = sbuf.remaining(); shortBuffer[uploadCnt * 2 + 1] = sbuf;
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 // Upload polygon data to vertex buffer object
if (size > 0) { if (size > 0) {
mBufferMemoryUsage -= tile.polygonVBO.size; mBufferMemoryUsage -= tile.polygonVBO.size;
glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id); glBindBuffer(GL_ARRAY_BUFFER, tile.polygonVBO.id);
// glBufferData(GL_ARRAY_BUFFER, 0, null,
// GL_DYNAMIC_DRAW);
if (useHalfFloat) { tile.polygonVBO.size = size * SHORT_BYTES;
tile.polygonVBO.size = size * SHORT_BYTES; glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size,
glBufferData(GL_ARRAY_BUFFER, tile.polygonVBO.size, sbuf, GL_DYNAMIC_DRAW);
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; mBufferMemoryUsage += tile.polygonVBO.size;
} else { } else {
@ -983,7 +967,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
tile.newData = false; tile.newData = false;
tile.isDrawn = true; tile.isReady = true;
tile.isLoading = false; tile.isLoading = false;
// double compile = SystemClock.uptimeMillis(); // double compile = SystemClock.uptimeMillis();
@ -1007,8 +991,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (timing) if (timing)
start = SystemClock.uptimeMillis(); start = SystemClock.uptimeMillis();
glStencilMask(0xFF); // glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
synchronized (this) { synchronized (this) {
mDrawX = mCurX; mDrawX = mCurX;
@ -1072,7 +1057,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
continue; continue;
} }
if (!tile.isDrawn) { if (!tile.isReady) {
if (tile.parent != null) { if (tile.parent != null) {
if (tile.parent.newData) if (tile.parent.newData)
uploadTileData(tile.parent); uploadTileData(tile.parent);
@ -1099,8 +1084,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (timing) if (timing)
clear_time = (SystemClock.uptimeMillis() - start); clear_time = (SystemClock.uptimeMillis() - start);
glEnable(GL_SCISSOR_TEST); // glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, mWidth, mHeight);
glUseProgram(polygonProgram); glUseProgram(polygonProgram);
glEnableVertexAttribArray(hPolygonVertexPosition); glEnableVertexAttribArray(hPolygonVertexPosition);
@ -1112,7 +1097,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tiles[i].isVisible) { if (tiles[i].isVisible) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
if (tile.isDrawn) if (tile.isReady)
drawPolygons(tile, 0); drawPolygons(tile, 0);
else else
drawProxyPolygons(tile); drawProxyPolygons(tile);
@ -1129,6 +1114,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
poly_time = (SystemClock.uptimeMillis() - start); poly_time = (SystemClock.uptimeMillis() - start);
} }
// glEnable(GL_SCISSOR_TEST);
// Draw lines // Draw lines
glEnable(GL_BLEND); glEnable(GL_BLEND);
glUseProgram(lineProgram); glUseProgram(lineProgram);
@ -1140,7 +1127,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (tiles[i].isVisible) { if (tiles[i].isVisible) {
GLMapTile tile = tiles[i]; GLMapTile tile = tiles[i];
if (tile.isDrawn) if (tile.isReady)
drawLines(tile, 0); drawLines(tile, 0);
else else
drawProxyLines(tile); drawProxyLines(tile);
@ -1150,10 +1137,11 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glDisableVertexAttribArray(hLineVertexPosition); glDisableVertexAttribArray(hLineVertexPosition);
glDisableVertexAttribArray(hLineTexturePosition); glDisableVertexAttribArray(hLineTexturePosition);
glDisable(GL_SCISSOR_TEST); glScissor(0, 0, mWidth, mHeight);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
mTextRenderer.beginDraw();
mTextRenderer.beginDraw(mDrawScale);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (!tiles[i].isVisible || tiles[i].texture == null) if (!tiles[i].isVisible || tiles[i].texture == null)
continue; 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) { // if (ext.indexOf("GL_OES_vertex_half_float") >= 0) {
useHalfFloat = true; // useHalfFloat = true;
shortBuffer = new ShortBuffer[rotateBuffers * 2]; shortBuffer = new ShortBuffer[rotateBuffers * 2];
} // }
else { // else {
floatBuffer = new FloatBuffer[rotateBuffers * 2]; // floatBuffer = new FloatBuffer[rotateBuffers * 2];
} // }
Log.d(TAG, "Extensions: " + ext); // Log.d(TAG, "Extensions: " + ext);
hLineMatrix = glGetUniformLocation(lineProgram, "u_center"); hLineMatrix = glGetUniformLocation(lineProgram, "u_center");
hLineMode = glGetUniformLocation(lineProgram, "u_mode"); hLineMode = glGetUniformLocation(lineProgram, "u_mode");
@ -1289,13 +1277,15 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glDisable(GL_DITHER); glDisable(GL_DITHER);
glClearColor(0.98f, 0.98f, 0.97f, 1.0f); glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
glClearStencil(0); glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
GlUtils.checkGlError("onSurfaceCreated"); GlUtils.checkGlError("onSurfaceCreated");
} }
private void drawProxyLines(GLMapTile tile) { 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.sx = tile.sx;
tile.parent.sy = tile.sy; tile.parent.sy = tile.sy;
tile.parent.sw = tile.sw; tile.parent.sw = tile.sw;
@ -1306,7 +1296,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// 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.isReady && c.isVisible) {
drawLines(c, 1); drawLines(c, 1);
drawn++; drawn++;
} }
@ -1314,7 +1304,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
if (drawn < 4 && tile.parent != null) { if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent; GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) { if (p != null && p.isReady) {
p.sx = tile.sx; p.sx = tile.sx;
p.sy = tile.sy; p.sy = tile.sy;
p.sw = tile.sw; p.sw = tile.sw;
@ -1326,7 +1316,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
private void drawProxyPolygons(GLMapTile tile) { 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.sx = tile.sx;
tile.parent.sy = tile.sy; tile.parent.sy = tile.sy;
tile.parent.sw = tile.sw; tile.parent.sw = tile.sw;
@ -1338,7 +1328,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
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)) { if (c != null && c.isReady && setTileScissor(c, 2)) {
drawPolygons(c, 1); drawPolygons(c, 1);
drawn++; drawn++;
} }
@ -1346,7 +1336,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (drawn < 4 && tile.parent != null) { if (drawn < 4 && tile.parent != null) {
GLMapTile p = tile.parent.parent; GLMapTile p = tile.parent.parent;
if (p != null && p.isDrawn) { if (p != null && p.isReady) {
p.sx = tile.sx; p.sx = tile.sx;
p.sy = tile.sy; p.sy = tile.sy;
p.sw = tile.sw; p.sw = tile.sw;

View File

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

View File

@ -16,68 +16,137 @@ package org.mapsforge.android.glrenderer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import org.mapsforge.android.utils.FastMath;
import org.mapsforge.core.Tile; import org.mapsforge.core.Tile;
class PolygonLayers { class PolygonLayers {
private static final int NUM_VERTEX_FLOATS = 2; private static final int NUM_VERTEX_FLOATS = 2;
static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1, // static final float[] mFillCoords = { -2, Tile.TILE_SIZE + 1,
Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2, // Tile.TILE_SIZE + 1, Tile.TILE_SIZE + 1, -2,
-2, 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) { // static FloatBuffer compileLayerData(PolygonLayer layers, FloatBuffer buf) {
FloatBuffer fbuf = buf; // FloatBuffer fbuf = buf;
int size = 4; // 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) // static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
size += l.verticesCnt; // 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; private static short[] mFillCoords;
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];
static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) { static ShortBuffer compileLayerData(PolygonLayer layers, ShortBuffer buf) {
ShortBuffer sbuf = buf; ShortBuffer sbuf = buf;
@ -96,30 +165,29 @@ class PolygonLayers {
sbuf.clear(); sbuf.clear();
} }
short[] data = tmpItem; if (mFillCoords == null) {
short min = (-2) << 4;
if (mByteFillCoords == null) { short max = (short) ((Tile.TILE_SIZE + 1) << 4);
mByteFillCoords = new short[8]; mFillCoords = new short[8];
FastMath.convertFloatToHalf(mFillCoords[0], mByteFillCoords, 0); mFillCoords[0] = min;
FastMath.convertFloatToHalf(mFillCoords[1], mByteFillCoords, 1); mFillCoords[1] = max;
FastMath.convertFloatToHalf(mFillCoords[2], mByteFillCoords, 2); mFillCoords[2] = max;
FastMath.convertFloatToHalf(mFillCoords[3], mByteFillCoords, 3); mFillCoords[3] = max;
FastMath.convertFloatToHalf(mFillCoords[4], mByteFillCoords, 4); mFillCoords[4] = min;
FastMath.convertFloatToHalf(mFillCoords[5], mByteFillCoords, 5); mFillCoords[5] = min;
FastMath.convertFloatToHalf(mFillCoords[6], mByteFillCoords, 6); mFillCoords[6] = max;
FastMath.convertFloatToHalf(mFillCoords[7], mByteFillCoords, 7); mFillCoords[7] = min;
} }
sbuf.put(mByteFillCoords, 0, 8); sbuf.put(mFillCoords, 0, 8);
int pos = 4; int pos = 4;
PoolItem last = null, items = null; ShortItem last = null, items = null;
for (PolygonLayer l = layers; l != null; l = l.next) { for (PolygonLayer l = layers; l != null; l = l.next) {
for (PoolItem item = l.pool; item != null; item = item.next) { for (ShortItem item = l.pool; item != null; item = item.next) {
PoolItem.toHalfFloat(item, data); sbuf.put(item.vertices, 0, item.used);
sbuf.put(data, 0, item.used);
last = item; last = item;
} }
@ -134,7 +202,7 @@ class PolygonLayers {
l.pool = null; l.pool = null;
} }
VertexPool.add(items); ShortPool.add(items);
sbuf.flip(); sbuf.flip();
@ -144,7 +212,7 @@ class PolygonLayers {
static void clear(PolygonLayer layers) { static void clear(PolygonLayer layers) {
for (PolygonLayer l = layers; l != null; l = l.next) { for (PolygonLayer l = layers; l != null; l = l.next) {
if (l.pool != null) 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 vec4 a_position;"
+ "attribute vec2 a_st;" + "attribute vec2 a_st;"
+ "varying vec2 v_st;" + "varying vec2 v_st;"
+ "const vec4 scale = vec4(1.0/16.0, 1.0/16.0, 0.0, 1.0);"
+ "void main() {" + "void main() {"
// + " gl_Position = u_center * vec4(a_position.x, a_position.y, 0.0, 1.0);" // + " gl_Position = u_center * vec4(a_position.x, a_position.y, 0.0, 1.0);"
// + " v_st = a_position.zw;" // + " 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;" + " v_st = a_st;"
+ "}"; + "}";
@ -165,8 +167,9 @@ class Shaders {
+ "precision mediump float; \n" + "precision mediump float; \n"
+ "uniform mat4 u_center;\n" + "uniform mat4 u_center;\n"
+ "attribute vec4 a_position;" + "attribute vec4 a_position;"
+ "const vec4 scale = vec4(1.0/16.0, 1.0/16.0, 0.0, 1.0);"
+ "void main() {" + "void main() {"
+ " gl_Position = u_center * a_position;" + " gl_Position = u_center * (scale * a_position);"
+ "}"; + "}";
final static String gPolygonFragmentShader = "" 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 * 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. * 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 * 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 * 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/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.mapsforge.android.glrenderer; package org.mapsforge.android.glrenderer;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
class VertexPool { public class ShortPool {
private static final int POOL_LIMIT = 8192; private static final int POOL_LIMIT = 8192;
@SuppressLint("UseValueOf") @SuppressLint("UseValueOf")
private static final Boolean lock = new Boolean(true); private static final Boolean lock = new Boolean(true);
static private PoolItem pool = null; static private ShortItem pool = null;
static private int count = 0; static private int count = 0;
static void init() { static ShortItem get() {
}
static PoolItem get() {
synchronized (lock) { synchronized (lock) {
if (count == 0) if (count == 0)
return new PoolItem(); return new ShortItem();
count--; count--;
PoolItem it = pool; ShortItem it = pool;
pool = pool.next; pool = pool.next;
it.used = 0; it.used = 0;
it.next = null; it.next = null;
@ -45,12 +41,12 @@ class VertexPool {
} }
} }
static void add(PoolItem items) { static void add(ShortItem items) {
if (items == null) if (items == null)
return; return;
synchronized (lock) { synchronized (lock) {
PoolItem last = items; ShortItem last = items;
// limit pool items // limit pool items
while (count < POOL_LIMIT) { while (count < POOL_LIMIT) {
@ -62,7 +58,7 @@ class VertexPool {
} }
// clear references // clear references
PoolItem tmp2, tmp = last.next; ShortItem tmp2, tmp = last.next;
while (tmp != null) { while (tmp != null) {
tmp2 = tmp; tmp2 = tmp;
tmp = tmp.next; tmp = tmp.next;

View File

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

View File

@ -21,9 +21,9 @@ import org.mapsforge.core.Tile;
*/ */
public class MapTile extends 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. * tile is removed from JobQueue and loading in DatabaseRenderer. set by MapWorker.

View File

@ -147,27 +147,14 @@
</rule> </rule>
<rule e="way" k="natural|" v="*"> <rule e="way" k="natural" v="wood">
<rule e="way" k="*" v="wood"> <area fill="#ebefe5" fade="7" blend="11" blend-fill="#d3dec8"/>
<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> </rule>
<rule e="way" k="landuse" v="*"> <rule e="way" k="landuse" v="forest">
<rule e="way" k="*" v="forest"> <area fill="#ebefe5" fade="7" blend="11" blend-fill="#d3dec8"/>
<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> </rule>
<!-- keep grass above forest:wood and leisure:park! --> <!-- keep grass above forest:wood and leisure:park! -->
<rule e="way" k="landuse" v="grass"> <rule e="way" k="landuse" v="grass">
@ -472,15 +459,28 @@
<rule e="way" k="*" v="*" zoom-min="13"> <rule e="way" k="*" v="*" zoom-min="13">
<rule e="way" k="*" v="residential|road|unclassified|living_street"> <rule e="way" k="*" v="residential|road|unclassified|living_street">
<rule e="way" k="bridge" v="yes|true"> <rule e="way" k="bridge" v="yes|true">
<line stroke="#ffffff" stroke-width="1.2" outline="2" stroke-linecap="butt" /> <line stroke="#ffffff" stroke-width="1.2" outline="2" stroke-linecap="butt" />
</rule> </rule>
<rule e="way" k="bridge" v="~|no|false"> <rule e="way" k="bridge" v="~|no|false">
<line stroke="#ffffff" stroke-width="1.2" outline="1" /> <line stroke="#ffffff" stroke-width="1.2" outline="1" />
</rule> </rule>
</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> </rule>
@ -683,11 +683,11 @@
<rule e="way" k="debug" v="area"> <rule e="way" k="debug" v="area">
<line stroke="#ff0000" stroke-width="1.2" fixed="true" stroke-linecap="butt" /> <line stroke="#ff0000" stroke-width="1.2" fixed="true" stroke-linecap="butt" />
<area fill="#880000ff"/> <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>
<rule e="way" k="debug" v="way"> <rule e="way" k="debug" v="way">
<line stroke="#00ffff" stroke-width="1.5" fixed="true" stroke-linecap="butt" /> <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>
</rule> </rule>
@ -723,7 +723,7 @@
<!-- place --> <!-- place -->
<rule e="node" k="place" v="*"> <rule e="node" k="place" v="*">
<rule e="node" k="*" v="suburb|town|village" zoom-max="14"> <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" /> stroke="#ffffff" stroke-width="2.0" />
</rule> </rule>
<rule e="node" k="*" v="island" zoom-min="10"> <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="src" type="tns:src" use="optional" />
<xs:attribute name="fill" type="tns:color" use="optional" <xs:attribute name="fill" type="tns:color" use="optional"
default="#000000" /> default="#000000" />
<xs:attribute name="stroke" type="tns:color" use="optional" <xs:attribute name="stroke" type="tns:color" u se="optional"
default="#00000000" /> default="#00000000" />
<xs:attribute name="stroke-width" type="tns:nonNegativeFloat" <xs:attribute name="stroke-width" type="tns:nonNegativeFloat"
use="optional" default="0" /> use="optional" default="0" />
<xs:attribute name="fade" type="xs:integer" use="optional" <xs:attribute name="fade" type="xs:integer" use="optional"
default="-1" /> 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>
<xs:complexType name="caption"> <xs:complexType name="caption">

View File

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

View File

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

View File

@ -59,7 +59,7 @@ public class MapDatabase implements IMapDatabase {
private static final MapFileInfo mMapInfo = private static final MapFileInfo mMapInfo =
new MapFileInfo(new BoundingBox(-180, -90, 180, 90), 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"); WebMercator.NAME, 0, 0, 0, "de", "comment", "author");
private boolean mOpenFile = false; private boolean mOpenFile = false;
@ -343,7 +343,8 @@ public class MapDatabase implements IMapDatabase {
} }
if (fail || index == null || tags == null || indexCnt == 0 || tagCnt == 0) { 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); + tagCnt);
return false; return false;
} }