- improve tile locking (use ref counter instead of boolean)
- flip over date line (inserting placeholder tiles in renderer) - make view coordinates consistent with tile coordinates (flip on y-axis)
This commit is contained in:
parent
5bf9deef89
commit
b4dd83fc09
@ -45,13 +45,15 @@ import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* A map application which uses the features from the mapsforge map library. The map can be centered to the current
|
||||
* location. A simple file browser for selecting the map file is also included. Some preferences can be adjusted via the
|
||||
* {@link EditPreferences} activity.
|
||||
* A map application which uses the features from the mapsforge map library. The
|
||||
* map can be centered to the current location. A simple file browser for
|
||||
* selecting the map file is also included. Some preferences can be adjusted via
|
||||
* the {@link EditPreferences} activity.
|
||||
*/
|
||||
public class TileMap extends MapActivity {
|
||||
// implements ActionBar.OnNavigationListener {
|
||||
// private static final String BUNDLE_CENTER_AT_FIRST_FIX = "centerAtFirstFix";
|
||||
// private static final String BUNDLE_CENTER_AT_FIRST_FIX =
|
||||
// "centerAtFirstFix";
|
||||
private static final String BUNDLE_SHOW_MY_LOCATION = "showMyLocation";
|
||||
private static final String BUNDLE_SNAP_TO_LOCATION = "snapToLocation";
|
||||
private static final int DIALOG_ENTER_COORDINATES = 0;
|
||||
@ -408,7 +410,8 @@ public class TileMap extends MapActivity {
|
||||
editText.setText(Double.toString(mapCenter.getLongitude()));
|
||||
|
||||
SeekBar zoomlevel = (SeekBar) dialog.findViewById(R.id.zoomLevel);
|
||||
zoomlevel.setMax(20); // FIXME mMapView.getMapGenerator().getZoomLevelMax());
|
||||
zoomlevel.setMax(20); // FIXME
|
||||
// mMapView.getMapGenerator().getZoomLevelMax());
|
||||
zoomlevel.setProgress(mMapView.getMapPosition().getZoomLevel());
|
||||
|
||||
final TextView textView = (TextView) dialog.findViewById(R.id.zoomlevelValue);
|
||||
@ -417,34 +420,42 @@ public class TileMap extends MapActivity {
|
||||
// } else if (id == DIALOG_INFO_MAP_FILE) {
|
||||
// MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
|
||||
//
|
||||
// TextView textView = (TextView) dialog.findViewById(R.id.infoMapFileViewName);
|
||||
// TextView textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewName);
|
||||
// textView.setText(mMapView.getMapFile());
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewSize);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewSize);
|
||||
// textView.setText(FileUtils.formatFileSize(mapInfo.fileSize,
|
||||
// getResources()));
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewVersion);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewVersion);
|
||||
// textView.setText(String.valueOf(mapInfo.fileVersion));
|
||||
//
|
||||
// // textView = (TextView) dialog.findViewById(R.id.infoMapFileViewDebug);
|
||||
// // textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewDebug);
|
||||
// // if (mapFileInfo.debugFile) {
|
||||
// // textView.setText(R.string.info_map_file_debug_yes);
|
||||
// // } else {
|
||||
// // textView.setText(R.string.info_map_file_debug_no);
|
||||
// // }
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewDate);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewDate);
|
||||
// Date date = new Date(mapInfo.mapDate);
|
||||
// textView.setText(DateFormat.getDateTimeInstance().format(date));
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewArea);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewArea);
|
||||
// BoundingBox boundingBox = mapInfo.boundingBox;
|
||||
// textView.setText(boundingBox.getMinLatitude() + ", "
|
||||
// + boundingBox.getMinLongitude() + " - \n"
|
||||
// + boundingBox.getMaxLatitude() + ", " + boundingBox.getMaxLongitude());
|
||||
// + boundingBox.getMaxLatitude() + ", " +
|
||||
// boundingBox.getMaxLongitude());
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewStartPosition);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewStartPosition);
|
||||
// GeoPoint startPosition = mapInfo.startPosition;
|
||||
// if (startPosition == null) {
|
||||
// textView.setText(null);
|
||||
@ -453,7 +464,8 @@ public class TileMap extends MapActivity {
|
||||
// + startPosition.getLongitude());
|
||||
// }
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewStartZoomLevel);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewStartZoomLevel);
|
||||
// Byte startZoomLevel = mapInfo.startZoomLevel;
|
||||
// if (startZoomLevel == null) {
|
||||
// textView.setText(null);
|
||||
@ -465,10 +477,12 @@ public class TileMap extends MapActivity {
|
||||
// .findViewById(R.id.infoMapFileViewLanguagePreference);
|
||||
// textView.setText(mapInfo.languagePreference);
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewComment);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewComment);
|
||||
// textView.setText(mapInfo.comment);
|
||||
//
|
||||
// textView = (TextView) dialog.findViewById(R.id.infoMapFileViewCreatedBy);
|
||||
// textView = (TextView)
|
||||
// dialog.findViewById(R.id.infoMapFileViewCreatedBy);
|
||||
// textView.setText(mapInfo.createdBy);
|
||||
} else {
|
||||
super.onPrepareDialog(id, dialog);
|
||||
@ -483,13 +497,17 @@ public class TileMap extends MapActivity {
|
||||
.getDefaultSharedPreferences(this);
|
||||
|
||||
// MapScaleBar mapScaleBar = mapView.getMapScaleBar();
|
||||
// mapScaleBar.setShowMapScaleBar(preferences.getBoolean("showScaleBar", false));
|
||||
// String scaleBarUnitDefault = getString(R.string.preferences_scale_bar_unit_default);
|
||||
// String scaleBarUnit = preferences.getString("scaleBarUnit", scaleBarUnitDefault);
|
||||
// mapScaleBar.setShowMapScaleBar(preferences.getBoolean("showScaleBar",
|
||||
// false));
|
||||
// String scaleBarUnitDefault =
|
||||
// getString(R.string.preferences_scale_bar_unit_default);
|
||||
// String scaleBarUnit = preferences.getString("scaleBarUnit",
|
||||
// scaleBarUnitDefault);
|
||||
// mapScaleBar.setImperialUnits(scaleBarUnit.equals("imperial"));
|
||||
|
||||
// if (preferences.contains("mapGenerator")) {
|
||||
// String name = preferences.getString("mapGenerator", MapGeneratorInternal.SW_RENDERER.name());
|
||||
// String name = preferences.getString("mapGenerator",
|
||||
// MapGeneratorInternal.SW_RENDERER.name());
|
||||
// MapGeneratorInternal mapGeneratorInternalNew;
|
||||
// try {
|
||||
// mapGeneratorInternalNew = MapGeneratorInternal.valueOf(name);
|
||||
@ -498,7 +516,8 @@ public class TileMap extends MapActivity {
|
||||
// }
|
||||
//
|
||||
// if (mapGeneratorInternalNew != mapGeneratorInternal) {
|
||||
// TileGenerator mapGenerator = MapGeneratorFactory.createMapGenerator(mapGeneratorInternalNew);
|
||||
// TileGenerator mapGenerator =
|
||||
// MapGeneratorFactory.createMapGenerator(mapGeneratorInternalNew);
|
||||
// mapView.setMapGenerator(mapGenerator);
|
||||
// mapGeneratorInternal = mapGeneratorInternalNew;
|
||||
// }
|
||||
@ -525,7 +544,8 @@ public class TileMap extends MapActivity {
|
||||
}
|
||||
|
||||
// try {
|
||||
// String textScaleDefault = getString(R.string.preferences_text_scale_default);
|
||||
// String textScaleDefault =
|
||||
// getString(R.string.preferences_text_scale_default);
|
||||
// mMapView.setTextScale(Float.parseFloat(preferences.getString("textScale",
|
||||
// textScaleDefault)));
|
||||
// } catch (NumberFormatException e) {
|
||||
@ -596,7 +616,8 @@ public class TileMap extends MapActivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the UI thread to display the given text message as toast notification.
|
||||
* Uses the UI thread to display the given text message as toast
|
||||
* notification.
|
||||
*
|
||||
* @param text
|
||||
* the text message to display
|
||||
|
@ -65,8 +65,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
||||
|
||||
private static final String SERVER_ADDR = "city.informatik.uni-bremen.de";
|
||||
private static final String URL = "/osci/map-live/";
|
||||
// private static final String URL = "/osci/oscim/";
|
||||
// private static final String URL = "/osci/map-live/";
|
||||
private static final String URL = "/osci/oscim/";
|
||||
|
||||
private final static float REF_TILE_SIZE = 4096.0f;
|
||||
|
||||
|
@ -91,10 +91,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
||||
|
||||
private static final String SERVER_ADDR = "city.informatik.uni-bremen.de";
|
||||
// private static final String URL = "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
|
||||
// private static final String URL =
|
||||
// "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
|
||||
private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile";
|
||||
// private static final String URL = "http://city.informatik.uni-bremen.de/tiles/tiles.py///test/%d/%d/%d.osmtile";
|
||||
// private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/gis2/%d/%d/%d.osmtile";
|
||||
// private static final String URL =
|
||||
// "http://city.informatik.uni-bremen.de/tiles/tiles.py///test/%d/%d/%d.osmtile";
|
||||
// private static final String URL =
|
||||
// "http://city.informatik.uni-bremen.de/osmstache/gis2/%d/%d/%d.osmtile";
|
||||
|
||||
private final static float REF_TILE_SIZE = 4096.0f;
|
||||
|
||||
@ -360,7 +363,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
return file;
|
||||
}
|
||||
|
||||
// /////////////// hand sewed tile protocol buffers decoder ///////////////////
|
||||
// /////////////// hand sewed tile protocol buffers decoder ////////////////
|
||||
private static final int BUFFER_SIZE = 65536;
|
||||
|
||||
private final byte[] mReadBuffer = new byte[BUFFER_SIZE];
|
||||
@ -604,7 +607,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
lastY = lat + lastY;
|
||||
|
||||
mMapGenerator.renderPointOfInterest(layer,
|
||||
tags, lastY / scale, lastX / scale);
|
||||
tags, Tile.TILE_SIZE - lastY / scale, lastX / scale);
|
||||
cnt += 2;
|
||||
}
|
||||
return cnt;
|
||||
@ -800,7 +803,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
} else {
|
||||
y = ((result >>> 1) ^ -(result & 1));
|
||||
lastY = lastY + y;
|
||||
coords[cnt++] = lastY / scale;
|
||||
coords[cnt++] = Tile.TILE_SIZE - lastY / scale;
|
||||
even = true;
|
||||
}
|
||||
}
|
||||
@ -940,7 +943,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
return result;
|
||||
}
|
||||
|
||||
// ///////////////////////// Lightweight HttpClient ///////////////////////////////////////
|
||||
// ///////////////////////// Lightweight HttpClient
|
||||
// ///////////////////////////////////////
|
||||
// would have written simple tcp server/client for this...
|
||||
|
||||
private int mMaxReq = 0;
|
||||
@ -1080,7 +1084,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
len += pos;
|
||||
|
||||
// this does the same but with a few more allocations:
|
||||
// byte[] request = String.format(REQUEST, Integer.valueOf(tile.zoomLevel),
|
||||
// byte[] request = String.format(REQUEST,
|
||||
// Integer.valueOf(tile.zoomLevel),
|
||||
// Integer.valueOf(tile.tileX), Integer.valueOf(tile.tileY)).getBytes();
|
||||
|
||||
try {
|
||||
@ -1138,7 +1143,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
}
|
||||
|
||||
// //////////////////////////// Tile cache ////////////////////////////////////
|
||||
// //////////////////////////// Tile cache ///////////////////////////////
|
||||
|
||||
private boolean cacheRead(Tile tile, File f) {
|
||||
if (f.exists() && f.length() > 0) {
|
||||
@ -1212,7 +1217,10 @@ public class MapDatabase implements IMapDatabase {
|
||||
mCacheFile = null;
|
||||
}
|
||||
|
||||
/* All code below is taken from or based on Google's Protocol Buffers implementation: */
|
||||
/*
|
||||
* All code below is taken from or based on Google's Protocol Buffers
|
||||
* implementation:
|
||||
*/
|
||||
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
|
@ -38,6 +38,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
// private Tag[] mTags = { new Tag("boundary", "administrative"), new
|
||||
// Tag("admin_level", "2") };
|
||||
private Tag[] mTags = { new Tag("natural", "water") };
|
||||
private Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") };
|
||||
|
||||
private Tag[] mNameTags;
|
||||
|
||||
private final MapInfo mMapInfo =
|
||||
@ -50,10 +52,12 @@ public class MapDatabase implements IMapDatabase {
|
||||
@Override
|
||||
public QueryResult executeQuery(JobTile tile, IMapDatabaseCallback mapDatabaseCallback) {
|
||||
|
||||
float lat1 = -0.5f;
|
||||
float lon1 = -0.5f;
|
||||
float lat2 = Tile.TILE_SIZE + 0.5f;
|
||||
float lon2 = Tile.TILE_SIZE + 0.5f;
|
||||
int size = Tile.TILE_SIZE;
|
||||
|
||||
float lat1 = -1;
|
||||
float lon1 = -1;
|
||||
float lat2 = size + 1;
|
||||
float lon2 = size + 1;
|
||||
|
||||
mCoords[0] = lon1;
|
||||
mCoords[1] = lat1;
|
||||
@ -70,13 +74,13 @@ public class MapDatabase implements IMapDatabase {
|
||||
mCoords[8] = lon1;
|
||||
mCoords[9] = lat1;
|
||||
|
||||
mIndex[0] = 8;
|
||||
mIndex[1] = 2;
|
||||
mIndex[0] = 10;
|
||||
mIndex[1] = 0;
|
||||
|
||||
lon1 = 40;
|
||||
lon2 = Tile.TILE_SIZE - 40;
|
||||
lon2 = size - 40;
|
||||
lat1 = 40;
|
||||
lat2 = Tile.TILE_SIZE - 40;
|
||||
lat2 = size - 40;
|
||||
|
||||
mCoords[10] = lon1;
|
||||
mCoords[11] = lat1;
|
||||
@ -93,19 +97,84 @@ public class MapDatabase implements IMapDatabase {
|
||||
mCoords[18] = lon1;
|
||||
mCoords[19] = lat1;
|
||||
|
||||
mIndex[2] = 8;
|
||||
mIndex[3] = 2;
|
||||
mIndex[2] = 10;
|
||||
mIndex[3] = 0;
|
||||
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
||||
|
||||
lon1 = Tile.TILE_SIZE / 2;
|
||||
lat1 = Tile.TILE_SIZE / 2;
|
||||
mIndex[0] = 4;
|
||||
mIndex[1] = -1;
|
||||
|
||||
mNameTags = new Tag[2];
|
||||
mNameTags[0] = new Tag("place", "city");
|
||||
mNameTags[1] = new Tag("name", tile.toString());
|
||||
mapDatabaseCallback.renderPointOfInterest((byte) 0, mNameTags, (int) lat1,
|
||||
(int) lon1);
|
||||
// middle horizontal
|
||||
mCoords[0] = 0;
|
||||
mCoords[1] = size / 2;
|
||||
mCoords[2] = size;
|
||||
mCoords[3] = size / 2;
|
||||
Tag[] tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false);
|
||||
|
||||
// center up
|
||||
mCoords[0] = size / 2;
|
||||
mCoords[1] = -size / 2;
|
||||
mCoords[2] = size / 2;
|
||||
mCoords[3] = size / 2;
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex,
|
||||
false);
|
||||
|
||||
// center down
|
||||
mCoords[0] = size / 2;
|
||||
mCoords[1] = size / 2;
|
||||
mCoords[2] = size / 2;
|
||||
mCoords[3] = size / 2 + size;
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false);
|
||||
|
||||
// left-top to center
|
||||
mCoords[0] = size / 2;
|
||||
mCoords[1] = size / 2;
|
||||
mCoords[2] = 10;
|
||||
mCoords[3] = 10;
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
|
||||
// middle horizontal
|
||||
mCoords[0] = 0;
|
||||
mCoords[1] = 10;
|
||||
mCoords[2] = size;
|
||||
mCoords[3] = 10;
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
|
||||
// middle horizontal
|
||||
mCoords[0] = 10;
|
||||
mCoords[1] = 0;
|
||||
mCoords[2] = 10;
|
||||
mCoords[3] = size;
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
|
||||
// lon1 = size / 2;
|
||||
// lat1 = size / 2;
|
||||
|
||||
// mNameTags = new Tag[2];
|
||||
// mNameTags[0] = new Tag("place", "city");
|
||||
// mNameTags[1] = new Tag("name", tile.toString());
|
||||
// mapDatabaseCallback.renderPointOfInterest((byte) 0, mNameTags, (int)
|
||||
// lat1,
|
||||
// (int) lon1);
|
||||
|
||||
return QueryResult.SUCCESS;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,7 @@ public class Compass {
|
||||
mAngle = event.values[0];
|
||||
|
||||
if (mMapView != null) {
|
||||
mMapView.getMapPosition().setRotation(mAngle);
|
||||
mMapView.getMapPosition().setRotation(-mAngle);
|
||||
mMapView.redrawMap();
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,8 @@ public class MapView extends FrameLayout {
|
||||
|
||||
public static final boolean debugFrameTime = false;
|
||||
public static final boolean testRegionZoom = false;
|
||||
public static final boolean staticLabeling = true;
|
||||
|
||||
private static final boolean debugDatabase = false;
|
||||
|
||||
RegionLookup mRegionLookup;
|
||||
@ -82,8 +84,6 @@ public class MapView extends FrameLayout {
|
||||
private String mRenderTheme;
|
||||
private Map<String, String> mMapOptions;
|
||||
|
||||
// private final Handler mHandler;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* the enclosing MapActivity instance.
|
||||
|
@ -27,9 +27,10 @@ import android.util.Log;
|
||||
* together with its zoom level.
|
||||
*/
|
||||
public class MapViewPosition {
|
||||
// private static final String TAG = "MapViewPosition";
|
||||
private static final String TAG = "MapViewPosition";
|
||||
|
||||
public final static int MAX_ZOOMLEVEL = 17;
|
||||
public final static int MIN_ZOOMLEVEL = 2;
|
||||
|
||||
private final static float MAX_ANGLE = 20;
|
||||
|
||||
@ -68,7 +69,7 @@ public class MapViewPosition {
|
||||
|
||||
void setViewport(int width, int height) {
|
||||
Matrix.frustumM(mProjMatrix, 0, -0.5f * width, 0.5f * width,
|
||||
-0.5f * height, 0.5f * height, 1, 2);
|
||||
0.5f * height, -0.5f * height, 1, 2);
|
||||
|
||||
Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
||||
|
||||
@ -92,14 +93,14 @@ public class MapViewPosition {
|
||||
// && mapPosition.scale == mScale
|
||||
// && mapPosition.angle == mRotation)
|
||||
// return false;
|
||||
byte z = mZoomLevel;
|
||||
|
||||
mapPosition.lat = mLatitude;
|
||||
mapPosition.lon = mLongitude;
|
||||
mapPosition.angle = mRotation;
|
||||
mapPosition.zoomLevel = mZoomLevel;
|
||||
mapPosition.scale = mScale;
|
||||
mapPosition.zoomLevel = z;
|
||||
|
||||
byte z = mZoomLevel;
|
||||
mapPosition.x = MercatorProjection.longitudeToPixelX(mLongitude, z);
|
||||
mapPosition.y = MercatorProjection.latitudeToPixelY(mLatitude, z);
|
||||
|
||||
@ -138,13 +139,12 @@ public class MapViewPosition {
|
||||
|
||||
if (mv[3] != 0) {
|
||||
float w = 1 / mv[3];
|
||||
float xx = mv[0] * w;
|
||||
float yy = mv[1] * w;
|
||||
|
||||
coords[position] = xx;
|
||||
coords[position + 1] = yy;
|
||||
coords[position] = mv[0] * w;
|
||||
coords[position + 1] = mv[1] * w;
|
||||
} else {
|
||||
// else what?
|
||||
Log.d(TAG, "... what?");
|
||||
}
|
||||
// else what?
|
||||
}
|
||||
|
||||
private void updateMatrix() {
|
||||
@ -152,7 +152,7 @@ public class MapViewPosition {
|
||||
|
||||
// tilt map
|
||||
float tilt = mTilt;
|
||||
Matrix.setRotateM(mTmpMatrix, 0, -tilt / (mHeight / 2), 1, 0, 0);
|
||||
Matrix.setRotateM(mTmpMatrix, 0, tilt / (mHeight / 2), 1, 0, 0);
|
||||
|
||||
// apply first rotation, then tilt
|
||||
Matrix.multiplyMM(mRotateMatrix, 0, mTmpMatrix, 0, mRotateMatrix, 0);
|
||||
@ -177,10 +177,10 @@ public class MapViewPosition {
|
||||
|
||||
float tilt = FloatMath.sin((float) Math.toRadians(mTilt)) * 4;
|
||||
|
||||
unproject(-1, 1, tilt, mBBoxCoords, 0); // top-left
|
||||
unproject(1, 1, tilt, mBBoxCoords, 2); // top-right
|
||||
unproject(1, -1, -tilt, mBBoxCoords, 4); // bottom-right
|
||||
unproject(-1, -1, -tilt, mBBoxCoords, 6); // bottom-left
|
||||
unproject(-1, 1, -tilt, mBBoxCoords, 0); // top-left
|
||||
unproject(1, 1, -tilt, mBBoxCoords, 2); // top-right
|
||||
unproject(1, -1, tilt, mBBoxCoords, 4); // bottom-right
|
||||
unproject(-1, -1, tilt, mBBoxCoords, 6); // bottom-left
|
||||
|
||||
byte z = mZoomLevel;
|
||||
double pixelX = MercatorProjection.longitudeToPixelX(mLongitude, z);
|
||||
@ -333,8 +333,8 @@ public class MapViewPosition {
|
||||
|
||||
if (mMapView.enableRotation || mMapView.enableCompass) {
|
||||
double rad = Math.toRadians(mRotation);
|
||||
double x = dx * Math.cos(rad) + dy * -Math.sin(rad);
|
||||
double y = dx * Math.sin(rad) + dy * Math.cos(rad);
|
||||
double x = dx * Math.cos(rad) + dy * Math.sin(rad);
|
||||
double y = dx * -Math.sin(rad) + dy * Math.cos(rad);
|
||||
dx = x;
|
||||
dy = y;
|
||||
}
|
||||
@ -357,7 +357,7 @@ public class MapViewPosition {
|
||||
moveMap(cx, cy);
|
||||
// Log.d("MapViewPosition", "rotate:" + angle + " " + (mRotation -
|
||||
// angle));
|
||||
mRotation -= angle;
|
||||
mRotation += angle;
|
||||
updateMatrix();
|
||||
}
|
||||
|
||||
@ -426,12 +426,13 @@ public class MapViewPosition {
|
||||
|
||||
int z = FastMath.log2((int) newScale);
|
||||
|
||||
if (z <= 0 || (z >= MAX_ZOOMLEVEL && mScale >= 8))
|
||||
if (z < MIN_ZOOMLEVEL || (z >= MAX_ZOOMLEVEL && mScale >= 8))
|
||||
return false;
|
||||
|
||||
if (z > MAX_ZOOMLEVEL) {
|
||||
// z16 shows everything, just increase scaling
|
||||
if (mScale * scale > 8)
|
||||
// z17 shows everything, just increase scaling
|
||||
// need to fix this for ScanBox
|
||||
if (mScale * scale > 2) // 8)
|
||||
return false;
|
||||
|
||||
mScale *= scale;
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.overlay;
|
||||
|
||||
public class Overlay {
|
||||
|
||||
synchronized void move() {
|
||||
|
||||
}
|
||||
|
||||
synchronized void addBitmap() {
|
||||
|
||||
}
|
||||
|
||||
synchronized boolean onTouch() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
synchronized void draw() {
|
||||
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010, 2011, 2012 mapsforge.org
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.overlay;
|
||||
|
||||
public class TiledOverlay extends Overlay {
|
||||
|
||||
}
|
@ -21,7 +21,6 @@ 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 java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@ -63,7 +62,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
private final MapView mMapView;
|
||||
private final MapViewPosition mMapViewPosition;
|
||||
|
||||
private static final MapPosition mMapPosition = new MapPosition();
|
||||
private static MapPosition mMapPosition;
|
||||
|
||||
private static ArrayList<VertexBufferObject> mVBOs;
|
||||
|
||||
@ -82,7 +81,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
// mNextTiles is set by TileLoader and swapped with
|
||||
// mDrawTiles in onDrawFrame in GL thread.
|
||||
private static TilesData mNextTiles, mDrawTiles;
|
||||
private static TilesData mNextTiles;
|
||||
/* package */static TilesData mDrawTiles;
|
||||
|
||||
// flag set by updateVisibleList when current visible tiles
|
||||
// changed. used in onDrawFrame to flip mNextTiles/mDrawTiles
|
||||
@ -95,9 +95,78 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
private static boolean mUpdateColor = false;
|
||||
|
||||
// lock to synchronize Main- and GL-Thread
|
||||
// drawlock to synchronize Main- and GL-Thread
|
||||
static ReentrantLock tilelock = new ReentrantLock();
|
||||
static ReentrantLock lock = new ReentrantLock();
|
||||
static ReentrantLock drawlock = new ReentrantLock();
|
||||
|
||||
/* package */static int mHolderCount;
|
||||
|
||||
// scanline fill class used to check tile visibility
|
||||
private static ScanBox mScanBox = new ScanBox() {
|
||||
@Override
|
||||
void setVisible(int y, int x1, int x2) {
|
||||
int cnt = mDrawTiles.cnt;
|
||||
|
||||
MapTile[] tiles = mDrawTiles.tiles;
|
||||
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
if (t.tileY == y && t.tileX >= x1 && t.tileX < x2)
|
||||
t.isVisible = true;
|
||||
}
|
||||
|
||||
int xmax = 1 << mZoom;
|
||||
if (x1 >= 0 && x2 < xmax)
|
||||
return;
|
||||
|
||||
// add placeholder tiles to show both sides
|
||||
// of date line...
|
||||
for (int x = x1; x < x2; x++) {
|
||||
MapTile holder = null;
|
||||
MapTile tile = null;
|
||||
boolean found = false;
|
||||
|
||||
int xx = x;
|
||||
|
||||
if (x >= 0 && x < xmax)
|
||||
continue;
|
||||
|
||||
if (x < 0)
|
||||
xx = xmax + x;
|
||||
else
|
||||
xx = x - xmax;
|
||||
|
||||
if (xx < 0 || xx >= xmax)
|
||||
continue;
|
||||
|
||||
for (int i = cnt; i < cnt + mHolderCount; i++)
|
||||
if (tiles[i].tileX == x && tiles[i].tileY == y) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < cnt; i++)
|
||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||
tile = tiles[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (tile == null)
|
||||
continue;
|
||||
|
||||
// Log.d(TAG, "add placeholder " + y + " " + x + ">>" + xx + " "
|
||||
// + tile);
|
||||
|
||||
holder = new MapTile(x, y, mZoom);
|
||||
holder.isVisible = true;
|
||||
holder.holder = tile;
|
||||
tiles[cnt + mHolderCount++] = holder;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
@ -108,8 +177,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
mMapView = mapView;
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
// mMapPosition = new MapPosition();
|
||||
|
||||
mMapPosition = new MapPosition();
|
||||
mMapPosition.init();
|
||||
|
||||
Matrix.setIdentityM(mMVPMatrix, 0);
|
||||
@ -141,63 +209,38 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* called by TileLoader when list of active tiles changed
|
||||
* Called by TileLoader when list of active tiles changed. the list is
|
||||
* copied to mNextTiles to be used in next call to onDrawFrame
|
||||
*
|
||||
* @param tiles
|
||||
* active tiles
|
||||
* @return mNextTiles (the previously active tiles)
|
||||
*/
|
||||
static TilesData updateTiles(TilesData tiles) {
|
||||
GLRenderer.tilelock.lock();
|
||||
static void updateTiles(TilesData tiles) {
|
||||
|
||||
// unlock previously active tiles
|
||||
for (int i = 0; i < mNextTiles.cnt; i++) {
|
||||
MapTile t = mNextTiles.tiles[i];
|
||||
boolean found = false;
|
||||
|
||||
for (int j = 0; j < tiles.cnt; j++) {
|
||||
if (tiles.tiles[j] == t) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < mDrawTiles.cnt; j++) {
|
||||
if (mDrawTiles.tiles[j] == t) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
t.unlock();
|
||||
}
|
||||
|
||||
TilesData tmp = mNextTiles;
|
||||
mNextTiles = tiles;
|
||||
MapTile[] newTiles = tiles.tiles;
|
||||
|
||||
// lock tiles (and their proxies) to not be removed from cache
|
||||
for (int i = 0; i < mNextTiles.cnt; i++) {
|
||||
MapTile t = mNextTiles.tiles[i];
|
||||
if (!t.isLocked)
|
||||
t.lock();
|
||||
}
|
||||
for (int i = 0, n = tiles.cnt; i < n; i++)
|
||||
newTiles[i].lock();
|
||||
|
||||
for (int j = 0; j < mDrawTiles.cnt; j++) {
|
||||
MapTile t = mDrawTiles.tiles[j];
|
||||
if (!t.isLocked)
|
||||
t.lock();
|
||||
}
|
||||
// dont flip next/drawTiles while copying
|
||||
GLRenderer.tilelock.lock();
|
||||
|
||||
// GLThread flips mNextTiles with mDrawTiles
|
||||
MapTile[] nextTiles = mNextTiles.tiles;
|
||||
|
||||
// unlock previously active tiles
|
||||
for (int i = 0, n = mNextTiles.cnt; i < n; i++)
|
||||
nextTiles[i].unlock();
|
||||
|
||||
// copy newTiles to nextTiles
|
||||
System.arraycopy(newTiles, 0, nextTiles, 0, tiles.cnt);
|
||||
|
||||
mNextTiles.cnt = tiles.cnt;
|
||||
|
||||
// flip next/drawTiles in next onDrawFrame
|
||||
mUpdateTiles = true;
|
||||
|
||||
GLRenderer.tilelock.unlock();
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -267,7 +310,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// add fill coordinates
|
||||
newSize += 8;
|
||||
|
||||
// FIXME probably not a good idea to do this in gl thread...
|
||||
// probably not a good idea to do this in gl thread...
|
||||
if (sbuf.capacity() < newSize) {
|
||||
ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
@ -317,7 +360,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
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;
|
||||
@ -385,68 +427,26 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
CACHE_TILES -= 50;
|
||||
}
|
||||
|
||||
private static boolean isVisible(MapTile tile) {
|
||||
float dx, dy, scale, div = 1;
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
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;
|
||||
ssize += Tile.TILE_SIZE;
|
||||
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;
|
||||
|
||||
private static void setMatrix(float[] matrix, MapTile tile,
|
||||
float div, boolean project) {
|
||||
float x, y, scale;
|
||||
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
|
||||
scale = mapPosition.scale / (div * COORD_MULTIPLIER);
|
||||
x = (float) (tile.pixelX - mapPosition.x * div);
|
||||
y = (float) (tile.pixelY - mapPosition.y * div);
|
||||
float x = (float) (tile.pixelX - mapPosition.x * div);
|
||||
float y = (float) (tile.pixelY - mapPosition.y * div);
|
||||
float scale = mapPosition.scale / div;
|
||||
|
||||
Matrix.setIdentityM(matrix, 0);
|
||||
|
||||
// scale to tile to world coordinates
|
||||
Matrix.scaleM(matrix, 0, scale, scale, 1);
|
||||
|
||||
// translate relative to map center
|
||||
Matrix.translateM(matrix, 0, x * COORD_MULTIPLIER,
|
||||
-(y + Tile.TILE_SIZE) * COORD_MULTIPLIER, 0);
|
||||
matrix[12] = x * scale;
|
||||
matrix[13] = y * scale;
|
||||
|
||||
// scale to tile to world coordinates
|
||||
scale /= COORD_MULTIPLIER;
|
||||
matrix[0] = scale;
|
||||
matrix[5] = scale;
|
||||
|
||||
if (mRotate)
|
||||
Matrix.multiplyMM(matrix, 0, mapPosition.rotation, 0, matrix, 0);
|
||||
@ -471,11 +471,17 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// prevent main thread recreating all tiles (updateMap)
|
||||
// while rendering is going. not have seen this happen
|
||||
// yet though
|
||||
GLRenderer.lock.lock();
|
||||
GLRenderer.drawlock.lock();
|
||||
|
||||
if (MapView.debugFrameTime)
|
||||
start = SystemClock.uptimeMillis();
|
||||
|
||||
if (mUpdateColor) {
|
||||
float cc[] = mClearColor;
|
||||
GLES20.glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||
mUpdateColor = false;
|
||||
}
|
||||
|
||||
// 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
|
||||
@ -496,14 +502,17 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
}
|
||||
|
||||
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||
GLRenderer.lock.unlock();
|
||||
GLRenderer.drawlock.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
||||
|
||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||
// coordinates)
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
||||
float[] coords = mTileCoords;
|
||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||
|
||||
int tileCnt = mDrawTiles.cnt;
|
||||
MapTile[] tiles = mDrawTiles.tiles;
|
||||
@ -517,29 +526,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// zoom-level changed.
|
||||
float div = scaleDiv(tiles[0]);
|
||||
|
||||
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
||||
|
||||
float s = Tile.TILE_SIZE;
|
||||
float scale = mapPosition.scale / div;
|
||||
float px = (float) (mapPosition.x * div);
|
||||
float py = (float) (mapPosition.y * div);
|
||||
double px = mapPosition.x * div;
|
||||
double py = mapPosition.y * div;
|
||||
|
||||
mTileCoords[0] = (px + mTileCoords[0] / scale) / s;
|
||||
mTileCoords[1] = (py - mTileCoords[1] / scale) / s;
|
||||
mTileCoords[2] = (px + mTileCoords[2] / scale) / s;
|
||||
mTileCoords[3] = (py - mTileCoords[3] / scale) / s;
|
||||
mTileCoords[4] = (px + mTileCoords[4] / scale) / s;
|
||||
mTileCoords[5] = (py - mTileCoords[5] / scale) / s;
|
||||
mTileCoords[6] = (px + mTileCoords[6] / scale) / s;
|
||||
mTileCoords[7] = (py - mTileCoords[7] / scale) / s;
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (float) ((px + coords[i + 0] / scale) / s);
|
||||
coords[i + 1] = (float) ((py + coords[i + 1] / scale) / s);
|
||||
}
|
||||
|
||||
byte z = tiles[0].zoomLevel;
|
||||
ScanBox.scan(mTileCoords, mDrawTiles, 1 << z);
|
||||
}
|
||||
|
||||
if (mUpdateColor && mClearColor != null) {
|
||||
GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
|
||||
mUpdateColor = false;
|
||||
mHolderCount = 0;
|
||||
mScanBox.scan(coords, tiles[0].zoomLevel);
|
||||
tileCnt += mHolderCount;
|
||||
}
|
||||
|
||||
uploadCnt = 0;
|
||||
@ -554,15 +553,21 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (!tile.isVisible)
|
||||
continue;
|
||||
|
||||
if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
||||
updateTextures++;
|
||||
if (MapView.staticLabeling) {
|
||||
if (tile.texture == null && TextRenderer.drawToTexture(tile))
|
||||
updateTextures++;
|
||||
}
|
||||
|
||||
if (tile.newData) {
|
||||
uploadTileData(tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tile.isReady) {
|
||||
if (tile.holder != null) {
|
||||
if (tile.holder.newData) {
|
||||
uploadTileData(tile.holder);
|
||||
}
|
||||
tile.isReady = tile.holder.isReady;
|
||||
} else if (!tile.isReady) {
|
||||
// check near relatives if they can serve as proxy
|
||||
MapTile rel = tile.rel.parent.tile;
|
||||
if (rel != null && rel.newData) {
|
||||
@ -583,22 +588,26 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (uploadCnt > 0)
|
||||
checkBufferUsage();
|
||||
|
||||
if (updateTextures > 0)
|
||||
TextRenderer.compileTextures();
|
||||
if (MapView.staticLabeling) {
|
||||
if (updateTextures > 0)
|
||||
TextRenderer.compileTextures();
|
||||
}
|
||||
|
||||
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(tiles[i]);
|
||||
MapTile t = tiles[i];
|
||||
if (t.isVisible && t.isReady)
|
||||
drawTile(t);
|
||||
}
|
||||
|
||||
// proxies are clipped to the region where nothing was drawn to depth
|
||||
// buffer. TODO draw all parent before grandparent
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
if (tiles[i].isVisible && !tiles[i].isReady)
|
||||
drawProxyTile(tiles[i]);
|
||||
MapTile t = tiles[i];
|
||||
if (t.isVisible && !t.isReady && (t.holder == null))
|
||||
drawProxyTile(t);
|
||||
}
|
||||
// GlUtils.checkGlError("end draw");
|
||||
|
||||
@ -608,56 +617,52 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mDrawCount = 0;
|
||||
mDrawSerial++;
|
||||
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
int z = mapPosition.zoomLevel;
|
||||
float s = mapPosition.scale;
|
||||
if (MapView.staticLabeling) {
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
int z = mapPosition.zoomLevel;
|
||||
float s = mapPosition.scale;
|
||||
|
||||
int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL, 0);
|
||||
float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
||||
if (scale < 1)
|
||||
scale = 1;
|
||||
int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL, 0);
|
||||
float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
||||
if (scale < 1)
|
||||
scale = 1;
|
||||
|
||||
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
||||
TextRenderer.beginDraw(FloatMath.sqrt(s) / scale, mProjMatrix);
|
||||
else
|
||||
TextRenderer.beginDraw(s, mProjMatrix);
|
||||
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
||||
TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
||||
else
|
||||
TextRenderer.beginDraw(1 / s, mProjMatrix);
|
||||
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
if (!tiles[i].isVisible || tiles[i].texture == null)
|
||||
continue;
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
if (!t.isVisible)
|
||||
continue;
|
||||
|
||||
setMatrix(mMVPMatrix, tiles[i], 1, false);
|
||||
TextRenderer.drawTile(tiles[i], mMVPMatrix);
|
||||
if (t.holder == null) {
|
||||
if (t.texture != null) {
|
||||
setMatrix(mMVPMatrix, t, 1, false);
|
||||
TextRenderer.drawTile(t, mMVPMatrix);
|
||||
}
|
||||
} else {
|
||||
if (t.holder.texture != null) {
|
||||
setMatrix(mMVPMatrix, t, 1, false);
|
||||
TextRenderer.drawTile(t.holder, mMVPMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
TextRenderer.endDraw();
|
||||
}
|
||||
TextRenderer.endDraw();
|
||||
|
||||
// TODO call overlay renderer here
|
||||
|
||||
// s = 0.5f;
|
||||
// mTileCoords[0] = -s;
|
||||
// mTileCoords[1] = s;
|
||||
// mTileCoords[2] = s;
|
||||
// mTileCoords[3] = s;
|
||||
// mTileCoords[4] = -s;
|
||||
// mTileCoords[5] = -s;
|
||||
// mTileCoords[6] = s;
|
||||
// mTileCoords[7] = -s;
|
||||
//
|
||||
// Matrix.setIdentityM(mMVPMatrix, 0);
|
||||
// // Matrix.scaleM(mMVPMatrix, 0, 0.99f, 0.99f, 1);
|
||||
// // Matrix.multiplyMM(mMVPMatrix, 0, mRotateMatrix, 0, mMVPMatrix, 0);
|
||||
// // Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
|
||||
// PolygonRenderer.debugDraw(mMVPMatrix, mTileCoords);
|
||||
|
||||
if (MapView.debugFrameTime) {
|
||||
GLES20.glFinish();
|
||||
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
|
||||
}
|
||||
GLRenderer.lock.unlock();
|
||||
GLRenderer.drawlock.unlock();
|
||||
}
|
||||
|
||||
// used to not draw a tile twice per frame...
|
||||
private static byte mDrawSerial = 0;
|
||||
// used to not draw a tile twice per frame.
|
||||
private static int mDrawSerial = 0;
|
||||
|
||||
private static void drawTile(MapTile tile) {
|
||||
// draw parents only once
|
||||
@ -665,15 +670,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
return;
|
||||
|
||||
float div = scaleDiv(tile);
|
||||
float[] mvp = mMVPMatrix;
|
||||
MapPosition pos = mMapPosition;
|
||||
|
||||
tile.lastDraw = mDrawSerial;
|
||||
|
||||
int z = mMapPosition.zoomLevel;
|
||||
float s = mMapPosition.scale;
|
||||
float[] mvp = mMVPMatrix;
|
||||
|
||||
setMatrix(mvp, tile, div, true);
|
||||
|
||||
if (tile.holder != null)
|
||||
tile = tile.holder;
|
||||
|
||||
GLES20.glPolygonOffset(0, mDrawCount++);
|
||||
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
||||
@ -696,21 +702,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
if (pl != null && pnext < lnext) {
|
||||
GLES20.glDisable(GL_BLEND);
|
||||
pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s, !clipped);
|
||||
pl = PolygonRenderer.drawPolygons(pos, pl, lnext, mvp, !clipped);
|
||||
clipped = true;
|
||||
} else {
|
||||
// FIXME
|
||||
if (!clipped) {
|
||||
PolygonRenderer.drawPolygons(null, 0, mvp, z, s, true);
|
||||
PolygonRenderer.drawPolygons(pos, null, 0, mvp, true);
|
||||
clipped = true;
|
||||
}
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s, simpleShader);
|
||||
ll = LineRenderer.drawLines(pos, ll, pnext, mvp, div,
|
||||
simpleShader, tile.lineOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO could use tile.proxies here
|
||||
// TODO should check tile.proxies here
|
||||
private static boolean drawProxyChild(MapTile tile) {
|
||||
int drawn = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@ -721,10 +728,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (c == null)
|
||||
continue;
|
||||
|
||||
if (!isVisible(c)) {
|
||||
drawn++;
|
||||
continue;
|
||||
}
|
||||
// if (!isVisible(c)) {
|
||||
// drawn++;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (c.isReady) {
|
||||
drawTile(c);
|
||||
@ -789,10 +796,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mHeight = height;
|
||||
|
||||
float s = 0.5f;
|
||||
// use this to scale only the view to see which tiles are rendered
|
||||
// use this to scale only the view to see better which tiles are
|
||||
// rendered
|
||||
// s = 1.0f;
|
||||
Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
||||
-s * height, s * height, 1, 2);
|
||||
s * height, -s * height, 1, 2);
|
||||
Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
||||
|
||||
// set to zero: we modify the z value with polygon-offset for clipping
|
||||
@ -805,7 +813,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mMapView.redrawMap();
|
||||
return;
|
||||
}
|
||||
|
||||
mNewSurface = false;
|
||||
|
||||
mBufferMemoryUsage = 0;
|
||||
@ -827,17 +834,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// Set up textures
|
||||
TextRenderer.setup(numTiles);
|
||||
|
||||
if (mClearColor != null) {
|
||||
GLES20.glClearColor(mClearColor[0], mClearColor[1],
|
||||
mClearColor[2], mClearColor[3]);
|
||||
} else {
|
||||
GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
|
||||
}
|
||||
|
||||
GlUtils.checkGlError("onSurfaceChanged");
|
||||
|
||||
GLES20.glClear(GL_STENCIL_BUFFER_BIT);
|
||||
if (mClearColor != null)
|
||||
mUpdateColor = true;
|
||||
|
||||
// FIXME this should be synchronized
|
||||
mMapView.redrawMap();
|
||||
}
|
||||
|
||||
@ -858,6 +858,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
TextRenderer.init();
|
||||
|
||||
mNewSurface = true;
|
||||
// mUpdateColor = true;
|
||||
|
||||
// glEnable(GL_SCISSOR_TEST);
|
||||
// glScissor(0, 0, mWidth, mHeight);
|
||||
@ -870,3 +871,46 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
private boolean mNewSurface;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// private static boolean isVisible(MapTile tile) {
|
||||
// float dx, dy, scale, div = 1;
|
||||
// MapPosition mapPosition = mMapPosition;
|
||||
// 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;
|
||||
// ssize += Tile.TILE_SIZE;
|
||||
// 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;
|
||||
// }
|
||||
|
@ -18,6 +18,7 @@ import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.utils.GlUtils;
|
||||
import org.oscim.view.MapPosition;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
import android.util.FloatMath;
|
||||
@ -74,26 +75,25 @@ class LineRenderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
// static int mSimple = 1;
|
||||
static LineLayer drawLines(MapPosition pos, LineLayer layer, int next,
|
||||
float[] matrix, float div, int mode, int bufferOffset) {
|
||||
|
||||
static LineLayer drawLines(MapTile tile, LineLayer layer, int next, float[] matrix,
|
||||
float div, double zoom, float scale, int mode) {
|
||||
// int mode = mSimple;
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
|
||||
if (layer == null)
|
||||
return null;
|
||||
|
||||
// TODO should use fast line program when view is not tilted
|
||||
GLES20.glUseProgram(lineProgram[mode]);
|
||||
|
||||
GLES20.glEnableVertexAttribArray(hLineVertexPosition[mode]);
|
||||
GLES20.glEnableVertexAttribArray(hLineTexturePosition[mode]);
|
||||
|
||||
GLES20.glVertexAttribPointer(hLineVertexPosition[mode], 2, GLES20.GL_SHORT,
|
||||
false, 8, tile.lineOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
||||
false, 8, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
||||
|
||||
GLES20.glVertexAttribPointer(hLineTexturePosition[mode], 2, GLES20.GL_SHORT,
|
||||
false, 8, tile.lineOffset + LINE_VERTICES_DATA_TEX_OFFSET);
|
||||
false, 8, bufferOffset + LINE_VERTICES_DATA_TEX_OFFSET);
|
||||
|
||||
GLES20.glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
|
||||
|
||||
|
@ -17,13 +17,12 @@ package org.oscim.view.renderer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.database.MapInfo;
|
||||
import org.oscim.theme.RenderTheme;
|
||||
import org.oscim.utils.GlConfigChooser;
|
||||
import org.oscim.view.MapPosition;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.MapViewPosition;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
|
||||
import android.content.Context;
|
||||
@ -37,9 +36,13 @@ public class MapRenderer extends GLSurfaceView {
|
||||
private GLRenderer mRenderer;
|
||||
|
||||
private static final int MAX_TILES_IN_QUEUE = 40;
|
||||
private static final int CACHE_THRESHOLD = 50;
|
||||
|
||||
private static MapView mMapView;
|
||||
|
||||
private static final MapPosition mMapPosition = new MapPosition();
|
||||
private final MapViewPosition mMapViewPosition;
|
||||
|
||||
// new jobs for the MapWorkers
|
||||
private static ArrayList<JobTile> mJobList;
|
||||
|
||||
@ -49,16 +52,21 @@ public class MapRenderer extends GLSurfaceView {
|
||||
// tiles that have new data to upload, see passTile()
|
||||
private static ArrayList<MapTile> mTilesLoaded;
|
||||
|
||||
// current center tile, values used to check if position has
|
||||
// TODO current boundary tiles, values used to check if position has
|
||||
// changed for updating current tile list
|
||||
private static long mTileX, mTileY;
|
||||
private static float mPrevScale;
|
||||
private static byte mPrevZoom;
|
||||
|
||||
private static boolean mInitial;
|
||||
|
||||
// private static MapPosition mCurPosition, mDrawPosition;
|
||||
private static int mWidth = 0, mHeight = 0;
|
||||
|
||||
// maps zoom-level to available zoom-levels in MapDatabase
|
||||
// e.g. 16->16, 15->16, 14->13, 13->13, 12->13,....
|
||||
// private static int[] mZoomLevels;
|
||||
|
||||
private static float[] mTileCoords = new float[8];
|
||||
private static int[] mBoundaryTiles = new int[8];
|
||||
|
||||
// used for passing tiles to be rendered from TileLoader(Main-Thread) to
|
||||
// GLThread
|
||||
static final class TilesData {
|
||||
@ -70,16 +78,61 @@ public class MapRenderer extends GLSurfaceView {
|
||||
}
|
||||
}
|
||||
|
||||
private static TilesData mCurrentTiles;
|
||||
/* package */static TilesData mCurrentTiles;
|
||||
|
||||
// maps zoom-level to available zoom-levels in MapDatabase
|
||||
// e.g. 16->16, 15->16, 14->13, 13->13, 12->13,....
|
||||
private static int[] mZoomLevels;
|
||||
private static ScanBox mScanBox = new ScanBox() {
|
||||
|
||||
@Override
|
||||
void setVisible(int y, int x1, int x2) {
|
||||
MapTile[] tiles = mCurrentTiles.tiles;
|
||||
int cnt = mCurrentTiles.cnt;
|
||||
int max = mCurrentTiles.tiles.length;
|
||||
int xmax = 1 << mZoom;
|
||||
|
||||
for (int x = x1; x < x2; x++) {
|
||||
// MapTile holder = null;
|
||||
MapTile tile = null;
|
||||
|
||||
// boolean found = false;
|
||||
if (cnt == max) {
|
||||
Log.d(TAG, "reached max currentTiles " + max);
|
||||
break;
|
||||
}
|
||||
int xx = x;
|
||||
|
||||
if (x < 0 || x >= xmax) {
|
||||
// flip-around date line
|
||||
if (x < 0)
|
||||
xx = xmax + x;
|
||||
else
|
||||
xx = x - xmax;
|
||||
|
||||
if (xx < 0 || xx >= xmax) {
|
||||
// Log.d(TAG, "tile out of bounds " + y + " " + xx);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < cnt; i++)
|
||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||
tile = tiles[i];
|
||||
break;
|
||||
}
|
||||
|
||||
if (tile == null) {
|
||||
tile = addTile(xx, y, mZoom, 0);
|
||||
tiles[cnt++] = tile;
|
||||
}
|
||||
}
|
||||
mCurrentTiles.cnt = cnt;
|
||||
}
|
||||
};
|
||||
|
||||
public MapRenderer(Context context, MapView mapView) {
|
||||
super(context);
|
||||
|
||||
mMapView = mapView;
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
|
||||
Log.d(TAG, "init GLSurfaceLayer");
|
||||
setEGLConfigChooser(new GlConfigChooser());
|
||||
@ -116,16 +169,9 @@ public class MapRenderer extends GLSurfaceView {
|
||||
if (mMapView == null)
|
||||
return;
|
||||
|
||||
MapPosition mapPosition = mMapView.getMapPosition().getMapPosition();
|
||||
|
||||
if (mapPosition == null) {
|
||||
Log.d(TAG, "X no map position");
|
||||
return;
|
||||
}
|
||||
|
||||
if (clear) {
|
||||
if (clear || mInitial) {
|
||||
// make sure onDrawFrame is not running
|
||||
GLRenderer.lock.lock();
|
||||
GLRenderer.drawlock.lock();
|
||||
// remove all tiles references
|
||||
Log.d(TAG, "CLEAR");
|
||||
for (MapTile t : mTiles)
|
||||
@ -134,74 +180,71 @@ public class MapRenderer extends GLSurfaceView {
|
||||
mTiles.clear();
|
||||
mTilesLoaded.clear();
|
||||
QuadTree.init();
|
||||
mInitial = true;
|
||||
|
||||
GLRenderer.lock.unlock();
|
||||
}
|
||||
|
||||
if (mInitial) {
|
||||
// set up TileData arrays that are passed to gl-thread
|
||||
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||
* (mHeight / (Tile.TILE_SIZE / 2) + 2);
|
||||
int num = mWidth;
|
||||
if (mWidth < mHeight)
|
||||
num = mHeight;
|
||||
|
||||
int size = Tile.TILE_SIZE >> 1;
|
||||
|
||||
int numTiles = (num * num) / (size * size) * 4;
|
||||
|
||||
mRenderer.clearTiles(numTiles);
|
||||
mCurrentTiles = new TilesData(numTiles);
|
||||
|
||||
MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
|
||||
if (mapInfo != null)
|
||||
mZoomLevels = mapInfo.zoomLevel;
|
||||
}
|
||||
// MapInfo mapInfo = mMapView.getMapDatabase().getMapInfo();
|
||||
// if (mapInfo != null)
|
||||
// mZoomLevels = mapInfo.zoomLevel;
|
||||
GLRenderer.drawlock.unlock();
|
||||
|
||||
byte zoomLevel = mapPosition.zoomLevel;
|
||||
float scale = mapPosition.scale;
|
||||
|
||||
long tileX = MercatorProjection.pixelXToTileX(mapPosition.x, zoomLevel)
|
||||
* Tile.TILE_SIZE;
|
||||
long tileY = MercatorProjection.pixelYToTileY(mapPosition.y, zoomLevel)
|
||||
* Tile.TILE_SIZE;
|
||||
|
||||
int zdir = 0;
|
||||
if (mInitial || mPrevZoom != zoomLevel) {
|
||||
changedPos = true;
|
||||
|
||||
} else if (tileX != mTileX || tileY != mTileY) {
|
||||
if (mPrevScale - scale > 0 && scale > 1.2)
|
||||
zdir = 1;
|
||||
changedPos = true;
|
||||
|
||||
} else if (mPrevScale - scale > 0.2 || mPrevScale - scale < -0.2) {
|
||||
if (mPrevScale - scale > 0 && scale > 1.2)
|
||||
zdir = 1;
|
||||
changedPos = true;
|
||||
}
|
||||
|
||||
if (mInitial) {
|
||||
mInitial = false;
|
||||
}
|
||||
|
||||
mTileX = tileX;
|
||||
mTileY = tileY;
|
||||
mPrevZoom = zoomLevel;
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
||||
|
||||
// GLRenderer.updatePosition(mapPosition);
|
||||
float s = Tile.TILE_SIZE;
|
||||
// load some additional tiles more than currently visible
|
||||
float scale = mapPosition.scale * 0.75f;
|
||||
double px = mapPosition.x;
|
||||
double py = mapPosition.y;
|
||||
float[] coords = mTileCoords;
|
||||
int zdir = 0;
|
||||
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
for (int i = 0; i < 8; i += 2) {
|
||||
coords[i + 0] = (float) ((px + coords[i + 0] / scale) / s);
|
||||
coords[i + 1] = (float) ((py + coords[i + 1] / scale) / s);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (mBoundaryTiles[i] != (int) coords[i]) {
|
||||
changedPos = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
mBoundaryTiles[i] = (int) coords[i];
|
||||
|
||||
// TODO all following should probably be done in an idler instead
|
||||
// to drain queued events. need to check how android handles things.
|
||||
|
||||
if (changedPos) {
|
||||
mPrevScale = scale;
|
||||
|
||||
updateVisibleList(mapPosition, zdir);
|
||||
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
|
||||
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||
if (remove > 50)
|
||||
if (remove > CACHE_THRESHOLD)
|
||||
limitCache(mapPosition, remove);
|
||||
}
|
||||
|
||||
limitLoadQueue();
|
||||
limitLoadQueue();
|
||||
} else {
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,118 +257,15 @@ public class MapRenderer extends GLSurfaceView {
|
||||
* zoom direction
|
||||
*/
|
||||
private static void updateVisibleList(MapPosition mapPosition, int zdir) {
|
||||
double x = mapPosition.x;
|
||||
double y = mapPosition.y;
|
||||
byte zoomLevel = mapPosition.zoomLevel;
|
||||
float scale = mapPosition.scale;
|
||||
|
||||
double add = 1.0f / scale;
|
||||
int offsetX = (int) ((mWidth >> 1) * add) + Tile.TILE_SIZE;
|
||||
int offsetY = (int) ((mHeight >> 1) * add) + Tile.TILE_SIZE;
|
||||
|
||||
long pixelRight = (long) x + offsetX;
|
||||
long pixelBottom = (long) y + offsetY;
|
||||
long pixelLeft = (long) x - offsetX;
|
||||
long pixelTop = (long) y - offsetY;
|
||||
|
||||
int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
|
||||
int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
|
||||
int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
|
||||
int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel);
|
||||
|
||||
mJobList.clear();
|
||||
|
||||
// set non processed tiles to isLoading == false
|
||||
mMapView.addJobs(null);
|
||||
|
||||
int tiles = 0;
|
||||
int max = mCurrentTiles.tiles.length - 1;
|
||||
|
||||
boolean fetchChildren = false;
|
||||
boolean fetchParent = false;
|
||||
boolean fetchProxy = false;
|
||||
if (mZoomLevels != null) {
|
||||
// check MapDatabase zoom-level-mapping
|
||||
if (mZoomLevels[zoomLevel] == 0) {
|
||||
mCurrentTiles.cnt = 0;
|
||||
mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mZoomLevels[zoomLevel] > zoomLevel) {
|
||||
fetchChildren = true;
|
||||
fetchProxy = true;
|
||||
|
||||
} else if (mZoomLevels[zoomLevel] < zoomLevel) {
|
||||
fetchParent = true;
|
||||
fetchProxy = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int yy = tileTop; yy <= tileBottom; yy++) {
|
||||
for (int xx = tileLeft; xx <= tileRight; xx++) {
|
||||
|
||||
if (tiles == max)
|
||||
break;
|
||||
|
||||
MapTile tile = QuadTree.getTile(xx, yy, zoomLevel);
|
||||
|
||||
if (tile == null) {
|
||||
tile = new MapTile(xx, yy, zoomLevel);
|
||||
|
||||
QuadTree.add(tile);
|
||||
mTiles.add(tile);
|
||||
}
|
||||
|
||||
if (!fetchProxy && !tile.isActive()) {
|
||||
mJobList.add(tile);
|
||||
}
|
||||
|
||||
mCurrentTiles.tiles[tiles++] = tile;
|
||||
|
||||
if (fetchChildren) {
|
||||
byte z = (byte) (zoomLevel + 1);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int cx = (xx << 1) + (i % 2);
|
||||
int cy = (yy << 1) + (i >> 1);
|
||||
|
||||
MapTile c = QuadTree.getTile(cx, cy, z);
|
||||
|
||||
if (c == null) {
|
||||
c = new MapTile(cx, cy, z);
|
||||
|
||||
QuadTree.add(c);
|
||||
mTiles.add(c);
|
||||
}
|
||||
|
||||
if (!c.isActive()) {
|
||||
mJobList.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||
// prefetch parent
|
||||
MapTile p = tile.rel.parent.tile;
|
||||
|
||||
if (p == null) {
|
||||
p = new MapTile(xx >> 1, yy >> 1, (byte) (zoomLevel - 1));
|
||||
|
||||
QuadTree.add(p);
|
||||
mTiles.add(p);
|
||||
mJobList.add(p);
|
||||
|
||||
} else if (!p.isActive()) {
|
||||
if (!mJobList.contains(p))
|
||||
mJobList.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pass new tile list to glThread
|
||||
mCurrentTiles.cnt = tiles;
|
||||
mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
mCurrentTiles.cnt = 0;
|
||||
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
||||
// Log.d(TAG, "visible: " + mCurrentTiles.cnt + "/" +
|
||||
// mCurrentTiles.tiles.length);
|
||||
GLRenderer.updateTiles(mCurrentTiles);
|
||||
|
||||
// note: this sets isLoading == true for all job tiles
|
||||
if (mJobList.size() > 0) {
|
||||
@ -335,6 +275,67 @@ public class MapRenderer extends GLSurfaceView {
|
||||
}
|
||||
}
|
||||
|
||||
/* package */
|
||||
static MapTile addTile(int x, int y, byte zoomLevel, int zdir) {
|
||||
MapTile tile;
|
||||
|
||||
tile = QuadTree.getTile(x, y, zoomLevel);
|
||||
|
||||
if (tile == null) {
|
||||
tile = new MapTile(x, y, zoomLevel);
|
||||
|
||||
QuadTree.add(tile);
|
||||
mTiles.add(tile);
|
||||
}
|
||||
|
||||
// if (!fetchProxy && !tile.isActive()) {
|
||||
if (!tile.isActive()) {
|
||||
mJobList.add(tile);
|
||||
}
|
||||
|
||||
// mCurrentTiles.tiles[tiles++] = tile;
|
||||
|
||||
// if (fetchChildren) {
|
||||
// byte z = (byte) (zoomLevel + 1);
|
||||
// for (int i = 0; i < 4; i++) {
|
||||
// int cx = (xx << 1) + (i % 2);
|
||||
// int cy = (yy << 1) + (i >> 1);
|
||||
//
|
||||
// MapTile c = QuadTree.getTile(cx, cy, z);
|
||||
//
|
||||
// if (c == null) {
|
||||
// c = new MapTile(cx, cy, z);
|
||||
//
|
||||
// QuadTree.add(c);
|
||||
// mTiles.add(c);
|
||||
// }
|
||||
//
|
||||
// if (!c.isActive()) {
|
||||
// mJobList.add(c);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (fetchParent || (!fetchProxy && zdir > 0 && zoomLevel > 0)) {
|
||||
if (zdir > 0 && zoomLevel > 0) {
|
||||
// prefetch parent
|
||||
MapTile p = tile.rel.parent.tile;
|
||||
|
||||
if (p == null) {
|
||||
p = new MapTile(x >> 1, y >> 1, (byte) (zoomLevel - 1));
|
||||
|
||||
QuadTree.add(p);
|
||||
mTiles.add(p);
|
||||
mJobList.add(p);
|
||||
|
||||
} else if (!p.isActive()) {
|
||||
if (!mJobList.contains(p))
|
||||
mJobList.add(p);
|
||||
}
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
private static void clearTile(MapTile t) {
|
||||
|
||||
t.newData = false;
|
||||
@ -407,8 +408,6 @@ public class MapRenderer extends GLSurfaceView {
|
||||
}
|
||||
|
||||
private static void limitCache(MapPosition mapPosition, int remove) {
|
||||
int removes = remove;
|
||||
|
||||
int size = mTiles.size();
|
||||
|
||||
// remove orphaned tiles
|
||||
@ -418,44 +417,46 @@ public class MapRenderer extends GLSurfaceView {
|
||||
if (t.isLocked() || t.isActive()) {
|
||||
i++;
|
||||
} else {
|
||||
// Log.d(TAG, "remove empty tile" + cur);
|
||||
// Log.d(TAG, "remove empty tile" + t);
|
||||
clearTile(t);
|
||||
mTiles.remove(i);
|
||||
removes--;
|
||||
remove--;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
// Log.d(TAG, "remove tiles: " + removes + " " + size);
|
||||
|
||||
if (removes <= 0)
|
||||
if (remove <= 0)
|
||||
return;
|
||||
|
||||
updateTileDistances(mTiles, mapPosition);
|
||||
Collections.sort(mTiles);
|
||||
|
||||
for (int i = 1; i <= removes; i++) {
|
||||
for (int i = 1; i < remove; i++) {
|
||||
|
||||
MapTile t = mTiles.remove(size - i);
|
||||
|
||||
synchronized (t) {
|
||||
if (t.isLocked()) {
|
||||
// dont remove tile used by renderthread
|
||||
Log.d(TAG, "X not removing " + t + " " + t.isLocked + " "
|
||||
+ t.distance);
|
||||
Log.d(TAG, "X not removing " + t
|
||||
// + " " + t.isLocked
|
||||
+ " " + t.distance);
|
||||
|
||||
mTiles.add(t);
|
||||
|
||||
// } else if (t.isLoading) {
|
||||
// // FIXME if we add tile back on next limit cache
|
||||
// // this will be removed. clearTile could interfere with
|
||||
// // MapGenerator... clear in passTile().
|
||||
// Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||
// t.isLoading = false;
|
||||
// // mTiles.add(t);
|
||||
} else {
|
||||
clearTile(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t.isLoading) {
|
||||
// NOTE: if we add tile back then on next limitCache
|
||||
// the tile will be removed. clearTile could interfere with
|
||||
// MapGenerator. so clear in passTile() instead.
|
||||
// mTiles.add(t);
|
||||
t.isLoading = false;
|
||||
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
clearTile(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -524,8 +525,8 @@ public class MapRenderer extends GLSurfaceView {
|
||||
MapTile tile = (MapTile) jobTile;
|
||||
|
||||
if (!tile.isLoading) {
|
||||
// no one should be able to use this tile now, mapgenerator passed
|
||||
// it, glthread does nothing until newdata is set.
|
||||
// no one should be able to use this tile now, TileGenerator passed
|
||||
// it, GL-Thread does nothing until newdata is set.
|
||||
Log.d(TAG, "passTile: canceled " + tile);
|
||||
synchronized (mTilesLoaded) {
|
||||
mTilesLoaded.add(tile);
|
||||
@ -573,4 +574,78 @@ public class MapRenderer extends GLSurfaceView {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
}
|
||||
|
||||
// private static void updateVisibleList(MapPosition mapPosition, int zdir)
|
||||
// {
|
||||
// double x = mapPosition.x;
|
||||
// double y = mapPosition.y;
|
||||
// byte zoomLevel = mapPosition.zoomLevel;
|
||||
// float scale = mapPosition.scale;
|
||||
//
|
||||
// double add = 1.0f / scale;
|
||||
// int offsetX = (int) ((mWidth >> 1) * add) + Tile.TILE_SIZE;
|
||||
// int offsetY = (int) ((mHeight >> 1) * add) + Tile.TILE_SIZE;
|
||||
//
|
||||
// long pixelRight = (long) x + offsetX;
|
||||
// long pixelBottom = (long) y + offsetY;
|
||||
// long pixelLeft = (long) x - offsetX;
|
||||
// long pixelTop = (long) y - offsetY;
|
||||
//
|
||||
// int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
|
||||
// int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
|
||||
// int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
|
||||
// int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom,
|
||||
// zoomLevel);
|
||||
//
|
||||
// mJobList.clear();
|
||||
//
|
||||
// // set non processed tiles to isLoading == false
|
||||
// mMapView.addJobs(null);
|
||||
//
|
||||
// int tiles = 0;
|
||||
// int max = mCurrentTiles.tiles.length - 1;
|
||||
//
|
||||
// // boolean fetchChildren = false;
|
||||
// // boolean fetchParent = false;
|
||||
// // boolean fetchProxy = false;
|
||||
// // if (mZoomLevels != null) {
|
||||
// // // check MapDatabase zoom-level-mapping
|
||||
// // if (mZoomLevels[zoomLevel] == 0) {
|
||||
// // mCurrentTiles.cnt = 0;
|
||||
// // mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
// // return;
|
||||
// // }
|
||||
// //
|
||||
// // if (mZoomLevels[zoomLevel] > zoomLevel) {
|
||||
// // fetchChildren = true;
|
||||
// // fetchProxy = true;
|
||||
// //
|
||||
// // } else if (mZoomLevels[zoomLevel] < zoomLevel) {
|
||||
// // fetchParent = true;
|
||||
// // fetchProxy = true;
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// for (int yy = tileTop; yy <= tileBottom; yy++) {
|
||||
// for (int xx = tileLeft; xx <= tileRight; xx++) {
|
||||
//
|
||||
// if (tiles == max)
|
||||
// break;
|
||||
//
|
||||
// // MapTile tile =
|
||||
// addTile(xx, yy, zoomLevel, zdir);
|
||||
// // mCurrentTiles.tiles[tiles++] = tile;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // pass new tile list to glThread
|
||||
// mCurrentTiles.cnt = tiles;
|
||||
// mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
//
|
||||
// // note: this sets isLoading == true for all job tiles
|
||||
// if (mJobList.size() > 0) {
|
||||
// updateTileDistances(mJobList, mapPosition);
|
||||
// Collections.sort(mJobList);
|
||||
// mMapView.addJobs(mJobList);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class MapTile extends JobTile {
|
||||
/**
|
||||
* tile is used by render thread. set by updateVisibleList (main thread).
|
||||
*/
|
||||
boolean isLocked;
|
||||
// boolean isLocked;
|
||||
|
||||
/**
|
||||
* tile has new data to upload to gl
|
||||
@ -63,29 +63,38 @@ class MapTile extends JobTile {
|
||||
*/
|
||||
QuadTree rel;
|
||||
|
||||
byte lastDraw = 0;
|
||||
int lastDraw = 0;
|
||||
|
||||
// keep track which tiles are locked as proxy for this tile
|
||||
final static int PROXY_PARENT = 16;
|
||||
final static int PROXY_GRAMPA = 32;
|
||||
final static int PROXY_HOLDER = 64;
|
||||
// 1-8: children
|
||||
byte proxies;
|
||||
|
||||
// counting the tiles that use this tile as proxy
|
||||
byte refs;
|
||||
|
||||
byte locked;
|
||||
|
||||
// this tile sits in fo another tile. e.g. x:-1,y:0,z:1 for x:1,y:0
|
||||
MapTile holder;
|
||||
|
||||
boolean isActive() {
|
||||
return isLoading || newData || isReady;
|
||||
}
|
||||
|
||||
boolean isLocked() {
|
||||
return isLocked || refs > 0;
|
||||
return locked > 0 || refs > 0;
|
||||
}
|
||||
|
||||
void lock() {
|
||||
isLocked = true;
|
||||
if (holder != null)
|
||||
return;
|
||||
|
||||
if (isReady || newData)
|
||||
locked++;
|
||||
|
||||
if (locked > 1 || isReady || newData)
|
||||
return;
|
||||
|
||||
MapTile p = rel.parent.tile;
|
||||
@ -113,9 +122,12 @@ class MapTile extends JobTile {
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
isLocked = false;
|
||||
if (holder != null)
|
||||
return;
|
||||
|
||||
if (proxies == 0)
|
||||
locked--;
|
||||
|
||||
if (locked > 0 || proxies == 0)
|
||||
return;
|
||||
|
||||
if ((proxies & (1 << 4)) != 0) {
|
||||
|
@ -41,15 +41,18 @@ import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.utils.GlUtils;
|
||||
import org.oscim.view.MapPosition;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
class PolygonRenderer {
|
||||
private static final String TAG = "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;
|
||||
private static final int STENCIL_BITS = 8;
|
||||
|
||||
private static final float FADE_START = 1.3f;
|
||||
|
||||
private static PolygonLayer[] mFillPolys;
|
||||
|
||||
@ -76,7 +79,7 @@ class PolygonRenderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void fillPolygons(double zoom, float scale) {
|
||||
private static void fillPolygons(int zoom, float scale) {
|
||||
boolean blend = false;
|
||||
|
||||
/* draw to framebuffer */
|
||||
@ -96,7 +99,7 @@ class PolygonRenderer {
|
||||
if (l.area.fade >= zoom || l.area.color[3] != 1.0) {
|
||||
/* fade in/out || draw alpha color */
|
||||
if (l.area.fade >= zoom) {
|
||||
f = (scale > 1.3f ? scale : 1.3f) - f;
|
||||
f = (scale > FADE_START ? scale : FADE_START) - f;
|
||||
if (f > 1.0f)
|
||||
f = 1.0f;
|
||||
}
|
||||
@ -159,8 +162,11 @@ class PolygonRenderer {
|
||||
// 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) {
|
||||
static PolygonLayer drawPolygons(MapPosition pos, PolygonLayer layer, int next,
|
||||
float[] matrix, boolean first) {
|
||||
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
|
||||
glUseProgram(polygonProgram);
|
||||
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
|
||||
|
@ -17,23 +17,10 @@
|
||||
|
||||
package org.oscim.view.renderer;
|
||||
|
||||
import org.oscim.view.renderer.MapRenderer.TilesData;
|
||||
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
public class ScanBox {
|
||||
|
||||
interface Callback {
|
||||
void call(MapTile tile);
|
||||
}
|
||||
|
||||
class SetVisible implements Callback {
|
||||
|
||||
@Override
|
||||
public void call(MapTile tile) {
|
||||
tile.isVisible = true;
|
||||
}
|
||||
}
|
||||
public abstract class ScanBox {
|
||||
|
||||
static class Edge {
|
||||
float x0, y0, x1, y1, dx, dy;
|
||||
@ -44,84 +31,50 @@ public class ScanBox {
|
||||
this.y0 = y0;
|
||||
this.x1 = x1;
|
||||
this.y1 = y1;
|
||||
this.dx = x1 - x0;
|
||||
this.dy = y1 - y0;
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
} else {
|
||||
this.x0 = x1;
|
||||
this.y0 = y1;
|
||||
this.x1 = x0;
|
||||
this.y1 = y0;
|
||||
this.dx = x0 - x1;
|
||||
this.dy = y0 - y1;
|
||||
dx = x0 - x1;
|
||||
dy = y0 - y1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Edge ab = new Edge();
|
||||
static Edge bc = new Edge();
|
||||
static Edge ca = new Edge();
|
||||
private Edge ab = new Edge();
|
||||
private Edge bc = new Edge();
|
||||
private Edge ca = new Edge();
|
||||
protected byte mZoom;
|
||||
|
||||
static void scanSpans(Edge e0, Edge e1) {
|
||||
void scan(float[] coords, byte zoom) {
|
||||
mZoom = zoom;
|
||||
|
||||
// sort edge by x-coordinate
|
||||
if (e0.x0 == e1.x0 && e0.y0 == e1.y0) {
|
||||
if (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) {
|
||||
Edge t = e0;
|
||||
e0 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
} else {
|
||||
if (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0) {
|
||||
Edge t = e0;
|
||||
e0 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
}
|
||||
ab.set(coords[0], coords[1], coords[2], coords[3]);
|
||||
bc.set(coords[2], coords[3], coords[4], coords[5]);
|
||||
ca.set(coords[4], coords[5], coords[0], coords[1]);
|
||||
scanTriangle();
|
||||
|
||||
float m0 = e0.dx / e0.dy;
|
||||
float m1 = e1.dx / e1.dy;
|
||||
|
||||
int d0 = e0.dx > 0 ? 1 : 0;// use y + 1 to compute x0
|
||||
int d1 = e1.dx < 0 ? 1 : 0; // use y + 1 to compute x1
|
||||
|
||||
float x0, x1;
|
||||
|
||||
int y = (int) Math.max(0, FloatMath.floor(e1.y0));
|
||||
int bottom = (int) Math.min(mMax, FloatMath.ceil(e1.y1));
|
||||
|
||||
for (; y < bottom; y++) {
|
||||
// float x0 = (m0 * Math.min(e0.dy, y + d0 - e0.y0) + e0.x0);
|
||||
// float x1 = (m1 * Math.min(e1.dy, y + d1 - e1.y0) + e1.x0);
|
||||
|
||||
x0 = y + d0 - e0.y0;
|
||||
if (e0.dy < x0)
|
||||
x0 = e0.dy;
|
||||
|
||||
x0 = e0.x0 + m0 * x0;
|
||||
|
||||
if (x0 < 0)
|
||||
x0 = 0;
|
||||
else
|
||||
x0 = FloatMath.ceil(x0);
|
||||
|
||||
x1 = y + d1 - e1.y0;
|
||||
if (e1.dy < x1)
|
||||
x1 = e1.dy;
|
||||
|
||||
x1 = e1.x0 + m1 * x1;
|
||||
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
else
|
||||
x1 = FloatMath.floor(x1);
|
||||
|
||||
setVisible(y, (int) x1, (int) x0);
|
||||
|
||||
// setVisible(y, (int) (x1 - 0.5f), (int) (x0 + 0.5f));
|
||||
}
|
||||
ab.set(coords[4], coords[5], coords[6], coords[7]);
|
||||
bc.set(coords[6], coords[7], coords[0], coords[1]);
|
||||
ca.set(coords[0], coords[1], coords[4], coords[5]);
|
||||
scanTriangle();
|
||||
}
|
||||
|
||||
static void scanTriangle() {
|
||||
/**
|
||||
* @param y
|
||||
* ...
|
||||
* @param x1
|
||||
* ...
|
||||
* @param x2
|
||||
* ...
|
||||
*/
|
||||
void setVisible(int y, int x1, int x2) {
|
||||
}
|
||||
|
||||
private void scanTriangle() {
|
||||
|
||||
if (ab.dy > bc.dy) {
|
||||
Edge t = ab;
|
||||
@ -138,6 +91,10 @@ public class ScanBox {
|
||||
bc = ca;
|
||||
ca = t;
|
||||
}
|
||||
// ca.dy > bc.dy > ab.dy
|
||||
|
||||
if (ca.dy == 0)
|
||||
return;
|
||||
|
||||
if (ab.dy != 0)
|
||||
scanSpans(ca, ab);
|
||||
@ -146,42 +103,68 @@ public class ScanBox {
|
||||
scanSpans(ca, bc);
|
||||
}
|
||||
|
||||
private static int mMax;
|
||||
private static final int MAX_SLOPE = 4;
|
||||
|
||||
public static void scan(float[] coords, TilesData tiles, int max) {
|
||||
sTiles = tiles;
|
||||
cntDoubles = 0;
|
||||
mMax = max;
|
||||
private void scanSpans(Edge e0, Edge e1) {
|
||||
|
||||
ab.set(coords[0], coords[1], coords[2], coords[3]);
|
||||
bc.set(coords[2], coords[3], coords[4], coords[5]);
|
||||
ca.set(coords[4], coords[5], coords[0], coords[1]);
|
||||
scanTriangle();
|
||||
int y0 = (int) Math.max(0, FloatMath.floor(e1.y0));
|
||||
int y1 = (int) Math.min((1 << mZoom), FloatMath.ceil(e1.y1));
|
||||
|
||||
ab.set(coords[4], coords[5], coords[6], coords[7]);
|
||||
bc.set(coords[6], coords[7], coords[0], coords[1]);
|
||||
ca.set(coords[0], coords[1], coords[4], coords[5]);
|
||||
scanTriangle();
|
||||
|
||||
// Log.d("..", "<doubles " + cntDoubles);
|
||||
}
|
||||
|
||||
private static TilesData sTiles;
|
||||
private static int cntDoubles;
|
||||
|
||||
private static void setVisible(int y, int x1, int x2) {
|
||||
|
||||
MapTile[] tiles = sTiles.tiles;
|
||||
for (int i = 0, n = sTiles.cnt; i < n; i++) {
|
||||
if (tiles[i].tileY == y) {
|
||||
if (tiles[i].tileX >= x1 && tiles[i].tileX < x2) {
|
||||
// if (tiles[i].isVisible) {
|
||||
// Log.d("..", ">>>" + y + " " + tiles[i].tileX);
|
||||
// cntDoubles++;
|
||||
// }
|
||||
tiles[i].isVisible = true;
|
||||
}
|
||||
// sort edge by x-coordinate
|
||||
if (e0.x0 == e1.x0 && e0.y0 == e1.y0) {
|
||||
// bottom-flat
|
||||
if (e0.x0 + e1.dy / e0.dy * e0.dx < e1.x1) {
|
||||
Edge t = e0;
|
||||
e0 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
} else {
|
||||
// top-flat
|
||||
if (e0.x1 - e1.dy / e0.dy * e0.dx < e1.x0) {
|
||||
Edge t = e0;
|
||||
e0 = e1;
|
||||
e1 = t;
|
||||
}
|
||||
}
|
||||
|
||||
float m0 = e0.dx / e0.dy;
|
||||
float m1 = e1.dx / e1.dy;
|
||||
|
||||
// still needed?
|
||||
if (m0 > MAX_SLOPE)
|
||||
m0 = MAX_SLOPE;
|
||||
else if (m0 < -MAX_SLOPE)
|
||||
m0 = -MAX_SLOPE;
|
||||
|
||||
if (m1 > MAX_SLOPE)
|
||||
m1 = MAX_SLOPE;
|
||||
else if (m1 < -MAX_SLOPE)
|
||||
m1 = -MAX_SLOPE;
|
||||
|
||||
int d0 = e0.dx > 0 ? 1 : 0; // use y + 1 to compute x0
|
||||
int d1 = e1.dx < 0 ? 1 : 0; // use y + 1 to compute x1
|
||||
|
||||
float x0, x1, dy;
|
||||
|
||||
for (int y = y0; y < y1; y++) {
|
||||
dy = y + d0 - e0.y0;
|
||||
if (e0.dy < dy)
|
||||
dy = e0.dy;
|
||||
|
||||
x0 = e0.x0 + m0 * dy;
|
||||
x0 = FloatMath.ceil(x0);
|
||||
|
||||
dy = y + d1 - e1.y0;
|
||||
if (e1.dy < dy)
|
||||
dy = e1.dy;
|
||||
|
||||
x1 = e1.x0 + m1 * dy;
|
||||
x1 = FloatMath.floor(x1);
|
||||
|
||||
if (x1 > x0)
|
||||
Log.d("...", "X set visible" + y + " " + x1 + "/" + x0);
|
||||
|
||||
setVisible(y, (int) x1, (int) x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ class Shaders {
|
||||
|
||||
final static String lineVertexShader = ""
|
||||
+ "precision mediump float;"
|
||||
// + "invariant gl_Position;"
|
||||
+ "uniform mat4 u_mvp;"
|
||||
+ "uniform float u_width;"
|
||||
+ "attribute vec2 a_position;"
|
||||
@ -111,20 +110,20 @@ class Shaders {
|
||||
+ "precision highp float; "
|
||||
+ "attribute vec4 vertex;"
|
||||
+ "attribute vec2 tex_coord;"
|
||||
+ "uniform mat4 mvp;"
|
||||
+ "uniform mat4 rotation;"
|
||||
+ "uniform float scale;"
|
||||
+ "uniform mat4 u_mv;"
|
||||
+ "uniform mat4 u_proj;"
|
||||
+ "uniform float u_scale;"
|
||||
+ "varying vec2 tex_c;"
|
||||
+ "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
||||
+ "const float coord_scale = 0.125;"
|
||||
+ "void main() {"
|
||||
+ " vec4 pos;"
|
||||
+ " if (mod(vertex.x, 2.0) == 0.0){"
|
||||
+ " pos = rotation * (mvp * vec4(vertex.xy + vertex.zw * (1.0 / scale), 0.0, 1.0));"
|
||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + vertex.zw * u_scale, 0.0, 1.0));"
|
||||
+ " } else {"
|
||||
// place as billboard
|
||||
+ " vec4 dir = mvp * vec4(vertex.xy, 0.0, 1.0);"
|
||||
+ " pos = rotation * (dir + vec4(vertex.zw * coord_scale, 0.0, 0.0));"
|
||||
+ " vec4 dir = u_mv * vec4(vertex.xy, 0.0, 1.0);"
|
||||
+ " pos = u_proj * (dir + vec4(vertex.zw * coord_scale, 0.0, 0.0));"
|
||||
+ " }"
|
||||
+ " gl_Position = pos;"
|
||||
+ " tex_c = tex_coord * div;"
|
||||
@ -175,7 +174,6 @@ class Shaders {
|
||||
final static String textFragmentShader = ""
|
||||
+ "precision highp float;"
|
||||
+ "uniform sampler2D tex;"
|
||||
+ "uniform vec4 col;"
|
||||
+ "varying vec2 tex_c;"
|
||||
+ "void main() {"
|
||||
+ " gl_FragColor = texture2D(tex, tex_c.xy);"
|
||||
|
@ -54,8 +54,8 @@ public class TextRenderer {
|
||||
private static int mVerticesVBO;
|
||||
|
||||
private static int mTextProgram;
|
||||
private static int hTextUVPMatrix;
|
||||
private static int hTextRotationMatrix;
|
||||
private static int hTextMVMatrix;
|
||||
private static int hTextProjectionMatrix;
|
||||
private static int hTextVertex;
|
||||
private static int hTextScale;
|
||||
private static int hTextTextureCoord;
|
||||
@ -83,11 +83,10 @@ public class TextRenderer {
|
||||
mTextProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
||||
Shaders.textFragmentShader);
|
||||
|
||||
hTextUVPMatrix = GLES20.glGetUniformLocation(mTextProgram, "mvp");
|
||||
hTextRotationMatrix = GLES20.glGetUniformLocation(mTextProgram, "rotation");
|
||||
|
||||
hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
||||
hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
||||
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
||||
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
||||
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "scale");
|
||||
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
||||
|
||||
}
|
||||
@ -150,12 +149,6 @@ public class TextRenderer {
|
||||
indices[i + 3] = (short) (j + 2);
|
||||
indices[i + 4] = (short) (j + 3);
|
||||
indices[i + 5] = (short) (j + 0);
|
||||
// indices[i + 0] = (short) (j + 0);
|
||||
// indices[i + 1] = (short) (j + 0);
|
||||
// indices[i + 2] = (short) (j + 1);
|
||||
// indices[i + 3] = (short) (j + 3);
|
||||
// indices[i + 4] = (short) (j + 2);
|
||||
// indices[i + 5] = (short) (j + 2);
|
||||
}
|
||||
|
||||
mShortBuffer.clear();
|
||||
@ -192,7 +185,7 @@ public class TextRenderer {
|
||||
if (tex.tile == null)
|
||||
break;
|
||||
|
||||
if (!tex.tile.isLocked)
|
||||
if (!tex.tile.isLocked())
|
||||
break;
|
||||
|
||||
tex = null;
|
||||
@ -293,11 +286,10 @@ public class TextRenderer {
|
||||
|
||||
if (t.caption != null) {
|
||||
x1 = x3 = (short) (SCALE * (-hw));
|
||||
y1 = y3 = (short) (SCALE * (-hh));
|
||||
y1 = y3 = (short) (SCALE * (hh));
|
||||
x2 = x4 = (short) (SCALE * (hw));
|
||||
y2 = y4 = (short) (SCALE * (hh));
|
||||
}
|
||||
else {
|
||||
y2 = y4 = (short) (SCALE * (-hh));
|
||||
} else {
|
||||
float vx = t.x1 - t.x2;
|
||||
float vy = t.y1 - t.y2;
|
||||
float a = FloatMath.sqrt(vx * vx + vy * vy);
|
||||
@ -322,14 +314,14 @@ public class TextRenderer {
|
||||
// x3 = (short) (dx | 2);
|
||||
// y2 = (short) (dy | 2);
|
||||
|
||||
x1 = (short) (SCALE * (vx * hw + ux * hh));
|
||||
y1 = (short) (SCALE * (vy * hw + uy * hh));
|
||||
x2 = (short) (SCALE * (-vx * hw + ux * hh));
|
||||
y3 = (short) (SCALE * (-vy * hw + uy * hh));
|
||||
x4 = (short) (SCALE * (-vx * hw - ux * hh));
|
||||
y4 = (short) (SCALE * (-vy * hw - uy * hh));
|
||||
x3 = (short) (SCALE * (vx * hw - ux * hh));
|
||||
y2 = (short) (SCALE * (vy * hw - uy * hh));
|
||||
x1 = (short) (SCALE * (vx * hw - ux * hh));
|
||||
y1 = (short) (SCALE * (vy * hw - uy * hh));
|
||||
x2 = (short) (SCALE * (-vx * hw - ux * hh));
|
||||
y3 = (short) (SCALE * (-vy * hw - uy * hh));
|
||||
x4 = (short) (SCALE * (-vx * hw + ux * hh));
|
||||
y4 = (short) (SCALE * (-vy * hw + uy * hh));
|
||||
x3 = (short) (SCALE * (vx * hw + ux * hh));
|
||||
y2 = (short) (SCALE * (vy * hw + uy * hh));
|
||||
|
||||
}
|
||||
short u1 = (short) (SCALE * x);
|
||||
@ -394,7 +386,8 @@ public class TextRenderer {
|
||||
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, mBitmap,
|
||||
mBitmapFormat, mBitmapType);
|
||||
|
||||
// FIXME shouldnt be needed here, still looking for sometimes corrupted labels..
|
||||
// FIXME shouldnt be needed here, still looking for sometimes corrupted
|
||||
// labels..
|
||||
GLES20.glFlush();
|
||||
|
||||
return true;
|
||||
@ -412,7 +405,7 @@ public class TextRenderer {
|
||||
|
||||
for (int i = 0; i < mTextures.length; i++) {
|
||||
tex = mTextures[i];
|
||||
if (tex.tile == null || !tex.tile.isLocked)
|
||||
if (tex.tile == null) // || !tex.tile.isLocked)
|
||||
continue;
|
||||
|
||||
mShortBuffer.put(tex.vertices, 0, tex.length);
|
||||
@ -426,14 +419,14 @@ public class TextRenderer {
|
||||
mShortBuffer);
|
||||
}
|
||||
|
||||
static void beginDraw(float scale, float[] rotation) {
|
||||
static void beginDraw(float scale, float[] projection) {
|
||||
GLES20.glUseProgram(mTextProgram);
|
||||
|
||||
GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
||||
GLES20.glEnableVertexAttribArray(hTextVertex);
|
||||
|
||||
GLES20.glUniform1f(hTextScale, scale);
|
||||
GLES20.glUniformMatrix4fv(hTextRotationMatrix, 1, false, rotation, 0);
|
||||
GLES20.glUniformMatrix4fv(hTextProjectionMatrix, 1, false, projection, 0);
|
||||
|
||||
if (debug) {
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
@ -461,7 +454,7 @@ public class TextRenderer {
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tile.texture.id);
|
||||
|
||||
GLES20.glUniformMatrix4fv(hTextUVPMatrix, 1, false, matrix, 0);
|
||||
GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
||||
|
||||
if (debug) {
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
@ -136,8 +136,8 @@ final class WayDecorator {
|
||||
} else if ((currentY - nextY) == 0)
|
||||
break;
|
||||
|
||||
float diff = ((diffX) / (diffY) - (float) (currentX - nextX)
|
||||
/ (currentY - nextY));
|
||||
float diff = diffX / diffY -
|
||||
(float) (currentX - nextX) / (currentY - nextY);
|
||||
|
||||
// skip segments with corners
|
||||
if (diff >= 0.1f || diff <= -0.1f)
|
||||
@ -221,8 +221,8 @@ final class WayDecorator {
|
||||
|
||||
// check overlapping labels of road with more than one
|
||||
// way
|
||||
short top2 = (t2.y1 < t2.y2 ? t2.y1 : t2.y2);
|
||||
short bot2 = (t2.y1 < t2.y2 ? t2.y2 : t2.y1);
|
||||
short top2 = t2.y1 < t2.y2 ? t2.y1 : t2.y2;
|
||||
short bot2 = t2.y1 < t2.y2 ? t2.y2 : t2.y1;
|
||||
|
||||
if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
||||
&& top2 - 10 < bot) {
|
||||
@ -240,7 +240,8 @@ final class WayDecorator {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Log.d("mapsforge", "add " + text + " " + first + " " + last);
|
||||
// Log.d("mapsforge", "add " + text + " " + first + " " +
|
||||
// last);
|
||||
|
||||
if (previousX < currentX) {
|
||||
x1 = previousX;
|
||||
|
Loading…
x
Reference in New Issue
Block a user