diff --git a/src/org/oscim/core/MercatorProjection.java b/src/org/oscim/core/MercatorProjection.java
index 8406e48b..b9e2df14 100644
--- a/src/org/oscim/core/MercatorProjection.java
+++ b/src/org/oscim/core/MercatorProjection.java
@@ -44,10 +44,12 @@ public final class MercatorProjection {
public static final double LONGITUDE_MIN = -LONGITUDE_MAX;
/**
- * Calculates the distance on the ground that is represented by a single pixel on the map.
+ * Calculates the distance on the ground that is represented by a single
+ * pixel on the map.
*
* @param latitude
- * the latitude coordinate at which the resolution should be calculated.
+ * the latitude coordinate at which the resolution should be
+ * calculated.
* @param zoomLevel
* the zoom level at which the resolution should be calculated.
* @return the ground resolution at the given latitude and zoom level.
@@ -58,7 +60,8 @@ public final class MercatorProjection {
}
/**
- * Converts a latitude coordinate (in degrees) to a pixel Y coordinate at a certain zoom level.
+ * Converts a latitude coordinate (in degrees) to a pixel Y coordinate at a
+ * certain zoom level.
*
* @param latitude
* the latitude coordinate that should be converted.
@@ -79,7 +82,8 @@ public final class MercatorProjection {
}
/**
- * Converts a latitude coordinate (in degrees) to a tile Y number at a certain zoom level.
+ * Converts a latitude coordinate (in degrees) to a tile Y number at a
+ * certain zoom level.
*
* @param latitude
* the latitude coordinate that should be converted.
@@ -103,7 +107,8 @@ public final class MercatorProjection {
/**
* @param longitude
* the longitude value which should be checked.
- * @return the given longitude value, limited to the possible longitude range.
+ * @return the given longitude value, limited to the possible longitude
+ * range.
*/
public static double limitLongitude(double longitude) {
return Math.max(Math.min(longitude, LONGITUDE_MAX), LONGITUDE_MIN);
@@ -120,7 +125,8 @@ public final class MercatorProjection {
}
/**
- * Converts a longitude coordinate (in degrees) to a pixel X coordinate at a certain zoom level.
+ * Converts a longitude coordinate (in degrees) to a pixel X coordinate at a
+ * certain zoom level.
*
* @param longitude
* the longitude coordinate that should be converted.
@@ -138,7 +144,8 @@ public final class MercatorProjection {
}
/**
- * Converts a longitude coordinate (in degrees) to the tile X number at a certain zoom level.
+ * Converts a longitude coordinate (in degrees) to the tile X number at a
+ * certain zoom level.
*
* @param longitude
* the longitude coordinate that should be converted.
@@ -151,7 +158,8 @@ public final class MercatorProjection {
}
/**
- * Converts a pixel X coordinate at a certain zoom level to a longitude coordinate.
+ * Converts a pixel X coordinate at a certain zoom level to a longitude
+ * coordinate.
*
* @param pixelX
* the pixel X coordinate that should be converted.
@@ -178,7 +186,8 @@ public final class MercatorProjection {
}
/**
- * Converts a pixel Y coordinate at a certain zoom level to a latitude coordinate.
+ * Converts a pixel Y coordinate at a certain zoom level to a latitude
+ * coordinate.
*
* @param pixelY
* the pixel Y coordinate that should be converted.
@@ -206,7 +215,8 @@ public final class MercatorProjection {
}
/**
- * Converts a tile X number at a certain zoom level to a longitude coordinate.
+ * Converts a tile X number at a certain zoom level to a longitude
+ * coordinate.
*
* @param tileX
* the tile X number that should be converted.
@@ -219,7 +229,8 @@ public final class MercatorProjection {
}
/**
- * Converts a tile Y number at a certain zoom level to a latitude coordinate.
+ * Converts a tile Y number at a certain zoom level to a latitude
+ * coordinate.
*
* @param tileY
* the tile Y number that should be converted.
diff --git a/src/org/oscim/utils/FastMath.java b/src/org/oscim/utils/FastMath.java
new file mode 100644
index 00000000..ae46db64
--- /dev/null
+++ b/src/org/oscim/utils/FastMath.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Hannes Janetzek
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.utils;
+
+public class FastMath {
+ /**
+ * from http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
+ *
+ * @param v
+ * ...
+ * @return ...
+ */
+ public static int log2(int v) {
+
+ int r = 0; // result of log2(v) will go here
+
+ if ((v & 0xFFFF0000) != 0) {
+ v >>= 16;
+ r |= 16;
+ }
+ if ((v & 0xFF00) != 0) {
+ v >>= 8;
+ r |= 8;
+ }
+ if ((v & 0xF0) != 0) {
+ v >>= 4;
+ r |= 4;
+ }
+ if ((v & 0xC) != 0) {
+ v >>= 2;
+ r |= 2;
+ }
+ if ((v & 0x2) != 0) {
+ r |= 1;
+ }
+ return r;
+ }
+}
diff --git a/src/org/oscim/view/DelayedTaskHandler.java b/src/org/oscim/view/DelayedTaskHandler.java
new file mode 100644
index 00000000..a25d7b79
--- /dev/null
+++ b/src/org/oscim/view/DelayedTaskHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Hannes Janetzek
+ *
+ * This program is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * this program. If not, see .
+ */
+package org.oscim.view;
+
+import android.os.Handler;
+import android.os.Message;
+
+public class DelayedTaskHandler extends Handler {
+ public final int MESSAGE_UPDATE_POSITION = 1;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_UPDATE_POSITION:
+
+ break;
+
+ }
+ }
+}
diff --git a/src/org/oscim/view/MapView.java b/src/org/oscim/view/MapView.java
index 2de20e42..3b962745 100644
--- a/src/org/oscim/view/MapView.java
+++ b/src/org/oscim/view/MapView.java
@@ -83,6 +83,8 @@ public class MapView extends FrameLayout {
private String mRenderTheme;
private Map mMapOptions;
+ // private final Handler mHandler;
+
/**
* @param context
* the enclosing MapActivity instance.
@@ -124,6 +126,8 @@ public class MapView extends FrameLayout {
MapActivity mapActivity = (MapActivity) context;
+ // mHandler = new DelayedTaskHandler();
+
debugSettings = new DebugSettings(false, false, false, false);
mMapDatabaseType = mapDatabaseType;
@@ -205,6 +209,29 @@ public class MapView extends FrameLayout {
return mMapViewPosition;
}
+ public void enableRotation(boolean enable) {
+ enableRotation = enable;
+
+ if (enable) {
+ enableCompass(false);
+ }
+ }
+
+ public void enableCompass(boolean enable) {
+ if (enable == this.enableCompass)
+ return;
+
+ this.enableCompass = enable;
+
+ if (enable)
+ enableRotation(false);
+
+ if (enable)
+ mCompass.enable();
+ else
+ mCompass.disable();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
// mMapZoomControls.onMapViewTouchEvent(motionEvent.getAction()
@@ -601,30 +628,6 @@ public class MapView extends FrameLayout {
mapWorker.proceed();
}
- public void enableRotation(boolean enable) {
- enableRotation = enable;
-
- if (enable) {
- enableCompass(false);
- }
- }
-
- public void enableCompass(boolean enable) {
- if (enable == this.enableCompass)
- return;
-
- this.enableCompass = enable;
-
- if (enable)
- enableRotation(false);
-
- if (enable)
- mCompass.enable();
- else
- mCompass.disable();
-
- }
-
// /**
// * Sets the visibility of the zoom controls.
// *
@@ -647,18 +650,4 @@ public class MapView extends FrameLayout {
// mJobParameters = new JobParameters(mJobParameters.theme, textScale);
// clearAndRedrawMapView();
// }
-
- // public final int
- // public Handler messageHandler = new Handler() {
- //
- // @Override
- // public void handleMessage(Message msg) {
- // switch (msg.what) {
- // // handle update
- // // .....
- // }
- // }
- //
- // };
-
}
diff --git a/src/org/oscim/view/MapViewPosition.java b/src/org/oscim/view/MapViewPosition.java
index 241b41a0..4a3086a2 100644
--- a/src/org/oscim/view/MapViewPosition.java
+++ b/src/org/oscim/view/MapViewPosition.java
@@ -17,25 +17,35 @@ package org.oscim.view;
import org.oscim.core.GeoPoint;
import org.oscim.core.MapPosition;
import org.oscim.core.MercatorProjection;
-
-import android.util.FloatMath;
+import org.oscim.utils.FastMath;
/**
- * A MapPosition stores the latitude and longitude coordinate of a MapView together with its zoom level.
+ * A MapPosition stores the latitude and longitude coordinate of a MapView
+ * together with its zoom level.
*/
public class MapViewPosition {
- private static float MAX_SCALE = 2.0f;
- private static float MIN_SCALE = 1.0f;
- public static int MAX_ZOOMLEVEL = 16;
+ private static final String TAG = "MapViewPosition";
+
+ public final static int MAX_ZOOMLEVEL = 16;
+
+ private final static float MAX_SCALE = 2.0f;
+ private final static float MIN_SCALE = 1.0f;
+
+ private final MapView mMapView;
private double mLatitude;
private double mLongitude;
- private final MapView mMapView;
private byte mZoomLevel;
private float mScale;
private float mRotation;
private float mTilt;
+ // 2^mZoomLevel * mScale;
+ private float mMapScale;
+
+ // private final static float MAP_SIZE = 1000000;
+ // private final static float MAP_SIZE2 = 1000000 >> 1;
+
MapViewPosition(MapView mapView) {
mMapView = mapView;
@@ -45,8 +55,24 @@ public class MapViewPosition {
mScale = 1;
mRotation = 0.0f;
mTilt = 0;
+ mMapScale = 1;
}
+ // private static double latitudeToMapView(double latitude) {
+ // double sinLatitude = Math.sin(latitude * (Math.PI / 180));
+ // return (0.5 - Math.log((1 + sinLatitude) / (1 - sinLatitude)) / (4 *
+ // Math.PI))
+ // * MAP_SIZE;
+ // }
+ //
+ // public static double longitudeToMapView(double longitude) {
+ // return (longitude + 180) / 360 * MAP_SIZE;
+ // }
+ //
+ // private static double pixelXToLongitude(double pixelX, byte zoomLevel) {
+ // return 360 * ((pixelX / ((long) Tile.TILE_SIZE << zoomLevel)) - 0.5);
+ // }
+
/**
* @return the current center point of the MapView.
*/
@@ -55,14 +81,16 @@ public class MapViewPosition {
}
/**
- * @return an immutable MapPosition or null, if this map position is not valid.
+ * @return an immutable MapPosition or null, if this map position is not
+ * valid.
* @see #isValid()
*/
public synchronized MapPosition getMapPosition() {
if (!isValid()) {
return null;
}
- // Log.d("MapViewPosition", "lat: " + mLatitude + " lon: " + mLongitude);
+ // Log.d("MapViewPosition", "lat: " + mLatitude + " lon: " +
+ // mLongitude);
return new MapPosition(mLatitude, mLongitude, mZoomLevel, mScale, mRotation);
}
@@ -178,7 +206,8 @@ public class MapViewPosition {
public synchronized void rotateMap(float angle, float cx, float cy) {
moveMap(cx, cy);
- // Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation - angle));
+ // Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation -
+ // angle));
mRotation -= angle;
}
@@ -186,7 +215,7 @@ public class MapViewPosition {
mRotation = f;
}
- public void setTile(float f) {
+ public void setTilt(float f) {
mTilt = f;
}
@@ -199,10 +228,12 @@ public class MapViewPosition {
mLatitude = MercatorProjection.limitLatitude(mapPosition.lat);
mLongitude = MercatorProjection.limitLongitude(mapPosition.lon);
mZoomLevel = mMapView.limitZoomLevel(mapPosition.zoomLevel);
+ mMapScale = 1 << mZoomLevel;
}
synchronized void setZoomLevel(byte zoomLevel) {
mZoomLevel = mMapView.limitZoomLevel(zoomLevel);
+ mMapScale = 1 << mZoomLevel;
}
synchronized void setScale(float scale) {
@@ -226,79 +257,25 @@ public class MapViewPosition {
moveMap(pivotX * (1.0f - scale),
pivotY * (1.0f - scale));
- float s = mScale * scale;
+ float newScale = mMapScale * scale;
- if (s >= MAX_SCALE) {
- if (s > 8)
+ int z = FastMath.log2((int) newScale);
+
+ if (z <= 0 || (z >= MAX_ZOOMLEVEL && mScale >= 8))
+ return;
+
+ if (z > MAX_ZOOMLEVEL) {
+ // z16 shows everything, just increase scaling
+ if (mScale * scale > 8)
return;
- if (mZoomLevel <= MAX_ZOOMLEVEL) {
- byte z = (byte) FloatMath.sqrt(s);
- mZoomLevel += z;
- s *= 1.0f / (1 << z);
- }
- } else if (s < MIN_SCALE) {
- byte z = (byte) FloatMath.sqrt(1 / s);
- if (z != 0 && mZoomLevel == 1)
- return;
- mZoomLevel -= z;
- s *= 1 << z;
+ mScale *= scale;
+ mMapScale = newScale;
+ return;
}
- mScale = s;
+ mZoomLevel = (byte) z;
+ mScale = newScale / (1 << z);
+ mMapScale = newScale;
}
-
- /**
- * Zooms in or out by the given amount of zoom levels.
- *
- * @param zoomLevelDiff
- * the difference to the current zoom level.
- * @param s
- * scale between min/max zoom
- * @return true if the zoom level was changed, false otherwise.
- */
- // public boolean zoom(byte zoomLevelDiff, float s) {
- // float scale = s;
- //
- // if (zoomLevelDiff > 0) {
- // // check if zoom in is possible
- // if (mMapViewPosition.getZoomLevel() + zoomLevelDiff > getMaximumPossibleZoomLevel()) {
- // return false;
- // }
- //
- // scale *= 1.0f / (1 << zoomLevelDiff);
- // } else if (zoomLevelDiff < 0) {
- // // check if zoom out is possible
- // if (mMapViewPosition.getZoomLevel() + zoomLevelDiff < mMapZoomControls.getZoomLevelMin()) {
- // return false;
- // }
- //
- // scale *= 1 << -zoomLevelDiff;
- // }
- //
- // if (scale == 0)
- // scale = 1;
- // // else
- // // scale = Math.round(256.0f * scale) / 256.0f;
- //
- // mMapViewPosition.setZoomLevel((byte) (mMapViewPosition.getZoomLevel() + zoomLevelDiff));
- //
- // // mapZoomControls.onZoomLevelChange(mapViewPosition.getZoomLevel());
- //
- // // zoomAnimator.setParameters(zoomStart, matrixScaleFactor,
- // // getWidth() >> 1, getHeight() >> 1);
- // // zoomAnimator.startAnimation();
- //
- // // if (scale > MAX_ZOOM) {
- // // scale = MAX_ZOOM;
- // // }
- //
- // if (zoomLevelDiff != 0 || mZoomFactor != scale) {
- // mZoomFactor = scale;
- // redrawTiles();
- // }
- //
- // return true;
- // }
-
}
diff --git a/src/org/oscim/view/TouchHandler.java b/src/org/oscim/view/TouchHandler.java
index 7915789b..a44a8e3a 100644
--- a/src/org/oscim/view/TouchHandler.java
+++ b/src/org/oscim/view/TouchHandler.java
@@ -29,7 +29,8 @@ import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
/**
- * Implementation for multi-touch capable devices. TODO write a AnimationTimer instead of using CountDownTimer
+ * Implementation for multi-touch capable devices. TODO write a AnimationTimer
+ * instead of using CountDownTimer
*/
public class TouchHandler {
private static final int INVALID_POINTER_ID = -1;
@@ -440,7 +441,8 @@ public class TouchHandler {
@Override
public void onScaleEnd(ScaleGestureDetector gd) {
- // Log.d("ScaleListener", "Sum " + mSumScale + " " + (mTimeEnd - mTimeStart));
+ // Log.d("ScaleListener", "Sum " + mSumScale + " " + (mTimeEnd -
+ // mTimeStart));
if (mTimer == null && mTimeEnd - mTimeStart < 150
&& (mSumScale < 0.99 || mSumScale > 1.01)) {
@@ -449,7 +451,7 @@ public class TouchHandler {
mZooutOut = mSumScale < 0.99;
- mTimer = new CountDownTimer((int) mScaleDuration, 30) {
+ mTimer = new CountDownTimer((int) mScaleDuration, 15) {
@Override
public void onTick(long tick) {
scale(tick);
@@ -468,7 +470,7 @@ public class TouchHandler {
private float mPrevScale;
private CountDownTimer mTimer;
boolean mZooutOut;
- private final float mScaleDuration = 350;
+ private final float mScaleDuration = 450;
boolean scale(long tick) {
diff --git a/src/org/oscim/view/overlay/Overlay.java b/src/org/oscim/view/overlay/Overlay.java
index 23aeb6db..4d5a2a04 100644
--- a/src/org/oscim/view/overlay/Overlay.java
+++ b/src/org/oscim/view/overlay/Overlay.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010, 2011, 2012 mapsforge.org
+ * Copyright 2012, Hannes Janetzek
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
diff --git a/src/org/oscim/view/renderer/GLRenderer.java b/src/org/oscim/view/renderer/GLRenderer.java
index 04e769c7..2463fef1 100644
--- a/src/org/oscim/view/renderer/GLRenderer.java
+++ b/src/org/oscim/view/renderer/GLRenderer.java
@@ -16,19 +16,12 @@ package org.oscim.view.renderer;
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_BLEND;
+import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_DYNAMIC_DRAW;
+import static android.opengl.GLES20.GL_ONE;
import static android.opengl.GLES20.GL_ONE_MINUS_SRC_ALPHA;
+import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL;
import static android.opengl.GLES20.GL_STENCIL_BUFFER_BIT;
-import static android.opengl.GLES20.glBindBuffer;
-import static android.opengl.GLES20.glBlendFunc;
-import static android.opengl.GLES20.glBufferData;
-import static android.opengl.GLES20.glClear;
-import static android.opengl.GLES20.glClearColor;
-import static android.opengl.GLES20.glClearStencil;
-import static android.opengl.GLES20.glDisable;
-import static android.opengl.GLES20.glEnable;
-import static android.opengl.GLES20.glGenBuffers;
-import static android.opengl.GLES20.glViewport;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -69,7 +62,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static ArrayList mVBOs;
private static int mWidth, mHeight;
- private static float mAspect;
private static int rotateBuffers = 2;
private static ShortBuffer shortBuffer[];
@@ -86,12 +78,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
private static float[] mProjMatrix = new float[16];
private static float[] mProjMatrixI = new float[16];
- // curTiles is set by TileLoader and swapped with
- // drawTiles in onDrawFrame in GL thread.
- private static TilesData curTiles, drawTiles;
+ // mNextTiles is set by TileLoader and swapped with
+ // mDrawTiles in onDrawFrame in GL thread.
+ private static TilesData mNextTiles, mDrawTiles;
// flag set by updateVisibleList when current visible tiles
- // changed. used in onDrawFrame to flip curTiles/drawTiles
+ // changed. used in onDrawFrame to flip mNextTiles/mDrawTiles
private static boolean mUpdateTiles;
private static MapPosition mCurPosition;
@@ -147,7 +139,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
* current MapPosition
* @param tiles
* active tiles
- * @return curTiles (the previously active tiles)
+ * @return mNextTiles (the previously active tiles)
*/
static TilesData updateTiles(MapPosition mapPosition, TilesData tiles) {
GLRenderer.tilelock.lock();
@@ -155,8 +147,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mCurPosition = mapPosition;
// unlock previously active tiles
- for (int i = 0; i < curTiles.cnt; i++) {
- MapTile t = curTiles.tiles[i];
+ for (int i = 0; i < mNextTiles.cnt; i++) {
+ MapTile t = mNextTiles.tiles[i];
boolean found = false;
for (int j = 0; j < tiles.cnt; j++) {
@@ -168,8 +160,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (found)
continue;
- for (int j = 0; j < drawTiles.cnt; j++) {
- if (drawTiles.tiles[j] == t) {
+ for (int j = 0; j < mDrawTiles.cnt; j++) {
+ if (mDrawTiles.tiles[j] == t) {
found = true;
break;
}
@@ -180,22 +172,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
t.unlock();
}
- TilesData tmp = curTiles;
- curTiles = tiles;
+ TilesData tmp = mNextTiles;
+ mNextTiles = tiles;
// lock tiles (and their proxies) to not be removed from cache
- for (int i = 0; i < curTiles.cnt; i++) {
- MapTile t = curTiles.tiles[i];
+ for (int i = 0; i < mNextTiles.cnt; i++) {
+ MapTile t = mNextTiles.tiles[i];
if (!t.isActive)
t.lock();
}
- for (int j = 0; j < drawTiles.cnt; j++) {
- MapTile t = drawTiles.tiles[j];
+ for (int j = 0; j < mDrawTiles.cnt; j++) {
+ MapTile t = mDrawTiles.tiles[j];
if (!t.isActive)
t.lock();
}
+ // GLThread flips mNextTiles with mDrawTiles
mUpdateTiles = true;
GLRenderer.tilelock.unlock();
@@ -236,46 +229,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mUpdateColor = true;
}
- private static boolean isVisible(MapPosition mapPosition, MapTile tile, float div) {
- double dx, dy, scale;
-
- if (div == 0) {
- dx = tile.pixelX - mapPosition.x;
- dy = tile.pixelY - mapPosition.y;
- scale = mapPosition.scale;
- } else {
- dx = tile.pixelX - mapPosition.x * div;
- dy = tile.pixelY - mapPosition.y * div;
- scale = mapPosition.scale / div;
- }
- int size = Tile.TILE_SIZE;
- int sx = (int) (dx * scale);
- int sy = (int) (dy * scale);
-
- // FIXME little hack, need to do scanline check or sth
- // this kindof works for typical screen aspect
- if (mRotate) {
- int ssize = mWidth > mHeight ? mWidth : mHeight;
-
- if (sy > ssize / 2 || sx > ssize / 2
- || sx + size * scale < -ssize / 2
- || sy + size * scale < -ssize / 2) {
- tile.isVisible = false;
- return false;
- }
- } else {
- if (sy > mHeight / 2 || sx > mWidth / 2
- || sx + size * scale < -mWidth / 2
- || sy + size * scale < -mHeight / 2) {
- tile.isVisible = false;
- return false;
- }
- }
- tile.isVisible = true;
-
- return true;
- }
-
private int uploadCnt = 0;
private boolean uploadTileData(MapTile tile) {
@@ -308,7 +261,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
// Log.d(TAG, "uploadTileData, " + tile);
- glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
+ GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
sbuf = shortBuffer[uploadCnt];
@@ -317,8 +270,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// FIXME probably not a good idea to do this in gl thread...
if (sbuf == null || sbuf.capacity() < newSize) {
- ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES).order(
- ByteOrder.nativeOrder());
+ ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
+ .order(ByteOrder.nativeOrder());
sbuf = bbuf.asShortBuffer();
shortBuffer[uploadCnt] = sbuf;
sbuf.put(mFillCoords, 0, 8);
@@ -346,7 +299,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
sbuf.flip();
if (newSize != sbuf.remaining()) {
-
Log.d(TAG, "tiles wrong: " + tile + " "
+ newSize + " "
+ sbuf.position() + " "
@@ -361,13 +313,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
newSize *= SHORT_BYTES;
+ // reuse memory allocated for vbo when possible and allocated
+ // memory is less then four times the new data
if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
+ // Log.d(TAG, "reuse buffer " + tile.vbo.size + " " + newSize);
} else {
mBufferMemoryUsage -= tile.vbo.size;
tile.vbo.size = newSize;
- glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
+ GLES20.glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
mBufferMemoryUsage += tile.vbo.size;
}
@@ -380,47 +335,96 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
private static void checkBufferUsage() {
- // try to clear some unused vbo when exceding limit
- if (mBufferMemoryUsage > LIMIT_BUFFERS) {
- Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- int buf[] = new int[1];
-
- synchronized (mVBOs) {
- for (VertexBufferObject vbo : mVBOs) {
-
- if (vbo.size == 0)
- continue;
-
- mBufferMemoryUsage -= vbo.size;
-
- // this should free allocated memory but it does not.
- // on HTC it causes oom exception?!
-
- // glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
- // glBufferData(GL_ARRAY_BUFFER, 0, null,
- // GLES20.GL_STATIC_DRAW);
-
- // recreate vbo instead
- buf[0] = vbo.id;
- GLES20.glDeleteBuffers(1, buf, 0);
- GLES20.glGenBuffers(1, buf, 0);
- vbo.id = buf[0];
-
- vbo.size = 0;
- }
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- Log.d(TAG, " > " + mBufferMemoryUsage / MB + "MB");
-
- if (mBufferMemoryUsage > LIMIT_BUFFERS && CACHE_TILES > 100)
- CACHE_TILES -= 50;
-
- } else if (CACHE_TILES < CACHE_TILES_MAX) {
- CACHE_TILES += 50;
+ if (mBufferMemoryUsage < LIMIT_BUFFERS) {
+ if (CACHE_TILES < CACHE_TILES_MAX)
+ CACHE_TILES += 50;
+ return;
}
+
+ // try to clear some unused vbo when exceding limit
+ Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
+
+ int vboIds[] = new int[10];
+ VertexBufferObject[] tmp = new VertexBufferObject[10];
+
+ int removed = 0;
+ synchronized (mVBOs) {
+ for (VertexBufferObject vbo : mVBOs) {
+
+ if (vbo.size == 0)
+ continue;
+
+ mBufferMemoryUsage -= vbo.size;
+ vbo.size = 0;
+
+ // this should free allocated memory but it does not.
+ // on HTC it causes OOM exception?!
+ // glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
+ // glBufferData(GL_ARRAY_BUFFER, 0, null,
+ // GLES20.GL_STATIC_DRAW);
+
+ // recreate vbo instead
+ vboIds[removed] = vbo.id;
+ tmp[removed++] = vbo;
+
+ if (removed == 10)
+ break;
+ }
+ }
+
+ if (removed > 0) {
+ GLES20.glDeleteBuffers(removed, vboIds, 0);
+ GLES20.glGenBuffers(removed, vboIds, 0);
+
+ for (int i = 0; i < removed; i++)
+ tmp[i].id = vboIds[i];
+
+ Log.d(TAG, "now: " + mBufferMemoryUsage / MB + "MB");
+ }
+
+ if (mBufferMemoryUsage > LIMIT_BUFFERS && CACHE_TILES > 100)
+ CACHE_TILES -= 50;
+ }
+
+ private static boolean isVisible(MapPosition mapPosition, MapTile tile) {
+ float dx, dy, scale, div = 1;
+ int diff = mapPosition.zoomLevel - tile.zoomLevel;
+
+ if (diff < 0)
+ div = (1 << -diff);
+ else if (diff > 0)
+ div = (1.0f / (1 << diff));
+
+ scale = mapPosition.scale / div;
+ dx = (float) (tile.pixelX - mapPosition.x * div);
+ dy = (float) (tile.pixelY - mapPosition.y * div);
+
+ int size = Tile.TILE_SIZE;
+ int sx = (int) (dx * scale);
+ int sy = (int) (dy * scale);
+
+ // FIXME little hack, need to do scanline check or sth
+ // this kindof works for typical screen aspect
+ if (mRotate) {
+ int ssize = mWidth > mHeight ? mWidth : mHeight;
+
+ if (sy > ssize / 2 || sx > ssize / 2
+ || sx + size * scale < -ssize / 2
+ || sy + size * scale < -ssize / 2) {
+ tile.isVisible = false;
+ return false;
+ }
+ } else {
+ if (sy > mHeight / 2 || sx > mWidth / 2
+ || sx + size * scale < -mWidth / 2
+ || sy + size * scale < -mHeight / 2) {
+ tile.isVisible = false;
+ return false;
+ }
+ }
+ tile.isVisible = true;
+
+ return true;
}
private static boolean mRotate = false;
@@ -429,17 +433,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
float div, boolean project) {
float x, y, scale;
- // if (mRotate) {
scale = mapPosition.scale / (div * COORD_MULTIPLIER);
x = (float) (tile.pixelX - mapPosition.x * div);
y = (float) (tile.pixelY - mapPosition.y * div);
Matrix.setIdentityM(matrix, 0);
- // scale to tile coordinates
+ // scale to tile to world coordinates
Matrix.scaleM(matrix, 0, scale, scale, 1);
- // translate relative to center
+ // translate relative to map center
Matrix.translateM(matrix, 0,
x * COORD_MULTIPLIER,
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER,
@@ -450,44 +453,31 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (project)
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
-
- // } else {
- // scale = (float) (2.0 * mapPosition.scale / (mHeight * div));
- // x = (float) (tile.pixelX - mapPosition.x * div);
- // y = (float) (tile.pixelY - mapPosition.y * div);
- //
- // matrix[12] = x * scale * mAspect;
- // matrix[13] = -(y + Tile.TILE_SIZE) * scale;
- // // increase the 'distance' with each tile drawn.
- // matrix[14] = -0.99f + offset * 0.01f;
- // matrix[0] = scale * mAspect / COORD_MULTIPLIER;
- // matrix[5] = scale / COORD_MULTIPLIER;
- // }
}
- private float[] mv = new float[4];
- private float[] mu = { 1, 1, -1, 1 };
-
- private float[] mUnprojMatrix = new float[16];
-
- private void unproject(MapPosition pos, float x, float y) {
- mu[0] = x;
- mu[1] = y;
- mu[2] = -1;
-
- // add tilt
- Matrix.multiplyMV(mv, 0, mTmpMatrix, 0, mu, 0);
- // Log.d(TAG, ">> " + mv[0] + " " + mv[1] + " " + mv[2]);
-
- Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
- float size = Tile.TILE_SIZE * pos.scale;
- if (mv[3] != 0) {
- float w = 1 / mv[3];
- float xx = Math.round(((mv[0] * w) / size) * 100) / 100f;
- float yy = Math.round(((mv[1] * w) / size) * 100) / 100f;
- Log.d(TAG, " " + xx + " " + yy);
- }
- }
+ // private float[] mv = new float[4];
+ // private float[] mu = { 1, 1, -1, 1 };
+ //
+ // private float[] mUnprojMatrix = new float[16];
+ //
+ // private void unproject(MapPosition pos, float x, float y) {
+ // mu[0] = x;
+ // mu[1] = y;
+ // mu[2] = -1;
+ //
+ // // add tilt
+ // Matrix.multiplyMV(mv, 0, mTmpMatrix, 0, mu, 0);
+ // // Log.d(TAG, ">> " + mv[0] + " " + mv[1] + " " + mv[2]);
+ //
+ // Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0);
+ // float size = Tile.TILE_SIZE * pos.scale;
+ // if (mv[3] != 0) {
+ // float w = 1 / mv[3];
+ // float xx = Math.round(((mv[0] * w) / size) * 100) / 100f;
+ // float yy = Math.round(((mv[1] * w) / size) * 100) / 100f;
+ // Log.d(TAG, " " + xx + " " + yy);
+ // }
+ // }
@Override
public void onDrawFrame(GL10 glUnused) {
@@ -498,30 +488,27 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (MapView.debugFrameTime)
start = SystemClock.uptimeMillis();
+ // Note: it seems faster to also clear the stencil buffer even
+ // when not needed. probaly otherwise it is masked out from the
+ // depth buffer as they share the same memory region afaik
GLES20.glDepthMask(true);
-
- // Note: having the impression it is faster to also clear the
- // stencil buffer even when not needed. probaly otherwise it
- // is masked out from the depth buffer as they share the same
- // memory region afaik
- glClear(GLES20.GL_COLOR_BUFFER_BIT
+ GLES20.glStencilMask(0xFF);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT
| GLES20.GL_DEPTH_BUFFER_BIT
- // | GLES20.GL_STENCIL_BUFFER_BIT
- );
+ | GLES20.GL_STENCIL_BUFFER_BIT);
// get position and current tiles to draw
GLRenderer.tilelock.lock();
mapPosition = mCurPosition;
-
if (mUpdateTiles) {
- TilesData tmp = drawTiles;
- drawTiles = curTiles;
- curTiles = tmp;
+ TilesData tmp = mDrawTiles;
+ mDrawTiles = mNextTiles;
+ mNextTiles = tmp;
mUpdateTiles = false;
}
GLRenderer.tilelock.unlock();
- if (drawTiles == null)
+ if (mDrawTiles == null)
return;
// if (mRotate != (mMapView.enableRotation || mMapView.enableCompass)) {
@@ -572,12 +559,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
}
if (mUpdateColor && mClearColor != null) {
- glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
+ GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2],
+ mClearColor[3]);
mUpdateColor = false;
}
- int tileCnt = drawTiles.cnt;
- MapTile[] tiles = drawTiles.tiles;
+ int tileCnt = mDrawTiles.cnt;
+ MapTile[] tiles = mDrawTiles.tiles;
uploadCnt = 0;
int updateTextures = 0;
@@ -586,7 +574,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
for (int i = 0; i < tileCnt; i++) {
MapTile tile = tiles[i];
- if (!isVisible(mapPosition, tile, 1))
+ if (!isVisible(mapPosition, tile))
continue;
if (tile.texture == null && TextRenderer.drawToTexture(tile))
@@ -621,32 +609,29 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (updateTextures > 0)
TextRenderer.compileTextures();
- GLES20.glEnable(GLES20.GL_DEPTH_TEST);
- GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
+ GLES20.glEnable(GL_DEPTH_TEST);
+ GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
for (int i = 0; i < tileCnt; i++) {
- if (tiles[i].isVisible && tiles[i].isReady) {
- drawTile(mapPosition, tiles[i], 1);
- }
+ if (tiles[i].isVisible && tiles[i].isReady)
+ drawTile(mapPosition, tiles[i]);
}
// proxies are clipped to the region where nothing was drawn to depth
- // buffer
- // TODO draw all parent before grandparent
+ // buffer. TODO draw all parent before grandparent
for (int i = 0; i < tileCnt; i++) {
- if (tiles[i].isVisible && !tiles[i].isReady) {
+ if (tiles[i].isVisible && !tiles[i].isReady)
drawProxyTile(mapPosition, tiles[i]);
- }
}
// GlUtils.checkGlError("end draw");
- GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
- GLES20.glDisable(GLES20.GL_DEPTH_TEST);
+ GLES20.glDisable(GL_POLYGON_OFFSET_FILL);
+ GLES20.glDisable(GL_DEPTH_TEST);
mDrawCount = 0;
mDrawSerial++;
- glEnable(GL_BLEND);
+ GLES20.glEnable(GL_BLEND);
int z = mapPosition.zoomLevel;
float s = mapPosition.scale;
@@ -683,11 +668,20 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// used to not draw a tile twice per frame...
private static byte mDrawSerial = 0;
- private static void drawTile(MapPosition mapPosition, MapTile tile, float div) {
+ private static void drawTile(MapPosition mapPosition, MapTile tile) {
// draw parents only once
if (tile.lastDraw == mDrawSerial)
return;
+ float div = 1;
+
+ int diff = mapPosition.zoomLevel - tile.zoomLevel;
+
+ if (diff < 0)
+ div = (1 << -diff);
+ else if (diff > 0)
+ div = (1.0f / (1 << diff));
+
tile.lastDraw = mDrawSerial;
int z = mapPosition.zoomLevel;
@@ -698,7 +692,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
GLES20.glPolygonOffset(0, mDrawCount++);
- glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
+ GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
LineLayer ll = tile.lineLayers;
PolygonLayer pl = tile.polygonLayers;
@@ -716,10 +710,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
pnext = pl.layer;
if (pl != null && pnext < lnext) {
- glDisable(GL_BLEND);
+ GLES20.glDisable(GL_BLEND);
- pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s,
- !clipped);
+ pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s, !clipped);
clipped = true;
@@ -730,7 +723,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
clipped = true;
}
- glEnable(GL_BLEND);
+ GLES20.glEnable(GL_BLEND);
ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s);
}
}
@@ -747,13 +740,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
if (c == null)
continue;
- if (!isVisible(mapPosition, c, 2)) {
+ if (!isVisible(mapPosition, c)) {
drawn++;
continue;
}
if (c.isReady) {
- drawTile(mapPosition, c, 2);
+ drawTile(mapPosition, c);
drawn++;
}
}
@@ -762,36 +755,38 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// TODO could use tile.proxies here
private static void drawProxyTile(MapPosition mapPosition, MapTile tile) {
-
+ boolean drawn = false;
if (mapPosition.scale > 1.5f) {
// prefer drawing children
if (!drawProxyChild(mapPosition, tile)) {
- MapTile t = tile.rel.parent.tile;
- if (t != null) {
+ if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
+ MapTile t = tile.rel.parent.tile;
if (t.isReady) {
- drawTile(mapPosition, t, 0.5f);
- } else {
- MapTile p = t.rel.parent.tile;
- if (p != null && p.isReady)
- drawTile(mapPosition, p, 0.25f);
+ drawTile(mapPosition, t);
+ drawn = true;
}
}
+
+ if (!drawn && (tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
+ MapTile t = tile.rel.parent.parent.tile;
+ if (t.isReady)
+ drawTile(mapPosition, t);
+
+ }
}
} else {
// prefer drawing parent
MapTile t = tile.rel.parent.tile;
if (t != null && t.isReady) {
- drawTile(mapPosition, t, 0.5f);
+ drawTile(mapPosition, t);
} else if (!drawProxyChild(mapPosition, tile)) {
- // need to check rel.parent here, t could alread be root
- if (t != null) {
- t = t.rel.parent.tile;
-
- if (t != null && t.isReady)
- drawTile(mapPosition, t, 0.25f);
+ if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
+ t = tile.rel.parent.parent.tile;
+ if (t.isReady)
+ drawTile(mapPosition, t);
}
}
}
@@ -811,8 +806,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mWidth = width;
mHeight = height;
- mAspect = (float) height / width;
-
// Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
// 0.5f, -1, 1);
@@ -828,7 +821,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
mProjMatrix[10] = 0;
mProjMatrix[14] = 0;
- glViewport(0, 0, width, height);
+ GLES20.glViewport(0, 0, width, height);
if (!changed && !mNewSurface) {
mMapView.redrawMap();
@@ -845,7 +838,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// Set up vertex buffer objects
int numVBO = (CACHE_TILES + (numTiles * 2));
int[] mVboIds = new int[numVBO];
- glGenBuffers(numVBO, mVboIds, 0);
+ GLES20.glGenBuffers(numVBO, mVboIds, 0);
GlUtils.checkGlError("glGenBuffers");
mVBOs = new ArrayList(numVBO);
@@ -857,22 +850,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
TextRenderer.setup(numTiles);
if (mClearColor != null) {
- glClearColor(mClearColor[0], mClearColor[1],
+ GLES20.glClearColor(mClearColor[0], mClearColor[1],
mClearColor[2], mClearColor[3]);
} else {
- glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
+ GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
}
GlUtils.checkGlError("onSurfaceChanged");
- glClear(GL_STENCIL_BUFFER_BIT);
+ GLES20.glClear(GL_STENCIL_BUFFER_BIT);
mMapView.redrawMap();
}
void clearTiles(int numTiles) {
- drawTiles = new TilesData(numTiles);
- curTiles = new TilesData(numTiles);
+ mDrawTiles = new TilesData(numTiles);
+ mNextTiles = new TilesData(numTiles);
}
@Override
@@ -904,9 +897,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
// glEnable(GL_SCISSOR_TEST);
// glScissor(0, 0, mWidth, mHeight);
- glClearStencil(0);
- glDisable(GLES20.GL_CULL_FACE);
- glBlendFunc(GLES20.GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ GLES20.glClearStencil(0);
+ GLES20.glDisable(GLES20.GL_CULL_FACE);
+ GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
diff --git a/src/org/oscim/view/renderer/LineLayer.java b/src/org/oscim/view/renderer/LineLayer.java
index de4835ee..b935dff4 100644
--- a/src/org/oscim/view/renderer/LineLayer.java
+++ b/src/org/oscim/view/renderer/LineLayer.java
@@ -25,7 +25,8 @@ class LineLayer {
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
// scale factor mapping extrusion vector to short values
private static final float DIR_SCALE = 2048;
- // mask for packing last two bits of extrusion vector with texture coordinates
+ // mask for packing last two bits of extrusion vector with texture
+ // coordinates
private static final int DIR_MASK = 0xFFFFFFFC;
// next layer
@@ -64,7 +65,8 @@ class LineLayer {
}
/*
- * line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj
+ * line extrusion is based on code from GLMap
+ * (https://github.com/olofsj/GLMap/) by olofsj
*/
void addLine(float[] points, short[] index, boolean closed) {
diff --git a/src/org/oscim/view/renderer/LineRenderer.java b/src/org/oscim/view/renderer/LineRenderer.java
index ac2373bf..8bcff25d 100644
--- a/src/org/oscim/view/renderer/LineRenderer.java
+++ b/src/org/oscim/view/renderer/LineRenderer.java
@@ -62,11 +62,10 @@ class LineRenderer {
static LineLayer drawLines(MapTile tile, LineLayer layer, int next, float[] matrix,
float div, double zoom, float scale) {
- float z = 1 / div;
-
if (layer == null)
return null;
+ // TODO should use fast line program when view is not tilted
GLES20.glUseProgram(lineProgram);
GLES20.glEnableVertexAttribArray(hLineVertexPosition);
@@ -81,7 +80,9 @@ class LineRenderer {
GLES20.glUniformMatrix4fv(hLineMatrix, 1, false, matrix, 0);
// scale factor to map one pixel on tile to one pixel on screen:
- float pixel = 2.0f / (scale * z);
+ // only works with orthographic projection
+ float s = scale / div;
+ float pixel = 2.0f / s;
if (mFast)
GLES20.glUniform1f(hLineScale, pixel);
@@ -89,7 +90,7 @@ class LineRenderer {
GLES20.glUniform1f(hLineScale, 0);
// line scale factor (for non fixed lines)
- float s = FloatMath.sqrt(scale * z);
+ float lineScale = FloatMath.sqrt(s);
boolean blur = false;
LineLayer l = layer;
@@ -117,33 +118,31 @@ class LineRenderer {
for (LineLayer o = l.outlines; o != null; o = o.outlines) {
if (line.blur != 0) {
- GLES20.glUniform1f(hLineScale, (l.width + o.width) / (scale * z)
- - (line.blur / (scale * z)));
+ GLES20.glUniform1f(hLineScale, (l.width + o.width) / s
+ - (line.blur / s));
blur = true;
}
if (zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL)
- GLES20.glUniform1f(hLineWidth,
- (l.width + o.width) / (scale * z));
+ GLES20.glUniform1f(hLineWidth, (l.width + o.width) / s);
else
- GLES20.glUniform1f(hLineWidth, l.width / (scale * z)
- + o.width / s);
+ GLES20.glUniform1f(hLineWidth, l.width / s + o.width / lineScale);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
}
}
else {
if (line.blur != 0) {
- GLES20.glUniform1f(hLineScale, (l.width / s) * line.blur);
+ GLES20.glUniform1f(hLineScale, (l.width / lineScale) * line.blur);
blur = true;
}
if (line.fixed || zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL) {
// invert scaling of extrusion vectors so that line width
- // stays the same
- GLES20.glUniform1f(hLineWidth, (l.width / (scale * z)));
+ // stays the same.
+ GLES20.glUniform1f(hLineWidth, l.width / s);
} else {
- GLES20.glUniform1f(hLineWidth, (l.width / s));
+ GLES20.glUniform1f(hLineWidth, l.width / lineScale);
}
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
diff --git a/src/org/oscim/view/renderer/MapRenderer.java b/src/org/oscim/view/renderer/MapRenderer.java
index fce9c3db..98a5d47f 100644
--- a/src/org/oscim/view/renderer/MapRenderer.java
+++ b/src/org/oscim/view/renderer/MapRenderer.java
@@ -91,13 +91,10 @@ public class MapRenderer extends GLSurfaceView {
mInitial = true;
}
- /**
- * called by MapView when position or map settings changes
- */
/**
* Update list of visible tiles and passes them to MapRenderer, when not
* available tiles are created and added to JobQueue (mapView.addJobs) for
- * loading by MapGenerator class
+ * loading by TileGenerator class
*
* @param clear
* ...
@@ -108,7 +105,7 @@ public class MapRenderer extends GLSurfaceView {
boolean changedPos = false;
boolean changedZoom = false;
- if (mMapView == null || mMapView.getMapPosition() == null)
+ if (mMapView == null)
return;
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
@@ -121,14 +118,17 @@ public class MapRenderer extends GLSurfaceView {
if (clear) {
// remove all tiles references
Log.d(TAG, "CLEAR");
- synchronized (GLRenderer.lock) {
- for (MapTile t : mTiles)
- clearTile(t);
- mTiles.clear();
- mTilesLoaded.clear();
- QuadTree.init();
- }
+ GLRenderer.tilelock.lock();
+
+ for (MapTile t : mTiles)
+ clearTile(t);
+
+ mTiles.clear();
+ mTilesLoaded.clear();
+ QuadTree.init();
+ GLRenderer.tilelock.unlock();
+
mInitial = true;
}
@@ -180,21 +180,29 @@ public class MapRenderer extends GLSurfaceView {
mTileY = tileY;
mPrevZoom = zoomLevel;
- if (changedZoom) {
- // need to update visible list first when zoom level changes
- // as scaling is relative to the tiles of current zoom-level
- updateVisibleList(mapPosition, 0);
- } else {
- // pass new position to glThread
- GLRenderer.updatePosition(mapPosition);
- }
-
+ GLRenderer.updatePosition(mapPosition);
if (!MapView.debugFrameTime)
requestRender();
- if (changedPos)
+ if (changedZoom || changedPos) {
+ // need to update visible list first when zoom level changes
+ // as scaling is relative to the tiles of current zoom-level
updateVisibleList(mapPosition, zdir);
+ if (!MapView.debugFrameTime)
+ requestRender();
+ }
+ // else {
+ // // pass new position to glThread
+ // GLRenderer.updatePosition(mapPosition);
+ // }
+
+ // if (!MapView.debugFrameTime)
+ // requestRender();
+
+ // if (changedPos)
+ // updateVisibleList(mapPosition, zdir);
+
if (changedPos || changedZoom) {
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
if (remove > 50)
@@ -202,7 +210,6 @@ public class MapRenderer extends GLSurfaceView {
}
limitLoadQueue();
-
}
/**
diff --git a/src/org/oscim/view/renderer/MapTile.java b/src/org/oscim/view/renderer/MapTile.java
index faee74e6..b0568b6d 100644
--- a/src/org/oscim/view/renderer/MapTile.java
+++ b/src/org/oscim/view/renderer/MapTile.java
@@ -19,7 +19,8 @@ import org.oscim.view.generator.JobTile;
class MapTile extends JobTile {
/**
- * VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m bytes lines vertices
+ * VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m
+ * bytes lines vertices
*/
VertexBufferObject vbo;
@@ -65,8 +66,8 @@ class MapTile extends JobTile {
byte lastDraw = 0;
// keep track which tiles are locked as proxy for this tile
- // 16: parent
- // 32: grandparent
+ final static int PROXY_PARENT = 16;
+ final static int PROXY_GRAMPA = 32;
// 1-8: children
byte proxies;
@@ -99,12 +100,12 @@ class MapTile extends JobTile {
MapTile p = rel.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) {
- proxies |= (1 << 4);
+ proxies |= PROXY_PARENT;
p.refs++;
} else {
p = rel.parent.parent.tile;
if (p != null && (p.isReady || p.newData || p.isLoading)) {
- proxies |= (1 << 5);
+ proxies |= PROXY_GRAMPA;
p.refs++;
}
}
diff --git a/src/org/oscim/view/renderer/PolygonRenderer.java b/src/org/oscim/view/renderer/PolygonRenderer.java
index faade673..137e5245 100644
--- a/src/org/oscim/view/renderer/PolygonRenderer.java
+++ b/src/org/oscim/view/renderer/PolygonRenderer.java
@@ -42,6 +42,8 @@ import org.oscim.utils.GlUtils;
import android.opengl.GLES20;
class PolygonRenderer {
+ private static final String TAG = "PolygonRenderer";
+
private static final int NUM_VERTEX_SHORTS = 2;
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
private static int STENCIL_BITS = 8;
@@ -71,7 +73,7 @@ class PolygonRenderer {
return true;
}
- private static void fillPolygons(int count, double zoom, float scale) {
+ private static void fillPolygons(double zoom, float scale) {
boolean blend = false;
/* draw to framebuffer */
@@ -83,7 +85,7 @@ class PolygonRenderer {
/* only draw where nothing was drawn yet */
glEnable(GLES20.GL_DEPTH_TEST);
- for (int c = 0; c < count; c++) {
+ for (int c = mStart; c < mCount; c++) {
PolygonLayer l = mFillPolys[c];
float f = 1.0f;
@@ -149,8 +151,13 @@ class PolygonRenderer {
glDisable(GL_BLEND);
}
- static PolygonLayer drawPolygons(PolygonLayer layer, int next,
- float[] matrix, double zoom, float scale, boolean clip) {
+ // layers to fill
+ private static int mCount;
+ // stencil buffer index to start fill
+ private static int mStart;
+
+ static PolygonLayer drawPolygons(final PolygonLayer layer, final int next,
+ final float[] matrix, final double zoom, final float scale, boolean first) {
glUseProgram(polygonProgram);
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
@@ -160,33 +167,42 @@ class PolygonRenderer {
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
+ // use stencilbuffer method for polygon drawing
glEnable(GL_STENCIL_TEST);
PolygonLayer l = layer;
- boolean first = clip;
- int cnt = 0;
+ if (first) {
+ mCount = 0;
+ mStart = 0;
+ } else {
+ mStart = mCount;
+ }
for (; l != null && l.layer < next; l = l.next) {
// fade out polygon layers (set in RederTheme)
if (l.area.fade > 0 && l.area.fade > zoom)
continue;
- if (cnt == 0) {
+ if (mCount == 0) {
+ // clear stencilbuffer (tile region)
+
// disable drawing to framebuffer
glColorMask(false, false, false, false);
// never pass the test: always apply fail op
glStencilFunc(GLES20.GL_ALWAYS, 0, 0xFF);
glStencilMask(0xFF);
- // glClear(GL_STENCIL_BUFFER_BIT);
- // clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
if (first) {
- // draw clip-region into depth buffer
+ // draw clip-region into depth buffer:
+ // this is used for lines and polygons
+
+ // write to depth buffer
GLES20.glDepthMask(true);
+
// to prevent overdraw gl_less restricts
// the clip to the area where no other
// tile was drawn
@@ -197,6 +213,7 @@ class PolygonRenderer {
if (first) {
first = false;
+ // dont modify depth buffer
GLES20.glDepthMask(false);
// only draw to this tile
GLES20.glDepthFunc(GLES20.GL_EQUAL);
@@ -205,29 +222,50 @@ class PolygonRenderer {
// stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
+ // no need for depth test while drawing stencil
+ glDisable(GLES20.GL_DEPTH_TEST);
+
+ } else if (mCount == mStart) {
+ // disable drawing to framebuffer
+ glColorMask(false, false, false, false);
+
+ // never pass the test: always apply fail op
+ glStencilFunc(GLES20.GL_ALWAYS, 0, 0xFF);
+
+ // stencil op for stencil method polygon drawing
+ glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
+
// no need for depth test while drawing stencil
glDisable(GLES20.GL_DEPTH_TEST);
}
- mFillPolys[cnt] = l;
+
+ mFillPolys[mCount] = l;
// set stencil mask to draw to
- glStencilMask(1 << cnt++);
+ glStencilMask(1 << mCount++);
glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.verticesCnt);
// draw up to 8 layers into stencil buffer
- if (cnt == STENCIL_BITS) {
- fillPolygons(cnt, zoom, scale);
- cnt = 0;
+ if (mCount == STENCIL_BITS) {
+ fillPolygons(zoom, scale);
+ mCount = 0;
+ mStart = 0;
}
}
- if (cnt > 0)
- fillPolygons(cnt, zoom, scale);
+ if (mCount > 0)
+ fillPolygons(zoom, scale);
+
+ //
+ // if (mCount > 5){
+ // mCount = 0;
+ // mStart = 0;
+ // }
glDisable(GL_STENCIL_TEST);
- if (clip && first)
+ if (first)
drawDepthClip();
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);