comments and cleanups

This commit is contained in:
Hannes Janetzek 2012-09-10 20:33:21 +02:00
parent 69fe74facc
commit baa40ed9ea
11 changed files with 186 additions and 175 deletions

View File

@ -27,26 +27,28 @@ public interface IMapRenderer extends GLSurfaceView.Renderer {
/** /**
* @param tile * @param tile
* the mapGeneratorJob holding Tile data * Tile data ready for rendering
* @return true if the tile was processed * @return true
*/ */
public boolean passTile(JobTile tile); public boolean passTile(JobTile tile);
/**
* @return true when tile passed to renderer is processed false otherwise. used to lock overwriting resources passed
* with the tile (e.g. lock until bitmap is loaded to texture)
*/
public boolean processedTile();
/** /**
* called by MapView on position and map changes * called by MapView on position and map changes
* *
* @param clear * @param clear
* ... * recreate all tiles (i.e. on theme change)
*/ */
public void redrawTiles(boolean clear); public void updateMap(boolean clear);
/**
* @return new MapGenerator Instance for this Renderer
*/
public IMapGenerator createMapGenerator(); public IMapGenerator createMapGenerator();
/**
* @param t
* the theme
*/
public void setRenderTheme(RenderTheme t); public void setRenderTheme(RenderTheme t);
} }

View File

