api: no more sync'ed Viewport methods
- remove synchronized viewport methods: viewport MUST only be changed on main-thread - when calling Map.setPosition() from another thread the position will be applied on the next main-loop iteration
This commit is contained in:
parent
381907526e
commit
8626aa2f53
@ -18,16 +18,20 @@ package org.oscim.android;
|
||||
|
||||
import org.oscim.android.gl.GLView;
|
||||
import org.oscim.map.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import android.widget.RelativeLayout.LayoutParams;
|
||||
|
||||
public class AndroidMap extends Map {
|
||||
static final Logger log = LoggerFactory.getLogger(AndroidMap.class);
|
||||
|
||||
private final MapView mMapView;
|
||||
final GLView mGLView;
|
||||
|
||||
private volatile boolean mWaitRedraw;
|
||||
private volatile boolean mPausing;
|
||||
private boolean mRenderRequest;
|
||||
private boolean mRenderWait;
|
||||
private boolean mPausing;
|
||||
|
||||
public AndroidMap(MapView mapView) {
|
||||
super();
|
||||
@ -52,14 +56,24 @@ public class AndroidMap extends Map {
|
||||
return mMapView.getHeight();
|
||||
}
|
||||
|
||||
private final Runnable mRedrawCb = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
prepareFrame();
|
||||
mGLView.requestRender();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void updateMap(boolean redraw) {
|
||||
//if (redraw && !mClearMap && !mPausing)
|
||||
// mGLView.requestRender();
|
||||
if (mPausing)
|
||||
return;
|
||||
|
||||
if (!mWaitRedraw) {
|
||||
mWaitRedraw = true;
|
||||
mMapView.post(mRedrawRequest);
|
||||
if (!mRenderRequest) {
|
||||
mRenderRequest = true;
|
||||
mMapView.post(mRedrawCb);
|
||||
} else {
|
||||
mRenderWait = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,25 +82,24 @@ public class AndroidMap extends Map {
|
||||
if (mPausing)
|
||||
return;
|
||||
|
||||
if (mClearMap)
|
||||
updateMap(false);
|
||||
else
|
||||
mGLView.requestRender();
|
||||
updateMap(true);
|
||||
}
|
||||
|
||||
private final Runnable mRedrawRequest = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
redrawMapInternal();
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doneFrame() {
|
||||
mRenderRequest = false;
|
||||
|
||||
if (mRenderWait) {
|
||||
//log.debug("redraw");
|
||||
mRenderWait = false;
|
||||
updateMap(true);
|
||||
//prepareFrame();
|
||||
//mGLView.requestRender();
|
||||
}
|
||||
};
|
||||
|
||||
void redrawMapInternal() {
|
||||
mWaitRedraw = false;
|
||||
|
||||
updateLayers();
|
||||
|
||||
mGLView.requestRender();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -100,6 +113,7 @@ public class AndroidMap extends Map {
|
||||
}
|
||||
|
||||
public void pause(boolean pause) {
|
||||
log.debug("pause... {}", pause);
|
||||
mPausing = pause;
|
||||
}
|
||||
}
|
||||
|
@ -38,15 +38,12 @@ import com.badlogic.gdx.utils.Timer.Task;
|
||||
public abstract class GdxMap implements ApplicationListener {
|
||||
final static Logger log = LoggerFactory.getLogger(GdxMap.class);
|
||||
|
||||
protected final Map mMap;
|
||||
private final MapAdapter mMapAdapter;
|
||||
protected Map mMap;
|
||||
|
||||
VectorTileLayer mMapLayer;
|
||||
private final MapRenderer mMapRenderer;
|
||||
private MapRenderer mMapRenderer;
|
||||
|
||||
public GdxMap() {
|
||||
mMap = mMapAdapter = new MapAdapter();
|
||||
mMapRenderer = new MapRenderer(mMap);
|
||||
}
|
||||
|
||||
protected void initDefaultLayers(TileSource tileSource, boolean tileGrid, boolean labels,
|
||||
@ -70,6 +67,8 @@ public abstract class GdxMap implements ApplicationListener {
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
mMap = new MapAdapter();
|
||||
mMapRenderer = new MapRenderer(mMap);
|
||||
|
||||
Gdx.graphics.setContinuousRendering(false);
|
||||
Gdx.app.setLogLevel(Application.LOG_DEBUG);
|
||||
@ -101,9 +100,13 @@ public abstract class GdxMap implements ApplicationListener {
|
||||
|
||||
}
|
||||
|
||||
/* private */boolean mRenderWait;
|
||||
/* private */boolean mRenderRequest;
|
||||
/* private */boolean mUpdateRequest;
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
if (!mMapAdapter.needsRedraw())
|
||||
if (!mRenderRequest)
|
||||
return;
|
||||
|
||||
mMapRenderer.onDrawFrame();
|
||||
@ -132,8 +135,7 @@ public abstract class GdxMap implements ApplicationListener {
|
||||
return mMap;
|
||||
}
|
||||
|
||||
static class MapAdapter extends Map {
|
||||
boolean mRenderRequest;
|
||||
class MapAdapter extends Map {
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
@ -145,21 +147,35 @@ public abstract class GdxMap implements ApplicationListener {
|
||||
return Gdx.graphics.getHeight();
|
||||
}
|
||||
|
||||
private final Runnable mRedrawCb = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
prepareFrame();
|
||||
Gdx.graphics.requestRendering();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void updateMap(boolean forceRender) {
|
||||
if (!mWaitRedraw) {
|
||||
mWaitRedraw = true;
|
||||
Gdx.app.postRunnable(mRedrawRequest);
|
||||
|
||||
if (!mRenderRequest) {
|
||||
mRenderRequest = true;
|
||||
Gdx.app.postRunnable(mRedrawCb);
|
||||
} else {
|
||||
mRenderWait = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
//updateMap(true);
|
||||
|
||||
mRenderRequest = true;
|
||||
if (mClearMap)
|
||||
updateMap(false);
|
||||
else
|
||||
else {
|
||||
Gdx.graphics.requestRendering();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -179,35 +195,22 @@ public abstract class GdxMap implements ApplicationListener {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all Layers on Main thread.
|
||||
*
|
||||
* @param forceRedraw
|
||||
* also render frame FIXME (does nothing atm)
|
||||
*/
|
||||
private void redrawMapInternal(boolean forceRedraw) {
|
||||
updateLayers();
|
||||
|
||||
mRenderRequest = true;
|
||||
Gdx.graphics.requestRendering();
|
||||
@Override
|
||||
public void beginFrame() {
|
||||
}
|
||||
|
||||
/* private */boolean mWaitRedraw;
|
||||
private final Runnable mRedrawRequest = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mWaitRedraw = false;
|
||||
redrawMapInternal(false);
|
||||
}
|
||||
};
|
||||
|
||||
public boolean needsRedraw() {
|
||||
if (!mRenderRequest)
|
||||
return false;
|
||||
|
||||
@Override
|
||||
public void doneFrame() {
|
||||
mRenderRequest = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mRenderWait) {
|
||||
mRenderWait = false;
|
||||
|
||||
mRenderRequest = true;
|
||||
|
||||
prepareFrame();
|
||||
Gdx.graphics.requestRendering();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.oscim.utils;
|
||||
|
||||
public class ThreadUtils {
|
||||
|
||||
public static void assertMainThread() {
|
||||
}
|
||||
|
||||
public static boolean isMainThread() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -27,14 +27,14 @@ import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Point;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.MapRenderer;
|
||||
import org.oscim.utils.ThreadUtils;
|
||||
import org.oscim.utils.async.Task;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Animator {
|
||||
static final Logger log = LoggerFactory.getLogger(Animator.class);
|
||||
|
||||
//static final Logger log = LoggerFactory.getLogger(MapAnimator.class);
|
||||
|
||||
private final static int ANIM_NONE = 0;
|
||||
private final static int ANIM_MOVE = 1 << 0;
|
||||
private final static int ANIM_SCALE = 1 << 1;
|
||||
@ -62,6 +62,8 @@ public class Animator {
|
||||
}
|
||||
|
||||
public synchronized void animateTo(long duration, BoundingBox bbox) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mMap.getMapPosition(mStartPos);
|
||||
/* TODO for large distance first scale out, then in
|
||||
* calculate the maximum scale at which the BoundingBox
|
||||
@ -89,12 +91,22 @@ public class Animator {
|
||||
animStart(duration, ANIM_MOVE | ANIM_SCALE | ANIM_ROTATE | ANIM_TILT);
|
||||
}
|
||||
|
||||
public synchronized void animateTo(BoundingBox bbox) {
|
||||
public void animateTo(BoundingBox bbox) {
|
||||
animateTo(1000, bbox);
|
||||
}
|
||||
|
||||
public synchronized void animateTo(long duration, GeoPoint geoPoint,
|
||||
/**
|
||||
* Animate to GeoPoint
|
||||
*
|
||||
* @param duration in ms
|
||||
* @param geoPoint
|
||||
* @param scale
|
||||
* @param relative alter scale relative to current scale
|
||||
*/
|
||||
public void animateTo(long duration, GeoPoint geoPoint,
|
||||
double scale, boolean relative) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mMap.getMapPosition(mStartPos);
|
||||
|
||||
if (relative)
|
||||
@ -110,11 +122,13 @@ public class Animator {
|
||||
animStart(duration, ANIM_MOVE | ANIM_SCALE);
|
||||
}
|
||||
|
||||
public synchronized void animateTo(GeoPoint p) {
|
||||
public void animateTo(GeoPoint p) {
|
||||
animateTo(500, p, 1, true);
|
||||
}
|
||||
|
||||
public synchronized void animateTo(long duration, MapPosition pos) {
|
||||
public void animateTo(long duration, MapPosition pos) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mMap.getMapPosition(mStartPos);
|
||||
|
||||
pos.scale = clamp(pos.scale,
|
||||
@ -130,8 +144,10 @@ public class Animator {
|
||||
animStart(duration, ANIM_MOVE | ANIM_SCALE | ANIM_ROTATE | ANIM_TILT);
|
||||
}
|
||||
|
||||
public synchronized void animateZoom(long duration, double scaleBy,
|
||||
public void animateZoom(long duration, double scaleBy,
|
||||
float pivotX, float pivotY) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mMap.getMapPosition(mCurPos);
|
||||
|
||||
if (mState == ANIM_SCALE)
|
||||
@ -150,9 +166,11 @@ public class Animator {
|
||||
animStart(duration, ANIM_SCALE);
|
||||
}
|
||||
|
||||
public synchronized void animateFling(float velocityX, float velocityY,
|
||||
public void animateFling(float velocityX, float velocityY,
|
||||
int xmin, int xmax, int ymin, int ymax) {
|
||||
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
if (velocityX * velocityX + velocityY * velocityY < 2048)
|
||||
return;
|
||||
|
||||
@ -177,87 +195,90 @@ public class Animator {
|
||||
}
|
||||
|
||||
private void animStart(float duration, int state) {
|
||||
mState = state;
|
||||
mCurPos.copy(mStartPos);
|
||||
mState = state;
|
||||
mDuration = duration;
|
||||
mAnimEnd = System.currentTimeMillis() + (long) duration;
|
||||
mMap.render();
|
||||
}
|
||||
|
||||
private void animCancel() {
|
||||
mState = ANIM_NONE;
|
||||
mPivot.x = 0;
|
||||
mPivot.y = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* called by MapRenderer at begin of each frame.
|
||||
*/
|
||||
public synchronized void updateAnimation() {
|
||||
void updateAnimation() {
|
||||
if (mState == ANIM_NONE)
|
||||
return;
|
||||
|
||||
long millisLeft = mAnimEnd - MapRenderer.frametime;
|
||||
|
||||
boolean changed = false;
|
||||
//boolean changed = false;
|
||||
|
||||
ViewController v = mMap.viewport();
|
||||
|
||||
synchronized (v) {
|
||||
/* cancel animation when position was changed since last
|
||||
* update, i.e. when it was modified outside the animator. */
|
||||
if (v.getMapPosition(mCurPos)) {
|
||||
animCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
float adv = clamp(1.0f - millisLeft / mDuration, 0, 1);
|
||||
|
||||
double scaleAdv = 1;
|
||||
if ((mState & ANIM_SCALE) != 0) {
|
||||
scaleAdv = doScale(v, adv);
|
||||
}
|
||||
|
||||
if ((mState & ANIM_MOVE) != 0) {
|
||||
v.moveTo(mStartPos.x + mDeltaPos.x * (adv / scaleAdv),
|
||||
mStartPos.y + mDeltaPos.y * (adv / scaleAdv));
|
||||
}
|
||||
|
||||
if ((mState & ANIM_FLING) != 0) {
|
||||
adv = (float) Math.sqrt(adv);
|
||||
double dx = mVelocity.x * adv;
|
||||
double dy = mVelocity.y * adv;
|
||||
if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) {
|
||||
v.moveMap((float) (dx - mScroll.x),
|
||||
(float) (dy - mScroll.y));
|
||||
mScroll.x = dx;
|
||||
mScroll.y = dy;
|
||||
}
|
||||
}
|
||||
if ((mState & ANIM_ROTATE) != 0) {
|
||||
v.setRotation(mStartPos.bearing + mDeltaPos.bearing * adv);
|
||||
}
|
||||
|
||||
if ((mState & ANIM_TILT) != 0) {
|
||||
v.setTilt(mStartPos.tilt + mDeltaPos.tilt * adv);
|
||||
}
|
||||
|
||||
if (millisLeft <= 0)
|
||||
animCancel();
|
||||
|
||||
/* remember current map position */
|
||||
changed = v.getMapPosition(mCurPos);
|
||||
//synchronized (v) {
|
||||
/* cancel animation when position was changed since last
|
||||
* update, i.e. when it was modified outside the animator. */
|
||||
if (v.getMapPosition(mCurPos)) {
|
||||
log.debug("cancel anim - changed");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
float adv = clamp(1.0f - millisLeft / mDuration, 0, 1);
|
||||
|
||||
double scaleAdv = 1;
|
||||
if ((mState & ANIM_SCALE) != 0) {
|
||||
scaleAdv = doScale(v, adv);
|
||||
}
|
||||
|
||||
if ((mState & ANIM_MOVE) != 0) {
|
||||
v.moveTo(mStartPos.x + mDeltaPos.x * (adv / scaleAdv),
|
||||
mStartPos.y + mDeltaPos.y * (adv / scaleAdv));
|
||||
}
|
||||
|
||||
if ((mState & ANIM_FLING) != 0) {
|
||||
adv = (float) Math.sqrt(adv);
|
||||
double dx = mVelocity.x * adv;
|
||||
double dy = mVelocity.y * adv;
|
||||
if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) {
|
||||
v.moveMap((float) (dx - mScroll.x),
|
||||
(float) (dy - mScroll.y));
|
||||
mScroll.x = dx;
|
||||
mScroll.y = dy;
|
||||
}
|
||||
}
|
||||
if ((mState & ANIM_ROTATE) != 0) {
|
||||
v.setRotation(mStartPos.bearing + mDeltaPos.bearing * adv);
|
||||
}
|
||||
|
||||
if ((mState & ANIM_TILT) != 0) {
|
||||
v.setTilt(mStartPos.tilt + mDeltaPos.tilt * adv);
|
||||
}
|
||||
|
||||
if (millisLeft <= 0) {
|
||||
//log.debug("animate END");
|
||||
cancel();
|
||||
}
|
||||
|
||||
/* remember current map position */
|
||||
final boolean changed = v.getMapPosition(mCurPos);
|
||||
|
||||
if (changed) {
|
||||
/* render and inform layers that position has changed */
|
||||
mMap.updateMap(true);
|
||||
} else {
|
||||
/* just render next frame */
|
||||
mMap.render();
|
||||
mMap.postDelayed(updateTask, 10);
|
||||
}
|
||||
}
|
||||
|
||||
private Task updateTask = new Task() {
|
||||
@Override
|
||||
public int go(boolean canceled) {
|
||||
if (!canceled)
|
||||
updateAnimation();
|
||||
return Task.DONE;
|
||||
}
|
||||
};
|
||||
|
||||
private double doScale(ViewController v, float adv) {
|
||||
double newScale = mStartPos.scale + mDeltaPos.scale * Math.sqrt(adv);
|
||||
|
||||
@ -267,7 +288,10 @@ public class Animator {
|
||||
return newScale / (mStartPos.scale + mDeltaPos.scale);
|
||||
}
|
||||
|
||||
public synchronized void cancel() {
|
||||
public void cancel() {
|
||||
//ThreadUtils.assertMainThread();
|
||||
mState = ANIM_NONE;
|
||||
mPivot.x = 0;
|
||||
mPivot.y = 0;
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import org.oscim.theme.IRenderTheme;
|
||||
import org.oscim.theme.ThemeFile;
|
||||
import org.oscim.theme.ThemeLoader;
|
||||
import org.oscim.tiling.TileSource;
|
||||
import org.oscim.utils.ThreadUtils;
|
||||
import org.oscim.utils.async.AsyncExecutor;
|
||||
import org.oscim.utils.async.TaskQueue;
|
||||
import org.slf4j.Logger;
|
||||
@ -85,7 +86,7 @@ public abstract class Map implements TaskQueue {
|
||||
|
||||
private final Layers mLayers;
|
||||
private final ViewController mViewport;
|
||||
private final Animator mAnimator;
|
||||
protected final Animator mAnimator;
|
||||
private final MapPosition mMapPosition;
|
||||
private final AsyncExecutor mAsyncExecutor;
|
||||
|
||||
@ -97,6 +98,8 @@ public abstract class Map implements TaskQueue {
|
||||
protected boolean mClearMap = true;
|
||||
|
||||
public Map() {
|
||||
ThreadUtils.init();
|
||||
|
||||
mViewport = new ViewController();
|
||||
mAnimator = new Animator(this);
|
||||
mLayers = new Layers(this);
|
||||
@ -237,9 +240,19 @@ public abstract class Map implements TaskQueue {
|
||||
/**
|
||||
* Set {@link MapPosition} of {@link Viewport} and trigger a redraw.
|
||||
*/
|
||||
public void setMapPosition(MapPosition mapPosition) {
|
||||
mViewport.setMapPosition(mapPosition);
|
||||
updateMap(true);
|
||||
public void setMapPosition(final MapPosition mapPosition) {
|
||||
if (!ThreadUtils.isMainThread())
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mViewport.setMapPosition(mapPosition);
|
||||
updateMap(true);
|
||||
}
|
||||
});
|
||||
else {
|
||||
mViewport.setMapPosition(mapPosition);
|
||||
updateMap(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMapPosition(double latitude, double longitude, double scale) {
|
||||
@ -253,6 +266,10 @@ public abstract class Map implements TaskQueue {
|
||||
* @return true when MapPosition was updated (has changed)
|
||||
*/
|
||||
public boolean getMapPosition(MapPosition mapPosition) {
|
||||
if (!ThreadUtils.isMainThread()) {
|
||||
return mViewport.getSyncMapPosition(mapPosition);
|
||||
}
|
||||
|
||||
return mViewport.getMapPosition(mapPosition);
|
||||
}
|
||||
|
||||
@ -289,14 +306,18 @@ public abstract class Map implements TaskQueue {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is run on main-loop before rendering a frame.
|
||||
* Caution: Do not call directly!
|
||||
* This function is run on main-thread before rendering a frame.
|
||||
*
|
||||
* For internal use only. Do not call!
|
||||
*/
|
||||
protected void updateLayers() {
|
||||
boolean changed = false;
|
||||
protected void prepareFrame() {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
MapPosition pos = mMapPosition;
|
||||
|
||||
changed |= mViewport.getMapPosition(pos);
|
||||
mAnimator.updateAnimation();
|
||||
|
||||
boolean changed = mViewport.getMapPosition(pos);
|
||||
|
||||
if (mClearMap)
|
||||
events.fire(CLEAR_EVENT, pos);
|
||||
@ -306,9 +327,17 @@ public abstract class Map implements TaskQueue {
|
||||
events.fire(UPDATE_EVENT, pos);
|
||||
|
||||
mClearMap = false;
|
||||
|
||||
mAnimator.updateAnimation();
|
||||
|
||||
mViewport.syncViewport();
|
||||
}
|
||||
|
||||
public boolean handleGesture(Gesture g, MotionEvent e) {
|
||||
return mLayers.handleGesture(g, e);
|
||||
}
|
||||
|
||||
public abstract void beginFrame();
|
||||
|
||||
public abstract void doneFrame();
|
||||
}
|
||||
|
@ -5,10 +5,13 @@ import org.oscim.core.Point;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.GLMatrix;
|
||||
import org.oscim.utils.FastMath;
|
||||
import org.oscim.utils.ThreadUtils;
|
||||
|
||||
public class ViewController extends Viewport {
|
||||
|
||||
public synchronized void setScreenSize(int width, int height) {
|
||||
public void setScreenSize(int width, int height) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mHeight = height;
|
||||
mWidth = width;
|
||||
|
||||
@ -50,7 +53,9 @@ public class ViewController extends Viewport {
|
||||
* @param mx the amount of pixels to move the map horizontally.
|
||||
* @param my the amount of pixels to move the map vertically.
|
||||
*/
|
||||
public synchronized void moveMap(float mx, float my) {
|
||||
public void moveMap(float mx, float my) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
Point p = applyRotation(mx, my);
|
||||
double tileScale = mPos.scale * Tile.SIZE;
|
||||
moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale);
|
||||
@ -94,7 +99,9 @@ public class ViewController extends Viewport {
|
||||
* @param pivotY
|
||||
* @return true if scale was changed
|
||||
*/
|
||||
public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||
public boolean scaleMap(float scale, float pivotX, float pivotY) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
// just sanitize input
|
||||
//scale = FastMath.clamp(scale, 0.5f, 2);
|
||||
if (scale < 0.000001)
|
||||
@ -126,7 +133,8 @@ public class ViewController extends Viewport {
|
||||
* @param pivotX
|
||||
* @param pivotY
|
||||
*/
|
||||
public synchronized void rotateMap(double radians, float pivotX, float pivotY) {
|
||||
public void rotateMap(double radians, float pivotX, float pivotY) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
double rsin = Math.sin(radians);
|
||||
double rcos = Math.cos(radians);
|
||||
@ -139,7 +147,9 @@ public class ViewController extends Viewport {
|
||||
setRotation(mPos.bearing + Math.toDegrees(radians));
|
||||
}
|
||||
|
||||
public synchronized void setRotation(double degree) {
|
||||
public void setRotation(double degree) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
while (degree > 180)
|
||||
degree -= 360;
|
||||
while (degree < -180)
|
||||
@ -149,11 +159,15 @@ public class ViewController extends Viewport {
|
||||
updateMatrices();
|
||||
}
|
||||
|
||||
public synchronized boolean tiltMap(float move) {
|
||||
public boolean tiltMap(float move) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
return setTilt(mPos.tilt + move);
|
||||
}
|
||||
|
||||
public synchronized boolean setTilt(float tilt) {
|
||||
public boolean setTilt(float tilt) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
tilt = FastMath.clamp(tilt, 0, MAX_TILT);
|
||||
if (tilt == mPos.tilt)
|
||||
return false;
|
||||
@ -162,7 +176,9 @@ public class ViewController extends Viewport {
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void setMapPosition(MapPosition mapPosition) {
|
||||
public void setMapPosition(MapPosition mapPosition) {
|
||||
ThreadUtils.assertMainThread();
|
||||
|
||||
mPos.scale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE);
|
||||
mPos.x = mapPosition.x;
|
||||
mPos.y = mapPosition.y;
|
||||
@ -199,4 +215,30 @@ public class ViewController extends Viewport {
|
||||
/* (AB)^-1 = B^-1*A^-1, invert projection */
|
||||
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixInverse);
|
||||
}
|
||||
|
||||
public final Viewport mNextFrame = new Viewport();
|
||||
|
||||
/** synchronize on this object when doing multiple calls on it */
|
||||
public final Viewport getSyncViewport() {
|
||||
return mNextFrame;
|
||||
}
|
||||
|
||||
void syncViewport() {
|
||||
synchronized (mNextFrame) {
|
||||
mNextFrame.copy(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getSyncViewport(Viewport v) {
|
||||
synchronized (mNextFrame) {
|
||||
return v.copy(mNextFrame);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getSyncMapPosition(MapPosition mapPosition) {
|
||||
synchronized (mNextFrame) {
|
||||
return mNextFrame.getMapPosition(mapPosition);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ public class Viewport {
|
||||
* @return true iff current position is different from
|
||||
* passed position.
|
||||
*/
|
||||
public synchronized boolean getMapPosition(MapPosition pos) {
|
||||
public boolean getMapPosition(MapPosition pos) {
|
||||
|
||||
boolean changed = (pos.scale != mPos.scale
|
||||
|| pos.x != mPos.x
|
||||
@ -114,7 +114,7 @@ public class Viewport {
|
||||
* @param box float[8] will be set.
|
||||
* @param add increase extents of box
|
||||
*/
|
||||
public synchronized void getMapExtents(float[] box, float add) {
|
||||
public void getMapExtents(float[] box, float add) {
|
||||
float t = getDepth(1);
|
||||
float t2 = getDepth(-1);
|
||||
|
||||
@ -143,6 +143,8 @@ public class Viewport {
|
||||
* Get Z-value of the map-plane for a point on screen -
|
||||
* calculate the intersection of a ray from camera origin
|
||||
* and the map plane
|
||||
* TODO use
|
||||
* www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf
|
||||
*/
|
||||
protected float getDepth(float y) {
|
||||
// origin is moved by VIEW_DISTANCE
|
||||
@ -244,7 +246,7 @@ public class Viewport {
|
||||
* @param y screen coordinate
|
||||
* @return the corresponding GeoPoint
|
||||
*/
|
||||
public synchronized GeoPoint fromScreenPoint(float x, float y) {
|
||||
public GeoPoint fromScreenPoint(float x, float y) {
|
||||
fromScreenPoint(x, y, mMovePoint);
|
||||
return new GeoPoint(
|
||||
MercatorProjection.toLatitude(mMovePoint.y),
|
||||
@ -257,7 +259,7 @@ public class Viewport {
|
||||
* @param x screen coordinate
|
||||
* @param y screen coordinate
|
||||
*/
|
||||
public synchronized void fromScreenPoint(double x, double y, Point out) {
|
||||
public void fromScreenPoint(double x, double y, Point out) {
|
||||
// scale to -1..1
|
||||
float mx = (float) (1 - (x / mWidth * 2));
|
||||
float my = (float) (1 - (y / mHeight * 2));
|
||||
@ -294,7 +296,7 @@ public class Viewport {
|
||||
* @param geoPoint the GeoPoint
|
||||
* @param out Point projected to screen pixel relative to center
|
||||
*/
|
||||
public synchronized void toScreenPoint(GeoPoint geoPoint, Point out) {
|
||||
public void toScreenPoint(GeoPoint geoPoint, Point out) {
|
||||
MercatorProjection.project(geoPoint, out);
|
||||
toScreenPoint(out.x, out.y, out);
|
||||
}
|
||||
@ -304,7 +306,7 @@ public class Viewport {
|
||||
*
|
||||
* @param out Point projected to screen coordinate
|
||||
*/
|
||||
public synchronized void toScreenPoint(double x, double y, Point out) {
|
||||
public void toScreenPoint(double x, double y, Point out) {
|
||||
|
||||
double cs = mPos.scale * Tile.SIZE;
|
||||
double cx = mPos.x * cs;
|
||||
@ -322,20 +324,17 @@ public class Viewport {
|
||||
out.y = -(mv[1] * (mHeight / 2));
|
||||
}
|
||||
|
||||
public synchronized boolean copy(Viewport viewport) {
|
||||
protected boolean copy(Viewport viewport) {
|
||||
mHeight = viewport.mHeight;
|
||||
mWidth = viewport.mWidth;
|
||||
mProjMatrix.copy(viewport.mProjMatrix);
|
||||
mProjMatrixUnscaled.copy(viewport.mProjMatrixUnscaled);
|
||||
mProjMatrixInverse.copy(viewport.mProjMatrixInverse);
|
||||
|
||||
mUnprojMatrix.copy(viewport.mUnprojMatrix);
|
||||
mRotationMatrix.copy(viewport.mRotationMatrix);
|
||||
mViewMatrix.copy(viewport.mViewMatrix);
|
||||
mViewProjMatrix.copy(viewport.mViewProjMatrix);
|
||||
return viewport.getMapPosition(mPos);
|
||||
}
|
||||
|
||||
public synchronized void initFrom(Viewport viewport) {
|
||||
mProjMatrix.copy(viewport.mProjMatrix);
|
||||
mProjMatrixUnscaled.copy(viewport.mProjMatrixUnscaled);
|
||||
mProjMatrixInverse.copy(viewport.mProjMatrixInverse);
|
||||
|
||||
mHeight = viewport.mHeight;
|
||||
mWidth = viewport.mWidth;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.oscim.renderer;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.map.Map;
|
||||
import org.oscim.map.Viewport;
|
||||
|
||||
public class GLViewport extends Viewport {
|
||||
@ -40,8 +41,8 @@ public class GLViewport extends Viewport {
|
||||
return changed;
|
||||
}
|
||||
|
||||
void setFrom(Viewport viewport) {
|
||||
changed = super.copy(viewport);
|
||||
void setFrom(Map map) {
|
||||
changed = map.viewport().getSyncViewport(this);
|
||||
getMapExtents(plane, 0);
|
||||
}
|
||||
|
||||
|
@ -70,10 +70,28 @@ public class MapRenderer {
|
||||
mClearColor = GLUtils.colorToFloat(color);
|
||||
}
|
||||
|
||||
private final Runnable renderBegin = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMap.beginFrame();
|
||||
}
|
||||
};
|
||||
private final Runnable renderDone = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMap.doneFrame();
|
||||
}
|
||||
};
|
||||
|
||||
public void onDrawFrame() {
|
||||
frametime = System.currentTimeMillis();
|
||||
|
||||
mMap.post(renderBegin);
|
||||
|
||||
draw();
|
||||
|
||||
mMap.post(renderDone);
|
||||
|
||||
mBufferPool.releaseBuffers();
|
||||
TextureItem.disposeTextures();
|
||||
}
|
||||
@ -98,8 +116,7 @@ public class MapRenderer {
|
||||
GLState.bindElementBuffer(-1);
|
||||
GLState.bindVertexBuffer(-1);
|
||||
|
||||
mMap.animator().updateAnimation();
|
||||
mViewport.setFrom(mMap.viewport());
|
||||
mViewport.setFrom(mMap);
|
||||
|
||||
if (GLAdapter.debugView) {
|
||||
/* modify this to scale only the view, to see
|
||||
@ -145,8 +162,6 @@ public class MapRenderer {
|
||||
if (width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
//mMap.viewport().getMatrix(null, mMatrices.proj, null);
|
||||
mViewport.initFrom(mMap.viewport());
|
||||
gl.viewport(0, 0, width, height);
|
||||
|
||||
//GL.scissor(0, 0, width, height);
|
||||
|
20
vtm/src/org/oscim/utils/ThreadUtils.java
Normal file
20
vtm/src/org/oscim/utils/ThreadUtils.java
Normal file
@ -0,0 +1,20 @@
|
||||
package org.oscim.utils;
|
||||
|
||||
public class ThreadUtils {
|
||||
|
||||
private static Thread MAIN_THREAD;
|
||||
|
||||
public static void assertMainThread() {
|
||||
if (MAIN_THREAD != Thread.currentThread())
|
||||
throw new RuntimeException("Access from non-main thread!");
|
||||
}
|
||||
|
||||
public static boolean isMainThread() {
|
||||
return MAIN_THREAD == Thread.currentThread();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
MAIN_THREAD = Thread.currentThread();
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user