From 80de20a423c02b8934e581b782325685f6780874 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Thu, 10 Jan 2013 06:56:25 +0100 Subject: [PATCH] reworking the gl projection/unprojection stuff --- src/org/oscim/renderer/BaseLayer.java | 13 +- src/org/oscim/renderer/GLRenderer.java | 30 +++-- src/org/oscim/view/MapViewPosition.java | 161 ++++++++++++++++++------ 3 files changed, 146 insertions(+), 58 deletions(-) diff --git a/src/org/oscim/renderer/BaseLayer.java b/src/org/oscim/renderer/BaseLayer.java index b93c8083..053346a7 100644 --- a/src/org/oscim/renderer/BaseLayer.java +++ b/src/org/oscim/renderer/BaseLayer.java @@ -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); } diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index c58bd797..d7d400d4 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -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(); } diff --git a/src/org/oscim/view/MapViewPosition.java b/src/org/oscim/view/MapViewPosition.java index 6789ce26..92f7a2cb 100644 --- a/src/org/oscim/view/MapViewPosition.java +++ b/src/org/oscim/view/MapViewPosition.java @@ -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; } /**