add osmdroid overlays + bonuspack
This commit is contained in:
@@ -25,7 +25,7 @@ import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
@@ -35,8 +35,7 @@ import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.Layers;
|
||||
import org.oscim.renderer.overlays.Overlay;
|
||||
import org.oscim.renderer.overlays.OverlayText;
|
||||
import org.oscim.renderer.overlays.RenderOverlay;
|
||||
import org.oscim.theme.RenderTheme;
|
||||
import org.oscim.utils.GlUtils;
|
||||
import org.oscim.view.MapView;
|
||||
@@ -61,7 +60,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
static int CACHE_TILES = CACHE_TILES_MAX;
|
||||
|
||||
private final MapView mMapView;
|
||||
private static MapView mMapView;
|
||||
static int mWidth, mHeight;
|
||||
|
||||
private static MapViewPosition mMapViewPosition;
|
||||
@@ -177,10 +176,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
* the MapView
|
||||
*/
|
||||
/** @param mapView
|
||||
* the MapView */
|
||||
public GLRenderer(MapView mapView) {
|
||||
|
||||
mMapView = mapView;
|
||||
@@ -213,15 +210,15 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
shortBuffer[i].put(mFillCoords, 0, 8);
|
||||
}
|
||||
|
||||
mOverlays = new ArrayList<Overlay>();
|
||||
// overlays = new ArrayList<RenderOverlay>();
|
||||
|
||||
// mOverlays.add(new OverlayGrid(mapView));
|
||||
// mOverlays.add(new OverlayTest(mapView));
|
||||
mOverlays.add(new OverlayText(mapView));
|
||||
// overlays.add(new OverlayText(mapView));
|
||||
|
||||
}
|
||||
|
||||
private static ArrayList<Overlay> mOverlays;
|
||||
// private static ArrayList<RenderOverlay> overlays;
|
||||
|
||||
public static void setRenderTheme(RenderTheme t) {
|
||||
mClearColor = GlUtils.colorToFloat(t.getMapBackground());
|
||||
@@ -234,7 +231,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
int newSize = layers.getSize();
|
||||
if (newSize == 0) {
|
||||
Log.d(TAG, "empty");
|
||||
// FIXME why are there so many tiles empty?
|
||||
// Log.d(TAG, "empty");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -315,14 +313,14 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
return tile.isReady;
|
||||
}
|
||||
|
||||
private static boolean uploadOverlayData(Overlay overlay) {
|
||||
private static boolean uploadOverlayData(RenderOverlay renderOverlay) {
|
||||
|
||||
if (uploadLayers(overlay.layers, overlay.vbo, true))
|
||||
overlay.isReady = true;
|
||||
if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, true))
|
||||
renderOverlay.isReady = true;
|
||||
|
||||
overlay.newData = false;
|
||||
renderOverlay.newData = false;
|
||||
|
||||
return overlay.isReady;
|
||||
return renderOverlay.isReady;
|
||||
}
|
||||
|
||||
private static void checkBufferUsage() {
|
||||
@@ -384,7 +382,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
public void onDrawFrame(GL10 glUnused) {
|
||||
|
||||
// prevent main thread recreating all tiles (updateMap)
|
||||
// while rendering is going.
|
||||
// while rendering is going on.
|
||||
drawlock.lock();
|
||||
try {
|
||||
draw();
|
||||
@@ -421,9 +419,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// get current tiles to draw
|
||||
mDrawTiles = TileManager.getActiveTiles(mDrawTiles);
|
||||
|
||||
// FIXME what if only drawing overlays?
|
||||
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean tilesChanged = false;
|
||||
// check if the tiles have changed...
|
||||
if (serial != mDrawTiles.serial) {
|
||||
@@ -450,14 +450,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
float div = scaleDiv(tiles[0]);
|
||||
|
||||
// transform screen coordinates to tile coordinates
|
||||
float s = Tile.TILE_SIZE;
|
||||
float scale = mapPosition.scale / div;
|
||||
float px = (float) mapPosition.x * div;
|
||||
float py = (float) mapPosition.y * div;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (px + coords[i + 0] / scale) / s;
|
||||
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
||||
coords[i + 0] = (px + coords[i + 0] / scale) / Tile.TILE_SIZE;
|
||||
coords[i + 1] = (py + coords[i + 1] / scale) / Tile.TILE_SIZE;
|
||||
}
|
||||
|
||||
mHolderCount = 0;
|
||||
@@ -514,11 +513,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
tilesChanged |= (uploadCnt > 0);
|
||||
|
||||
// if (changed || tilesChanged) {
|
||||
for (Overlay overlay : mOverlays) {
|
||||
overlay.update(changed, tilesChanged);
|
||||
}
|
||||
// }
|
||||
// update overlays
|
||||
List<RenderOverlay> overlays = mMapView.getOverlayManager().getRenderLayers();
|
||||
|
||||
for (int i = 0, n = overlays.size(); i < n; i++)
|
||||
overlays.get(i).update(mMapPosition, changed, tilesChanged);
|
||||
|
||||
GLES20.glEnable(GL_DEPTH_TEST);
|
||||
GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
@@ -538,7 +537,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (t.isVisible && !t.isReady && (t.holder == null))
|
||||
drawProxyTile(t);
|
||||
}
|
||||
// GlUtils.checkGlError("end draw");
|
||||
|
||||
GLES20.glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
GLES20.glDisable(GL_DEPTH_TEST);
|
||||
@@ -549,22 +547,25 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
|
||||
// call overlay renderer
|
||||
for (Overlay overlay : mOverlays) {
|
||||
if (overlay.newData) {
|
||||
if (overlay.vbo == null)
|
||||
overlay.vbo = BufferObject.get();
|
||||
for (int i = 0, n = overlays.size(); i < n; i++) {
|
||||
RenderOverlay renderOverlay = overlays.get(i);
|
||||
|
||||
if (overlay.vbo == null)
|
||||
continue;
|
||||
if (renderOverlay.newData) {
|
||||
if (renderOverlay.vbo == null) {
|
||||
renderOverlay.vbo = BufferObject.get();
|
||||
|
||||
if (uploadOverlayData(overlay))
|
||||
overlay.isReady = true;
|
||||
if (renderOverlay.vbo == null)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uploadOverlayData(renderOverlay))
|
||||
renderOverlay.isReady = true;
|
||||
}
|
||||
if (!overlay.isReady)
|
||||
continue;
|
||||
|
||||
// setMatrix(mMVPMatrix, overlay);
|
||||
overlay.render(mMapPosition, mMVPMatrix, mProjMatrix);
|
||||
if (renderOverlay.isReady) {
|
||||
// setMatrix(mMVPMatrix, overlay);
|
||||
renderOverlay.render(mMapPosition, mMVPMatrix, mProjMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
if (MapView.debugFrameTime) {
|
||||
@@ -594,6 +595,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mapPosition.viewMatrix, 0);
|
||||
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
|
||||
}
|
||||
|
||||
// mMapView.getOverlayManager().onUpdate(mMapPosition);
|
||||
|
||||
}
|
||||
|
||||
// used to not draw a tile twice per frame.
|
||||
|
||||
@@ -32,7 +32,7 @@ public class GLView extends GLSurfaceView {
|
||||
setEGLConfigChooser(new GlConfigChooser());
|
||||
setEGLContextClientVersion(2);
|
||||
|
||||
// setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
||||
setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
||||
mRenderer = new GLRenderer(mMapView);
|
||||
setRenderer(mRenderer);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class QuadTree {
|
||||
|
||||
static boolean remove(MapTile t) {
|
||||
if (t.rel == null) {
|
||||
// Bad Things(tm) happened
|
||||
Log.d(TAG, "already removed " + t);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,9 @@
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen Design */
|
||||
|
||||
package org.oscim.renderer;
|
||||
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
public abstract class ScanBox {
|
||||
|
||||
@@ -31,16 +28,14 @@ public abstract class ScanBox {
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
} else {
|
||||
this.x0 = x1;
|
||||
this.y0 = y1;
|
||||
this.x1 = x0;
|
||||
this.y1 = y0;
|
||||
dx = x0 - x1;
|
||||
dy = y0 - y1;
|
||||
}
|
||||
this.dx = this.x1 - this.x0;
|
||||
this.dy = this.y1 - this.y0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,33 +44,32 @@ public abstract class ScanBox {
|
||||
private Edge ca = new Edge();
|
||||
protected byte mZoom;
|
||||
|
||||
void scan(float[] coords, byte zoom) {
|
||||
abstract void setVisible(int y, int x1, int x2);
|
||||
|
||||
public void scan(float[] coords, byte zoom) {
|
||||
mZoom = zoom;
|
||||
|
||||
// top-left -> top-right
|
||||
ab.set(coords[0], coords[1], coords[2], coords[3]);
|
||||
// top-right -> bottom-right
|
||||
bc.set(coords[2], coords[3], coords[4], coords[5]);
|
||||
// bottom-right -> bottom-left
|
||||
ca.set(coords[4], coords[5], coords[0], coords[1]);
|
||||
|
||||
scanTriangle();
|
||||
|
||||
ab.set(coords[4], coords[5], coords[6], coords[7]);
|
||||
bc.set(coords[6], coords[7], coords[0], coords[1]);
|
||||
ca.set(coords[0], coords[1], coords[4], coords[5]);
|
||||
scanTriangle();
|
||||
}
|
||||
// top-left -> bottom-right
|
||||
ab.set(coords[0], coords[1], coords[4], coords[5]);
|
||||
// bottom-right -> bottom-left
|
||||
bc.set(coords[4], coords[5], coords[6], coords[7]);
|
||||
// bottom-left -> top-left
|
||||
ca.set(coords[6], coords[7], coords[0], coords[1]);
|
||||
|
||||
/**
|
||||
* @param y
|
||||
* ...
|
||||
* @param x1
|
||||
* ...
|
||||
* @param x2
|
||||
* ...
|
||||
*/
|
||||
void setVisible(int y, int x1, int x2) {
|
||||
scanTriangle();
|
||||
}
|
||||
|
||||
private void scanTriangle() {
|
||||
|
||||
// sort so that ca.dy > bc.dy > ab.dy
|
||||
if (ab.dy > bc.dy) {
|
||||
Edge t = ab;
|
||||
ab = bc;
|
||||
@@ -91,23 +85,21 @@ public abstract class ScanBox {
|
||||
bc = ca;
|
||||
ca = t;
|
||||
}
|
||||
// ca.dy > bc.dy > ab.dy
|
||||
|
||||
// shouldnt be possible, anyway
|
||||
if (ca.dy == 0)
|
||||
return;
|
||||
|
||||
if (ab.dy != 0)
|
||||
if (ab.dy > 0.1)
|
||||
scanSpans(ca, ab);
|
||||
|
||||
if (bc.dy != 0)
|
||||
if (bc.dy > 0.1)
|
||||
scanSpans(ca, bc);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
private static final int MAX_SLOPE = 4;
|
||||
|
||||
private void scanSpans(Edge e0, Edge e1) {
|
||||
|
||||
// scan the y-range of the edge with less dy
|
||||
int y0 = (int) Math.max(0, FloatMath.floor(e1.y0));
|
||||
int y1 = (int) Math.min((1 << mZoom), FloatMath.ceil(e1.y1));
|
||||
|
||||
@@ -131,41 +123,99 @@ public abstract class ScanBox {
|
||||
float m0 = e0.dx / e0.dy;
|
||||
float m1 = e1.dx / e1.dy;
|
||||
|
||||
// still needed?
|
||||
if (m0 > MAX_SLOPE)
|
||||
m0 = MAX_SLOPE;
|
||||
else if (m0 < -MAX_SLOPE)
|
||||
m0 = -MAX_SLOPE;
|
||||
// FIXME, something is wrong here, with a steep angle
|
||||
// 'fill' can shoot far over the area in one direction
|
||||
int maxSlope = 8;
|
||||
if (m0 > maxSlope)
|
||||
m0 = maxSlope;
|
||||
else if (m0 < -maxSlope)
|
||||
m0 = -maxSlope;
|
||||
|
||||
if (m1 > MAX_SLOPE)
|
||||
m1 = MAX_SLOPE;
|
||||
else if (m1 < -MAX_SLOPE)
|
||||
m1 = -MAX_SLOPE;
|
||||
if (m1 > maxSlope)
|
||||
m1 = maxSlope;
|
||||
else if (m1 < -maxSlope)
|
||||
m1 = -maxSlope;
|
||||
|
||||
// e0 goes to the right, e1 to the left
|
||||
int d0 = e0.dx > 0 ? 1 : 0; // use y + 1 to compute x0
|
||||
int d1 = e1.dx < 0 ? 1 : 0; // use y + 1 to compute x1
|
||||
|
||||
float x0, x1, dy;
|
||||
float dy;
|
||||
|
||||
for (int y = y0; y < y1; y++) {
|
||||
dy = y + d0 - e0.y0;
|
||||
if (e0.dy < dy)
|
||||
|
||||
dy = d0 + y - e0.y0;
|
||||
if (dy > e0.dy)
|
||||
dy = e0.dy;
|
||||
|
||||
x0 = e0.x0 + m0 * dy;
|
||||
x0 = FloatMath.ceil(x0);
|
||||
float x0 = FloatMath.ceil(e0.x0 + m0 * dy);
|
||||
|
||||
dy = y + d1 - e1.y0;
|
||||
if (e1.dy < dy)
|
||||
dy = d1 + y - e1.y0;
|
||||
if (dy > e1.dy)
|
||||
dy = e1.dy;
|
||||
|
||||
x1 = e1.x0 + m1 * dy;
|
||||
x1 = FloatMath.floor(x1);
|
||||
float x1 = FloatMath.floor(e1.x0 + m1 * dy);
|
||||
|
||||
if (x1 > x0)
|
||||
Log.d("...", "X set visible" + y + " " + x1 + "/" + x0);
|
||||
|
||||
setVisible(y, (int) x1, (int) x0);
|
||||
if (x1 < x0)
|
||||
setVisible(y, (int) x1, (int) x0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen
|
||||
* Design
|
||||
*/
|
||||
|
||||
// // scan-line conversion
|
||||
// function edge(a, b) {
|
||||
// if (a.row > b.row) { var t = a; a = b; b = t; }
|
||||
// return {
|
||||
// x0: a.column,
|
||||
// y0: a.row,
|
||||
// x1: b.column,
|
||||
// y1: b.row,
|
||||
// dx: b.column - a.column,
|
||||
// dy: b.row - a.row
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// // scan-line conversion
|
||||
// function scanSpans(e0, e1, ymin, ymax, scanLine) {
|
||||
// var y0 = Math.max(ymin, Math.floor(e1.y0)),
|
||||
// y1 = Math.min(ymax, Math.ceil(e1.y1));
|
||||
//
|
||||
// // sort edges by x-coordinate
|
||||
// if ((e0.x0 == e1.x0 && e0.y0 == e1.y0)
|
||||
// ? (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1)
|
||||
// : (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0)) {
|
||||
// var t = e0; e0 = e1; e1 = t;
|
||||
// }
|
||||
//
|
||||
// // scan lines!
|
||||
// var m0 = e0.dx / e0.dy,
|
||||
// m1 = e1.dx / e1.dy,
|
||||
// d0 = e0.dx > 0, // use y + 1 to compute x0
|
||||
// d1 = e1.dx < 0; // use y + 1 to compute x1
|
||||
// for (var y = y0; y < y1; y++) {
|
||||
// var x0 = m0 * Math.max(0, Math.min(e0.dy, y + d0 - e0.y0)) + e0.x0,
|
||||
// x1 = m1 * Math.max(0, Math.min(e1.dy, y + d1 - e1.y0)) + e1.x0;
|
||||
// scanLine(Math.floor(x1), Math.ceil(x0), y);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // scan-line conversion
|
||||
// function scanTriangle(a, b, c, ymin, ymax, scanLine) {
|
||||
// var ab = edge(a, b),
|
||||
// bc = edge(b, c),
|
||||
// ca = edge(c, a);
|
||||
//
|
||||
// // sort edges by y-length
|
||||
// if (ab.dy > bc.dy) { var t = ab; ab = bc; bc = t; }
|
||||
// if (ab.dy > ca.dy) { var t = ab; ab = ca; ca = t; }
|
||||
// if (bc.dy > ca.dy) { var t = bc; bc = ca; ca = t; }
|
||||
//
|
||||
// // scan span! scan span!
|
||||
// if (ab.dy) scanSpans(ca, ab, ymin, ymax, scanLine);
|
||||
// if (bc.dy) scanSpans(ca, bc, ymin, ymax, scanLine);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
*/
|
||||
package org.oscim.renderer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLUtils;
|
||||
@@ -24,11 +25,12 @@ import android.util.Log;
|
||||
public class TextureObject {
|
||||
private static TextureObject pool;
|
||||
|
||||
private static ArrayList<Bitmap> mBitmaps;
|
||||
|
||||
// shared bitmap and canvas for default texture size
|
||||
public final static int TEXTURE_WIDTH = 256;
|
||||
public final static int TEXTURE_HEIGHT = 256;
|
||||
private static Bitmap[] mBitmap;
|
||||
private static Canvas[] mCanvas;
|
||||
|
||||
private static int mBitmapFormat;
|
||||
private static int mBitmapType;
|
||||
private static int objectCount = 10;
|
||||
@@ -37,22 +39,38 @@ public class TextureObject {
|
||||
TextureObject to;
|
||||
|
||||
if (pool == null) {
|
||||
init(10);
|
||||
objectCount += 10;
|
||||
Log.d("...", "textures: " + objectCount);
|
||||
objectCount += 1;
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "textures: " + objectCount);
|
||||
pool = new TextureObject(-1);
|
||||
}
|
||||
|
||||
to = pool;
|
||||
pool = pool.next;
|
||||
|
||||
to.next = null;
|
||||
|
||||
to.bitmap = getBitmap();
|
||||
to.bitmap.eraseColor(Color.TRANSPARENT);
|
||||
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "get texture " + to.id + " " + to.bitmap);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
public static synchronized void release(TextureObject to) {
|
||||
|
||||
while (to != null) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "release texture " + to.id);
|
||||
|
||||
TextureObject next = to.next;
|
||||
|
||||
if (to.bitmap != null) {
|
||||
mBitmaps.add(to.bitmap);
|
||||
to.bitmap = null;
|
||||
}
|
||||
|
||||
to.next = pool;
|
||||
pool = to;
|
||||
|
||||
@@ -60,6 +78,26 @@ public class TextureObject {
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void uploadTexture(TextureObject to) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "upload texture " + to.id);
|
||||
|
||||
if (to.id < 0) {
|
||||
int[] textureIds = new int[1];
|
||||
GLES20.glGenTextures(1, textureIds, 0);
|
||||
to.id = textureIds[0];
|
||||
initTexture(to.id);
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "new texture " + to.id);
|
||||
}
|
||||
|
||||
uploadTexture(to, to.bitmap, mBitmapFormat, mBitmapType,
|
||||
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||
|
||||
mBitmaps.add(to.bitmap);
|
||||
to.bitmap = null;
|
||||
}
|
||||
|
||||
public static void uploadTexture(TextureObject to, Bitmap bitmap,
|
||||
int format, int type, int w, int h) {
|
||||
|
||||
@@ -77,73 +115,74 @@ public class TextureObject {
|
||||
}
|
||||
}
|
||||
|
||||
static void initTexture(int id) {
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
||||
GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
|
||||
GLES20.GL_CLAMP_TO_EDGE); // Set V Wrapping
|
||||
}
|
||||
|
||||
static void init(int num) {
|
||||
pool = null;
|
||||
|
||||
TextureObject to;
|
||||
|
||||
int[] textureIds = new int[num];
|
||||
GLES20.glGenTextures(num, textureIds, 0);
|
||||
|
||||
for (int i = 1; i < num; i++) {
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
||||
GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
|
||||
GLES20.GL_CLAMP_TO_EDGE); // Set V Wrapping
|
||||
|
||||
initTexture(textureIds[i]);
|
||||
to = new TextureObject(textureIds[i]);
|
||||
|
||||
to.next = pool;
|
||||
pool = to;
|
||||
}
|
||||
|
||||
mBitmap = new Bitmap[4];
|
||||
mCanvas = new Canvas[4];
|
||||
mBitmaps = new ArrayList<Bitmap>(10);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mBitmap[i] = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||
Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
mCanvas[i] = new Canvas(mBitmap[i]);
|
||||
|
||||
mBitmaps.add(bitmap);
|
||||
}
|
||||
mBitmapFormat = GLUtils.getInternalFormat(mBitmap[0]);
|
||||
mBitmapType = GLUtils.getType(mBitmap[0]);
|
||||
|
||||
mBitmapFormat = GLUtils.getInternalFormat(mBitmaps.get(0));
|
||||
mBitmapType = GLUtils.getType(mBitmaps.get(0));
|
||||
}
|
||||
|
||||
private static int curCanvas = 0;
|
||||
private static Bitmap getBitmap() {
|
||||
int size = mBitmaps.size();
|
||||
if (size == 0) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
public static Canvas getCanvas() {
|
||||
curCanvas = ++curCanvas % 4;
|
||||
|
||||
mBitmap[curCanvas].eraseColor(Color.TRANSPARENT);
|
||||
|
||||
return mCanvas[curCanvas];
|
||||
}
|
||||
|
||||
public static TextureObject uploadCanvas(short offset, short indices) {
|
||||
TextureObject to = get();
|
||||
uploadTexture(to, mBitmap[curCanvas],
|
||||
mBitmapFormat, mBitmapType,
|
||||
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||
|
||||
to.offset = offset;
|
||||
to.vertices = (short) (indices - offset);
|
||||
|
||||
return to;
|
||||
mBitmaps.add(bitmap);
|
||||
}
|
||||
size = 4;
|
||||
}
|
||||
return mBitmaps.remove(size - 1);
|
||||
}
|
||||
|
||||
public TextureObject next;
|
||||
|
||||
public Bitmap bitmap;
|
||||
|
||||
int id;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// vertex offset from which this texture is referenced
|
||||
// or store texture id with vertex?
|
||||
short offset;
|
||||
short vertices;
|
||||
public short offset;
|
||||
public short vertices;
|
||||
|
||||
TextureObject(int id) {
|
||||
this.id = id;
|
||||
|
||||
@@ -24,8 +24,11 @@ import org.oscim.renderer.layer.TextureLayer;
|
||||
import org.oscim.utils.GlUtils;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
import android.util.Log;
|
||||
|
||||
public final class TextureRenderer {
|
||||
public final static boolean debug = false;
|
||||
|
||||
private static int mTextureProgram;
|
||||
private static int hTextureMVMatrix;
|
||||
private static int hTextureProjMatrix;
|
||||
@@ -35,7 +38,7 @@ public final class TextureRenderer {
|
||||
private static int hTextureTexCoord;
|
||||
private static int mIndicesVBO;
|
||||
|
||||
final static int INDICES_PER_SPRITE = 6;
|
||||
public final static int INDICES_PER_SPRITE = 6;
|
||||
final static int VERTICES_PER_SPRITE = 4;
|
||||
final static int SHORTS_PER_VERTICE = 6;
|
||||
// per texture
|
||||
@@ -89,9 +92,9 @@ public final class TextureRenderer {
|
||||
|
||||
public static Layer draw(Layer layer, float scale, float[] projection,
|
||||
float matrix[], int offset) {
|
||||
GlUtils.checkGlError("draw texture0");
|
||||
|
||||
// GlUtils.checkGlError("draw texture >");
|
||||
GLES20.glUseProgram(mTextureProgram);
|
||||
GlUtils.checkGlError("draw texture1");
|
||||
|
||||
int va = hTextureTexCoord;
|
||||
if (!GLRenderer.vertexArray[va]) {
|
||||
@@ -106,39 +109,48 @@ public final class TextureRenderer {
|
||||
}
|
||||
|
||||
TextureLayer tl = (TextureLayer) layer;
|
||||
GlUtils.checkGlError("draw texture2.");
|
||||
GLES20.glUniform1f(hTextureScale, scale);
|
||||
|
||||
if (tl.fixed)
|
||||
GLES20.glUniform1f(hTextureScale, scale);
|
||||
else
|
||||
GLES20.glUniform1f(hTextureScale, 1);
|
||||
|
||||
GLES20.glUniform1f(hTextureScreenScale, 1f / GLRenderer.mWidth);
|
||||
|
||||
GLES20.glUniformMatrix4fv(hTextureProjMatrix, 1, false, projection, 0);
|
||||
GLES20.glUniformMatrix4fv(hTextureMVMatrix, 1, false, matrix, 0);
|
||||
GlUtils.checkGlError("draw texture2");
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||
GlUtils.checkGlError("draw texture3");
|
||||
|
||||
for (TextureObject to = tl.textures; to != null; to = to.next) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "draw texture: " + to.id + " " + to.offset + " " + to.vertices);
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
|
||||
GlUtils.checkGlError("draw texture4");
|
||||
int maxVertices = MAX_ITEMS * INDICES_PER_SPRITE;
|
||||
|
||||
GlUtils.checkGlError("draw texture5");
|
||||
for (int i = 0; i < to.vertices; i += maxVertices) {
|
||||
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
|
||||
int off = (to.offset + i) * 8 + offset;
|
||||
|
||||
// to.offset * 24(shorts) * 2(short-bytes) / 6(indices)
|
||||
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
||||
GLES20.GL_SHORT, false, 12, to.offset * 8 + offset);
|
||||
GlUtils.checkGlError("draw texture..");
|
||||
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
||||
GLES20.GL_SHORT, false, 12, off);
|
||||
|
||||
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
|
||||
GLES20.GL_SHORT, false, 12, to.offset * 8 + offset + 8);
|
||||
GlUtils.checkGlError("draw texture...");
|
||||
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
|
||||
GLES20.GL_SHORT, false, 12, off + 8);
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, to.vertices,
|
||||
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
int numVertices = to.vertices - i;
|
||||
if (numVertices > maxVertices)
|
||||
numVertices = maxVertices;
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numVertices,
|
||||
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GlUtils.checkGlError("draw texture");
|
||||
|
||||
// GlUtils.checkGlError("< draw texture");
|
||||
|
||||
return layer.next;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
SymbolLayer sl = (SymbolLayer) mLayers.textureLayers;
|
||||
|
||||
SymbolItem it = new SymbolItem();
|
||||
SymbolItem it = SymbolItem.get();
|
||||
it.x = mPoiX;
|
||||
it.y = mPoiY;
|
||||
it.bitmap = bitmap;
|
||||
|
||||
@@ -23,16 +23,13 @@ import org.oscim.core.Tile;
|
||||
import org.oscim.generator.JobTile;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.renderer.layer.VertexPool;
|
||||
import org.oscim.renderer.overlays.Overlay;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.MapViewPosition;
|
||||
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
// FIXME move GLSurfaceView in separate class
|
||||
public class TileManager { // extends GLSurfaceView {
|
||||
private final static String TAG = "TileManager";
|
||||
public class TileManager {
|
||||
static final String TAG = TileManager.class.getSimpleName();
|
||||
|
||||
private static final int MAX_TILES_IN_QUEUE = 40;
|
||||
private static final int CACHE_THRESHOLD = 10;
|
||||
@@ -45,17 +42,12 @@ public class TileManager { // extends GLSurfaceView {
|
||||
// new jobs for the MapWorkers
|
||||
private static ArrayList<JobTile> mJobList;
|
||||
|
||||
// all tiles currently referenced
|
||||
// all tiles
|
||||
private static ArrayList<MapTile> mTiles;
|
||||
|
||||
// tiles that have new data to upload, see passTile()
|
||||
private static ArrayList<MapTile> mTilesLoaded;
|
||||
|
||||
private static ArrayList<Overlay> mOverlays;
|
||||
|
||||
// TODO current boundary tiles, values used to check if position has
|
||||
// changed for updating current tile list
|
||||
|
||||
private static boolean mInitial;
|
||||
|
||||
// private static MapPosition mCurPosition, mDrawPosition;
|
||||
@@ -67,8 +59,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
|
||||
private static float[] mTileCoords = new float[8];
|
||||
|
||||
// private static int[] mBoundaryTiles = new int[8];
|
||||
|
||||
static int mUpdateCnt;
|
||||
static ReentrantLock tilelock = new ReentrantLock();
|
||||
static Tiles mCurrentTiles;
|
||||
@@ -123,10 +113,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
}
|
||||
};
|
||||
|
||||
// why not try a pattern every now and then?
|
||||
// but should do the same for GLRenderer.
|
||||
// findbugs found that volatile thingy, though this class
|
||||
// is created before any other thread starts
|
||||
private static volatile TileManager SINGLETON;
|
||||
|
||||
public static TileManager create(MapView mapView) {
|
||||
@@ -147,27 +133,15 @@ public class TileManager { // extends GLSurfaceView {
|
||||
}
|
||||
|
||||
private TileManager(MapView mapView) {
|
||||
// super(context);
|
||||
|
||||
mMapView = mapView;
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
|
||||
// Log.d(TAG, "init GLSurfaceLayer");
|
||||
// setEGLConfigChooser(new GlConfigChooser());
|
||||
// setEGLContextClientVersion(2);
|
||||
//
|
||||
// // setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
|
||||
// mRenderer = new GLRenderer(mMapView);
|
||||
// setRenderer(mRenderer);
|
||||
//
|
||||
// // if (!debugFrameTime)
|
||||
// setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
|
||||
|
||||
mJobList = new ArrayList<JobTile>();
|
||||
mTiles = new ArrayList<MapTile>();
|
||||
mTilesLoaded = new ArrayList<MapTile>(30);
|
||||
mOverlays = new ArrayList<Overlay>(5);
|
||||
|
||||
// this is probably a good place to init these
|
||||
VertexPool.init();
|
||||
QuadTree.init();
|
||||
|
||||
@@ -191,6 +165,7 @@ public class TileManager { // extends GLSurfaceView {
|
||||
if (mMapView == null)
|
||||
return;
|
||||
|
||||
// FIXME too messy!
|
||||
if (clear || mInitial) {
|
||||
// make sure onDrawFrame is not running
|
||||
GLRenderer.drawlock.lock();
|
||||
@@ -209,10 +184,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
|
||||
QuadTree.init();
|
||||
|
||||
// TODO clear overlay items data
|
||||
mOverlays.clear();
|
||||
// mOverlays.add(new Overlay());
|
||||
|
||||
// set up TileData arrays that are passed to gl-thread
|
||||
int num = mWidth;
|
||||
if (mWidth < mHeight)
|
||||
@@ -246,11 +217,13 @@ public class TileManager { // extends GLSurfaceView {
|
||||
}
|
||||
|
||||
float s = Tile.TILE_SIZE;
|
||||
// load some additional tiles more than currently visible
|
||||
// load some tiles more than currently visible
|
||||
// TODO limit how many more...
|
||||
float scale = mapPosition.scale * 0.75f;
|
||||
float px = (float) mapPosition.x;
|
||||
float py = (float) mapPosition.y;
|
||||
|
||||
// TODO hint whether to prefetch parent / children
|
||||
int zdir = 0;
|
||||
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
@@ -258,9 +231,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
||||
}
|
||||
|
||||
// TODO all following should probably be done in an idler instead
|
||||
// to drain queued events. need to check how android handles things.
|
||||
|
||||
boolean changed = updateVisibleList(mapPosition, zdir);
|
||||
|
||||
mMapView.render();
|
||||
@@ -276,6 +246,8 @@ public class TileManager { // extends GLSurfaceView {
|
||||
}
|
||||
|
||||
public static Tiles getActiveTiles(Tiles td) {
|
||||
if (mCurrentTiles == null)
|
||||
return td;
|
||||
|
||||
if (td != null && td.serial == mUpdateCnt)
|
||||
return td;
|
||||
@@ -409,58 +381,65 @@ public class TileManager { // extends GLSurfaceView {
|
||||
|
||||
tile = QuadTree.getTile(x, y, zoomLevel);
|
||||
|
||||
if (tile == null) {
|
||||
tile = new MapTile(x, y, zoomLevel);
|
||||
QuadTree.add(tile);
|
||||
if (tile != null) {
|
||||
if (!tile.isActive())
|
||||
mJobList.add(tile);
|
||||
|
||||
mTiles.add(tile);
|
||||
mJobList.add(tile);
|
||||
tileCounter++;
|
||||
} else if (!tile.isActive()) {
|
||||
mJobList.add(tile);
|
||||
return tile;
|
||||
}
|
||||
// mNewTiles.tiles[tiles++] = tile;
|
||||
|
||||
// if (fetchChildren) {
|
||||
// byte z = (byte) (zoomLevel + 1);
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// int cx = (xx << 1) + (i % 2);
|
||||
// int cy = (yy << 1) + (i >> 1);
|
||||
//
|
||||
// MapTile c = QuadTree.getTile(cx, cy, z);
|
||||
//
|
||||
// if (c == null) {
|
||||
// c = new MapTile(cx, cy, z);
|
||||
//
|
||||
// QuadTree.add(c);
|
||||
// mTiles.add(c);
|
||||
// }
|
||||
//
|
||||
// if (!c.isActive()) {
|
||||
// mJobList.add(c);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
tile = new MapTile(x, y, zoomLevel);
|
||||
QuadTree.add(tile);
|
||||
|
||||
// if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||
mTiles.add(tile);
|
||||
mJobList.add(tile);
|
||||
tileCounter++;
|
||||
|
||||
// if (zdir > 0 && zoomLevel > 0) {
|
||||
// // prefetch parent
|
||||
// MapTile p = tile.rel.parent.tile;
|
||||
//
|
||||
// if (p == null) {
|
||||
// p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
|
||||
//
|
||||
// QuadTree.add(p);
|
||||
// mTiles.add(p);
|
||||
// mJobList.add(p);
|
||||
//
|
||||
// } else if (!p.isActive()) {
|
||||
// if (!mJobList.contains(p))
|
||||
// mJobList.add(p);
|
||||
// }
|
||||
// }
|
||||
return tile;
|
||||
|
||||
// mNewTiles.tiles[tiles++] = tile;
|
||||
// boolean fetchParent = false;
|
||||
// boolean fetchProxy = false;
|
||||
// boolean fetchChildren = false;
|
||||
// if (fetchChildren) {
|
||||
// byte z = (byte) (zoomLevel + 1);
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// int cx = (x << 1) + (i % 2);
|
||||
// int cy = (y << 1) + (i >> 1);
|
||||
//
|
||||
// MapTile c = QuadTree.getTile(cx, cy, z);
|
||||
//
|
||||
// if (c == null) {
|
||||
// c = new MapTile(cx, cy, z);
|
||||
//
|
||||
// QuadTree.add(c);
|
||||
// mTiles.add(c);
|
||||
// }
|
||||
//
|
||||
// if (!c.isActive()) {
|
||||
// mJobList.add(c);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||
// if (zdir > 0 && zoomLevel > 0) {
|
||||
// // prefetch parent
|
||||
// MapTile p = tile.rel.parent.tile;
|
||||
//
|
||||
// if (p == null) {
|
||||
// p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
|
||||
//
|
||||
// QuadTree.add(p);
|
||||
// mTiles.add(p);
|
||||
// mJobList.add(p);
|
||||
//
|
||||
// } else if (!p.isActive()) {
|
||||
// if (!mJobList.contains(p))
|
||||
// mJobList.add(p);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private static void clearTile(MapTile t) {
|
||||
@@ -492,7 +471,7 @@ public class TileManager { // extends GLSurfaceView {
|
||||
byte zoom = mapPosition.zoomLevel;
|
||||
long x = (long) mapPosition.x;
|
||||
long y = (long) mapPosition.y;
|
||||
// long center = Tile.TILE_SIZE << (zoom - 1);
|
||||
long center = Tile.TILE_SIZE << (zoom - 1);
|
||||
int diff;
|
||||
long dx, dy;
|
||||
|
||||
@@ -506,11 +485,10 @@ public class TileManager { // extends GLSurfaceView {
|
||||
if (diff == 0) {
|
||||
dx = (t.pixelX + h) - x;
|
||||
dy = (t.pixelY + h) - y;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
||||
// 0.25f;
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
|
||||
dx %= center;
|
||||
dy %= center;
|
||||
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * 0.25f;
|
||||
// t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
|
||||
} else if (diff > 0) {
|
||||
// tile zoom level is child of current
|
||||
|
||||
@@ -522,20 +500,19 @@ public class TileManager { // extends GLSurfaceView {
|
||||
dx = ((t.pixelX + h) >> (diff >> 1)) - x;
|
||||
dy = ((t.pixelY + h) >> (diff >> 1)) - y;
|
||||
}
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
|
||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy));
|
||||
dx %= center;
|
||||
dy %= center;
|
||||
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
|
||||
// t.distance = FloatMath.sqrt((dx * dx + dy * dy));
|
||||
|
||||
} else {
|
||||
// tile zoom level is parent of current
|
||||
dx = ((t.pixelX + h) << -diff) - x;
|
||||
dy = ((t.pixelY + h) << -diff) - y;
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
||||
// (-diff * 0.5f);
|
||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
|
||||
dx %= center;
|
||||
dy %= center;
|
||||
t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) * (-diff * 0.5f);
|
||||
// t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -565,10 +542,9 @@ public class TileManager { // extends GLSurfaceView {
|
||||
|
||||
for (int i = 1; i < remove; i++) {
|
||||
MapTile t = mTiles.remove(size - i);
|
||||
// synchronized (t) {
|
||||
|
||||
if (t.isLocked()) {
|
||||
// dont remove tile used by GLRenderer
|
||||
// dont remove tile used by GLRenderer, or somewhere else
|
||||
Log.d(TAG, "X not removing " + t + " " + t.distance);
|
||||
mTiles.add(t);
|
||||
} else if (t.isLoading) {
|
||||
@@ -585,7 +561,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
} else {
|
||||
clearTile(t);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +591,7 @@ public class TileManager { // extends GLSurfaceView {
|
||||
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
||||
|
||||
MapTile t = mTilesLoaded.get(i);
|
||||
// synchronized (t) {
|
||||
|
||||
if (t.isLocked()) {
|
||||
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
||||
// t.isActive);
|
||||
@@ -629,7 +604,6 @@ public class TileManager { // extends GLSurfaceView {
|
||||
mTiles.remove(t);
|
||||
clearTile(t);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,21 +624,22 @@ public class TileManager { // extends GLSurfaceView {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// synchronized (tile) {
|
||||
if (tile.vbo == null) {
|
||||
tile.vbo = BufferObject.get();
|
||||
|
||||
if (tile.vbo == null) {
|
||||
Log.d(TAG, "no VBOs left for " + tile);
|
||||
tile.isLoading = false;
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
if (tile.vbo != null) {
|
||||
// BAD Things(tm) happend...
|
||||
Log.d(TAG, "tile loaded before " + tile);
|
||||
return true;
|
||||
}
|
||||
|
||||
tile.vbo = BufferObject.get();
|
||||
|
||||
if (tile.vbo == null) {
|
||||
Log.d(TAG, "no VBOs left for " + tile);
|
||||
tile.isLoading = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
tile.newData = true;
|
||||
tile.isLoading = false;
|
||||
// }
|
||||
|
||||
mMapView.render();
|
||||
|
||||
@@ -685,23 +660,4 @@ public class TileManager { // extends GLSurfaceView {
|
||||
if (mWidth > 0 && mHeight > 0)
|
||||
mInitial = true;
|
||||
}
|
||||
|
||||
// public void setRenderTheme(RenderTheme t) {
|
||||
// if (mRenderer != null)
|
||||
// mRenderer.setRenderTheme(t);
|
||||
//
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
//
|
||||
// Log.d(TAG, "onSizeChanged" + w + " " + h);
|
||||
// mWidth = w;
|
||||
// mHeight = h;
|
||||
//
|
||||
// if (mWidth > 0 && mHeight > 0)
|
||||
// mInitial = true;
|
||||
//
|
||||
// super.onSizeChanged(w, h, oldw, oldh);
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -35,6 +35,5 @@ public abstract class Layer {
|
||||
VertexPoolItem pool;
|
||||
protected VertexPoolItem curItem;
|
||||
|
||||
protected void clear() {
|
||||
}
|
||||
abstract protected void clear();
|
||||
}
|
||||
|
||||
@@ -118,6 +118,10 @@ public class Layers {
|
||||
TextureLayer sl = (TextureLayer) l;
|
||||
sl.compile(sbuf);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
addLayerItems(sbuf, textureLayers, Layer.SYMBOL, 0);
|
||||
|
||||
}
|
||||
|
||||
private static void addLayerItems(ShortBuffer sbuf, Layer l, byte type, int pos) {
|
||||
@@ -162,14 +166,22 @@ public class Layers {
|
||||
layers = layers.next;
|
||||
}
|
||||
|
||||
while (textureLayers != null) {
|
||||
textureLayers.clear();
|
||||
Layer l = textureLayers;
|
||||
while (l != null) {
|
||||
|
||||
// TextureLayer sl = (TextureLayer) textureLayers;
|
||||
// if (sl.textures != null)
|
||||
// TextureObject.release(sl.textures);
|
||||
l.clear();
|
||||
|
||||
textureLayers = textureLayers.next;
|
||||
if (l.pool != null) {
|
||||
VertexPool.release(l.pool);
|
||||
l.pool = null;
|
||||
l.curItem = null;
|
||||
}
|
||||
|
||||
// if (l instanceof TextLayer)
|
||||
// ((TextLayer) l).clear();
|
||||
|
||||
l = l.next;
|
||||
}
|
||||
textureLayers = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,18 @@ public final class LineLayer extends Layer {
|
||||
outlines = link;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* line extrusion is based on code from GLMap
|
||||
* (https://github.com/olofsj/GLMap/) by olofsj
|
||||
*
|
||||
* @param points
|
||||
* array of points as float x_n = i, y_n = i+1
|
||||
* @param index
|
||||
* array of line indices holding the length of the individual
|
||||
* lines
|
||||
* @param closed
|
||||
* whether to connect start- and end-point
|
||||
*/
|
||||
|
||||
public void addLine(float[] points, short[] index, boolean closed) {
|
||||
float x, y, nextX, nextY, prevX, prevY;
|
||||
float a, ux, uy, vx, vy, wx, wy;
|
||||
@@ -83,7 +90,7 @@ public final class LineLayer extends Layer {
|
||||
if (length < 0)
|
||||
break;
|
||||
|
||||
// save some vertices
|
||||
// Note: just a hack to save some vertices
|
||||
if (rounded && i > 200)
|
||||
rounded = false;
|
||||
|
||||
@@ -520,4 +527,8 @@ public final class LineLayer extends Layer {
|
||||
si.used = opos;
|
||||
curItem = si;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,4 +87,7 @@ public final class PolygonLayer extends Layer {
|
||||
curItem = si;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,15 +15,55 @@
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class SymbolItem {
|
||||
private static Object lock = new Object();
|
||||
private static SymbolItem pool;
|
||||
|
||||
public static SymbolItem get() {
|
||||
synchronized (lock) {
|
||||
if (pool == null)
|
||||
return new SymbolItem();
|
||||
|
||||
SymbolItem ti = pool;
|
||||
pool = pool.next;
|
||||
|
||||
ti.next = null;
|
||||
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
|
||||
public static void release(SymbolItem ti) {
|
||||
if (ti == null)
|
||||
return;
|
||||
|
||||
synchronized (lock) {
|
||||
while (ti != null) {
|
||||
SymbolItem next = ti.next;
|
||||
|
||||
ti.drawable = null;
|
||||
ti.bitmap = null;
|
||||
|
||||
ti.next = pool;
|
||||
pool = ti;
|
||||
|
||||
ti = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SymbolItem next;
|
||||
|
||||
public Bitmap bitmap;
|
||||
public Drawable drawable;
|
||||
public float x;
|
||||
public float y;
|
||||
public boolean billboard;
|
||||
public int state;
|
||||
|
||||
// center, top, bottom, left, right, top-left...
|
||||
byte placement;
|
||||
// byte placement;
|
||||
|
||||
}
|
||||
|
||||
@@ -20,34 +20,37 @@ import org.oscim.renderer.TextureObject;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
|
||||
// TODO share one static texture for all poi map symabols
|
||||
|
||||
public final class SymbolLayer extends TextureLayer {
|
||||
private static String TAG = SymbolLayer.class.getSimpleName();
|
||||
private final static String TAG = SymbolLayer.class.getSimpleName();
|
||||
|
||||
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
||||
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||
private final static float SCALE = 8.0f;
|
||||
|
||||
private static short[] mVertices;
|
||||
|
||||
SymbolItem symbols;
|
||||
|
||||
private Canvas mCanvas;
|
||||
private Rect mRect = new Rect();
|
||||
|
||||
public SymbolLayer() {
|
||||
if (mVertices == null)
|
||||
mVertices = new short[TextureRenderer.MAX_ITEMS * 24];
|
||||
type = Layer.SYMBOL;
|
||||
fixed = true;
|
||||
mCanvas = new Canvas();
|
||||
}
|
||||
|
||||
public void addSymbol(SymbolItem item) {
|
||||
|
||||
verticesCnt += 4;
|
||||
|
||||
SymbolItem it = symbols;
|
||||
|
||||
for (; it != null; it = it.next) {
|
||||
for (SymbolItem it = symbols; it != null; it = it.next) {
|
||||
if (it.bitmap == item.bitmap) {
|
||||
// insert after same bitmap
|
||||
item.next = it.next;
|
||||
it.next = item;
|
||||
return;
|
||||
@@ -58,30 +61,77 @@ public final class SymbolLayer extends TextureLayer {
|
||||
symbols = item;
|
||||
}
|
||||
|
||||
public void addDrawable(Drawable drawable, int state, float x, float y) {
|
||||
|
||||
verticesCnt += 4;
|
||||
|
||||
SymbolItem item = SymbolItem.get();
|
||||
item.drawable = drawable;
|
||||
item.x = x;
|
||||
item.y = y;
|
||||
item.billboard = true;
|
||||
item.state = state;
|
||||
|
||||
for (SymbolItem it = symbols; it != null; it = it.next) {
|
||||
if (it.drawable == item.drawable && it.state == item.state) {
|
||||
// insert after same drawable
|
||||
item.next = it.next;
|
||||
it.next = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item.next = symbols;
|
||||
symbols = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
}
|
||||
|
||||
private final static int LBIT_MASK = 0xfffffffe;
|
||||
|
||||
// TODO ... reuse texture when only symbol position changed
|
||||
@Override
|
||||
public void compile(ShortBuffer sbuf) {
|
||||
public boolean prepare() {
|
||||
|
||||
short numIndices = 0;
|
||||
short offsetIndices = 0;
|
||||
short curIndices = 0;
|
||||
|
||||
int pos = 0;
|
||||
short buf[] = mVertices;
|
||||
int bufLen = buf.length;
|
||||
curItem = VertexPool.get();
|
||||
pool = curItem;
|
||||
VertexPoolItem si = curItem;
|
||||
|
||||
int pos = si.used;
|
||||
short buf[] = si.vertices;
|
||||
|
||||
int advanceY = 0;
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
|
||||
Canvas canvas = TextureObject.getCanvas();
|
||||
TextureObject to = TextureObject.get();
|
||||
textures = to;
|
||||
mCanvas.setBitmap(to.bitmap);
|
||||
|
||||
int maxIndices = TextureRenderer.MAX_ITEMS * TextureRenderer.INDICES_PER_SPRITE;
|
||||
|
||||
for (SymbolItem it = symbols; it != null;) {
|
||||
float width, height;
|
||||
|
||||
// add bitmap
|
||||
float width = it.bitmap.getWidth();
|
||||
float height = it.bitmap.getHeight();
|
||||
if (it.bitmap != null) {
|
||||
// add bitmap
|
||||
width = it.bitmap.getWidth();
|
||||
height = it.bitmap.getHeight();
|
||||
} else {
|
||||
width = it.drawable.getIntrinsicWidth();
|
||||
height = it.drawable.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
if (height > advanceY)
|
||||
advanceY = (int) height;
|
||||
@@ -91,43 +141,67 @@ public final class SymbolLayer extends TextureLayer {
|
||||
y += advanceY;
|
||||
advanceY = (int) (height + 0.5f);
|
||||
|
||||
if (y + height > TEXTURE_HEIGHT) {
|
||||
Log.d(TAG, "reached max symbols");
|
||||
|
||||
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||
offsetIndices = numIndices;
|
||||
|
||||
to.next = textures;
|
||||
textures = to;
|
||||
|
||||
sbuf.put(buf, 0, pos);
|
||||
pos = 0;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
advanceY = (int) height;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.drawBitmap(it.bitmap, x, y, null);
|
||||
if (y + height > TEXTURE_HEIGHT || curIndices == maxIndices) {
|
||||
Log.d(TAG, "reached max symbols: " + numIndices);
|
||||
|
||||
float hw = width / 2.0f;
|
||||
float hh = height / 2.0f;
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = curIndices;
|
||||
|
||||
short x1 = (short) (SCALE * (-hw));
|
||||
short x2 = (short) (SCALE * (hw));
|
||||
short y1 = (short) (SCALE * (hh));
|
||||
short y2 = (short) (SCALE * (-hh));
|
||||
numIndices += curIndices;
|
||||
offsetIndices = numIndices;
|
||||
curIndices = 0;
|
||||
|
||||
to.next = TextureObject.get();
|
||||
to = to.next;
|
||||
|
||||
mCanvas.setBitmap(to.bitmap);
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
advanceY = (int) height;
|
||||
}
|
||||
|
||||
if (it.bitmap != null) {
|
||||
mCanvas.drawBitmap(it.bitmap, x, y, null);
|
||||
} else {
|
||||
it.drawable.copyBounds(mRect);
|
||||
it.drawable.setBounds((int) x, (int) y, (int) (x + width), (int) (y + height));
|
||||
it.drawable.draw(mCanvas);
|
||||
it.drawable.setBounds(mRect);
|
||||
}
|
||||
|
||||
short x1, y1, x2, y2;
|
||||
|
||||
if (it.bitmap != null) {
|
||||
float hw = width / 2.0f;
|
||||
float hh = height / 2.0f;
|
||||
x1 = (short) (SCALE * (-hw));
|
||||
x2 = (short) (SCALE * (hw));
|
||||
y1 = (short) (SCALE * (hh));
|
||||
y2 = (short) (SCALE * (-hh));
|
||||
} else {
|
||||
// use drawable offsets (for marker hotspot)
|
||||
x2 = (short) (SCALE * (mRect.left));
|
||||
y2 = (short) (SCALE * (mRect.top));
|
||||
x1 = (short) (SCALE * (mRect.right));
|
||||
y1 = (short) (SCALE * (mRect.bottom));
|
||||
|
||||
}
|
||||
|
||||
short u1 = (short) (SCALE * x);
|
||||
short v1 = (short) (SCALE * y);
|
||||
short u2 = (short) (SCALE * (x + width));
|
||||
short v2 = (short) (SCALE * (y + height));
|
||||
|
||||
// add symbol items referencing the same bitmap
|
||||
// add symbol items referencing the same bitmap / drawable
|
||||
for (SymbolItem it2 = it;; it2 = it2.next) {
|
||||
|
||||
if (it2 == null || it2.bitmap != it.bitmap) {
|
||||
if (it2 == null
|
||||
// || (curIndices == maxIndices)
|
||||
|| (it.drawable != null && it2.drawable != it.drawable)
|
||||
|| (it.bitmap != null && it2.bitmap != it.bitmap)) {
|
||||
it = it2;
|
||||
break;
|
||||
}
|
||||
@@ -166,24 +240,41 @@ public final class SymbolLayer extends TextureLayer {
|
||||
buf[pos++] = v1;
|
||||
|
||||
// six elements used to draw the four vertices
|
||||
numIndices += 6;
|
||||
curIndices += TextureRenderer.INDICES_PER_SPRITE;
|
||||
|
||||
if (pos == VertexPoolItem.SIZE) {
|
||||
si.used = VertexPoolItem.SIZE;
|
||||
si = si.next = VertexPool.get();
|
||||
buf = si.vertices;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// FIXME this does not work, need to draw bitmap on next
|
||||
// texture...
|
||||
if (pos == bufLen) {
|
||||
sbuf.put(buf, 0, pos);
|
||||
pos = 0;
|
||||
}
|
||||
// if (pos == bufLen) {
|
||||
// sbuf.put(buf, 0, pos);
|
||||
// pos = 0;
|
||||
// }
|
||||
|
||||
x += width;
|
||||
}
|
||||
}
|
||||
|
||||
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = curIndices;
|
||||
|
||||
to.next = textures;
|
||||
textures = to;
|
||||
si.used = pos;
|
||||
curItem = si;
|
||||
|
||||
sbuf.put(buf, 0, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
TextureObject.release(textures);
|
||||
SymbolItem.release(symbols);
|
||||
textures = null;
|
||||
symbols = null;
|
||||
verticesCnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@ public class TextItem {
|
||||
|
||||
TextItem ti = pool;
|
||||
pool = pool.next;
|
||||
|
||||
ti.next = null;
|
||||
|
||||
return ti;
|
||||
}
|
||||
}
|
||||
@@ -73,5 +75,6 @@ public class TextItem {
|
||||
public Text text;
|
||||
public float width;
|
||||
public short x1, y1, x2, y2;
|
||||
|
||||
// public byte placement
|
||||
}
|
||||
|
||||
@@ -25,26 +25,28 @@ import android.util.Log;
|
||||
|
||||
public final class TextLayer extends TextureLayer {
|
||||
|
||||
private static String TAG = TextureLayer.class.getSimpleName();
|
||||
// private static String TAG = TextureLayer.class.getSimpleName();
|
||||
|
||||
private final static int TEXTURE_WIDTH = TextureObject.TEXTURE_WIDTH;
|
||||
private final static int TEXTURE_HEIGHT = TextureObject.TEXTURE_HEIGHT;
|
||||
private final static float SCALE = 8.0f;
|
||||
private final static int LBIT_MASK = 0xfffffffe;
|
||||
|
||||
private static short[] mVertices;
|
||||
private static int mFontPadX = 1;
|
||||
private static int mFontPadY = 1;
|
||||
|
||||
TextItem labels;
|
||||
|
||||
private Canvas mCanvas;
|
||||
|
||||
public TextItem getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public TextLayer() {
|
||||
if (mVertices == null)
|
||||
mVertices = new short[TextureRenderer.MAX_ITEMS * 24];
|
||||
type = Layer.SYMBOL;
|
||||
mCanvas = new Canvas();
|
||||
fixed = true;
|
||||
}
|
||||
|
||||
public void addText(TextItem item) {
|
||||
@@ -53,8 +55,10 @@ public final class TextLayer extends TextureLayer {
|
||||
|
||||
for (; it != null; it = it.next) {
|
||||
if (it.text == item.text) {
|
||||
// insert after text of same type
|
||||
item.next = it.next;
|
||||
it.next = item;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -64,24 +68,44 @@ public final class TextLayer extends TextureLayer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compile(ShortBuffer sbuf) {
|
||||
int numLabel = 0;
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "prepare");
|
||||
|
||||
// int numLabel = 0;
|
||||
// int numTextures = 0;
|
||||
|
||||
short numIndices = 0;
|
||||
short offsetIndices = 0;
|
||||
|
||||
int pos = 0;
|
||||
short buf[] = mVertices;
|
||||
int bufLen = buf.length;
|
||||
curItem = VertexPool.get();
|
||||
pool = curItem;
|
||||
|
||||
VertexPoolItem si = curItem;
|
||||
|
||||
int pos = si.used;
|
||||
short buf[] = si.vertices;
|
||||
|
||||
int advanceY = 0;
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float yy;
|
||||
|
||||
Canvas canvas = TextureObject.getCanvas();
|
||||
TextureObject to = TextureObject.get();
|
||||
textures = to;
|
||||
mCanvas.setBitmap(to.bitmap);
|
||||
|
||||
for (TextItem it = labels; it != null; it = it.next) {
|
||||
numLabel++;
|
||||
// numLabel++;
|
||||
|
||||
float width = it.width + 2 * mFontPadX;
|
||||
float height = (int) (it.text.fontHeight) + 2 * mFontPadY + 0.5f;
|
||||
@@ -99,33 +123,27 @@ public final class TextLayer extends TextureLayer {
|
||||
// numLabel + " "
|
||||
// + ((numIndices - offsetIndices) / 6));
|
||||
|
||||
// need to sync bitmap upload somehow???
|
||||
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = (short) (numIndices - offsetIndices);
|
||||
offsetIndices = numIndices;
|
||||
|
||||
to.next = textures;
|
||||
textures = to;
|
||||
to.next = TextureObject.get();
|
||||
to = to.next;
|
||||
|
||||
sbuf.put(buf, 0, pos);
|
||||
pos = 0;
|
||||
mCanvas.setBitmap(to.bitmap);
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
advanceY = (int) height;
|
||||
|
||||
// clear bitmap, TODO rotate two canvas to reduce the chance
|
||||
// of having upload lock draing to the canvas?
|
||||
canvas = TextureObject.getCanvas();
|
||||
// numTextures++;
|
||||
}
|
||||
}
|
||||
|
||||
yy = y + (height - 1) - it.text.fontDescent - mFontPadY;
|
||||
|
||||
if (it.text.stroke != null)
|
||||
canvas.drawText(it.string, x + it.width / 2, yy, it.text.stroke);
|
||||
mCanvas.drawText(it.string, x + it.width / 2, yy, it.text.stroke);
|
||||
|
||||
canvas.drawText(it.string, x + it.width / 2, yy, it.text.paint);
|
||||
mCanvas.drawText(it.string, x + it.width / 2, yy, it.text.paint);
|
||||
|
||||
// FIXME !!!
|
||||
if (width > TEXTURE_WIDTH)
|
||||
@@ -207,30 +225,41 @@ public final class TextLayer extends TextureLayer {
|
||||
// six indices to draw the four vertices
|
||||
numIndices += 6;
|
||||
|
||||
// FIXME this does not work, need to draw bitmap on next
|
||||
// texture...
|
||||
if (pos == bufLen) {
|
||||
Log.d(TAG, "--- reached max label per texture " + numLabel);
|
||||
sbuf.put(buf, 0, pos);
|
||||
if (pos == VertexPoolItem.SIZE) {
|
||||
si.used = VertexPoolItem.SIZE;
|
||||
si = si.next = VertexPool.get();
|
||||
buf = si.vertices;
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
// FIXME this does not work, need to draw bitmap on next
|
||||
// texture...
|
||||
// if (numLabel == TextureRenderer.MAX_ITEMS) {
|
||||
// Log.d(TAG, "--- reached max label per texture " + numLabel);
|
||||
// sbuf.put(buf, 0, pos);
|
||||
// pos = 0;
|
||||
// }
|
||||
|
||||
x += width;
|
||||
}
|
||||
|
||||
TextureObject to = TextureObject.uploadCanvas(offsetIndices, numIndices);
|
||||
to.offset = offsetIndices;
|
||||
to.vertices = (short) (numIndices - offsetIndices);
|
||||
|
||||
to.next = textures;
|
||||
textures = to;
|
||||
|
||||
sbuf.put(buf, 0, pos);
|
||||
si.used = pos;
|
||||
curItem = si;
|
||||
|
||||
// Log.d(TAG, "added labels " + numTextures + " " + numLabel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
TextureObject.release(textures);
|
||||
TextItem.release(labels);
|
||||
textures = null;
|
||||
labels = null;
|
||||
verticesCnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,13 @@ import org.oscim.renderer.TextureObject;
|
||||
|
||||
public abstract class TextureLayer extends Layer {
|
||||
public TextureObject textures;
|
||||
public boolean fixed;
|
||||
|
||||
/**
|
||||
* @param sbuf
|
||||
* buffer to add vertices
|
||||
*/
|
||||
void compile(ShortBuffer sbuf) {
|
||||
}
|
||||
abstract void compile(ShortBuffer sbuf);
|
||||
|
||||
abstract public boolean prepare();
|
||||
}
|
||||
|
||||
@@ -15,15 +15,12 @@
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
public class VertexPoolItem {
|
||||
final short[] vertices;
|
||||
final short[] vertices = new short[SIZE];
|
||||
|
||||
int used;
|
||||
VertexPoolItem next;
|
||||
|
||||
VertexPoolItem() {
|
||||
vertices = new short[SIZE];
|
||||
used = 0;
|
||||
}
|
||||
|
||||
// must be multiple of 4 (expected in LineLayer/PolygonLayer)
|
||||
static final int SIZE = 256;
|
||||
// and 24 (Texture Layer)
|
||||
static final int SIZE = 360;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
package org.oscim.renderer.overlays;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.LineLayer;
|
||||
@@ -27,13 +28,13 @@ import android.graphics.Color;
|
||||
import android.graphics.Paint.Cap;
|
||||
import android.util.Log;
|
||||
|
||||
public class OverlayGrid extends Overlay {
|
||||
public class OverlayGrid extends RenderOverlay {
|
||||
|
||||
private float[] mPoints;
|
||||
private short[] mIndex;
|
||||
private Text mText;
|
||||
|
||||
OverlayGrid(MapView mapView) {
|
||||
public OverlayGrid(MapView mapView) {
|
||||
super(mapView);
|
||||
|
||||
int size = Tile.TILE_SIZE;
|
||||
@@ -91,6 +92,8 @@ public class OverlayGrid extends Overlay {
|
||||
tl.addText(ti);
|
||||
}
|
||||
}
|
||||
tl.prepare();
|
||||
|
||||
layers.textureLayers = tl;
|
||||
}
|
||||
|
||||
@@ -107,7 +110,7 @@ public class OverlayGrid extends Overlay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
|
||||
|
||||
updateMapPosition();
|
||||
|
||||
@@ -134,6 +137,8 @@ public class OverlayGrid extends Overlay {
|
||||
ll.width = 1.5f;
|
||||
ll.addLine(mPoints, mIndex, false);
|
||||
|
||||
Log.d("...", "update labels");
|
||||
|
||||
addLabels(x, y, mCurZ);
|
||||
|
||||
newData = true;
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
*/
|
||||
package org.oscim.renderer.overlays;
|
||||
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.LineLayer;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.renderer.layer.SymbolItem;
|
||||
import org.oscim.renderer.layer.SymbolLayer;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.theme.renderinstruction.BitmapUtils;
|
||||
import org.oscim.view.MapView;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint.Cap;
|
||||
|
||||
public class OverlayTest extends Overlay {
|
||||
public class OverlayTest extends RenderOverlay {
|
||||
|
||||
TextItem labels;
|
||||
|
||||
@@ -31,15 +31,16 @@ public class OverlayTest extends Overlay {
|
||||
|
||||
private boolean first = true;
|
||||
|
||||
OverlayTest(MapView mapView) {
|
||||
public OverlayTest(MapView mapView) {
|
||||
super(mapView);
|
||||
|
||||
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||
ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||
ll.width = 2;
|
||||
float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100, -100 };
|
||||
short[] index = { (short) points.length };
|
||||
ll.addLine(points, index, false);
|
||||
// LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||
// ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||
// ll.width = 2;
|
||||
// float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100, -100 };
|
||||
// short[] index = { (short) points.length };
|
||||
// ll.addLine(points, index, false);
|
||||
|
||||
//
|
||||
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
||||
// pl.area = new Area(Color.argb(128, 255, 0, 0));
|
||||
@@ -53,30 +54,33 @@ public class OverlayTest extends Overlay {
|
||||
// short[] pindex = { (short) ppoints.length };
|
||||
// pl.addPolygon(ppoints, pindex);
|
||||
|
||||
// SymbolLayer sl = new SymbolLayer();
|
||||
// SymbolItem it = new SymbolItem();
|
||||
//
|
||||
// it.x = 0;
|
||||
// it.y = 0;
|
||||
// // billboard always faces camera
|
||||
// it.billboard = true;
|
||||
//
|
||||
// try {
|
||||
// it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||
// } catch (IOException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// sl.addSymbol(it);
|
||||
//
|
||||
// SymbolItem it2 = new SymbolItem();
|
||||
// it2.bitmap = it.bitmap;
|
||||
// it2.x = 0;
|
||||
// it2.y = 0;
|
||||
// // billboard always faces camera
|
||||
// it2.billboard = false;
|
||||
//
|
||||
// sl.addSymbol(it2);
|
||||
SymbolLayer sl = new SymbolLayer();
|
||||
SymbolItem it = new SymbolItem();
|
||||
|
||||
it.x = 0;
|
||||
it.y = 0;
|
||||
// billboard always faces camera
|
||||
it.billboard = true;
|
||||
|
||||
try {
|
||||
it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
sl.addSymbol(it);
|
||||
|
||||
SymbolItem it2 = new SymbolItem();
|
||||
it2.bitmap = it.bitmap;
|
||||
it2.x = 0;
|
||||
it2.y = 0;
|
||||
// billboard always faces camera
|
||||
it2.billboard = false;
|
||||
|
||||
sl.addSymbol(it2);
|
||||
sl.fixed = false;
|
||||
|
||||
layers.textureLayers = sl;
|
||||
|
||||
// TextLayer tl = new TextLayer();
|
||||
// Text t = Text.createText(20, 2, Color.WHITE, Color.BLACK, false);
|
||||
@@ -92,14 +96,16 @@ public class OverlayTest extends Overlay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
|
||||
// keep position constant (or update layer relative to new position)
|
||||
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
//mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
|
||||
if (first) {
|
||||
// fix at initial position
|
||||
// mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
updateMapPosition();
|
||||
|
||||
first = false;
|
||||
((SymbolLayer) (layers.textureLayers)).prepare();
|
||||
|
||||
// pass layers to be uploaded and drawn to GL Thread
|
||||
// afterwards never modify 'layers' outside of this function!
|
||||
|
||||
@@ -17,8 +17,8 @@ package org.oscim.renderer.overlays;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.TileManager;
|
||||
import org.oscim.renderer.MapTile;
|
||||
import org.oscim.renderer.TileManager;
|
||||
import org.oscim.renderer.Tiles;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.renderer.layer.TextLayer;
|
||||
@@ -29,20 +29,23 @@ import org.oscim.view.MapView;
|
||||
import android.os.SystemClock;
|
||||
import android.util.FloatMath;
|
||||
|
||||
public class OverlayText extends Overlay {
|
||||
public class OverlayText extends RenderOverlay {
|
||||
|
||||
private Tiles tiles;
|
||||
private LabelThread mThread;
|
||||
/* package */boolean mRun;
|
||||
/* package */boolean mRerun;
|
||||
|
||||
private MapPosition mWorkPos;
|
||||
private TextLayer mWorkLayer;
|
||||
private TextLayer mNewLayer;
|
||||
|
||||
/* package */boolean mRun;
|
||||
/* package */boolean mRerun;
|
||||
|
||||
class LabelThread extends PausableThread {
|
||||
|
||||
@Override
|
||||
protected void doWork() {
|
||||
SystemClock.sleep(250);
|
||||
SystemClock.sleep(300);
|
||||
mRun = false;
|
||||
updateLabels();
|
||||
mMapView.redrawMap();
|
||||
@@ -70,14 +73,29 @@ public class OverlayText extends Overlay {
|
||||
void updateLabels() {
|
||||
tiles = TileManager.getActiveTiles(tiles);
|
||||
|
||||
// Log.d("...", "relabel " + mRerun + " " + x + " " + y);
|
||||
if (tiles.cnt == 0)
|
||||
return;
|
||||
|
||||
mMapView.getMapViewPosition().getMapPosition(mWorkPos, null);
|
||||
|
||||
// TODO tiles might be from another zoomlevel than the current:
|
||||
TextLayer tl = mWorkLayer;
|
||||
|
||||
if (tl == null)
|
||||
tl = new TextLayer();
|
||||
|
||||
// tiles might be from another zoomlevel than the current:
|
||||
// this scales MapPosition to the zoomlevel of tiles...
|
||||
// TODO create a helper function in MapPosition
|
||||
int diff = tiles.tiles[0].zoomLevel - mWorkPos.zoomLevel;
|
||||
|
||||
if (diff > 1 || diff < -2) {
|
||||
synchronized (this) {
|
||||
mNewLayer = tl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float div = FastMath.pow(diff);
|
||||
|
||||
// fix map position to tile coordinates
|
||||
@@ -89,14 +107,11 @@ public class OverlayText extends Overlay {
|
||||
mWorkPos.zoomLevel += diff;
|
||||
mWorkPos.scale = div;
|
||||
|
||||
// Log.d("...", "relabel " + mRerun + " " + x + " " + y);
|
||||
|
||||
TextLayer tl = new TextLayer();
|
||||
|
||||
float angle = (float) Math.toRadians(mWorkPos.angle);
|
||||
float cos = FloatMath.cos(angle);
|
||||
float sin = FloatMath.sin(angle);
|
||||
|
||||
// TODO more sophisticated placement :)
|
||||
for (int i = 0, n = tiles.cnt; i < n; i++) {
|
||||
MapTile t = tiles.tiles[i];
|
||||
if (!t.isVisible)
|
||||
@@ -104,7 +119,6 @@ public class OverlayText extends Overlay {
|
||||
|
||||
int dx = (t.tileX - x) * Tile.TILE_SIZE;
|
||||
int dy = (t.tileY - y) * Tile.TILE_SIZE;
|
||||
// Log.d("...", "update tiles " + dx + " " + dy);
|
||||
|
||||
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
|
||||
|
||||
@@ -129,20 +143,27 @@ public class OverlayText extends Overlay {
|
||||
}
|
||||
}
|
||||
|
||||
// draw text to bitmaps and create vertices
|
||||
tl.prepare();
|
||||
|
||||
// everything synchronized?
|
||||
synchronized (this) {
|
||||
mWorkLayer = tl;
|
||||
mNewLayer = tl;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
|
||||
// Log.d("...", "update " + tilesChanged + " " + positionChanged);
|
||||
|
||||
if (mWorkLayer != null) {
|
||||
if (mNewLayer != null) {
|
||||
|
||||
// keep text layer, not recrating its canvas each time...
|
||||
mWorkLayer = (TextLayer) layers.textureLayers;
|
||||
layers.clear();
|
||||
layers.textureLayers = mWorkLayer;
|
||||
mWorkLayer = null;
|
||||
|
||||
layers.textureLayers = mNewLayer;
|
||||
mNewLayer = null;
|
||||
|
||||
// make the 'labeled' MapPosition current
|
||||
MapPosition tmp = mMapPosition;
|
||||
@@ -154,7 +175,6 @@ public class OverlayText extends Overlay {
|
||||
}
|
||||
|
||||
if (tilesChanged || positionChanged) {
|
||||
|
||||
if (!mRun) {
|
||||
mRun = true;
|
||||
synchronized (mThread) {
|
||||
|
||||
@@ -28,12 +28,14 @@ import org.oscim.view.MapView;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.Matrix;
|
||||
import android.util.Log;
|
||||
|
||||
public abstract class Overlay {
|
||||
public abstract class RenderOverlay {
|
||||
|
||||
protected final MapView mMapView;
|
||||
// keep the Position for which the Overlay is rendered
|
||||
protected MapPosition mMapPosition;
|
||||
|
||||
// current Layers to draw
|
||||
public final Layers layers;
|
||||
|
||||
// flag to set when data is ready for (re)compilation.
|
||||
@@ -44,19 +46,14 @@ public abstract class Overlay {
|
||||
|
||||
public BufferObject vbo;
|
||||
|
||||
public Overlay(MapView mapView) {
|
||||
public RenderOverlay(MapView mapView) {
|
||||
mMapView = mapView;
|
||||
mMapPosition = new MapPosition();
|
||||
layers = new Layers();
|
||||
}
|
||||
|
||||
synchronized boolean onTouch(boolean down) {
|
||||
Log.d("...", "Overlay handle onTouch " + down);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* update mMapPosition
|
||||
* Utility: update mMapPosition
|
||||
*
|
||||
* @return true if position has changed
|
||||
*/
|
||||
@@ -68,12 +65,13 @@ public abstract class Overlay {
|
||||
// use synchronized (this){} when updating 'layers' from another thread
|
||||
|
||||
/**
|
||||
* @param curPos TODO
|
||||
* @param positionChanged
|
||||
* true when MapPosition has changed
|
||||
* @param tilesChanged
|
||||
* true when loaded tiles changed
|
||||
*/
|
||||
public synchronized void update(boolean positionChanged, boolean tilesChanged) {
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
|
||||
// // keep position constant (or update layer relative to new position)
|
||||
// mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
//
|
||||
@@ -110,23 +108,20 @@ public abstract class Overlay {
|
||||
// float scale = curPos.scale / div;
|
||||
|
||||
for (Layer l = layers.textureLayers; l != null;) {
|
||||
|
||||
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv,
|
||||
layers.texOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private float setMatrix(MapPosition curPos, float[] matrix) {
|
||||
// TODO if oPos == curPos this could be simplified
|
||||
|
||||
MapPosition oPos = mMapPosition;
|
||||
|
||||
byte z = oPos.zoomLevel;
|
||||
// int diff = curPos.zoomLevel - z;
|
||||
float div = FastMath.pow(z - curPos.zoomLevel);
|
||||
// if (diff < 0)
|
||||
// div = (1 << -diff);
|
||||
// else if (diff > 0)
|
||||
// div = (1.0f / (1 << diff));
|
||||
|
||||
float div = FastMath.pow(z - curPos.zoomLevel);
|
||||
float x = (float) (oPos.x - curPos.x * div);
|
||||
float y = (float) (oPos.y - curPos.y * div);
|
||||
|
||||
@@ -145,8 +140,8 @@ public abstract class Overlay {
|
||||
matrix[12] = x * scale;
|
||||
matrix[13] = y * scale;
|
||||
|
||||
// scale to current tile world coordinates
|
||||
scale = (curPos.scale / oPos.scale) / div;
|
||||
// scale to tile to world coordinates
|
||||
scale /= GLRenderer.COORD_MULTIPLIER;
|
||||
matrix[0] = scale;
|
||||
matrix[5] = scale;
|
||||
Reference in New Issue
Block a user