Viewport screen-pivot + extent option
This commit is contained in:
parent
da93f0ab72
commit
6f85e24ed9
@ -11,6 +11,10 @@ import org.oscim.utils.ThreadUtils;
|
|||||||
|
|
||||||
public class ViewController extends Viewport {
|
public class ViewController extends Viewport {
|
||||||
|
|
||||||
|
protected float mPivotY = 0.0f;
|
||||||
|
|
||||||
|
private final float[] mat = new float[16];
|
||||||
|
|
||||||
public void setScreenSize(int width, int height) {
|
public void setScreenSize(int width, int height) {
|
||||||
ThreadUtils.assertMainThread();
|
ThreadUtils.assertMainThread();
|
||||||
|
|
||||||
@ -26,19 +30,19 @@ public class ViewController extends Viewport {
|
|||||||
* 1. invert translate to VIEW_DISTANCE */
|
* 1. invert translate to VIEW_DISTANCE */
|
||||||
|
|
||||||
float ratio = (mHeight / mWidth) * VIEW_SCALE;
|
float ratio = (mHeight / mWidth) * VIEW_SCALE;
|
||||||
float[] tmp = new float[16];
|
|
||||||
|
|
||||||
GLMatrix.frustumM(tmp, 0, -VIEW_SCALE, VIEW_SCALE,
|
GLMatrix.frustumM(mat, 0, -VIEW_SCALE, VIEW_SCALE,
|
||||||
ratio, -ratio, VIEW_NEAR, VIEW_FAR);
|
ratio, -ratio, VIEW_NEAR, VIEW_FAR);
|
||||||
|
|
||||||
mProjMatrix.set(tmp);
|
mProjMatrix.set(mat);
|
||||||
|
|
||||||
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
|
mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE);
|
||||||
mProjMatrix.multiplyRhs(mTmpMatrix);
|
mProjMatrix.multiplyRhs(mTmpMatrix);
|
||||||
|
|
||||||
/* set inverse projection matrix (without scaling) */
|
/* set inverse projection matrix (without scaling) */
|
||||||
mProjMatrix.get(tmp);
|
mProjMatrix.get(mat);
|
||||||
GLMatrix.invertM(tmp, 0, tmp, 0);
|
GLMatrix.invertM(mat, 0, mat, 0);
|
||||||
mProjMatrixInverse.set(tmp);
|
mProjMatrixInverse.set(mat);
|
||||||
|
|
||||||
mProjMatrixUnscaled.copy(mProjMatrix);
|
mProjMatrixUnscaled.copy(mProjMatrix);
|
||||||
|
|
||||||
@ -49,6 +53,15 @@ public class ViewController extends Viewport {
|
|||||||
updateMatrices();
|
updateMatrices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set pivot height relative to screen center. E.g. 0.5 is usually preferred
|
||||||
|
* for navigation, moving the center to 25% of the screen height.
|
||||||
|
* Range is [-1, 1].
|
||||||
|
*/
|
||||||
|
public void setMapScreenCenter(float pivotY) {
|
||||||
|
mPivotY = FastMath.clamp(pivotY, -1, 1) * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves this Viewport by the given amount of pixels.
|
* Moves this Viewport by the given amount of pixels.
|
||||||
*
|
*
|
||||||
@ -120,10 +133,12 @@ public class ViewController extends Viewport {
|
|||||||
|
|
||||||
mPos.scale = newScale;
|
mPos.scale = newScale;
|
||||||
|
|
||||||
if (pivotX != 0 || pivotY != 0)
|
if (pivotX != 0 || pivotY != 0) {
|
||||||
|
pivotY -= mHeight * mPivotY;
|
||||||
|
|
||||||
moveMap(pivotX * (1.0f - scale),
|
moveMap(pivotX * (1.0f - scale),
|
||||||
pivotY * (1.0f - scale));
|
pivotY * (1.0f - scale));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +156,8 @@ public class ViewController extends Viewport {
|
|||||||
double rsin = Math.sin(radians);
|
double rsin = Math.sin(radians);
|
||||||
double rcos = Math.cos(radians);
|
double rcos = Math.cos(radians);
|
||||||
|
|
||||||
|
pivotY -= mHeight * mPivotY;
|
||||||
|
|
||||||
float x = (float) (pivotX - pivotX * rcos + pivotY * rsin);
|
float x = (float) (pivotX - pivotX * rcos + pivotY * rsin);
|
||||||
float y = (float) (pivotY - pivotX * rsin - pivotY * rcos);
|
float y = (float) (pivotY - pivotX * rsin - pivotY * rcos);
|
||||||
|
|
||||||
@ -202,20 +219,14 @@ public class ViewController extends Viewport {
|
|||||||
|
|
||||||
mViewMatrix.copy(mRotationMatrix);
|
mViewMatrix.copy(mRotationMatrix);
|
||||||
|
|
||||||
|
mTmpMatrix.setTranslation(0, mPivotY * mHeight, 0);
|
||||||
|
mViewMatrix.multiplyLhs(mTmpMatrix);
|
||||||
|
|
||||||
mViewProjMatrix.multiplyMM(mProjMatrix, mViewMatrix);
|
mViewProjMatrix.multiplyMM(mProjMatrix, mViewMatrix);
|
||||||
|
|
||||||
/* inverse projection matrix: */
|
mViewProjMatrix.get(mat);
|
||||||
/* invert scale */
|
GLMatrix.invertM(mat, 0, mat, 0);
|
||||||
mUnprojMatrix.setScale(mWidth, mWidth, 1);
|
mUnprojMatrix.set(mat);
|
||||||
|
|
||||||
/* invert rotation and tilt */
|
|
||||||
mTmpMatrix.transposeM(mRotationMatrix);
|
|
||||||
|
|
||||||
/* (AB)^-1 = B^-1*A^-1, invert scale, tilt and rotation */
|
|
||||||
mTmpMatrix.multiplyLhs(mUnprojMatrix);
|
|
||||||
|
|
||||||
/* (AB)^-1 = B^-1*A^-1, invert projection */
|
|
||||||
mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixInverse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Viewport mNextFrame = new Viewport();
|
public final Viewport mNextFrame = new Viewport();
|
||||||
|
@ -71,7 +71,7 @@ public class Viewport {
|
|||||||
/** scale map plane at VIEW_DISTANCE to near plane */
|
/** scale map plane at VIEW_DISTANCE to near plane */
|
||||||
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
public final static float VIEW_SCALE = (VIEW_NEAR / VIEW_DISTANCE) * 0.5f;
|
||||||
|
|
||||||
protected Viewport() {
|
public Viewport() {
|
||||||
mPos.scale = MIN_SCALE;
|
mPos.scale = MIN_SCALE;
|
||||||
mPos.x = 0.5;
|
mPos.x = 0.5;
|
||||||
mPos.y = 0.5;
|
mPos.y = 0.5;
|
||||||
@ -115,17 +115,14 @@ public class Viewport {
|
|||||||
* @param add increase extents of box
|
* @param add increase extents of box
|
||||||
*/
|
*/
|
||||||
public void getMapExtents(float[] box, float add) {
|
public void getMapExtents(float[] box, float add) {
|
||||||
float t = getDepth(1);
|
/* top-right */
|
||||||
float t2 = getDepth(-1);
|
unproject(1, -1, box, 0);
|
||||||
|
/* top-left */
|
||||||
// top-right
|
unproject(-1, -1, box, 2);
|
||||||
unproject(1, -1, t, box, 0);
|
/* bottom-left */
|
||||||
// top-left
|
unproject(-1, 1, box, 4);
|
||||||
unproject(-1, -1, t, box, 2);
|
/* bottom-right */
|
||||||
// bottom-left
|
unproject(1, 1, box, 6);
|
||||||
unproject(-1, 1, t2, box, 4);
|
|
||||||
// bottom-right
|
|
||||||
unproject(1, 1, t2, box, 6);
|
|
||||||
|
|
||||||
if (add == 0)
|
if (add == 0)
|
||||||
return;
|
return;
|
||||||
@ -139,49 +136,31 @@ public class Viewport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected void unproject(float x, float y, float[] coords, int position) {
|
||||||
* 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
|
|
||||||
double cx = VIEW_DISTANCE;
|
|
||||||
// 'height' of the ray
|
|
||||||
double ry = y * (mHeight / mWidth) * 0.5f;
|
|
||||||
|
|
||||||
double ua;
|
|
||||||
|
|
||||||
if (y == 0)
|
|
||||||
ua = 1;
|
|
||||||
else {
|
|
||||||
// tilt of the plane (center is kept on x = 0)
|
|
||||||
double t = Math.toRadians(mPos.tilt);
|
|
||||||
double px = y * Math.sin(t);
|
|
||||||
double py = y * Math.cos(t);
|
|
||||||
ua = 1 + (px * ry) / (py * cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
mv[0] = 0;
|
|
||||||
mv[1] = (float) (ry / ua);
|
|
||||||
mv[2] = (float) (cx - cx / ua);
|
|
||||||
|
|
||||||
mProjMatrixUnscaled.prj(mv);
|
|
||||||
|
|
||||||
return mv[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void unproject(float x, float y, float z, float[] coords, int position) {
|
|
||||||
mv[0] = x;
|
mv[0] = x;
|
||||||
mv[1] = y;
|
mv[1] = y;
|
||||||
mv[2] = z;
|
mv[2] = -1;
|
||||||
|
|
||||||
mUnprojMatrix.prj(mv);
|
mUnprojMatrix.prj(mv);
|
||||||
|
double nx = mv[0];
|
||||||
|
double ny = mv[1];
|
||||||
|
double nz = mv[2];
|
||||||
|
|
||||||
coords[position + 0] = mv[0];
|
mv[0] = x;
|
||||||
coords[position + 1] = mv[1];
|
mv[1] = y;
|
||||||
|
mv[2] = 1;
|
||||||
|
mUnprojMatrix.prj(mv);
|
||||||
|
double fx = mv[0];
|
||||||
|
double fy = mv[1];
|
||||||
|
double fz = mv[2];
|
||||||
|
|
||||||
|
double dx = fx - nx;
|
||||||
|
double dy = fy - ny;
|
||||||
|
double dz = fz - nz;
|
||||||
|
|
||||||
|
double dist = -nz / dz;
|
||||||
|
|
||||||
|
coords[position + 0] = (float) (nx + dist * dx);
|
||||||
|
coords[position + 1] = (float) (ny + dist * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,6 +232,14 @@ public class Viewport {
|
|||||||
MercatorProjection.toLongitude(mMovePoint.x));
|
MercatorProjection.toLongitude(mMovePoint.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void unprojectScreen(double x, double y, float[] out) {
|
||||||
|
/* scale to -1..1 */
|
||||||
|
float mx = (float) (1 - (x / mWidth * 2));
|
||||||
|
float my = (float) (1 - (y / mHeight * 2));
|
||||||
|
|
||||||
|
unproject(-mx, my, out, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the map position for x,y in screen coordinates.
|
* Get the map position for x,y in screen coordinates.
|
||||||
*
|
*
|
||||||
@ -260,11 +247,7 @@ public class Viewport {
|
|||||||
* @param y screen coordinate
|
* @param y screen coordinate
|
||||||
*/
|
*/
|
||||||
public void fromScreenPoint(double x, double y, Point out) {
|
public void fromScreenPoint(double x, double y, Point out) {
|
||||||
// scale to -1..1
|
unprojectScreen(x, y, mu);
|
||||||
float mx = (float) (1 - (x / mWidth * 2));
|
|
||||||
float my = (float) (1 - (y / mHeight * 2));
|
|
||||||
|
|
||||||
unproject(-mx, my, getDepth(-my), mu, 0);
|
|
||||||
|
|
||||||
double cs = mPos.scale * Tile.SIZE;
|
double cs = mPos.scale * Tile.SIZE;
|
||||||
double cx = mPos.x * cs;
|
double cx = mPos.x * cs;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user