@ -269,14 +269,14 @@ public class MapView extends GLSurfaceView {
if (getWidth() <= 0 || getHeight() <= 0) if (getWidth() <= 0 || getHeight() <= 0)
return; return;
mMapRenderer.redrawTiles(false); mMapRenderer.updateMap(false);
} }
private void clearAndRedrawMapView() { private void clearAndRedrawMapView() {
if (getWidth() <= 0 || getHeight() <= 0) if (getWidth() <= 0 || getHeight() <= 0)
return; return;
mMapRenderer.redrawTiles(true); mMapRenderer.updateMap(true);
} }
/** /**

View File

@ -37,7 +37,8 @@ public class TouchHandler {
/* package */final MapViewPosition mMapPosition; /* package */final MapViewPosition mMapPosition;
private final float mMapMoveDelta; private final float mMapMoveDelta;
private boolean mMoveThresholdReached; private boolean mMoveStart;
private boolean mRotationStart;
private float mPosX; private float mPosX;
private float mPosY; private float mPosY;
private float mAngle; private float mAngle;
@ -76,7 +77,8 @@ public class TouchHandler {
private boolean onActionDown(MotionEvent event) { private boolean onActionDown(MotionEvent event) {
mPosX = event.getX(); mPosX = event.getX();
mPosY = event.getY(); mPosY = event.getY();
mMoveThresholdReached = false; mMoveStart = false;
mRotationStart = false;
// save the ID of the pointer // save the ID of the pointer
mActivePointerId = event.getPointerId(0); mActivePointerId = event.getPointerId(0);
// Log.d("...", "set active pointer" + mActivePointerId); // Log.d("...", "set active pointer" + mActivePointerId);
@ -97,13 +99,13 @@ public class TouchHandler {
if (!mScaling) { if (!mScaling) {
mScaling = scaling; mScaling = scaling;
} }
if (!scaling && !mMoveThresholdReached) { if (!scaling && !mMoveStart) {
if (Math.abs(moveX) > 3 * mMapMoveDelta if (Math.abs(moveX) > 3 * mMapMoveDelta
|| Math.abs(moveY) > 3 * mMapMoveDelta) { || Math.abs(moveY) > 3 * mMapMoveDelta) {
// the map movement threshold has been reached // the map movement threshold has been reached
// longPressDetector.pressStop(); // longPressDetector.pressStop();
mMoveThresholdReached = true; mMoveStart = true;
// save the position of the event // save the position of the event
mPosX = event.getX(pointerIndex); mPosX = event.getX(pointerIndex);
@ -134,9 +136,15 @@ public class TouchHandler {
double y = cx * Math.sin(r) + cy * Math.cos(r) - cy; double y = cx * Math.sin(r) + cy * Math.cos(r) - cy;
// Log.d("...", "move " + x + " " + y + " " + cx + " " + cy); // Log.d("...", "move " + x + " " + y + " " + cx + " " + cy);
mMapPosition.rotateMap(angle - mAngle, (float) x, (float) y); if (!mRotationStart) {
mAngle = angle; if (Math.abs(angle - mAngle) > 3.0)
mMapView.redrawTiles(); mRotationStart = true;
}
else {
mMapPosition.rotateMap(angle - mAngle, (float) x, (float) y);
mAngle = angle;
mMapView.redrawTiles();
}
} }
} }
// save the position of the event // save the position of the event

View File

@ -151,6 +151,7 @@ class LineLayer {
// add first vertex twice // add first vertex twice
ddx = (int) ((ux - vx) * DIR_SCALE); ddx = (int) ((ux - vx) * DIR_SCALE);
ddy = (int) ((uy - vy) * DIR_SCALE); ddy = (int) ((uy - vy) * DIR_SCALE);
// last two bit encode texture coord (-1)
dx = (short) (0 | ddx & DIR_MASK); dx = (short) (0 | ddx & DIR_MASK);
dy = (short) (2 | ddy & DIR_MASK); dy = (short) (2 | ddy & DIR_MASK);

View File

@ -18,7 +18,6 @@ import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_BLEND;
import static android.opengl.GLES20.GL_DYNAMIC_DRAW; import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA; import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA;
import static android.opengl.GLES20.GL_SCISSOR_TEST;
import static android.opengl.GLES20.GL_STENCIL_BUFFER_BIT; import static android.opengl.GLES20.GL_STENCIL_BUFFER_BIT;
import static android.opengl.GLES20.glBindBuffer; import static android.opengl.GLES20.glBindBuffer;
import static android.opengl.GLES20.glBlendFunc; import static android.opengl.GLES20.glBlendFunc;
@ -29,7 +28,6 @@ import static android.opengl.GLES20.glClearStencil;
import static android.opengl.GLES20.glDisable; import static android.opengl.GLES20.glDisable;
import static android.opengl.GLES20.glEnable; import static android.opengl.GLES20.glEnable;
import static android.opengl.GLES20.glGenBuffers; import static android.opengl.GLES20.glGenBuffers;
import static android.opengl.GLES20.glScissor;
import static android.opengl.GLES20.glViewport; import static android.opengl.GLES20.glViewport;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -56,18 +54,6 @@ import android.util.Log;
public class MapRenderer implements org.mapsforge.android.IMapRenderer { public class MapRenderer implements org.mapsforge.android.IMapRenderer {
/**
* used for passing tiles to be rendered from TileLoader(Main) to GLThread
*/
static class TilesData {
int cnt = 0;
final MapTile[] tiles;
TilesData(int numTiles) {
tiles = new MapTile[numTiles];
}
}
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;
@ -77,7 +63,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static final int CACHE_TILES_MAX = 200; private static final int CACHE_TILES_MAX = 200;
private static final int LIMIT_BUFFERS = 16 * MB; private static final int LIMIT_BUFFERS = 16 * MB;
private static int CACHE_TILES = CACHE_TILES_MAX; static int CACHE_TILES = CACHE_TILES_MAX;
private final MapView mMapView; private final MapView mMapView;
private static ArrayList<VertexBufferObject> mVBOs; private static ArrayList<VertexBufferObject> mVBOs;
@ -97,19 +83,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static float[] mProjMatrix = new float[16]; private static float[] mProjMatrix = new float[16];
private static float[] mRotTMatrix = new float[16]; private static float[] mRotTMatrix = new float[16];
// newTiles is set in updateVisibleList and swapped // curTiles is set by TileLoader and swapped with
// with curTiles on main thread. curTiles is swapped // drawTiles in onDrawFrame in GL thread.
// with drawTiles in onDrawFrame in GL thread.
private static TilesData curTiles, drawTiles; private static TilesData curTiles, drawTiles;
// draw position is updated from current position in onDrawFrame
// keeping the position and active tiles consistent while drawing
private static MapPosition mCurPosition, mDrawPosition;
// flag set by updateVisibleList when current visible tiles // flag set by updateVisibleList when current visible tiles
// changed. used in onDrawFrame to flip curTiles/drawTiles // changed. used in onDrawFrame to flip curTiles/drawTiles
private static boolean mUpdateTiles; private static boolean mUpdateTiles;
private static MapPosition mCurPosition;
private float[] mClearColor = null; private float[] mClearColor = null;
// number of tiles drawn in one frame // number of tiles drawn in one frame
@ -117,8 +100,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static boolean mUpdateColor = false; private static boolean mUpdateColor = false;
// lock to synchronize Main- and GL-Thread
static Object lock = new Object(); static Object lock = new Object();
// used for passing tiles to be rendered from TileLoader(Main-Thread) to GLThread
static class TilesData {
int cnt = 0;
final MapTile[] tiles;
TilesData(int numTiles) {
tiles = new MapTile[numTiles];
}
}
/** /**
* @param mapView * @param mapView
* the MapView * the MapView
@ -136,16 +130,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
* called by MapView when position or map settings changes * called by MapView when position or map settings changes
*/ */
@Override @Override
public void redrawTiles(boolean clear) { public void updateMap(boolean clear) {
TileLoader.redrawTiles(clear); TileLoader.updateMap(clear);
} }
/**
* called by TileLoader when only position changed
*
* @param mapPosition
* current MapPosition
*/
static void updatePosition(MapPosition mapPosition) { static void updatePosition(MapPosition mapPosition) {
// synchronized (MapRenderer.lock) {
mCurPosition = mapPosition; mCurPosition = mapPosition;
// }
} }
/**
* called by TileLoader when list of active tiles changed
*
* @param mapPosition
* current MapPosition
* @param tiles
* active tiles
* @return curTiles (the previously active tiles)
*/
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) { static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
synchronized (MapRenderer.lock) { synchronized (MapRenderer.lock) {
@ -169,6 +176,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
/**
* called by TileLoader. when tile is removed from cache, reuse its vbo.
*
* @param vbo
* the VBO
*/
static void addVBO(VertexBufferObject vbo) { static void addVBO(VertexBufferObject vbo) {
synchronized (mVBOs) { synchronized (mVBOs) {
mVBOs.add(vbo); mVBOs.add(vbo);
@ -176,7 +189,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
/** /**
* called by MapWorkers when tile is loaded * called from MapWorker Thread when tile is loaded by MapGenerator
*/ */
@Override @Override
public synchronized boolean passTile(JobTile jobTile) { public synchronized boolean passTile(JobTile jobTile) {
@ -186,6 +199,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// no one should be able to use this tile now, mapgenerator passed it, // no one should be able to use this tile now, mapgenerator passed it,
// glthread does nothing until newdata is set. // glthread does nothing until newdata is set.
Log.d(TAG, "passTile: canceled " + tile); Log.d(TAG, "passTile: canceled " + tile);
TileLoader.addTileLoaded(tile);
return true; return true;
} }
@ -220,13 +234,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private static boolean mRotate = false; private static boolean mRotate = false;
private static void setMatrix(MapTile tile, float div, int offset) { private static void setMatrix(MapPosition mapPosition, MapTile tile, float div,
int offset) {
float x, y, scale; float x, y, scale;
if (mRotate) { if (mRotate) {
scale = (float) (1.0 * mDrawPosition.scale / (mHeight * div)); scale = (float) (1.0 * mapPosition.scale / (mHeight * div));
x = (float) (tile.pixelX - mDrawPosition.x * div); x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mDrawPosition.y * div); y = (float) (tile.pixelY - mapPosition.y * div);
Matrix.setIdentityM(mMVPMatrix, 0); Matrix.setIdentityM(mMVPMatrix, 0);
@ -243,9 +258,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
} }
else { else {
scale = (float) (2.0 * mDrawPosition.scale / (mHeight * div)); scale = (float) (2.0 * mapPosition.scale / (mHeight * div));
x = (float) (tile.pixelX - mDrawPosition.x * div); x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mDrawPosition.y * div); y = (float) (tile.pixelY - mapPosition.y * div);
mMVPMatrix[12] = x * scale * mAspect; mMVPMatrix[12] = x * scale * mAspect;
mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale; mMVPMatrix[13] = -(y + Tile.TILE_SIZE) * scale;
@ -257,29 +272,41 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
private static boolean isVisible(MapTile tile, float div) { private static boolean isVisible(MapPosition mapPosition, MapTile tile, float div) {
double dx, dy, scale; double dx, dy, scale;
if (div == 0) { if (div == 0) {
dx = tile.pixelX - mDrawPosition.x; dx = tile.pixelX - mapPosition.x;
dy = tile.pixelY - mDrawPosition.y; dy = tile.pixelY - mapPosition.y;
scale = mDrawPosition.scale; scale = mapPosition.scale;
} else { } else {
dx = tile.pixelX - mDrawPosition.x * div; dx = tile.pixelX - mapPosition.x * div;
dy = tile.pixelY - mDrawPosition.y * div; dy = tile.pixelY - mapPosition.y * div;
scale = mDrawPosition.scale / div; scale = mapPosition.scale / div;
} }
int size = Tile.TILE_SIZE; int size = Tile.TILE_SIZE;
int sx = (int) (dx * scale); int sx = (int) (dx * scale);
int sy = (int) (dy * scale); int sy = (int) (dy * scale);
if (sy > mHeight / 2 || sx > mWidth / 2 // FIXME little hack, need to do scanline check or sth
|| sx + size * scale < -mWidth / 2 // this kindof works for typical screen aspect
|| sy + size * scale < -mHeight / 2) { if (mRotate) {
tile.isVisible = false; int ssize = mWidth > mHeight ? mWidth : mHeight;
return false;
}
if (sy > ssize / 2 || sx > ssize / 2
|| sx + size * scale < -ssize / 2
|| sy + size * scale < -ssize / 2) {
tile.isVisible = false;
return false;
}
} else {
if (sy > mHeight / 2 || sx > mWidth / 2
|| sx + size * scale < -mWidth / 2
|| sy + size * scale < -mHeight / 2) {
tile.isVisible = false;
return false;
}
}
tile.isVisible = true; tile.isVisible = true;
return true; return true;
@ -429,6 +456,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
@Override @Override
public void onDrawFrame(GL10 glUnused) { public void onDrawFrame(GL10 glUnused) {
long start = 0; long start = 0;
MapPosition mapPosition;
if (MapView.debugFrameTime) if (MapView.debugFrameTime)
start = SystemClock.uptimeMillis(); start = SystemClock.uptimeMillis();
@ -452,7 +480,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// get position and current tiles to draw // get position and current tiles to draw
synchronized (MapRenderer.lock) { synchronized (MapRenderer.lock) {
mDrawPosition = mCurPosition; mapPosition = mCurPosition;
if (mUpdateTiles) { if (mUpdateTiles) {
TilesData tmp = drawTiles; TilesData tmp = drawTiles;
@ -472,7 +500,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
MapTile tile = tiles[i]; MapTile tile = tiles[i];
if (!isVisible(tile, 1)) if (!isVisible(mapPosition, tile, 1))
continue; continue;
if (tile.texture == null && TextRenderer.drawToTexture(tile)) if (tile.texture == null && TextRenderer.drawToTexture(tile))
@ -508,15 +536,17 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
TextRenderer.compileTextures(); TextRenderer.compileTextures();
if (mRotate) { if (mRotate) {
Matrix.setRotateM(mRotateMatrix, 0, mDrawPosition.angle, 0, 0, 1); Matrix.setRotateM(mRotateMatrix, 0, mapPosition.angle, 0, 0, 1);
Matrix.transposeM(mRotTMatrix, 0, mRotateMatrix, 0); Matrix.transposeM(mRotTMatrix, 0, mRotateMatrix, 0);
} else {
Matrix.setIdentityM(mRotTMatrix, 0);
} }
GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_DEPTH_TEST);
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && tiles[i].isReady) { if (tiles[i].isVisible && tiles[i].isReady) {
drawTile(tiles[i], 1); drawTile(mapPosition, tiles[i], 1);
} }
} }
@ -524,7 +554,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// TODO draw all parent before grandparent // TODO draw all parent before grandparent
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && !tiles[i].isReady) { if (tiles[i].isVisible && !tiles[i].isReady) {
drawProxyTile(tiles[i]); drawProxyTile(mapPosition, tiles[i]);
} }
} }
// GlUtils.checkGlError("end draw"); // GlUtils.checkGlError("end draw");
@ -535,17 +565,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mDrawSerial++; mDrawSerial++;
glEnable(GL_BLEND); glEnable(GL_BLEND);
int z = mDrawPosition.zoomLevel; int z = mapPosition.zoomLevel;
float s = mDrawPosition.scale; float s = mapPosition.scale;
int zoomLevelDiff = Math.max(z - MapGenerator.STROKE_MAX_ZOOM_LEVEL, 0); int zoomLevelDiff = Math.max(z - MapGenerator.STROKE_MAX_ZOOM_LEVEL, 0);
float scale = (float) Math.pow(1.4, zoomLevelDiff); float scale = (float) Math.pow(1.4, zoomLevelDiff);
if (scale < 1) if (scale < 1)
scale = 1; scale = 1;
// scale = (1.0f * mDrawPosition.scale / mHeight);
// TextRenderer.beginDraw(scale);
if (z >= MapGenerator.STROKE_MAX_ZOOM_LEVEL) if (z >= MapGenerator.STROKE_MAX_ZOOM_LEVEL)
TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix); TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mRotTMatrix);
else else
@ -555,7 +582,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (!tiles[i].isVisible || tiles[i].texture == null) if (!tiles[i].isVisible || tiles[i].texture == null)
continue; continue;
setMatrix(tiles[i], 1, 0); setMatrix(mapPosition, tiles[i], 1, 0);
TextRenderer.drawTile(tiles[i], mMVPMatrix); TextRenderer.drawTile(tiles[i], mMVPMatrix);
} }
TextRenderer.endDraw(); TextRenderer.endDraw();
@ -569,19 +596,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
// used to not draw a tile twice per frame... // used to not draw a tile twice per frame...
private static byte mDrawSerial = 0; private static byte mDrawSerial = 0;
private static void drawTile(MapTile tile, float div) { private static void drawTile(MapPosition mapPosition, MapTile tile, float div) {
// draw parents only once // draw parents only once
if (tile.lastDraw == mDrawSerial) if (tile.lastDraw == mDrawSerial)
return; return;
tile.lastDraw = mDrawSerial; tile.lastDraw = mDrawSerial;
int z = mDrawPosition.zoomLevel; int z = mapPosition.zoomLevel;
float s = mDrawPosition.scale; float s = mapPosition.scale;
// mDrawCount is used to calculation z offset. // mDrawCount is used to calculation z offset.
// (used for depth clipping) // (used for depth clipping)
setMatrix(tile, div, mDrawCount++); setMatrix(mapPosition, tile, div, mDrawCount++);
glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id); glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
@ -621,7 +648,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
private static boolean drawProxyChild(MapTile tile) { private static boolean drawProxyChild(MapPosition mapPosition, MapTile tile) {
int drawn = 0; int drawn = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (tile.rel.child[i] == null) if (tile.rel.child[i] == null)
@ -631,32 +658,32 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (c == null) if (c == null)
continue; continue;
if (!isVisible(c, 2)) { if (!isVisible(mapPosition, c, 2)) {
drawn++; drawn++;
continue; continue;
} }
if (c.isReady) { if (c.isReady) {
drawTile(c, 2); drawTile(mapPosition, c, 2);
drawn++; drawn++;
} }
} }
return drawn == 4; return drawn == 4;
} }
private static void drawProxyTile(MapTile tile) { private static void drawProxyTile(MapPosition mapPosition, MapTile tile) {
if (mDrawPosition.scale > 1.5f) { if (mapPosition.scale > 1.5f) {
// prefer drawing children // prefer drawing children
if (!drawProxyChild(tile)) { if (!drawProxyChild(mapPosition, tile)) {
MapTile t = tile.rel.parent.tile; MapTile t = tile.rel.parent.tile;
if (t != null) { if (t != null) {
if (t.isReady) { if (t.isReady) {
drawTile(t, 0.5f); drawTile(mapPosition, t, 0.5f);
} else { } else {
MapTile p = t.rel.parent.tile; MapTile p = t.rel.parent.tile;
if (p != null && p.isReady) if (p != null && p.isReady)
drawTile(p, 0.25f); drawTile(mapPosition, p, 0.25f);
} }
} }
} }
@ -665,16 +692,16 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
MapTile t = tile.rel.parent.tile; MapTile t = tile.rel.parent.tile;
if (t != null && t.isReady) { if (t != null && t.isReady) {
drawTile(t, 0.5f); drawTile(mapPosition, t, 0.5f);
} else if (!drawProxyChild(tile)) { } else if (!drawProxyChild(mapPosition, tile)) {
// need to check rel.parent here, t could alread be root // need to check rel.parent here, t could alread be root
if (t != null) { if (t != null) {
t = t.rel.parent.tile; t = t.rel.parent.tile;
if (t != null && t.isReady) if (t != null && t.isReady)
drawTile(t, 0.25f); drawTile(mapPosition, t, 0.25f);
} }
} }
} }
@ -683,25 +710,22 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
@Override @Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) { public void onSurfaceChanged(GL10 glUnused, int width, int height) {
Log.d(TAG, "SurfaceChanged:" + width + " " + height); Log.d(TAG, "SurfaceChanged:" + width + " " + height);
// mTilesLoaded.clear();
// mTiles.clear();
// LineLayers.finish();
drawTiles = curTiles = null; drawTiles = curTiles = null;
mBufferMemoryUsage = 0; mBufferMemoryUsage = 0;
// mInitial = true;
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
return; return;
// STENCIL_BITS = GlConfigChooser.stencilSize;
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
mAspect = (float) height / width; mAspect = (float) height / width;
Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1); Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.5f, -1, 1);
// Matrix.frustumM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f, 0.7f,
// 1, 100);
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2) int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
@ -736,8 +760,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glClearStencil(0); glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST); // glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, mWidth, mHeight); // glScissor(0, 0, mWidth, mHeight);
glDisable(GLES20.GL_CULL_FACE);
glBlendFunc(GLES20.GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GLES20.GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@ -772,11 +798,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
PolygonLayers.init(); PolygonLayers.init();
} }
@Override
public boolean processedTile() {
return true;
}
@Override @Override
public IMapGenerator createMapGenerator() { public IMapGenerator createMapGenerator() {
return new MapGenerator(mMapView); return new MapGenerator(mMapView);

View File

@ -18,7 +18,6 @@ package org.mapsforge.android.glrenderer;
class Shaders { class Shaders {
final static String lineVertexShader = "" final static String lineVertexShader = ""
// + "#version 130\n"
+ "precision mediump float;" + "precision mediump float;"
+ "uniform mat4 mvp;" + "uniform mat4 mvp;"
+ "attribute vec2 a_position;" + "attribute vec2 a_position;"
@ -27,13 +26,13 @@ class Shaders {
+ "uniform float u_width;" + "uniform float u_width;"
+ "const float dscale = 8.0/2048.0;" + "const float dscale = 8.0/2048.0;"
+ "void main() {" + "void main() {"
// scale extrusion to line u_width pixel // scale extrusion to u_width pixel
// just ignore the two most insignificant bits of a_st :) // just ignore the two most insignificant bits of a_st :)
+ " vec2 dir = dscale * u_width * a_st;" + " vec2 dir = dscale * u_width * a_st;"
+ " gl_Position = mvp * vec4(a_position + dir, 0.0,1.0);" + " gl_Position = mvp * vec4(a_position + dir, 0.0,1.0);"
// last two bits of a_st hold the texture coordinates // last two bits of a_st hold the texture coordinates
// TODO use bit operations when available!
+ " v_st = u_width * (abs(mod(a_st,4.0)) - 1.0);" + " v_st = u_width * (abs(mod(a_st,4.0)) - 1.0);"
// TODO use bit operations when available (gles 1.3)
// + " v_st = u_width * vec2(ivec2(a_st) & 3 - 1);" // + " v_st = u_width * vec2(ivec2(a_st) & 3 - 1);"
+ "}"; + "}";
@ -60,12 +59,13 @@ class Shaders {
+ "const float zero = 0.0;" + "const float zero = 0.0;"
+ "void main() {" + "void main() {"
+ " float len;" + " float len;"
// + " if (v_st.t == zero)" + " if (v_st.t == zero)"
// + " len = abs(v_st.s);" + " len = abs(v_st.s);"
// + " else " + " else "
+ " len = length(v_st);" + " len = length(v_st);"
// fade to alpha. u_wscale is the width in pixel which should be faded, // fade to alpha. u_wscale is the width in pixel which should be faded,
// u_width - len the position of this fragment on the perpendicular to the line // u_width - len the position of this fragment on the perpendicular to
// this line segment
+ " gl_FragColor = smoothstep(zero, u_wscale, u_width - len) * u_color;" + " gl_FragColor = smoothstep(zero, u_wscale, u_width - len) * u_color;"
+ "}"; + "}";

View File

@ -34,20 +34,15 @@ import android.util.Log;
* JobQueue (mapView.addJobs) for loading by MapGenerator class * JobQueue (mapView.addJobs) for loading by MapGenerator class
*/ */
public class TileLoader { class TileLoader {
private static final String TAG = "TileLoader"; private static final String TAG = "TileLoader";
private static final int MAX_TILES_IN_QUEUE = 40; private static final int MAX_TILES_IN_QUEUE = 40;
private static final int CACHE_TILES_MAX = 200;
// private static final int MB = 1024 * 1024;
// private static final int LIMIT_BUFFERS = 16 * MB;
private static int CACHE_TILES = CACHE_TILES_MAX;
private static MapView mMapView; private static MapView mMapView;
// new jobs for the MapWorkers
private static ArrayList<JobTile> mJobList; private static ArrayList<JobTile> mJobList;
// private static ArrayList<VertexBufferObject> mVBOs;
// all tiles currently referenced // all tiles currently referenced
private static ArrayList<MapTile> mTiles; private static ArrayList<MapTile> mTiles;
@ -65,7 +60,7 @@ public class TileLoader {
// private static MapPosition mCurPosition, mDrawPosition; // private static MapPosition mCurPosition, mDrawPosition;
private static int mWidth, mHeight; private static int mWidth, mHeight;
private static TilesData newTiles; // , curTiles, drawTiles; private static TilesData newTiles;
static void init(MapView mapView, int w, int h, int numTiles) { static void init(MapView mapView, int w, int h, int numTiles) {
mMapView = mapView; mMapView = mapView;
@ -84,7 +79,7 @@ public class TileLoader {
newTiles = new TilesData(numTiles); newTiles = new TilesData(numTiles);
} }
static void redrawTiles(boolean clear) { static void updateMap(boolean clear) {
boolean changedPos = false; boolean changedPos = false;
boolean changedZoom = false; boolean changedZoom = false;
@ -151,13 +146,7 @@ public class TileLoader {
updateVisibleList(mapPosition, 0); updateVisibleList(mapPosition, 0);
} else { } else {
// pass new position to glThread // pass new position to glThread
MapRenderer.updatePosition(mapPosition); MapRenderer.updatePosition(mapPosition);
// synchronized () {
// // do not change position while drawing
// mCurPosition = mapPosition;
// }
} }
if (!MapView.debugFrameTime) if (!MapView.debugFrameTime)
@ -167,7 +156,7 @@ public class TileLoader {
updateVisibleList(mapPosition, zdir); updateVisibleList(mapPosition, zdir);
if (changedPos || changedZoom) { if (changedPos || changedZoom) {
int remove = mTiles.size() - CACHE_TILES; int remove = mTiles.size() - MapRenderer.CACHE_TILES;
if (remove > 50) if (remove > 50)
limitCache(mapPosition, remove); limitCache(mapPosition, remove);
} }
@ -178,6 +167,18 @@ public class TileLoader {
} }
/**
* Manage tiles that have data to be uploaded to gl
*
* @param tile
* tile processed by MapGenerator
*/
static void addTileLoaded(MapTile tile) {
synchronized (mTilesLoaded) {
mTilesLoaded.add(tile);
}
}
private static boolean updateVisibleList(MapPosition mapPosition, int zdir) { private static boolean updateVisibleList(MapPosition mapPosition, int zdir) {
double x = mapPosition.x; double x = mapPosition.x;
double y = mapPosition.y; double y = mapPosition.y;
@ -253,28 +254,6 @@ public class TileLoader {
newTiles.cnt = tiles; newTiles.cnt = tiles;
newTiles = MapRenderer.updateTiles(mapPosition, newTiles); newTiles = MapRenderer.updateTiles(mapPosition, newTiles);
// pass new tile list to glThread
// synchronized (MapRenderer.lock) {
//
// for (int i = 0; i < curTiles.cnt; i++)
// curTiles.tiles[i].isActive = false;
//
// for (int j = 0; j < drawTiles.cnt; j++)
// drawTiles.tiles[j].isActive = true;
//
// for (int i = 0; i < tiles; i++)
// newTiles.tiles[i].isActive = true;
//
// TilesData tmp = curTiles;
// curTiles = newTiles;
// curTiles.cnt = tiles;
// newTiles = tmp;
//
// mCurPosition = mapPosition;
//
// mUpdateTiles = true;
// }
if (mJobList.size() > 0) { if (mJobList.size() > 0) {
updateTileDistances(mJobList, mapPosition); updateTileDistances(mJobList, mapPosition);
Collections.sort(mJobList); Collections.sort(mJobList);
@ -467,11 +446,15 @@ public class TileLoader {
// check if this tile could be used as proxy // check if this tile could be used as proxy
Log.d(TAG, "X not removing proxy: " + t + " " + t.distance); Log.d(TAG, "X not removing proxy: " + t + " " + t.distance);
mTiles.add(t); mTiles.add(t);
} else if (t.isLoading) {
// FIXME !!! if we add tile back on next limit cache
// this will be removed. clearTile could interfere with
// MapGenerator... clear in passTile().
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
t.isLoading = false;
// mTiles.add(t);
} else { } else {
if (t.isLoading) {
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
t.isLoading = false;
}
clearTile(t); clearTile(t);
} }
} }
@ -499,12 +482,12 @@ public class TileLoader {
if (size < MAX_TILES_IN_QUEUE) if (size < MAX_TILES_IN_QUEUE)
return; return;
while (size-- > MAX_TILES_IN_QUEUE - 20) { for (int i = 0, n = size - MAX_TILES_IN_QUEUE + 20; i < n; i++) {
MapTile t = mTilesLoaded.get(size); MapTile t = mTilesLoaded.get(i);
synchronized (t) { synchronized (t) {
if (t.rel == null) { if (t.rel == null) {
mTilesLoaded.remove(size); mTilesLoaded.remove(i);
continue; continue;
} }
@ -513,7 +496,7 @@ public class TileLoader {
continue; continue;
} }
mTilesLoaded.remove(size); mTilesLoaded.remove(i);
mTiles.remove(t); mTiles.remove(t);
// Log.d(TAG, "remove unused tile data: " + t); // Log.d(TAG, "remove unused tile data: " + t);
clearTile(t); clearTile(t);
@ -521,10 +504,4 @@ public class TileLoader {
} }
} }
} }
static void addTileLoaded(MapTile tile) {
synchronized (mTilesLoaded) {
mTilesLoaded.add(0, tile);
}
}
} }

View File

@ -92,6 +92,6 @@ public class MapWorker extends PausableThread {
@Override @Override
protected boolean hasWork() { protected boolean hasWork() {
return !mJobQueue.isEmpty() && mMapRenderer.processedTile(); return !mJobQueue.isEmpty();
} }
} }

View File

@ -128,9 +128,6 @@
<use-area name="park"/> <use-area name="park"/>
</rule> </rule>
<rule e="way" k="*" v="reservoir|basin">
<use-area name="water" />
</rule>
</rule> </rule>
<rule e="way" k="landuse" v="village_green|recreation_ground" > <rule e="way" k="landuse" v="village_green|recreation_ground" >
@ -159,6 +156,7 @@
<!-- <line stroke="#abcfab" width="1.5" fixed="true" cap="butt"/> --> <!-- <line stroke="#abcfab" width="1.5" fixed="true" cap="butt"/> -->
</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|meadow"> <rule e="way" k="landuse" v="grass|meadow">
<use-area name="greens"/> <use-area name="greens"/>
@ -266,7 +264,11 @@
<use-line name="water:outline"/> <use-line name="water:outline"/>
</rule> </rule>
</rule> </rule>
<rule e="way" k="landuse" v="reservoir|basin">
<use-area name="water" />
</rule>
<!-- waterways --> <!-- waterways -->
<rule e="way" k="waterway" v="*"> <rule e="way" k="waterway" v="*">

View File

@ -249,7 +249,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
* *
*/ */
@Override @Override
public synchronized void redrawTiles(boolean clear) { public synchronized void updateMap(boolean clear) {
boolean update = false; boolean update = false;
@ -565,10 +565,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
" gl_FragColor = texture2D(sTexture, vTextureCoord); \n" + " gl_FragColor = texture2D(sTexture, vTextureCoord); \n" +
"}\n"; "}\n";
@Override // @Override
public boolean processedTile() { // public boolean processedTile() {
return processedTile; // return processedTile;
} // }
@Override @Override
public IMapGenerator createMapGenerator() { public IMapGenerator createMapGenerator() {

View File

@ -104,10 +104,10 @@ public class TileMap extends MapActivity {
return true; return true;
case R.id.menu_position: case R.id.menu_position:
mMapView.enableRotation(true);
return true; return true;
case R.id.menu_rotation_enable: case R.id.menu_rotation_enable:
mMapView.enableRotation(true);
return true; return true;
case R.id.menu_position_my_location_enable: case R.id.menu_position_my_location_enable: