reworking the gl projection/unprojection stuff

This commit is contained in:
Hannes Janetzek 2013-01-10 06:56:25 +01:00
parent dd3c0a71c3
commit 80de20a423
3 changed files with 146 additions and 58 deletions

@ -68,7 +68,8 @@ public class BaseLayer {
}
GLES20.glDisable(GL_POLYGON_OFFSET_FILL);
//GLES20.glFinish()
//Log.d(TAG, "building took " + (end - start));
mDrawSerial++;
}
@ -90,18 +91,18 @@ public class BaseLayer {
if (tile.layers == null)
return;
GLES20.glPolygonOffset(0, GLRenderer.depthOffset(tile));
// set depth offset (used for clipping to tile boundaries)
GLES20.glPolygonOffset(-1, -GLRenderer.depthOffset(tile));
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
boolean clipped = false;
int simpleShader = 0; // mRotate ? 0 : 1;
int simpleShader = (pos.tilt == 0 ? 1 : 0);
for (Layer l = tile.layers.layers; l != null;) {
switch (l.type) {
case Layer.POLYGON:
GLES20.glDisable(GL_BLEND);
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
clipped = true;
@ -114,6 +115,7 @@ public class BaseLayer {
}
// clip lines to quad in depth buffer
GLState.test(true, false);
GLES20.glEnable(GL_BLEND);
l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
tile.layers.lineOffset);
@ -138,7 +140,6 @@ public class BaseLayer {
float y = (float) (tile.pixelY - pos.y * div);
float scale = pos.scale / div;
//Matrix.setIdentityM(matrix, 0);
for (int i = 0; i < 16; i++)
matrix[i] = 0;
@ -153,8 +154,6 @@ public class BaseLayer {
matrix[10] = 1;
matrix[15] = 1;
// Matrix.multiplyMM(matrix, 0, pos.viewMatrix, 0, matrix, 0);
// Matrix.multiplyMM(matrix, 0, mfProjMatrix, 0, matrix, 0);
Matrix.multiplyMM(matrix, 0, mVPMatrix, 0, matrix, 0);
}

@ -494,7 +494,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
if (debugView) {
float mm = 0.5f;
GLState.test(false, false);
float mm = 0.25f; // * mHeight;
float min = -mm;
float max = mm;
float ymax = mm * mHeight / mWidth;
@ -511,10 +513,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
pos.zoomLevel = -1;
mMapViewPosition.getMapPosition(pos, mDebugCoords);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0,
pos.viewMatrix, 0);
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
}
if (GlUtils.checkGlOutOfMemory("finish")) {
@ -524,7 +528,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
public static int depthOffset(MapTile t) {
return ((t.tileX % 4) + (t.tileY % 4 * 4) * 2) * 20;
return ((t.tileX % 4) + (t.tileY % 4 * 4) + 1);
}
@Override
@ -547,16 +551,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
MapViewPosition.VIEW_FAR);
Matrix.setIdentityM(mTmpMatrix, 0);
Matrix.translateM(mTmpMatrix, 0, 0, 0, -MapViewPosition.VIEW_DISTANCE * 2);
Matrix.translateM(mTmpMatrix, 0, 0, 0, -MapViewPosition.VIEW_DISTANCE);
Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mTmpMatrix, 0);
if (debugView) {
// modify this to scale only the view, to see better which tiles are
// rendered
Matrix.setIdentityM(mMVPMatrix, 0);
Matrix.scaleM(mMVPMatrix, 0, 0.5f, 0.5f, 1);
Matrix.multiplyMM(mProjMatrix, 0, mMVPMatrix, 0, mProjMatrix, 0);
}
// if (debugView) {
// // modify this to scale only the view, to see better which tiles are
// // rendered
// Matrix.setIdentityM(mMVPMatrix, 0);
// Matrix.scaleM(mMVPMatrix, 0, 0.75f, 0.75f, 1);
// Matrix.multiplyMM(mProjMatrix, 0, mMVPMatrix, 0, mProjMatrix, 0);
// }
BaseLayer.setProjection(mProjMatrix);
@ -578,17 +582,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
int numVBO = (CACHE_TILES + (numTiles * 2));
BufferObject.init(numVBO);
// Set up textures
// TextRenderer.setup(numTiles);
if (mClearColor != null)
mUpdateColor = true;
GLState.init();
//vertexArray[0] = false;
//vertexArray[1] = false;
mMapView.redrawMap();
}

@ -26,6 +26,7 @@ import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection;
import org.oscim.core.Tile;
import org.oscim.utils.FastMath;
import org.oscim.utils.GeometryUtils.Point2D;
import android.graphics.Point;
import android.opengl.Matrix;
@ -46,7 +47,7 @@ public class MapViewPosition {
public final static int MAX_ZOOMLEVEL = 17;
public final static int MIN_ZOOMLEVEL = 2;
private final static float MAX_ANGLE = 40;
private final static float MAX_ANGLE = 42;
private final MapView mMapView;
@ -86,11 +87,25 @@ public class MapViewPosition {
private float[] mRotMatrix = new float[16];
private float[] mTmpMatrix = new float[16];
private static int mHeight, mWidth;
public final static float VIEW_SCALE = 1f / 4;
public final static float VIEW_DISTANCE = 1;
public final static float VIEW_NEAR = VIEW_DISTANCE;
public final static float VIEW_FAR = VIEW_DISTANCE * 4;
// only use in synchronized functions!
Point2D mMovePoint = new Point2D();
private static float mHeight, mWidth;
// public final static float VIEW_SCALE = 1 / 4f;
// public final static float VIEW_DISTANCE = 2f;
// public final static float VIEW_NEAR = 1;
// public final static float VIEW_FAR = 4;
// public final static float VIEW_SCALE = 1 / 3f;
// public final static float VIEW_DISTANCE = 2.7f;
// public final static float VIEW_NEAR = 2;
// public final static float VIEW_FAR = 4;
public final static float VIEW_SCALE = 1 / 4f;
public final static float VIEW_DISTANCE = 3.0f;
public final static float VIEW_NEAR = 2;
public final static float VIEW_FAR = 8;
void setViewport(int width, int height) {
float sw = VIEW_SCALE;
@ -101,11 +116,27 @@ public class MapViewPosition {
aspect * sh, -aspect * sh, VIEW_NEAR, VIEW_FAR);
Matrix.setIdentityM(mTmpMatrix, 0);
Matrix.translateM(mTmpMatrix, 0, 0, 0, -VIEW_DISTANCE * 2);
Matrix.translateM(mTmpMatrix, 0, 0, 0, -VIEW_DISTANCE);
Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mTmpMatrix, 0);
Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0);
mv[0] = 0;
mv[1] = 1;
mv[2] = 0;
mv[3] = 1;
Matrix.multiplyMV(mv, 0, mProjMatrixI, 0, mv, 0);
Log.d(TAG, " " + mv[0] + " " + mv[1] + " " + mv[2]);
Log.d(TAG, " " + mv[0] / mv[3] + " " + mv[1] / mv[3] + " " + mv[2] / mv[3]);
mv[0] = 0;
mv[1] = 1;
mv[2] = 1;
mv[3] = 1;
Matrix.multiplyMV(mv, 0, mProjMatrixI, 0, mv, 0);
Log.d(TAG, " " + mv[0] + " " + mv[1] + " " + mv[2]);
Log.d(TAG, " " + mv[0] / mv[3] + " " + mv[1] / mv[3] + " " + mv[2] / mv[3]);
mHeight = height;
mWidth = width;
@ -143,16 +174,72 @@ public class MapViewPosition {
if (coords == null)
return true;
float tilt = getZ(1);
// float tilt = getZ(1);
unproject(-1, 1, tilt, coords, 0); // bottom-left
unproject(1, 1, tilt, coords, 2); // bottom-right
unproject(1, -1, -tilt, coords, 4); // top-right
unproject(-1, -1, -tilt, coords, 6); // top-left
float t = getZ2(1);
float t2 = getZ2(-1);
//Log.d(TAG, "t:" + mTilt + " z: " + tilt + " -> " + t + " " + t2);
//
// unproject(-1, 1, tilt, coords, 0); // bottom-left
// unproject(1, 1, tilt, coords, 2); // bottom-right
// unproject(1, -1, -tilt, coords, 4); // top-right
// unproject(-1, -1, -tilt, coords, 6); // top-left
unproject2(-1, 1, t2, coords, 4); // bottom-left
unproject2(1, 1, t2, coords, 6); // bottom-right
unproject2(1, -1, t, coords, 0); // top-right
unproject2(-1, -1, t, coords, 2); // top-left
// Log.d(TAG, "" + coords[0] + ":" + coords[1] + ", " + coords[2] + ":" + coords[3] + ", "
// + ", " + coords[4] + ":" + coords[5] + ", " + ", " + coords[6] + ":" + coords[7]);
return true;
}
private float getZ2(float y) {
mv[0] = 0;
mv[1] = y;
mv[2] = -0.1f; //FIXME! please
mv[3] = 1;
Matrix.setRotateM(mTmpMatrix, 0, mTilt, 1, 0, 0);
Matrix.multiplyMV(mv, 0, mTmpMatrix, 0, mv, 0);
Matrix.multiplyMV(mv, 0, mProjMatrix, 0, mv, 0);
//d = d / (VIEW_FAR - VIEW_NEAR);
//Log.d(TAG, " > " + mv[2] / mv[3] + " (" + mv[2] + " " + mv[3] + ")");
float d = mv[2] / mv[3];
Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
//Log.d(TAG, " < " + mv[2] / mv[3] + " (" + mv[2] + " " + mv[3] + ")");
return d;
}
private void unproject2(float x, float y, float z, float[] coords, int position) {
mv[0] = x;
mv[1] = y;
mv[2] = z;
mv[3] = 1;
//float a = (float) Math.sqrt(x * x + y * y + z * z + 1);
// mv[0] /= a;
// mv[1] /= a;
// mv[2] /= a;
//mv[3] = a;
Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
if (mv[3] != 0) {
coords[position] = mv[0] / mv[3];
coords[position + 1] = (mv[1] / mv[3]);
} else {
// else what?
Log.d(TAG, "uproject failed");
}
}
/** @return the current center point of the MapView. */
public synchronized GeoPoint getMapCenter() {
return new GeoPoint(mLatitude, mLongitude);
@ -188,11 +275,19 @@ public class MapViewPosition {
float[] coords = mBBoxCoords;
float tilt = getZ(1);
unproject(-1, 1, -tilt, coords, 0); // top-left
unproject(1, 1, -tilt, coords, 2); // top-right
unproject(1, -1, tilt, coords, 4); // bottom-right
unproject(-1, -1, tilt, coords, 6); // bottom-left
// float tilt = getZ(1);
float t = getZ(1);
float t2 = getZ(-1);
// unproject(-1, 1, -tilt, coords, 0); // top-left
// unproject(1, 1, -tilt, coords, 2); // top-right
// unproject(1, -1, tilt, coords, 4); // bottom-right
// unproject(-1, -1, tilt, coords, 6); // bottom-left
unproject2(-1, 1, t2, coords, 4); // bottom-left
unproject2(1, 1, t2, coords, 6); // bottom-right
unproject2(1, -1, t, coords, 0); // top-right
unproject2(-1, -1, t, coords, 2); // top-left
byte z = mZoomLevel;
double dx, dy;
@ -237,7 +332,7 @@ public class MapViewPosition {
//* 1.3f // for dist = 2
//* 0.8f // for dist = 4
* 0.5f
* ((float) mHeight / mWidth) * y;
* (mHeight / mWidth) * y;
}
/**
@ -254,10 +349,11 @@ public class MapViewPosition {
float mx = ((mWidth / 2) - x) / (mWidth / 2);
float my = ((mHeight / 2) - y) / (mHeight / 2);
unproject(-mx, my, getZ(my), mu, 0);
unproject2(-mx, my, getZ2(-my), mu, 0);
out.x = (int) (mPosX + mu[0] / mScale);
out.y = (int) (mPosY + mu[1] / mScale);
Log.d(">>>", "getScreenPointOnMap " + reuse);
return out;
}
@ -272,7 +368,7 @@ public class MapViewPosition {
float mx = ((mWidth / 2) - x) / (mWidth / 2);
float my = ((mHeight / 2) - y) / (mHeight / 2);
unproject(-mx, my, getZ(my), mu, 0);
unproject2(-mx, my, getZ2(-my), mu, 0);
double dx = mPosX + mu[0] / mScale;
double dy = mPosY + mu[1] / mScale;
@ -281,7 +377,7 @@ public class MapViewPosition {
MercatorProjection.pixelYToLatitude(dy, mZoomLevel),
MercatorProjection.pixelXToLongitude(dx, mZoomLevel));
// Log.d(">>>", "fromScreenPixels " + p);
Log.d(">>>", "fromScreenPixels " + p);
return p;
}
@ -385,7 +481,6 @@ public class MapViewPosition {
// Matrix.multiplyMM(mViewMatrix, 0, mTmpMatrix, 0, mViewMatrix, 0);
// get unproject matrix:
// Matrix.invertM(mTmpMatrix, 0, mViewMatrix, 0);
Matrix.setIdentityM(mUnprojMatrix, 0);
// inverse scale
@ -400,6 +495,10 @@ public class MapViewPosition {
// unapply projection, tilt, rotate and scale
// (AB)^-1 = B^-1*A^-1
Matrix.multiplyMM(mUnprojMatrix, 0, mTmpMatrix, 0, mProjMatrixI, 0);
Matrix.multiplyMM(mTmpMatrix, 0, mProjMatrix, 0, mViewMatrix, 0);
Matrix.invertM(mUnprojMatrix, 0, mTmpMatrix, 0);
}
/** @return true if this MapViewPosition is valid, false otherwise. */
@ -423,33 +522,24 @@ public class MapViewPosition {
return true;
}
// JAVA...
class Point2D {
double x;
double y;
}
// only use in synchronized functions!
Point2D mMovePoint = new Point2D();
/**
* Moves this MapViewPosition by the given amount of pixels.
* @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) {
getMove(mx, my);
Point2D p = getMove(mx, my);
mLatitude = MercatorProjection.pixelYToLatitude(mPosY - mMovePoint.y, mZoomLevel);
mLatitude = MercatorProjection.pixelYToLatitude(mPosY - p.y, mZoomLevel);
mLatitude = MercatorProjection.limitLatitude(mLatitude);
mLongitude = MercatorProjection.pixelXToLongitude(mPosX - mMovePoint.x, mZoomLevel);
mLongitude = MercatorProjection.pixelXToLongitude(mPosX - p.x, mZoomLevel);
mLongitude = MercatorProjection.wrapLongitude(mLongitude);
updatePosition();
}
private void getMove(float mx, float my) {
private Point2D getMove(float mx, float my) {
double dx = mx / mScale;
double dy = my / mScale;
@ -465,6 +555,7 @@ public class MapViewPosition {
mMovePoint.x = dx;
mMovePoint.y = dy;
return mMovePoint;
}
/**