refactor: dont pass matrices with MapPosition -> use GLRender.Matrices

This commit is contained in:
Hannes Janetzek 2013-02-15 16:56:13 +01:00
parent 811ff6ed4a
commit 55030c1166
17 changed files with 362 additions and 272 deletions

View File

@ -15,7 +15,6 @@
*/ */
package org.oscim.core; package org.oscim.core;
import android.opengl.Matrix;
/** A MapPosition Container. */ /** A MapPosition Container. */
public class MapPosition { public class MapPosition {
@ -31,11 +30,6 @@ public class MapPosition {
public double x; public double x;
public double y; public double y;
public float[] viewMatrix;
// // DO NOT MODIFY! shared with MapViewPosition
// public float[] projMatrix;
public MapPosition() { public MapPosition() {
this.zoomLevel = (byte) 1; this.zoomLevel = (byte) 1;
this.scale = 1; this.scale = 1;
@ -46,15 +40,6 @@ public class MapPosition {
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel); this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
} }
// FIXME remove this here
public void init() {
viewMatrix = new float[16];
Matrix.setIdentityM(viewMatrix, 0);
//
// rotateMatrix = new float[16];
// Matrix.setIdentityM(rotateMatrix, 0);
}
// public Point geopointToMap(GeoPoint in, Point reuse) { // public Point geopointToMap(GeoPoint in, Point reuse) {
// Point out = reuse == null ? new Point() : reuse; // Point out = reuse == null ? new Point() : reuse;
// out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), zoomLevel) - x); // out.x = (int) (MercatorProjection.longitudeToPixelX(in.getLongitude(), zoomLevel) - x);

View File

@ -73,9 +73,9 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
class ItemOverlay extends BasicOverlay { class ItemOverlay extends BasicOverlay {
private SymbolLayer mSymbolLayer; private final SymbolLayer mSymbolLayer;
private float[] mMvp = new float[16]; private final float[] mMvp = new float[16];
private float[] mVec = new float[4]; private final float[] mVec = new float[4];
public ItemOverlay(MapView mapView) { public ItemOverlay(MapView mapView) {
super(mapView); super(mapView);
@ -84,7 +84,8 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
// note: this is called from GL-Thread. so check your syncs! // note: this is called from GL-Thread. so check your syncs!
@Override @Override
public synchronized void update(MapPosition curPos, boolean positionChanged, public synchronized void update(MapPosition curPos,
boolean positionChanged,
boolean tilesChanged) { boolean tilesChanged) {
if (!tilesChanged && !mUpdate) if (!tilesChanged && !mUpdate)
@ -97,7 +98,7 @@ public abstract class ItemizedOverlay<Item extends OverlayItem> extends Overlay
int my = (int) curPos.y; int my = (int) curPos.y;
// TODO could pass mvp as param // TODO could pass mvp as param
mMapView.getMapViewPosition().getMVP(mMvp); mMapView.getMapViewPosition().getMatrix(null, null, mMvp);
float[] matrix = mMvp; float[] matrix = mMvp;
float[] vec = mVec; float[] vec = mVec;

View File

@ -25,6 +25,7 @@ import org.oscim.renderer.layer.Layer;
import org.oscim.renderer.layer.LineLayer; import org.oscim.renderer.layer.LineLayer;
import org.oscim.renderer.overlays.BasicOverlay; import org.oscim.renderer.overlays.BasicOverlay;
import org.oscim.theme.renderinstruction.Line; import org.oscim.theme.renderinstruction.Line;
import org.oscim.utils.FastMath;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import android.content.Context; import android.content.Context;
@ -52,10 +53,10 @@ public class PathOverlay extends Overlay {
// projected points // projected points
private float[] mPPoints; private float[] mPPoints;
private short[] mIndex; private final short[] mIndex;
private int mSize; private int mSize;
private Line mLine; private final Line mLine;
// limit coords // limit coords
private final int max = 2048; private final int max = 2048;
@ -70,7 +71,8 @@ public class PathOverlay extends Overlay {
// note: this is called from GL-Thread. so check your syncs! // note: this is called from GL-Thread. so check your syncs!
// TODO use an Overlay-Thread to build up layers (like for Labeling) // TODO use an Overlay-Thread to build up layers (like for Labeling)
@Override @Override
public synchronized void update(MapPosition curPos, boolean positionChanged, public synchronized void update(MapPosition curPos,
boolean positionChanged,
boolean tilesChanged) { boolean tilesChanged) {
if (!tilesChanged && !mUpdatePoints) if (!tilesChanged && !mUpdatePoints)
@ -144,7 +146,7 @@ public class PathOverlay extends Overlay {
// skip too near points // skip too near points
int dx = x - px; int dx = x - px;
int dy = y - py; int dy = y - py;
if ((i == 0) || dx > MIN_DIST || dx < -MIN_DIST || dy > MIN_DIST || dy < -MIN_DIST) { if ((i == 0) || FastMath.absMaxCmp(dx, dy, MIN_DIST)) {
projected[i + 0] = px = x; projected[i + 0] = px = x;
projected[i + 1] = py = y; projected[i + 1] = py = y;
i += 2; i += 2;

View File

@ -19,6 +19,7 @@ import static android.opengl.GLES20.glStencilMask;
import static org.oscim.generator.JobTile.STATE_READY; import static org.oscim.generator.JobTile.STATE_READY;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layer;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
@ -49,10 +50,10 @@ public class BaseMap {
mfProjMatrix[14] = 0; mfProjMatrix[14] = 0;
} }
static void draw(MapTile[] tiles, int tileCnt, MapPosition pos) { static void draw(MapTile[] tiles, int tileCnt, MapPosition pos, Matrices m) {
mDrawCnt = 0; mDrawCnt = 0;
Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, pos.viewMatrix, 0); Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, m.view, 0);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);

View File

@ -74,12 +74,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// bytes currently loaded in VBOs // bytes currently loaded in VBOs
private static int mBufferMemoryUsage; private static int mBufferMemoryUsage;
private static float[] mMVPMatrix = new float[16];
private static float[] mProjMatrix = new float[16];
private static float[] mTmpMatrix = new float[16];
private static float[] mTileCoords = new float[8]; private static float[] mTileCoords = new float[8];
private static float[] mDebugCoords = new float[8]; private static float[] mDebugCoords = new float[8];
public class Matrices {
public final float[] viewproj = new float[16];
public final float[] proj = new float[16];
public final float[] view = new float[16];
// for temporary use by callee
public final float[] mvp = new float[16];
}
private static Matrices mMatrices;
//private //private
static float[] mClearColor = null; static float[] mClearColor = null;
private static boolean mUpdateColor = false; private static boolean mUpdateColor = false;
@ -171,9 +180,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mMapView = mapView; mMapView = mapView;
mMapViewPosition = mapView.getMapViewPosition(); mMapViewPosition = mapView.getMapViewPosition();
mMapPosition = new MapPosition(); mMapPosition = new MapPosition();
mMapPosition.init();
Matrix.setIdentityM(mMVPMatrix, 0); //Matrix.setIdentityM(mMVPMatrix, 0);
mMatrices = new Matrices();
// add half pixel to tile clip/fill coordinates to avoid rounding issues // add half pixel to tile clip/fill coordinates to avoid rounding issues
short min = -4; short min = -4;
@ -366,7 +375,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// coordinates) // coordinates)
MapPosition pos = mMapPosition; MapPosition pos = mMapPosition;
float[] coords = mTileCoords; float[] coords = mTileCoords;
boolean changed = mMapViewPosition.getMapPosition(pos, coords); boolean changed;
synchronized(mMapViewPosition){
changed = mMapViewPosition.getMapPosition(pos);
mMapViewPosition.getMapViewProjection(coords);
mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj);
}
int tileCnt = mDrawTiles.cnt; int tileCnt = mDrawTiles.cnt;
MapTile[] tiles = mDrawTiles.tiles; MapTile[] tiles = mDrawTiles.tiles;
@ -455,7 +469,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
overlays.get(i).update(mMapPosition, changed, tilesChanged); overlays.get(i).update(mMapPosition, changed, tilesChanged);
/* draw base layer */ /* draw base layer */
BaseMap.draw(tiles, tileCnt, pos); BaseMap.draw(tiles, tileCnt, pos, mMatrices);
/* draw overlays */ /* draw overlays */
for (int i = 0, n = overlays.size(); i < n; i++) { for (int i = 0, n = overlays.size(); i < n; i++) {
@ -466,7 +480,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
renderOverlay.newData = false; renderOverlay.newData = false;
} }
if (renderOverlay.isReady) if (renderOverlay.isReady)
renderOverlay.render(mMapPosition, mMVPMatrix, mProjMatrix); renderOverlay.render(mMapPosition, mMatrices);
} }
if (MapView.debugFrameTime) { if (MapView.debugFrameTime) {
@ -490,15 +504,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mDebugCoords[6] = max; mDebugCoords[6] = max;
mDebugCoords[7] = -ymax; mDebugCoords[7] = -ymax;
PolygonRenderer.debugDraw(mProjMatrix, mDebugCoords, 0); PolygonRenderer.debugDraw(mMatrices.proj, mDebugCoords, 0);
pos.zoomLevel = -1; pos.zoomLevel = -1;
mMapViewPosition.getMapPosition(pos, mDebugCoords); mMapViewPosition.getMapViewProjection(mDebugCoords);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, PolygonRenderer.debugDraw(mMatrices.viewproj, mDebugCoords, 1);
pos.viewMatrix, 0);
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
} }
@ -560,32 +571,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
GLES20.glScissor(0, 0, mWidth, mHeight); mMapViewPosition.getMatrix(null, mMatrices.proj, null);
float s = MapViewPosition.VIEW_SCALE;
float aspect = mHeight / (float) mWidth;
Matrix.frustumM(mProjMatrix, 0, -s, s,
aspect * s, -aspect * s, MapViewPosition.VIEW_NEAR,
MapViewPosition.VIEW_FAR);
Matrix.setIdentityM(mTmpMatrix, 0);
Matrix.translateM(mTmpMatrix, 0, 0, 0, -MapViewPosition.VIEW_DISTANCE);
Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mTmpMatrix, 0);
if (debugView) { if (debugView) {
// modify this to scale only the view, to see better which tiles are // modify this to scale only the view, to see better which tiles are
// rendered // rendered
Matrix.setIdentityM(mMVPMatrix, 0); Matrix.setIdentityM(mMatrices.mvp, 0);
Matrix.scaleM(mMVPMatrix, 0, 0.5f, 0.5f, 1); Matrix.scaleM(mMatrices.mvp, 0, 0.5f, 0.5f, 1);
Matrix.multiplyMM(mProjMatrix, 0, mMVPMatrix, 0, mProjMatrix, 0); Matrix.multiplyMM(mMatrices.proj, 0, mMatrices.mvp, 0, mMatrices.proj, 0);
} }
BaseMap.setProjection(mProjMatrix); BaseMap.setProjection(mMatrices.proj);
GLES20.glViewport(0, 0, width, height); GLES20.glViewport(0, 0, width, height);
//GLES20.glScissor(0, 0, width, height); GLES20.glScissor(0, 0, width, height);
//GLES20.glEnable(GLES20.GL_SCISSOR_TEST); GLES20.glEnable(GLES20.GL_SCISSOR_TEST);
GLES20.glClearStencil(0x00); GLES20.glClearStencil(0x00);

View File

@ -29,6 +29,7 @@ import org.oscim.generator.TileDistanceSort;
import org.oscim.renderer.layer.TextItem; import org.oscim.renderer.layer.TextItem;
import org.oscim.renderer.layer.VertexPool; import org.oscim.renderer.layer.VertexPool;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
import android.util.Log; import android.util.Log;
@ -49,6 +50,7 @@ public class TileManager {
private static final int CACHE_THRESHOLD = 30; private static final int CACHE_THRESHOLD = 30;
private final MapView mMapView; private final MapView mMapView;
private final MapViewPosition mMapViewPosition;
private final MapPosition mMapPosition; private final MapPosition mMapPosition;
private boolean mInitialized; private boolean mInitialized;
private int mWidth = 0; private int mWidth = 0;
@ -82,7 +84,7 @@ public class TileManager {
public TileManager(MapView mapView) { public TileManager(MapView mapView) {
mMapView = mapView; mMapView = mapView;
mMapViewPosition = mapView.getMapViewPosition();
mMapPosition = new MapPosition(); mMapPosition = new MapPosition();
mJobs = new ArrayList<JobTile>(); mJobs = new ArrayList<JobTile>();
mTiles = new MapTile[GLRenderer.CACHE_TILES]; mTiles = new MapTile[GLRenderer.CACHE_TILES];
@ -159,7 +161,11 @@ public class TileManager {
MapPosition mapPosition = mMapPosition; MapPosition mapPosition = mMapPosition;
float[] coords = mTileCoords; float[] coords = mTileCoords;
changedPos = mMapView.getMapViewPosition().getMapPosition(mapPosition, coords);
synchronized(mMapViewPosition){
changedPos = mMapViewPosition.getMapPosition(mapPosition);
mMapViewPosition.getMapViewProjection(coords);
}
if (changedPos) { if (changedPos) {
mMapView.render(); mMapView.render();

View File

@ -17,6 +17,7 @@ package org.oscim.renderer.overlays;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.renderer.BufferObject; import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.renderer.LineRenderer; import org.oscim.renderer.LineRenderer;
import org.oscim.renderer.PolygonRenderer; import org.oscim.renderer.PolygonRenderer;
@ -27,7 +28,6 @@ import org.oscim.utils.FastMath;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.Matrix;
// Base class to use the Layers drawing 'API' // Base class to use the Layers drawing 'API'
public abstract class BasicOverlay extends RenderOverlay { public abstract class BasicOverlay extends RenderOverlay {
@ -47,25 +47,33 @@ public abstract class BasicOverlay extends RenderOverlay {
* use synchronized when modifying layers * use synchronized when modifying layers
*/ */
@Override @Override
public synchronized void render(MapPosition pos, float[] mv, float[] proj) { public synchronized void render(MapPosition pos, Matrices m) {
setMatrix(pos, mv);
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0); float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
GLState.test(false, false); GLState.test(false, false);
for (Layer l = layers.layers; l != null;) { if (layers.layers != null) {
if (l.type == Layer.POLYGON) { setMatrix(pos, m, true);
l = PolygonRenderer.draw(pos, l, mvp, true, false);
} else { for (Layer l = layers.layers; l != null;) {
l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset); if (l.type == Layer.POLYGON) {
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
} else {
l = LineRenderer.draw(pos, l, m.mvp, div, 0, layers.lineOffset);
}
} }
} }
for (Layer l = layers.textureLayers; l != null;) { if (layers.textureLayers != null) {
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv); setMatrix(pos, m, false);
float scale = (mMapPosition.scale / pos.scale) * div;
for (Layer l = layers.textureLayers; l != null;) {
l = TextureRenderer.draw(l, scale, m.proj, m.mvp);
}
} }
} }

View File

@ -21,6 +21,7 @@ import java.nio.ShortBuffer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.renderer.layer.VertexPool; import org.oscim.renderer.layer.VertexPool;
import org.oscim.renderer.layer.VertexPoolItem; import org.oscim.renderer.layer.VertexPoolItem;
@ -58,7 +59,7 @@ public class BuildingOverlay extends RenderOverlay {
private VertexPoolItem mVertices, mCurVertices; private VertexPoolItem mVertices, mCurVertices;
private VertexPoolItem mIndices[], mCurIndices[]; private VertexPoolItem mIndices[], mCurIndices[];
private int mIndiceCnt[] = { 0, 0, 0 }; private final int mIndiceCnt[] = { 0, 0, 0 };
private void addOutline(float[] points, float height) { private void addOutline(float[] points, float height) {
int len = points.length; int len = points.length;
@ -338,21 +339,19 @@ public class BuildingOverlay extends RenderOverlay {
mNumVertices * 4 * 2, sbuf, GLES20.GL_STATIC_DRAW); mNumVertices * 4 * 2, sbuf, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); mMapView.getMapViewPosition().getMapPosition(mMapPosition);
// tell GLRenderer to call 'render' // tell GLRenderer to call 'render'
isReady = true; isReady = true;
} }
@Override @Override
public synchronized void render(MapPosition pos, float[] mv, float[] proj) { public synchronized void render(MapPosition pos, Matrices m) {
setMatrix(pos, m);
setMatrix(pos, mv);
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
GLState.useProgram(buildingProgram); GLState.useProgram(buildingProgram);
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, m.mvp, 0);
GLES20.glUniform4f(hBuildingColor, 0.5f, 0.5f, 0.5f, 0.7f); GLES20.glUniform4f(hBuildingColor, 0.5f, 0.5f, 0.5f, 0.7f);
GLState.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition); GLState.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition);
@ -413,7 +412,7 @@ public class BuildingOverlay extends RenderOverlay {
} }
@Override @Override
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m) {
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
@ -432,19 +431,19 @@ public class BuildingOverlay extends RenderOverlay {
float scale = curPos.scale / div; float scale = curPos.scale / div;
Matrix.setIdentityM(matrix, 0); Matrix.setIdentityM(m.mvp, 0);
// translate relative to map center // translate relative to map center
matrix[12] = x * scale; m.mvp[12] = x * scale;
matrix[13] = y * scale; m.mvp[13] = y * scale;
// scale to current tile world coordinates // scale to current tile world coordinates
scale = (curPos.scale / oPos.scale) / div; scale = (curPos.scale / oPos.scale) / div;
scale /= GLRenderer.COORD_MULTIPLIER; scale /= GLRenderer.COORD_MULTIPLIER;
matrix[0] = scale; m.mvp[0] = scale;
matrix[5] = scale; m.mvp[5] = scale;
matrix[10] = scale / 1000f; m.mvp[10] = scale / 1000f;
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0);
} }
final static String buildingVertexShader = "" final static String buildingVertexShader = ""

View File

@ -19,12 +19,12 @@ import java.nio.ByteOrder;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.Matrix;
/* /*
* This is an example how to integrate custom OpenGL drawing routines as map overlay * This is an example how to integrate custom OpenGL drawing routines as map overlay
@ -84,7 +84,7 @@ public class CustomOverlay extends RenderOverlay {
} }
@Override @Override
public void render(MapPosition pos, float[] tmp, float[] proj) { public void render(MapPosition pos, Matrices m) {
// Use the program object // Use the program object
GLState.useProgram(mProgramObject); GLState.useProgram(mProgramObject);
@ -106,12 +106,14 @@ public class CustomOverlay extends RenderOverlay {
/* apply view and projection matrices */ /* apply view and projection matrices */
// set mvp (tmp) matrix relative to mMapPosition // set mvp (tmp) matrix relative to mMapPosition
// i.e. fixed on the map // i.e. fixed on the map
setMatrix(pos, tmp); setMatrix(pos, m);
Matrix.multiplyMM(tmp, 0, proj, 0, tmp, 0);
//Matrix.multiplyMM(tmp, 0, proj, 0, tmp, 0);
// or set mvp matrix fixed on screen center // or set mvp matrix fixed on screen center
// Matrix.multiplyMM(tmp, 0, proj, 0, pos.viewMatrix, 0); // Matrix.multiplyMM(tmp, 0, proj, 0, pos.viewMatrix, 0);
GLES20.glUniformMatrix4fv(hMatrixPosition, 1, false, tmp, 0); GLES20.glUniformMatrix4fv(hMatrixPosition, 1, false, m.mvp, 0);
// Draw the triangle // Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

View File

@ -21,6 +21,7 @@ import java.nio.ShortBuffer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.generator.JobTile; import org.oscim.generator.JobTile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.renderer.MapTile; import org.oscim.renderer.MapTile;
import org.oscim.renderer.TileSet; import org.oscim.renderer.TileSet;
@ -54,7 +55,7 @@ public class ExtrusionOverlay extends RenderOverlay {
private boolean initialized = false; private boolean initialized = false;
// FIXME sum up size used while filling layer only up to: // FIXME sum up size used while filling layer only up to:
private int BUFFERSIZE = 65536 * 2; private final int BUFFERSIZE = 65536 * 2;
private TileSet mTileSet; private TileSet mTileSet;
private ShortBuffer mShortBuffer; private ShortBuffer mShortBuffer;
private MapTile[] mTiles; private MapTile[] mTiles;
@ -64,7 +65,7 @@ public class ExtrusionOverlay extends RenderOverlay {
public void update(MapPosition curPos, boolean positionChanged, public void update(MapPosition curPos, boolean positionChanged,
boolean tilesChanged) { boolean tilesChanged) {
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); mMapView.getMapViewPosition().getMapPosition(mMapPosition);
if (!initialized) { if (!initialized) {
initialized = true; initialized = true;
@ -155,16 +156,16 @@ public class ExtrusionOverlay extends RenderOverlay {
return null; return null;
} }
private boolean debug = false; private final boolean debug = false;
private final float[] mVPMatrix = new float[16]; //private final float[] mVPMatrix = new float[16];
@Override @Override
public void render(MapPosition pos, float[] mv, float[] proj) { public void render(MapPosition pos, Matrices m) {
// TODO one could render in one pass to texture and then draw the texture // TODO one could render in one pass to texture and then draw the texture
// with alpha... might be faster. // with alpha... might be faster.
Matrix.multiplyMM(mVPMatrix, 0, proj, 0, pos.viewMatrix, 0); //Matrix.multiplyMM(mVPMatrix, 0, proj, 0, pos.viewMatrix, 0);
proj = mVPMatrix; //proj = mVPMatrix;
MapTile[] tiles = mTiles; MapTile[] tiles = mTiles;
@ -190,8 +191,8 @@ public class ExtrusionOverlay extends RenderOverlay {
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mTileCnt; i++) {
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers; ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
setMatrix(pos, mv, proj, tiles[i], div, 0); setMatrix(pos, m, tiles[i], div, 0);
GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
@ -242,8 +243,8 @@ public class ExtrusionOverlay extends RenderOverlay {
MapTile t = tiles[i]; MapTile t = tiles[i];
ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers; ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers;
int d = GLRenderer.depthOffset(t) * 10; int d = GLRenderer.depthOffset(t) * 10;
setMatrix(pos, mv, proj, t, div, d); setMatrix(pos, m, t, div, d);
GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
@ -268,8 +269,8 @@ public class ExtrusionOverlay extends RenderOverlay {
GLES20.glDepthFunc(GLES20.GL_EQUAL); GLES20.glDepthFunc(GLES20.GL_EQUAL);
int d = GLRenderer.depthOffset(t) * 10; int d = GLRenderer.depthOffset(t) * 10;
setMatrix(pos, mv, proj, t, div, d); setMatrix(pos, m, t, div, d);
GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
@ -298,8 +299,8 @@ public class ExtrusionOverlay extends RenderOverlay {
// drawing gl_lines with the same coordinates does not result in // drawing gl_lines with the same coordinates does not result in
// same depth values as polygons, so add offset and draw gl_lequal: // same depth values as polygons, so add offset and draw gl_lequal:
GLES20.glDepthFunc(GLES20.GL_LEQUAL); GLES20.glDepthFunc(GLES20.GL_LEQUAL);
GlUtils.addOffsetM(mv, 100); GlUtils.addOffsetM(m.mvp, 100);
GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0);
GLES20.glUniform1i(uExtMode, 3); GLES20.glUniform1i(uExtMode, 3);
GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3], GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3],
@ -315,20 +316,20 @@ public class ExtrusionOverlay extends RenderOverlay {
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
} }
private static void setMatrix(MapPosition mapPosition, float[] matrix, float[] proj, private static void setMatrix(MapPosition mapPosition, Matrices m,
MapTile tile, float div, int delta) { MapTile tile, float div, int delta) {
float x = (float) (tile.pixelX - mapPosition.x * div); float x = (float) (tile.pixelX - mapPosition.x * div);
float y = (float) (tile.pixelY - mapPosition.y * div); float y = (float) (tile.pixelY - mapPosition.y * div);
float scale = mapPosition.scale / div; float scale = mapPosition.scale / div;
GlUtils.setTileMatrix(matrix, x, y, scale); GlUtils.setTileMatrix(m.mvp, x, y, scale);
// scale height // scale height
matrix[10] = scale / (1000f * GLRenderer.COORD_MULTIPLIER); m.mvp[10] = scale / (1000f * GLRenderer.COORD_MULTIPLIER);
Matrix.multiplyMM(matrix, 0, proj, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0);
GlUtils.addOffsetM(matrix, delta); GlUtils.addOffsetM(m.mvp, delta);
} }
private final float _a = 0.86f; private final float _a = 0.86f;

View File

@ -22,6 +22,7 @@ import java.nio.ShortBuffer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
@ -160,17 +161,16 @@ public class ModelOverlay extends RenderOverlay {
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 64 * 4, fbuf, GLES20.GL_STATIC_DRAW); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 64 * 4, fbuf, GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); mMapView.getMapViewPosition().getMapPosition(mMapPosition);
// tell GLRenderer to call 'render' // tell GLRenderer to call 'render'
isReady = true; isReady = true;
} }
@Override @Override
public synchronized void render(MapPosition pos, float[] mv, float[] proj) { public synchronized void render(MapPosition pos, Matrices m) {
setMatrix(pos, mv); setMatrix(pos, m);
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
GLState.useProgram(polygonProgram); GLState.useProgram(polygonProgram);
@ -182,7 +182,7 @@ public class ModelOverlay extends RenderOverlay {
GLES20.glVertexAttribPointer(hPolygonVertexPosition, 3, GLES20.GL_FLOAT, false, 16, 0); GLES20.glVertexAttribPointer(hPolygonVertexPosition, 3, GLES20.GL_FLOAT, false, 16, 0);
GLES20.glVertexAttribPointer(hPolygonLightPosition, 1, GLES20.GL_FLOAT, false, 16, 12); GLES20.glVertexAttribPointer(hPolygonLightPosition, 1, GLES20.GL_FLOAT, false, 16, 12);
GLES20.glUniformMatrix4fv(hPolygonMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(hPolygonMatrix, 1, false, m.mvp, 0);
GLES20.glUniform4f(hPolygonColor, 0.5f, 0.5f, 0.5f, 0.7f); GLES20.glUniform4f(hPolygonColor, 0.5f, 0.5f, 0.5f, 0.7f);
// draw to depth buffer // draw to depth buffer
@ -211,7 +211,7 @@ public class ModelOverlay extends RenderOverlay {
} }
@Override @Override
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m) {
// TODO if oPos == curPos this could be simplified // TODO if oPos == curPos this could be simplified
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
@ -231,19 +231,19 @@ public class ModelOverlay extends RenderOverlay {
float scale = curPos.scale / div; float scale = curPos.scale / div;
Matrix.setIdentityM(matrix, 0); Matrix.setIdentityM(m.mvp, 0);
// translate relative to map center // translate relative to map center
matrix[12] = x * scale; m.mvp[12] = x * scale;
matrix[13] = y * scale; m.mvp[13] = y * scale;
// scale to current tile world coordinates // scale to current tile world coordinates
scale = (curPos.scale / oPos.scale) / div; scale = (curPos.scale / oPos.scale) / div;
scale /= GLRenderer.COORD_MULTIPLIER; scale /= GLRenderer.COORD_MULTIPLIER;
matrix[0] = scale; m.mvp[0] = scale;
matrix[5] = scale; m.mvp[5] = scale;
matrix[10] = scale; // 1000f; m.mvp[10] = scale; // 1000f;
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0);
} }
@Override @Override

View File

@ -17,6 +17,7 @@ package org.oscim.renderer.overlays;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
import org.oscim.view.MapView; import org.oscim.view.MapView;
@ -65,21 +66,21 @@ public abstract class RenderOverlay {
* *
* @param pos * @param pos
* current MapPosition * current MapPosition
* @param mv * @param m
* current model-view matrix * current render matrices + matrix for temporary use
* @param proj
* current projection matrix
*/ */
public abstract void render(MapPosition pos, float[] mv, float[] proj); public abstract void render(MapPosition pos, Matrices m);
/** /**
* Utility: set matrix relative to the difference of current MapPosition * Utility: set m.mvp matrix relative to the difference of current MapPosition
* and the last updated Overlay MapPosition * and the last updated Overlay MapPosition
* *
* @param curPos ... * @param curPos ...
* @param matrix ... * @param m ...
* @param project
* apply view and projection, or just view otherwise
*/ */
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m, boolean project) {
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel); float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
@ -101,10 +102,24 @@ public abstract class RenderOverlay {
// set scale to be relative to current scale // set scale to be relative to current scale
float s = (curPos.scale / oPos.scale) / div; float s = (curPos.scale / oPos.scale) / div;
GlUtils.setMatrix(matrix, x * scale, y * scale, GlUtils.setMatrix(m.mvp, x * scale, y * scale,
s / GLRenderer.COORD_MULTIPLIER); s / GLRenderer.COORD_MULTIPLIER);
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); if (project)
Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0);
else
Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0);
}
/**
* Utility: set m.mvp matrix relative to the difference of current MapPosition
* and the last updated Overlay MapPosition and add m.viewproj
*
* @param curPos ...
* @param m ...
*/
protected void setMatrix(MapPosition curPos, Matrices m) {
setMatrix(curPos, m, true);
} }
/** /**
@ -113,6 +128,6 @@ public abstract class RenderOverlay {
* @return true if position has changed * @return true if position has changed
*/ */
protected boolean updateMapPosition() { protected boolean updateMapPosition() {
return mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); return mMapView.getMapViewPosition().getMapPosition(mMapPosition);
} }
} }

View File

@ -21,6 +21,7 @@ import java.nio.ShortBuffer;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.GlUtils; import org.oscim.utils.GlUtils;
@ -73,31 +74,31 @@ public class TestLineOverlay extends RenderOverlay {
// -> max line length is 2^12/4=1024 // -> max line length is 2^12/4=1024
// - texture 'end' is 'length'-'start' // - texture 'end' is 'length'-'start'
private final short[] box = { // private final short[] box = {
// '-' start // // '-' start
0, 0, 0, 0, // 0, 0, 0, 0,
// 0. // // 0.
-800, 0, 255, 0, // -800, 0, 255, 0,
// 2. // // 2.
100, 0, 255, 0, // 100, 0, 255, 0,
// 1. // // 1.
0, 0, 255, 1, // 0, 0, 255, 1,
// 3. // // 3.
800, 0, 255, 1, // 800, 0, 255, 1,
//
-800, 200, 127, 0, // -800, 200, 127, 0,
0, 200, 127, 0, // 0, 200, 127, 0,
0, 200, 127, 1, // 0, 200, 127, 1,
800, 200, 127, 1, // 800, 200, 127, 1,
//
-800, 400, 255, 0, // -800, 400, 255, 0,
0, 400, 255, 0, // 0, 400, 255, 0,
0, 400, 255, 1, // 0, 400, 255, 1,
800, 400, 255, 1, // 800, 400, 255, 1,
//
// '-' end // // '-' end
0, 0, 0, 0, // 0, 0, 0, 0,
}; // };
private short[] indices = { private short[] indices = {
0, 1, 2, 0, 1, 2,
@ -298,17 +299,17 @@ public class TestLineOverlay extends RenderOverlay {
GLES20.GL_STATIC_DRAW); GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); mMapView.getMapViewPosition().getMapPosition(mMapPosition);
// tell GLRenderer to call 'render' // tell GLRenderer to call 'render'
isReady = true; isReady = true;
} }
@Override @Override
public synchronized void render(MapPosition pos, float[] mv, float[] proj) { public synchronized void render(MapPosition pos, Matrices m) {
setMatrix(pos, mv); setMatrix(pos, m);
Matrix.multiplyMM(mv, 0, proj, 0, mv, 0); //Matrix.multiplyMM(mv, 0, proj, 0, mv, 0);
GLState.useProgram(testProgram); GLState.useProgram(testProgram);
GLES20.glDisable(GLES20.GL_CULL_FACE); GLES20.glDisable(GLES20.GL_CULL_FACE);
@ -319,7 +320,7 @@ public class TestLineOverlay extends RenderOverlay {
GLES20.glEnableVertexAttribArray(htestVertexFlip); GLES20.glEnableVertexAttribArray(htestVertexFlip);
GLES20.glUniformMatrix4fv(htestMatrix, 1, false, mv, 0); GLES20.glUniformMatrix4fv(htestMatrix, 1, false, m.mvp, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
@ -355,7 +356,7 @@ public class TestLineOverlay extends RenderOverlay {
} }
@Override @Override
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m) {
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
byte z = oPos.zoomLevel; byte z = oPos.zoomLevel;
@ -373,19 +374,19 @@ public class TestLineOverlay extends RenderOverlay {
float scale = curPos.scale / div; float scale = curPos.scale / div;
Matrix.setIdentityM(matrix, 0); Matrix.setIdentityM(m.mvp, 0);
// translate relative to map center // translate relative to map center
matrix[12] = x * scale; m.mvp[12] = x * scale;
matrix[13] = y * scale; m.mvp[13] = y * scale;
// scale to current tile world coordinates // scale to current tile world coordinates
scale = (curPos.scale / oPos.scale) / div; scale = (curPos.scale / oPos.scale) / div;
scale /= GLRenderer.COORD_MULTIPLIER; scale /= GLRenderer.COORD_MULTIPLIER;
matrix[0] = scale; m.mvp[0] = scale;
matrix[5] = scale; m.mvp[5] = scale;
matrix[10] = 1; //scale; // 1000f; m.mvp[10] = 1; //scale; // 1000f;
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0);
} }
@Override @Override

View File

@ -18,6 +18,7 @@ package org.oscim.renderer.overlays;
import org.oscim.core.MapPosition; import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.MapTile; import org.oscim.renderer.MapTile;
import org.oscim.renderer.TileSet; import org.oscim.renderer.TileSet;
import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layer;
@ -45,7 +46,7 @@ public class TextOverlay extends BasicOverlay {
private final static String TAG = TextOverlay.class.getName(); private final static String TAG = TextOverlay.class.getName();
private TileSet mTiles; private TileSet mTiles;
private LabelThread mThread; private final LabelThread mThread;
private MapPosition mWorkPos; private MapPosition mWorkPos;
@ -170,7 +171,7 @@ public class TextOverlay extends BasicOverlay {
if (mTiles.cnt == 0) if (mTiles.cnt == 0)
return; return;
mMapView.getMapViewPosition().getMapPosition(mWorkPos, null); mMapView.getMapViewPosition().getMapPosition(mWorkPos);
TextLayer tl = mWorkLayer; TextLayer tl = mWorkLayer;
@ -415,7 +416,7 @@ public class TextOverlay extends BasicOverlay {
} }
@Override @Override
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m) {
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel); float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
@ -424,10 +425,10 @@ public class TextOverlay extends BasicOverlay {
float scale = curPos.scale / div; float scale = curPos.scale / div;
GlUtils.setMatrix(matrix, x * scale, y * scale, GlUtils.setMatrix(m.mvp, x * scale, y * scale,
scale / GLRenderer.COORD_MULTIPLIER); scale / GLRenderer.COORD_MULTIPLIER);
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0);
} }
private boolean mHolding; private boolean mHolding;

View File

@ -17,12 +17,13 @@ package org.oscim.renderer.overlays;
// TODO // TODO
// 1. rewrite :) // 1. rewrite :)
// 1.1 test if label is actually visible
// 2. compare previous to current state // 2. compare previous to current state
// 2.1 test for new labels to be placed // 2.1 test for new labels to be placed
// 2.2 handle collisions // 2.2 handle collisions
// 3 join segments that belong to one feature // 3 join segments that belong to one feature
// 4 handle zoom-level changes // 4 handle zoom-level changes
// 5 3D-Tree might be handy // 5 R-Tree might be handy
// //
import java.util.HashMap; import java.util.HashMap;
@ -32,6 +33,7 @@ import org.oscim.core.Tile;
import org.oscim.generator.JobTile; import org.oscim.generator.JobTile;
import org.oscim.renderer.BufferObject; import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLRenderer.Matrices;
import org.oscim.renderer.GLState; import org.oscim.renderer.GLState;
import org.oscim.renderer.LineRenderer; import org.oscim.renderer.LineRenderer;
import org.oscim.renderer.MapTile; import org.oscim.renderer.MapTile;
@ -49,6 +51,7 @@ import org.oscim.utils.GlUtils;
import org.oscim.utils.OBB2D; import org.oscim.utils.OBB2D;
import org.oscim.utils.PausableThread; import org.oscim.utils.PausableThread;
import org.oscim.view.MapView; import org.oscim.view.MapView;
import org.oscim.view.MapViewPosition;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint.Cap; import android.graphics.Paint.Cap;
@ -60,6 +63,7 @@ import android.util.Log;
public class TextOverlayExp extends BasicOverlay { public class TextOverlayExp extends BasicOverlay {
private final static String TAG = TextOverlayExp.class.getName(); private final static String TAG = TextOverlayExp.class.getName();
private final MapViewPosition mMapViewPosition;
private TileSet mTileSet; private TileSet mTileSet;
private final LabelThread mThread; private final LabelThread mThread;
@ -70,6 +74,8 @@ public class TextOverlayExp extends BasicOverlay {
// TextLayer that is ready to be added to 'layers' // TextLayer that is ready to be added to 'layers'
private TextLayer mNextLayer; private TextLayer mNextLayer;
private final float[] mTmpCoords = new float[8];
/* package */boolean mRun; /* package */boolean mRun;
class LabelThread extends PausableThread { class LabelThread extends PausableThread {
@ -102,6 +108,7 @@ public class TextOverlayExp extends BasicOverlay {
public TextOverlayExp(MapView mapView) { public TextOverlayExp(MapView mapView) {
super(mapView); super(mapView);
mMapViewPosition = mapView.getMapViewPosition();
layers.textureLayers = new TextLayer(); layers.textureLayers = new TextLayer();
mTmpLayer = new TextLayer(); mTmpLayer = new TextLayer();
@ -145,10 +152,6 @@ public class TextOverlayExp extends BasicOverlay {
private byte checkOverlap(TextLayer tl, TextItem ti) { private byte checkOverlap(TextLayer tl, TextItem ti) {
for (TextItem lp = tl.labels; lp != null;) { for (TextItem lp = tl.labels; lp != null;) {
if (lp.text.caption) {
lp = lp.next;
continue;
}
// check bounding box // check bounding box
if (!TextItem.bboxOverlaps(ti, lp, 100)) { if (!TextItem.bboxOverlaps(ti, lp, 100)) {
@ -186,11 +189,12 @@ public class TextOverlayExp extends BasicOverlay {
if (ti.bbox == null) { if (ti.bbox == null) {
ti.bbox = new OBB2D(ti.x, ti.y, ti.x1, ti.y1, ti.bbox = new OBB2D(ti.x, ti.y, ti.x1, ti.y1,
ti.width + 10, ti.text.fontHeight + 10); ti.width + 5, ti.text.fontHeight + 5);
} }
if (lp.bbox == null) { if (lp.bbox == null) {
lp.bbox = new OBB2D(lp.x, lp.y, lp.x1, lp.y1, lp.bbox = new OBB2D(lp.x, lp.y, lp.x1, lp.y1,
lp.width + 10, lp.text.fontHeight + 10); lp.width + 5, lp.text.fontHeight + 5);
} }
boolean intersect = ti.bbox.overlaps(lp.bbox); boolean intersect = ti.bbox.overlaps(lp.bbox);
@ -203,9 +207,8 @@ public class TextOverlayExp extends BasicOverlay {
//Log.d(TAG, "intersection " + lp.string + " <> " + ti.string //Log.d(TAG, "intersection " + lp.string + " <> " + ti.string
// + " at " + ti.x + ":" + ti.y); // + " at " + ti.x + ":" + ti.y);
if (lp.text.priority > ti.text.priority || lp.length < ti.length) { if (!lp.text.caption
//if (lp.length > ti.length) { && (lp.text.priority > ti.text.priority || lp.length < ti.length)) {
//Log.d(TAG, "drop " + lp.string);
TextItem tmp = lp; TextItem tmp = lp;
lp = lp.next; lp = lp.next;
@ -241,35 +244,50 @@ public class TextOverlayExp extends BasicOverlay {
return 0; return 0;
} }
private int mMinX;
private int mMinY;
private int mMaxX;
private int mMaxY;
private boolean isVisible(TextItem ti) {
return true;
}
private Layers mDebugLayer; private Layers mDebugLayer;
private final float[] mMVP = new float[16];
boolean updateLabels() { boolean updateLabels() {
if (mTmpLayer == null) if (mTmpLayer == null)
return false; return false;
// get current tiles
mTileSet = GLRenderer.getVisibleTiles(mTileSet); mTileSet = GLRenderer.getVisibleTiles(mTileSet);
if (mTileSet.cnt == 0) if (mTileSet.cnt == 0)
return false; return false;
// reuse text layer
TextLayer tl = mTmpLayer; TextLayer tl = mTmpLayer;
mTmpLayer = null; mTmpLayer = null;
Layers dbg = null;//new Layers(); Layers dbg = null; //new Layers();
float[] coords = mTmpCoords;
synchronized (mMapViewPosition) {
mMapViewPosition.getMapPosition(mTmpPos);
mMapViewPosition.getMapViewProjection(coords);
mMapViewPosition.getMatrix(null, null, mMVP);
}
// mTiles might be from another zoomlevel than the current: // mTiles might be from another zoomlevel than the current:
// this scales MapPosition to the zoomlevel of mTiles... // this scales MapPosition to the zoomlevel of mTiles...
// TODO create a helper function in MapPosition // TODO create a helper function in MapPosition
mMapView.getMapViewPosition().getMapPosition(mTmpPos, null);
// capture current state
MapTile[] tiles = mTileSet.tiles; MapTile[] tiles = mTileSet.tiles;
int diff = tiles[0].zoomLevel - mTmpPos.zoomLevel; int diff = tiles[0].zoomLevel - mTmpPos.zoomLevel;
float div = FastMath.pow(diff); float div = FastMath.pow(diff);
float scale = mTmpPos.scale * div; float scale = mTmpPos.scale * div;
double angle = Math.toRadians(mTmpPos.angle); double angle = Math.toRadians(mTmpPos.angle);
float cos = (float) Math.cos(angle); float cos = (float) Math.cos(angle);
float sin = (float) Math.sin(angle); float sin = (float) Math.sin(angle);
@ -301,9 +319,6 @@ public class TextOverlayExp extends BasicOverlay {
if (t.state == JobTile.STATE_NONE || t.state == JobTile.STATE_LOADING) if (t.state == JobTile.STATE_NONE || t.state == JobTile.STATE_LOADING)
continue; continue;
//if (t.joined != MapTile.JOINED)
// joinTile()
float dx = (float) (t.pixelX - mTmpPos.x); float dx = (float) (t.pixelX - mTmpPos.x);
float dy = (float) (t.pixelY - mTmpPos.y); float dy = (float) (t.pixelY - mTmpPos.y);
@ -329,33 +344,70 @@ public class TextOverlayExp extends BasicOverlay {
} }
} }
if (ti.text.caption) { if (!ti.text.caption)
ti2.move(ti, dx, dy, scale);
ti2.setAxisAlignedBBox();
ti2.bbox = new OBB2D(ti2.x, ti2.y, cos, -sin, ti2.width + 6,
ti2.text.fontHeight + 6, true);
boolean overlaps = false;
for (TextItem lp = tl.labels; lp != null; lp = lp.next) {
if (!lp.text.caption)
continue;
if (ti2.bbox.overlaps(lp.bbox)) {
Log.d(TAG, "overlap > " + ti2.string + " " + lp.string);
//if (TextItem.bboxOverlaps(ti2, lp, 4)) {
overlaps = true;
break;
}
}
if (!overlaps) {
tl.addText(ti2);
ti2 = null;
}
continue; continue;
ti2.move(ti, dx, dy, scale);
ti2.setAxisAlignedBBox();
ti2.bbox = new OBB2D(ti2.x, ti2.y, cos, -sin, ti2.width + 6,
ti2.text.fontHeight + 6, true);
boolean overlaps = false;
for (TextItem lp = tl.labels; lp != null; lp = lp.next) {
if (!lp.text.caption)
continue;
if (ti2.bbox.overlaps(lp.bbox)) {
Log.d(TAG, "overlap > " + ti2.string + " " + lp.string);
//if (TextItem.bboxOverlaps(ti2, lp, 4)) {
overlaps = true;
break;
}
}
if (!overlaps) {
tl.addText(ti2);
ti2 = null;
} }
/* text is way label */ }
}
/* add way labels */
for (int i = 0, n = mTileSet.cnt; i < n; i++) {
MapTile t = tiles[i];
if (t.state == JobTile.STATE_NONE || t.state == JobTile.STATE_LOADING)
continue;
float dx = (float) (t.pixelX - mTmpPos.x);
float dy = (float) (t.pixelY - mTmpPos.y);
// flip around date-line
if (dx > maxx) {
dx = dx - maxx * 2;
} else if (dx < -maxx) {
dx = dx + maxx * 2;
}
dx *= scale;
dy *= scale;
for (TextItem ti = t.labels; ti != null; ti = ti.next) {
if (ti.text.caption)
continue;
// acquire a TextItem to add to TextLayer
if (ti2 == null) {
if (mPool == null)
ti2 = TextItem.get();
else {
ti2 = mPool;
mPool = mPool.next;
ti2.next = null;
}
}
// check if path at current scale is long enough for text // check if path at current scale is long enough for text
if (dbg == null && ti.width > ti.length * scale) if (dbg == null && ti.width > ti.length * scale)
@ -423,6 +475,7 @@ public class TextOverlayExp extends BasicOverlay {
} }
} }
} }
for (TextItem ti = tl.labels; ti != null; ti = ti.next) { for (TextItem ti = tl.labels; ti != null; ti = ti.next) {
// scale back to fixed zoom-level. could be done in setMatrix // scale back to fixed zoom-level. could be done in setMatrix
ti.x /= scale; ti.x /= scale;
@ -457,9 +510,7 @@ public class TextOverlayExp extends BasicOverlay {
tl.setScale(scale); tl.setScale(scale);
tl.prepare(); tl.prepare();
//TextItem.printPool(); // remove tile locks
//Log.d(TAG, "new labels: " + count);
GLRenderer.releaseTiles(mTileSet); GLRenderer.releaseTiles(mTileSet);
// pass new labels for rendering // pass new labels for rendering
@ -514,12 +565,8 @@ public class TextOverlayExp extends BasicOverlay {
@Override @Override
public void compile() { public void compile() {
int newSize = layers.getSize(); int newSize = layers.getSize();
//if (newSize == 0)
// Log.d(TAG, "text layer size " + newSize);
if (newSize == 0) { if (newSize == 0) {
//BufferObject.release(vbo);
//vbo = null;
isReady = false; isReady = false;
return; return;
} }
@ -535,31 +582,34 @@ public class TextOverlayExp extends BasicOverlay {
} }
@Override @Override
public synchronized void render(MapPosition pos, float[] mv, float[] proj) { public synchronized void render(MapPosition pos, Matrices m) {
setMatrix(pos, mv);
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel); float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
GLState.test(false, false); GLState.test(false, false);
for (Layer l = layers.layers; l != null;) { if (layers.layers != null) {
if (l.type == Layer.POLYGON) { setMatrix(pos, m);
l = PolygonRenderer.draw(pos, l, mvp, true, false); Matrix.multiplyMM(m.mvp, 0, m.proj, 0, m.mvp,0);
} else { for (Layer l = layers.layers; l != null;) {
l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset); if (l.type == Layer.POLYGON) {
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
} else {
l = LineRenderer.draw(pos, l, m.mvp, div, 0, layers.lineOffset);
}
} }
} }
setMatrix(pos, m);
for (Layer l = layers.textureLayers; l != null;) { for (Layer l = layers.textureLayers; l != null;) {
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv); float scale = (mMapPosition.scale / pos.scale) * div;
l = TextureRenderer.draw(l, scale, m.proj, m.mvp);
} }
} }
@Override @Override
protected void setMatrix(MapPosition curPos, float[] matrix) { protected void setMatrix(MapPosition curPos, Matrices m) {
MapPosition oPos = mMapPosition; MapPosition oPos = mMapPosition;
float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel); float div = FastMath.pow(oPos.zoomLevel - curPos.zoomLevel);
@ -568,10 +618,10 @@ public class TextOverlayExp extends BasicOverlay {
float scale = curPos.scale / div; float scale = curPos.scale / div;
GlUtils.setMatrix(matrix, x * scale, y * scale, GlUtils.setMatrix(m.mvp, x * scale, y * scale,
scale / GLRenderer.COORD_MULTIPLIER); scale / GLRenderer.COORD_MULTIPLIER);
Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0);
} }
private boolean mHolding; private boolean mHolding;

View File

@ -65,7 +65,13 @@ public class FastMath {
return a2 < a1 ? a1 : a2; return a2 < a1 ? a1 : a2;
} }
// test if any absolute value is greater than 'cmp'
public static boolean absMaxCmp(float value1, float value2, float cmp){ public static boolean absMaxCmp(float value1, float value2, float cmp){
return value1 < -cmp || value1 > cmp || value2 < -cmp || value2 > cmp; return value1 < -cmp || value1 > cmp || value2 < -cmp || value2 > cmp;
} }
// test if any absolute value is greater than 'cmp'
public static boolean absMaxCmp(int value1, int value2, int cmp){
return value1 < -cmp || value1 > cmp || value2 < -cmp || value2 > cmp;
}
} }

View File

@ -66,7 +66,7 @@ public class MapViewPosition {
private double mPosX; private double mPosX;
private double mPosY; private double mPosY;
private AnimationHandler mHandler; private final AnimationHandler mHandler;
MapViewPosition(MapView mapView) { MapViewPosition(MapView mapView) {
mMapView = mapView; mMapView = mapView;
@ -81,18 +81,19 @@ public class MapViewPosition {
mHandler = new AnimationHandler(this); mHandler = new AnimationHandler(this);
} }
private float[] mProjMatrix = new float[16]; private final float[] mProjMatrix = new float[16];
private float[] mProjMatrixI = new float[16]; private final float[] mProjMatrixI = new float[16];
private float[] mUnprojMatrix = new float[16]; private final float[] mUnprojMatrix = new float[16];
private float[] mViewMatrix = new float[16]; private final float[] mViewMatrix = new float[16];
private float[] mRotMatrix = new float[16]; private final float[] mVPMatrix = new float[16];
private float[] mTmpMatrix = new float[16]; private final float[] mRotMatrix = new float[16];
private final float[] mTmpMatrix = new float[16];
// temporary vars: only use in synchronized functions! // temporary vars: only use in synchronized functions!
private Point2D mMovePoint = new Point2D(); private final Point2D mMovePoint = new Point2D();
private float[] mv = { 0, 0, 0, 1 }; private final float[] mv = { 0, 0, 0, 1 };
private float[] mu = { 0, 0, 0, 1 }; private final float[] mu = { 0, 0, 0, 1 };
private float[] mBBoxCoords = new float[8]; private final float[] mBBoxCoords = new float[8];
private float mHeight, mWidth; private float mHeight, mWidth;
@ -120,8 +121,7 @@ public class MapViewPosition {
updateMatrix(); updateMatrix();
} }
public synchronized boolean getMapPosition(final MapPosition mapPosition, public synchronized boolean getMapPosition(final MapPosition mapPosition) {
final float[] projection) {
// if (!isValid()) // if (!isValid())
// return false; // return false;
@ -145,21 +145,34 @@ public class MapViewPosition {
mapPosition.x = mPosX; mapPosition.x = mPosX;
mapPosition.y = mPosY; mapPosition.y = mPosY;
if (mapPosition.viewMatrix != null) return true;
System.arraycopy(mViewMatrix, 0, mapPosition.viewMatrix, 0, 16); }
if (projection == null) /**
return true; * get a copy of current matrices
* @param view ...
* @param proj ...
* @param vp view and projection
*/
public synchronized void getMatrix(float[] view, float[] proj, float[] vp) {
if (view != null)
System.arraycopy(mViewMatrix, 0, view, 0, 16);
if (proj!= null)
System.arraycopy(mProjMatrix, 0, proj, 0, 16);
if (vp != null)
System.arraycopy(mVPMatrix, 0, vp, 0, 16);
}
public synchronized void getMapViewProjection(float[] box) {
float t = getZ(1); float t = getZ(1);
float t2 = getZ(-1); float t2 = getZ(-1);
unproject(1, -1, t, projection, 0); // top-right unproject(1, -1, t, box, 0); // top-right
unproject(-1, -1, t, projection, 2); // top-left unproject(-1, -1, t, box, 2); // top-left
unproject(-1, 1, t2, projection, 4); // bottom-left unproject(-1, 1, t2, box, 4); // bottom-left
unproject(1, 1, t2, projection, 6); // bottom-right unproject(1, 1, t2, box, 6); // bottom-right
return true;
} }
// get the z-value of the map-plane for a point on screen // get the z-value of the map-plane for a point on screen
@ -365,8 +378,9 @@ public class MapViewPosition {
mv[2] = 0; mv[2] = 0;
mv[3] = 1; mv[3] = 1;
Matrix.multiplyMV(mv, 0, mViewMatrix, 0, mv, 0); // Matrix.multiplyMV(mv, 0, mViewMatrix, 0, mv, 0);
Matrix.multiplyMV(mv, 0, mProjMatrix, 0, mv, 0); // Matrix.multiplyMV(mv, 0, mProjMatrix, 0, mv, 0);
Matrix.multiplyMV(mv, 0, mVPMatrix, 0, mv, 0);
out.x = (int) (mv[0] / mv[3] * mWidth / 2); out.x = (int) (mv[0] / mv[3] * mWidth / 2);
out.y = (int) (mv[1] / mv[3] * mHeight / 2); out.y = (int) (mv[1] / mv[3] * mHeight / 2);
@ -376,10 +390,6 @@ public class MapViewPosition {
return out; return out;
} }
public synchronized void getMVP(float[] matrix) {
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, mViewMatrix, 0);
}
// public static Point project(float x, float y, float[] matrix, float[] tmpVec, Point reuse) { // public static Point project(float x, float y, float[] matrix, float[] tmpVec, Point reuse) {
// Point out = reuse == null ? new Point() : reuse; // Point out = reuse == null ? new Point() : reuse;
// //
@ -420,6 +430,8 @@ public class MapViewPosition {
Matrix.multiplyMM(mViewMatrix, 0, mRotMatrix, 0, mTmpMatrix, 0); Matrix.multiplyMM(mViewMatrix, 0, mRotMatrix, 0, mTmpMatrix, 0);
Matrix.multiplyMM(mVPMatrix, 0, mProjMatrix, 0, mViewMatrix, 0);
//--- unproject matrix: //--- unproject matrix:
// Matrix.multiplyMM(mTmpMatrix, 0, mProjMatrix, 0, mViewMatrix, 0); // Matrix.multiplyMM(mTmpMatrix, 0, mProjMatrix, 0, mViewMatrix, 0);
// Matrix.invertM(mUnprojMatrix, 0, mTmpMatrix, 0); // Matrix.invertM(mUnprojMatrix, 0, mTmpMatrix, 0);