- started overlays
- started symbol layer - move renderer and generator out of view package - hopefully the last big refactoring for a while... - improve perspective, plane should be more far away to decrease foreshortening
@ -21,7 +21,7 @@
|
|||||||
>
|
>
|
||||||
<!-- android:theme="@style/Theme.TileMap" -->
|
<!-- android:theme="@style/Theme.TileMap" -->
|
||||||
<activity
|
<activity
|
||||||
android:name="org.oscim.app.TileMap"
|
android:name="TileMap"
|
||||||
android:configChanges="orientation|screenSize" >
|
android:configChanges="orientation|screenSize" >
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
@ -15,4 +15,4 @@
|
|||||||
# 'key.alias' for the name of the key to use.
|
# 'key.alias' for the name of the key to use.
|
||||||
# The password will be asked during the build when you use the 'release' target.
|
# The password will be asked during the build when you use the 'release' target.
|
||||||
|
|
||||||
jar.libs.dir=lib
|
#jar.libs.dir=
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
package org.oscim.app;
|
package org.oscim.app;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
import org.oscim.view.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.location.Criteria;
|
import android.location.Criteria;
|
||||||
|
@ -4,21 +4,18 @@ import java.io.FileFilter;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
||||||
import org.oscim.app.filefilter.FilterByFileExtension;
|
import org.oscim.app.filefilter.FilterByFileExtension;
|
||||||
import org.oscim.app.filefilter.ValidMapFile;
|
|
||||||
import org.oscim.app.filefilter.ValidRenderTheme;
|
import org.oscim.app.filefilter.ValidRenderTheme;
|
||||||
import org.oscim.app.filepicker.FilePicker;
|
import org.oscim.app.filepicker.FilePicker;
|
||||||
import org.oscim.app.preferences.EditPreferences;
|
import org.oscim.app.preferences.EditPreferences;
|
||||||
import org.oscim.core.GeoPoint;
|
import org.oscim.core.GeoPoint;
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.database.MapDatabases;
|
import org.oscim.database.MapDatabases;
|
||||||
import org.oscim.theme.InternalRenderTheme;
|
import org.oscim.theme.InternalRenderTheme;
|
||||||
import org.oscim.utils.AndroidUtils;
|
import org.oscim.utils.AndroidUtils;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapActivity;
|
import org.oscim.view.MapActivity;
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -59,11 +56,11 @@ public class TileMap extends MapActivity {
|
|||||||
private static final int DIALOG_ENTER_COORDINATES = 0;
|
private static final int DIALOG_ENTER_COORDINATES = 0;
|
||||||
private static final int DIALOG_INFO_MAP_FILE = 1;
|
private static final int DIALOG_INFO_MAP_FILE = 1;
|
||||||
private static final int DIALOG_LOCATION_PROVIDER_DISABLED = 2;
|
private static final int DIALOG_LOCATION_PROVIDER_DISABLED = 2;
|
||||||
private static final FileFilter FILE_FILTER_EXTENSION_MAP =
|
// private static final FileFilter FILE_FILTER_EXTENSION_MAP =
|
||||||
new FilterByFileExtension(".map");
|
// new FilterByFileExtension(".map");
|
||||||
private static final FileFilter FILE_FILTER_EXTENSION_XML =
|
private static final FileFilter FILE_FILTER_EXTENSION_XML =
|
||||||
new FilterByFileExtension(".xml");
|
new FilterByFileExtension(".xml");
|
||||||
private static final int SELECT_MAP_FILE = 0;
|
// private static final int SELECT_MAP_FILE = 0;
|
||||||
private static final int SELECT_RENDER_THEME_FILE = 1;
|
private static final int SELECT_RENDER_THEME_FILE = 1;
|
||||||
|
|
||||||
LocationHandler mLocation;
|
LocationHandler mLocation;
|
||||||
@ -232,11 +229,12 @@ public class TileMap extends MapActivity {
|
|||||||
return mMapView.onTrackballEvent(event);
|
return mMapView.onTrackballEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startMapFilePicker() {
|
// private void startMapFilePicker() {
|
||||||
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
// FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
||||||
FilePicker.setFileSelectFilter(new ValidMapFile());
|
// FilePicker.setFileSelectFilter(new ValidMapFile());
|
||||||
startActivityForResult(new Intent(this, FilePicker.class), SELECT_MAP_FILE);
|
// startActivityForResult(new Intent(this, FilePicker.class),
|
||||||
}
|
// SELECT_MAP_FILE);
|
||||||
|
// }
|
||||||
|
|
||||||
private void startRenderThemePicker() {
|
private void startRenderThemePicker() {
|
||||||
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_XML);
|
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_XML);
|
||||||
@ -598,12 +596,12 @@ public class TileMap extends MapActivity {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
static class VersionHelper {
|
// static class VersionHelper {
|
||||||
@TargetApi(11)
|
// @TargetApi(11)
|
||||||
static void refreshActionBarMenu(Activity activity) {
|
// static void refreshActionBarMenu(Activity activity) {
|
||||||
activity.invalidateOptionsMenu();
|
// activity.invalidateOptionsMenu();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSaveInstanceState(Bundle outState) {
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
|
@ -12,10 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view;
|
package org.oscim.core;
|
||||||
|
|
||||||
import org.oscim.core.GeoPoint;
|
|
||||||
import org.oscim.core.MercatorProjection;
|
|
||||||
|
|
||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
|
|
||||||
@ -30,11 +27,13 @@ public class MapPosition {
|
|||||||
public byte zoomLevel;
|
public byte zoomLevel;
|
||||||
public float scale;
|
public float scale;
|
||||||
public float angle;
|
public float angle;
|
||||||
|
public float tilt;
|
||||||
|
|
||||||
public double x;
|
public double x;
|
||||||
public double y;
|
public double y;
|
||||||
|
|
||||||
public float[] rotation;
|
public float[] viewMatrix;
|
||||||
|
public float[] rotateMatrix;
|
||||||
|
|
||||||
public MapPosition() {
|
public MapPosition() {
|
||||||
this.zoomLevel = (byte) 1;
|
this.zoomLevel = (byte) 1;
|
||||||
@ -46,9 +45,13 @@ public class MapPosition {
|
|||||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME remove this here
|
||||||
public void init() {
|
public void init() {
|
||||||
rotation = new float[16];
|
viewMatrix = new float[16];
|
||||||
Matrix.setIdentityM(rotation, 0);
|
Matrix.setIdentityM(viewMatrix, 0);
|
||||||
|
|
||||||
|
rotateMatrix = new float[16];
|
||||||
|
Matrix.setIdentityM(rotateMatrix, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,7 +63,6 @@ public class MapPosition {
|
|||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
|
public MapPosition(GeoPoint geoPoint, byte zoomLevel, float scale) {
|
||||||
// this.geoPoint = geoPoint;
|
|
||||||
this.zoomLevel = zoomLevel;
|
this.zoomLevel = zoomLevel;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.lat = geoPoint.getLatitude();
|
this.lat = geoPoint.getLatitude();
|
||||||
@ -84,10 +86,10 @@ public class MapPosition {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("MapPosition [geoPoint=");
|
builder.append("MapPosition [");
|
||||||
builder.append("lat");
|
builder.append("lat=");
|
||||||
builder.append(this.lat);
|
builder.append(this.lat);
|
||||||
builder.append("lon");
|
builder.append(", lon=");
|
||||||
builder.append(this.lon);
|
builder.append(this.lon);
|
||||||
builder.append(", zoomLevel=");
|
builder.append(", zoomLevel=");
|
||||||
builder.append(this.zoomLevel);
|
builder.append(this.zoomLevel);
|
@ -14,7 +14,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.core;
|
package org.oscim.core;
|
||||||
|
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the spherical Mercator projection.
|
* An implementation of the spherical Mercator projection.
|
||||||
|
@ -24,7 +24,8 @@ public class WebMercator {
|
|||||||
*/
|
*/
|
||||||
public static final String NAME = "SphericalMercator";
|
public static final String NAME = "SphericalMercator";
|
||||||
|
|
||||||
private static final double f900913 = 20037508.342789244;
|
// earth radius * pi, roughly
|
||||||
|
public static final double f900913 = 20037508.342789244;
|
||||||
private static final double f900913_2 = 20037508.342789244 * 2;
|
private static final double f900913_2 = 20037508.342789244 * 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,7 @@ package org.oscim.database;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -30,7 +30,7 @@ import org.oscim.database.QueryResult;
|
|||||||
import org.oscim.database.mapfile.header.MapFileHeader;
|
import org.oscim.database.mapfile.header.MapFileHeader;
|
||||||
import org.oscim.database.mapfile.header.MapFileInfo;
|
import org.oscim.database.mapfile.header.MapFileInfo;
|
||||||
import org.oscim.database.mapfile.header.SubFileParameter;
|
import org.oscim.database.mapfile.header.SubFileParameter;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
|
||||||
@ -819,7 +819,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
|
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
|
||||||
int[] textPos = new int[3];
|
int[] textPos = new int[3];
|
||||||
// float[] labelPosition;
|
// float[] labelPosition;
|
||||||
boolean skippedWays = false;
|
// boolean skippedWays = false;
|
||||||
int wayDataBlocks;
|
int wayDataBlocks;
|
||||||
|
|
||||||
// skip string block
|
// skip string block
|
||||||
@ -858,7 +858,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
if (tags == null)
|
if (tags == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
skippedWays = true;
|
// skippedWays = true;
|
||||||
|
|
||||||
mReadBuffer.setBufferPosition(pos);
|
mReadBuffer.setBufferPosition(pos);
|
||||||
}
|
}
|
||||||
@ -885,12 +885,12 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
// bit 5-8 represent the number of tag IDs
|
// bit 5-8 represent the number of tag IDs
|
||||||
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
|
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
|
||||||
|
|
||||||
boolean changed = skippedWays;
|
// boolean changed = skippedWays;
|
||||||
skippedWays = false;
|
// skippedWays = false;
|
||||||
|
|
||||||
if (numberOfTags != 0) {
|
if (numberOfTags != 0) {
|
||||||
tags = mReadBuffer.readTags(wayTags, numberOfTags);
|
tags = mReadBuffer.readTags(wayTags, numberOfTags);
|
||||||
changed = true;
|
// changed = true;
|
||||||
}
|
}
|
||||||
if (tags == null)
|
if (tags == null)
|
||||||
return false;
|
return false;
|
||||||
@ -904,8 +904,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
// check if the way has a name
|
// check if the way has a name
|
||||||
if ((featureByte & WAY_FEATURE_NAME) != 0) {
|
if ((featureByte & WAY_FEATURE_NAME) != 0) {
|
||||||
textPos[0] = mReadBuffer.readUnsignedInt();
|
textPos[0] = mReadBuffer.readUnsignedInt();
|
||||||
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset
|
// String str =
|
||||||
+ textPos[0]);
|
mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos[0]);
|
||||||
// if (changed) {
|
// if (changed) {
|
||||||
// Tag[] tmp = tags;
|
// Tag[] tmp = tags;
|
||||||
// tags = new Tag[tmp.length + 1];
|
// tags = new Tag[tmp.length + 1];
|
||||||
|
@ -39,7 +39,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
@ -65,8 +65,8 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
private static final String CACHE_FILE = "%d-%d-%d.tile";
|
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 SERVER_ADDR = "city.informatik.uni-bremen.de";
|
||||||
// private static final String URL = "/osci/map-live/";
|
private static final String URL = "/osci/map-live/";
|
||||||
private static final String URL = "/osci/oscim/";
|
// private static final String URL = "/osci/oscim/";
|
||||||
|
|
||||||
private final static float REF_TILE_SIZE = 4096.0f;
|
private final static float REF_TILE_SIZE = 4096.0f;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
@ -33,7 +33,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
import org.postgresql.PGConnection;
|
import org.postgresql.PGConnection;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -24,7 +24,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
|||||||
import org.oscim.database.MapInfo;
|
import org.oscim.database.MapInfo;
|
||||||
import org.oscim.database.OpenResult;
|
import org.oscim.database.OpenResult;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -40,7 +40,7 @@ public class MapDatabase implements IMapDatabase {
|
|||||||
private Tag[] mTags = { new Tag("natural", "water") };
|
private Tag[] mTags = { new Tag("natural", "water") };
|
||||||
private Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") };
|
private Tag[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") };
|
||||||
|
|
||||||
private Tag[] mNameTags;
|
// private Tag[] mNameTags;
|
||||||
|
|
||||||
private final MapInfo mMapInfo =
|
private final MapInfo mMapInfo =
|
||||||
new MapInfo(new BoundingBox(-180, -90, 180, 90),
|
new MapInfo(new BoundingBox(-180, -90, 180, 90),
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.generator;
|
package org.oscim.generator;
|
||||||
|
|
||||||
//import static org.oscim.view.mapgenerator.JobTile.LOADING;
|
//import static org.oscim.view.mapgenerator.JobTile.LOADING;
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.generator;
|
package org.oscim.generator;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
|
@ -12,11 +12,11 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.generator;
|
package org.oscim.generator;
|
||||||
|
|
||||||
|
import org.oscim.renderer.MapRenderer;
|
||||||
|
import org.oscim.renderer.TileGenerator;
|
||||||
import org.oscim.utils.PausableThread;
|
import org.oscim.utils.PausableThread;
|
||||||
import org.oscim.view.renderer.MapRenderer;
|
|
||||||
import org.oscim.view.renderer.TileGenerator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a
|
* A MapWorker uses a {@link TileGenerator} to generate map tiles. It runs in a
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.generator;
|
package org.oscim.generator;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
118
src/org/oscim/renderer/BufferObject.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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 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 License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.oscim.renderer;
|
||||||
|
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
|
||||||
|
class BufferObject {
|
||||||
|
private static BufferObject pool;
|
||||||
|
|
||||||
|
static synchronized BufferObject get() {
|
||||||
|
BufferObject bo;
|
||||||
|
|
||||||
|
if (pool == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bo = pool;
|
||||||
|
pool = pool.next;
|
||||||
|
bo.next = null;
|
||||||
|
return bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static synchronized BufferObject get(int size) {
|
||||||
|
// BufferObject bo, prev = null;
|
||||||
|
//
|
||||||
|
// if (pool == null) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int max = size * 4;
|
||||||
|
//
|
||||||
|
// for (bo = pool; bo != null; bo = bo.next) {
|
||||||
|
// if (bo.size > size && size < max)
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// prev = bo;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (prev != null && bo != null) {
|
||||||
|
// prev.next = bo.next;
|
||||||
|
// bo.next = null;
|
||||||
|
// return bo;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// bo = pool;
|
||||||
|
// pool = pool.next;
|
||||||
|
// bo.next = null;
|
||||||
|
// return bo;
|
||||||
|
// }
|
||||||
|
|
||||||
|
static synchronized void release(BufferObject bo) {
|
||||||
|
bo.next = pool;
|
||||||
|
pool = bo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: only call from GL-Thread
|
||||||
|
static synchronized int limitUsage(int reduce) {
|
||||||
|
int vboIds[] = new int[10];
|
||||||
|
BufferObject[] tmp = new BufferObject[10];
|
||||||
|
int removed = 0;
|
||||||
|
int freed = 0;
|
||||||
|
|
||||||
|
for (BufferObject bo = pool; bo != null; bo = bo.next) {
|
||||||
|
if (bo.size > 0) {
|
||||||
|
freed += bo.size;
|
||||||
|
bo.size = 0;
|
||||||
|
vboIds[removed] = bo.id;
|
||||||
|
tmp[removed++] = bo;
|
||||||
|
|
||||||
|
if (removed == 10 || reduce < freed)
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
return freed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init(int num) {
|
||||||
|
int[] mVboIds = new int[num];
|
||||||
|
GLES20.glGenBuffers(num, mVboIds, 0);
|
||||||
|
|
||||||
|
BufferObject bo;
|
||||||
|
|
||||||
|
for (int i = 1; i < num; i++) {
|
||||||
|
bo = new BufferObject(mVboIds[i]);
|
||||||
|
bo.next = pool;
|
||||||
|
pool = bo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int id;
|
||||||
|
int size;
|
||||||
|
BufferObject next;
|
||||||
|
|
||||||
|
BufferObject(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
|
import static android.opengl.GLES20.GL_ARRAY_BUFFER;
|
||||||
import static android.opengl.GLES20.GL_BLEND;
|
import static android.opengl.GLES20.GL_BLEND;
|
||||||
@ -31,13 +31,14 @@ import java.util.concurrent.locks.ReentrantLock;
|
|||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.MapRenderer.TilesData;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.utils.GlUtils;
|
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.MapViewPosition;
|
import org.oscim.view.MapViewPosition;
|
||||||
import org.oscim.view.renderer.MapRenderer.TilesData;
|
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
@ -55,7 +56,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private static final int CACHE_TILES_MAX = 250;
|
private static final int CACHE_TILES_MAX = 250;
|
||||||
private static final int LIMIT_BUFFERS = 16 * MB;
|
private static final int LIMIT_BUFFERS = 16 * MB;
|
||||||
|
|
||||||
static final float COORD_MULTIPLIER = 8.0f;
|
public static final float COORD_MULTIPLIER = 8.0f;
|
||||||
|
|
||||||
static int CACHE_TILES = CACHE_TILES_MAX;
|
static int CACHE_TILES = CACHE_TILES_MAX;
|
||||||
|
|
||||||
@ -64,9 +65,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
private static MapPosition mMapPosition;
|
private static MapPosition mMapPosition;
|
||||||
|
|
||||||
private static ArrayList<VertexBufferObject> mVBOs;
|
// private static ArrayList<BufferObject> mVBOs;
|
||||||
|
|
||||||
private static int mWidth, mHeight;
|
static int mWidth, mHeight;
|
||||||
|
|
||||||
private static int rotateBuffers = 2;
|
private static int rotateBuffers = 2;
|
||||||
private static ShortBuffer shortBuffer[];
|
private static ShortBuffer shortBuffer[];
|
||||||
@ -77,7 +78,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
private static float[] mMVPMatrix = new float[16];
|
private static float[] mMVPMatrix = new float[16];
|
||||||
private static float[] mProjMatrix = new float[16];
|
private static float[] mProjMatrix = new float[16];
|
||||||
|
private static float[] mTmpMatrix = new float[16];
|
||||||
private static float[] mTileCoords = new float[8];
|
private static float[] mTileCoords = new float[8];
|
||||||
|
private static float[] mDebugCoords = new float[8];
|
||||||
|
|
||||||
// mNextTiles is set by TileLoader and swapped with
|
// mNextTiles is set by TileLoader and swapped with
|
||||||
// mDrawTiles in onDrawFrame in GL thread.
|
// mDrawTiles in onDrawFrame in GL thread.
|
||||||
@ -99,8 +102,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
static ReentrantLock tilelock = new ReentrantLock();
|
static ReentrantLock tilelock = new ReentrantLock();
|
||||||
static ReentrantLock drawlock = new ReentrantLock();
|
static ReentrantLock drawlock = new ReentrantLock();
|
||||||
|
|
||||||
|
// Add additional tiles that serve as placeholer when flipping
|
||||||
|
// over date-line.
|
||||||
|
// I dont really like this but cannot think of a better solution:
|
||||||
|
// the other option would be to run scanbox each time for upload,
|
||||||
|
// drawing, proxies and text layer. needing to add placeholder only
|
||||||
|
// happens rarely, unless you live on Fidschi
|
||||||
/* package */static int mHolderCount;
|
/* package */static int mHolderCount;
|
||||||
|
|
||||||
|
static boolean[] vertexArray = { false, false };
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
final class GLState {
|
||||||
|
boolean blend = false;
|
||||||
|
boolean depth = false;
|
||||||
|
}
|
||||||
|
|
||||||
// scanline fill class used to check tile visibility
|
// scanline fill class used to check tile visibility
|
||||||
private static ScanBox mScanBox = new ScanBox() {
|
private static ScanBox mScanBox = new ScanBox() {
|
||||||
@Override
|
@Override
|
||||||
@ -120,33 +137,35 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// add placeholder tiles to show both sides
|
// add placeholder tiles to show both sides
|
||||||
// of date line...
|
// of date line. a little too complicated...
|
||||||
for (int x = x1; x < x2; x++) {
|
for (int x = x1; x < x2; x++) {
|
||||||
MapTile holder = null;
|
MapTile holder = null;
|
||||||
MapTile tile = null;
|
MapTile tile = null;
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
|
||||||
int xx = x;
|
|
||||||
|
|
||||||
if (x >= 0 && x < xmax)
|
if (x >= 0 && x < xmax)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
int xx = x;
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
xx = xmax + x;
|
xx = xmax + x;
|
||||||
else
|
else
|
||||||
xx = x - xmax;
|
xx = x - xmax;
|
||||||
|
|
||||||
if (xx < 0 || xx >= xmax)
|
if (xx < 0 || xx >= xmax) {
|
||||||
|
// Log.d(TAG, "out of bounds " + y + " " + x + "/" + xx);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
for (int i = cnt; i < cnt + mHolderCount; i++)
|
for (int i = cnt; i < cnt + mHolderCount; i++)
|
||||||
if (tiles[i].tileX == x && tiles[i].tileY == y) {
|
if (tiles[i].tileX == x && tiles[i].tileY == y) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found) {
|
||||||
|
// Log.d(TAG, "already added " + y + " " + x + "/" + xx);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < cnt; i++)
|
for (int i = 0; i < cnt; i++)
|
||||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||||
@ -154,11 +173,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile == null)
|
if (tile == null) {
|
||||||
|
// Log.d(TAG, "not found " + y + " " + x + "/" + xx);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
// Log.d(TAG, "add placeholder " + y + " " + x + ">>" + xx + " "
|
|
||||||
// + tile);
|
|
||||||
|
|
||||||
holder = new MapTile(x, y, mZoom);
|
holder = new MapTile(x, y, mZoom);
|
||||||
holder.isVisible = true;
|
holder.isVisible = true;
|
||||||
@ -173,7 +191,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
* the MapView
|
* the MapView
|
||||||
*/
|
*/
|
||||||
public GLRenderer(MapView mapView) {
|
public GLRenderer(MapView mapView) {
|
||||||
Log.d(TAG, "init MapRenderer");
|
|
||||||
|
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
mMapViewPosition = mapView.getMapViewPosition();
|
mMapViewPosition = mapView.getMapViewPosition();
|
||||||
@ -208,14 +225,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mUpdateTiles = false;
|
mUpdateTiles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ArrayList<Overlay> mOverlays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by TileLoader when list of active tiles changed. the list is
|
* Called by TileLoader when list of active tiles changed. the list is
|
||||||
* copied to mNextTiles to be used in next call to onDrawFrame
|
* copied to mNextTiles to be used in next call to onDrawFrame
|
||||||
*
|
*
|
||||||
* @param tiles
|
* @param tiles
|
||||||
* active tiles
|
* active tiles
|
||||||
|
* @param overlays
|
||||||
|
* ...
|
||||||
*/
|
*/
|
||||||
static void updateTiles(TilesData tiles) {
|
static void updateTiles(TilesData tiles, ArrayList<Overlay> overlays) {
|
||||||
|
|
||||||
MapTile[] newTiles = tiles.tiles;
|
MapTile[] newTiles = tiles.tiles;
|
||||||
|
|
||||||
@ -223,6 +244,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
for (int i = 0, n = tiles.cnt; i < n; i++)
|
for (int i = 0, n = tiles.cnt; i < n; i++)
|
||||||
newTiles[i].lock();
|
newTiles[i].lock();
|
||||||
|
|
||||||
|
mOverlays = overlays;
|
||||||
|
|
||||||
// dont flip next/drawTiles while copying
|
// dont flip next/drawTiles while copying
|
||||||
GLRenderer.tilelock.lock();
|
GLRenderer.tilelock.lock();
|
||||||
|
|
||||||
@ -243,28 +266,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
GLRenderer.tilelock.unlock();
|
GLRenderer.tilelock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* called by TileLoader. when tile is removed from cache reuse its vbo.
|
|
||||||
*
|
|
||||||
* @param vbo
|
|
||||||
* the VBO
|
|
||||||
*/
|
|
||||||
static void addVBO(VertexBufferObject vbo) {
|
|
||||||
synchronized (mVBOs) {
|
|
||||||
mVBOs.add(vbo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVBO(MapTile tile) {
|
|
||||||
synchronized (mVBOs) {
|
|
||||||
int numVBOs = mVBOs.size();
|
|
||||||
|
|
||||||
if (numVBOs > 0 && tile.vbo == null) {
|
|
||||||
tile.vbo = mVBOs.remove(numVBOs - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRenderTheme(RenderTheme t) {
|
void setRenderTheme(RenderTheme t) {
|
||||||
int bg = t.getMapBackground();
|
int bg = t.getMapBackground();
|
||||||
float[] c = new float[4];
|
float[] c = new float[4];
|
||||||
@ -276,161 +277,121 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mUpdateColor = true;
|
mUpdateColor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int uploadCnt = 0;
|
private static int uploadCnt = 0;
|
||||||
|
|
||||||
private boolean uploadTileData(MapTile tile) {
|
private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) {
|
||||||
// Upload line data to vertex buffer object
|
|
||||||
// Log.d(TAG, "uploadTileData, " + tile);
|
|
||||||
|
|
||||||
int lineSize = LineRenderer.sizeOf(tile.lineLayers);
|
int newSize = layers.getSize();
|
||||||
int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
|
if (newSize == 0)
|
||||||
int newSize = lineSize + polySize;
|
|
||||||
|
|
||||||
if (newSize == 0) {
|
|
||||||
LineRenderer.clear(tile.lineLayers);
|
|
||||||
PolygonRenderer.clear(tile.polygonLayers);
|
|
||||||
tile.lineLayers = null;
|
|
||||||
tile.polygonLayers = null;
|
|
||||||
tile.newData = false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
||||||
|
|
||||||
// use multiple buffers to avoid overwriting buffer while current
|
// use multiple buffers to avoid overwriting buffer while current
|
||||||
// data is uploaded (or rather the blocking which is probably done to
|
// data is uploaded (or rather the blocking which is probably done to
|
||||||
// avoid overwriting)
|
// avoid overwriting)
|
||||||
if (uploadCnt >= rotateBuffers) {
|
if (uploadCnt >= rotateBuffers) {
|
||||||
uploadCnt = 0;
|
uploadCnt = 0;
|
||||||
// GLES20.glFlush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortBuffer sbuf = shortBuffer[uploadCnt];
|
ShortBuffer sbuf = shortBuffer[uploadCnt];
|
||||||
|
|
||||||
// add fill coordinates
|
// add fill coordinates
|
||||||
|
if (addFill)
|
||||||
newSize += 8;
|
newSize += 8;
|
||||||
|
|
||||||
// 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) {
|
if (sbuf.capacity() < newSize) {
|
||||||
ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
|
sbuf = ByteBuffer
|
||||||
.order(ByteOrder.nativeOrder());
|
.allocateDirect(newSize * SHORT_BYTES)
|
||||||
sbuf = bbuf.asShortBuffer();
|
.order(ByteOrder.nativeOrder())
|
||||||
|
.asShortBuffer();
|
||||||
|
|
||||||
shortBuffer[uploadCnt] = sbuf;
|
shortBuffer[uploadCnt] = sbuf;
|
||||||
|
if (addFill)
|
||||||
sbuf.put(mFillCoords, 0, 8);
|
sbuf.put(mFillCoords, 0, 8);
|
||||||
|
} else {
|
||||||
|
sbuf.clear();
|
||||||
|
if (addFill)
|
||||||
|
sbuf.put(mFillCoords, 0, 8);
|
||||||
|
// if (addFill)
|
||||||
|
// sbuf.position(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
sbuf.clear();
|
layers.compile(sbuf, addFill);
|
||||||
sbuf.position(8);
|
|
||||||
|
|
||||||
PolygonRenderer.compileLayerData(tile.polygonLayers, sbuf);
|
|
||||||
|
|
||||||
tile.lineOffset = (8 + polySize);
|
|
||||||
if (tile.lineOffset != sbuf.position())
|
|
||||||
Log.d(TAG, "tiles lineoffset is wrong: " + tile + " "
|
|
||||||
+ tile.lineOffset + " "
|
|
||||||
+ sbuf.position() + " "
|
|
||||||
+ sbuf.limit() + " "
|
|
||||||
+ sbuf.remaining() + " "
|
|
||||||
+ PolygonRenderer.sizeOf(tile.polygonLayers) + " "
|
|
||||||
+ tile.rel);
|
|
||||||
|
|
||||||
tile.lineOffset *= SHORT_BYTES;
|
|
||||||
|
|
||||||
LineRenderer.compileLayerData(tile.lineLayers, sbuf);
|
|
||||||
|
|
||||||
sbuf.flip();
|
sbuf.flip();
|
||||||
|
|
||||||
if (newSize != sbuf.remaining()) {
|
if (newSize != sbuf.remaining()) {
|
||||||
Log.d(TAG, "tiles wrong: " + tile + " "
|
Log.d(TAG, "wrong size: "
|
||||||
+ newSize + " "
|
+ newSize + " "
|
||||||
+ sbuf.position() + " "
|
+ sbuf.position() + " "
|
||||||
+ sbuf.limit() + " "
|
+ sbuf.limit() + " "
|
||||||
+ sbuf.remaining() + " "
|
+ sbuf.remaining());
|
||||||
+ LineRenderer.sizeOf(tile.lineLayers)
|
|
||||||
+ tile.isLoading + " "
|
|
||||||
+ tile.rel);
|
|
||||||
|
|
||||||
tile.newData = false;
|
// tile.newData = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
newSize *= SHORT_BYTES;
|
newSize *= SHORT_BYTES;
|
||||||
|
|
||||||
// reuse memory allocated for vbo when possible and allocated
|
// reuse memory allocated for vbo when possible and allocated
|
||||||
// memory is less then four times the new data
|
// memory is less then four times the new data
|
||||||
if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
|
if (vbo.size > newSize && vbo.size < newSize * 4
|
||||||
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
|
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
|
||||||
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
||||||
} else {
|
} else {
|
||||||
mBufferMemoryUsage -= tile.vbo.size;
|
mBufferMemoryUsage -= vbo.size;
|
||||||
tile.vbo.size = newSize;
|
vbo.size = newSize;
|
||||||
GLES20.glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
GLES20.glBufferData(GL_ARRAY_BUFFER, vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||||
mBufferMemoryUsage += tile.vbo.size;
|
mBufferMemoryUsage += vbo.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadCnt++;
|
uploadCnt++;
|
||||||
|
|
||||||
tile.isReady = true;
|
|
||||||
tile.newData = false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean uploadTileData(MapTile tile) {
|
||||||
|
|
||||||
|
if (uploadLayers(tile.layers, tile.vbo, true))
|
||||||
|
tile.isReady = true;
|
||||||
|
|
||||||
|
tile.newData = false;
|
||||||
|
|
||||||
|
return tile.isReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean uploadOverlayData(Overlay overlay) {
|
||||||
|
|
||||||
|
if (uploadLayers(overlay.layers, overlay.vbo, true))
|
||||||
|
overlay.isReady = true;
|
||||||
|
|
||||||
|
overlay.newData = false;
|
||||||
|
|
||||||
|
return overlay.isReady;
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkBufferUsage() {
|
private static void checkBufferUsage() {
|
||||||
|
// try to clear some unused vbo when exceding limit
|
||||||
|
|
||||||
if (mBufferMemoryUsage < LIMIT_BUFFERS) {
|
if (mBufferMemoryUsage < LIMIT_BUFFERS) {
|
||||||
if (CACHE_TILES < CACHE_TILES_MAX)
|
if (CACHE_TILES < CACHE_TILES_MAX)
|
||||||
CACHE_TILES += 50;
|
CACHE_TILES += 50;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to clear some unused vbo when exceding limit
|
|
||||||
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
|
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
|
||||||
|
|
||||||
int vboIds[] = new int[10];
|
mBufferMemoryUsage -= BufferObject.limitUsage(2 * MB);
|
||||||
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");
|
Log.d(TAG, "now: " + mBufferMemoryUsage / MB + "MB");
|
||||||
}
|
|
||||||
|
|
||||||
if (mBufferMemoryUsage > LIMIT_BUFFERS && CACHE_TILES > 100)
|
if (mBufferMemoryUsage > LIMIT_BUFFERS && CACHE_TILES > 100)
|
||||||
CACHE_TILES -= 50;
|
CACHE_TILES -= 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean mRotate = false;
|
|
||||||
|
|
||||||
private static void setMatrix(float[] matrix, MapTile tile,
|
private static void setMatrix(float[] matrix, MapTile tile,
|
||||||
float div, boolean project) {
|
float div, boolean project) {
|
||||||
|
|
||||||
MapPosition mapPosition = mMapPosition;
|
MapPosition mapPosition = mMapPosition;
|
||||||
|
|
||||||
float x = (float) (tile.pixelX - mapPosition.x * div);
|
float x = (float) (tile.pixelX - mapPosition.x * div);
|
||||||
@ -448,12 +409,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
matrix[0] = scale;
|
matrix[0] = scale;
|
||||||
matrix[5] = scale;
|
matrix[5] = scale;
|
||||||
|
|
||||||
if (mRotate)
|
Matrix.multiplyMM(matrix, 0, mapPosition.viewMatrix, 0, matrix, 0);
|
||||||
Matrix.multiplyMM(matrix, 0, mapPosition.rotation, 0, matrix, 0);
|
|
||||||
|
|
||||||
if (project)
|
if (project)
|
||||||
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
|
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float scaleDiv(MapTile t) {
|
private static float scaleDiv(MapTile t) {
|
||||||
@ -492,14 +451,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
| GLES20.GL_DEPTH_BUFFER_BIT
|
| GLES20.GL_DEPTH_BUFFER_BIT
|
||||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
// get current tiles to draw
|
|
||||||
if (mUpdateTiles) {
|
if (mUpdateTiles) {
|
||||||
|
// get current tiles to draw
|
||||||
GLRenderer.tilelock.lock();
|
GLRenderer.tilelock.lock();
|
||||||
|
mUpdateTiles = false;
|
||||||
|
|
||||||
TilesData tmp = mDrawTiles;
|
TilesData tmp = mDrawTiles;
|
||||||
mDrawTiles = mNextTiles;
|
mDrawTiles = mNextTiles;
|
||||||
mNextTiles = tmp;
|
mNextTiles = tmp;
|
||||||
mUpdateTiles = false;
|
|
||||||
GLRenderer.tilelock.unlock();
|
GLRenderer.tilelock.unlock();
|
||||||
|
|
||||||
|
// force update of mapPosition
|
||||||
|
mMapPosition.zoomLevel = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||||
@ -507,14 +470,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
|
||||||
|
|
||||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||||
// coordinates)
|
// coordinates)
|
||||||
MapPosition mapPosition = mMapPosition;
|
MapPosition mapPosition = mMapPosition;
|
||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||||
|
|
||||||
|
for (Overlay overlay : mOverlays) {
|
||||||
|
overlay.update(mMapView);
|
||||||
|
}
|
||||||
|
|
||||||
int tileCnt = mDrawTiles.cnt;
|
int tileCnt = mDrawTiles.cnt;
|
||||||
MapTile[] tiles = mDrawTiles.tiles;
|
MapTile[] tiles = mDrawTiles.tiles;
|
||||||
|
|
||||||
@ -539,24 +504,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
mHolderCount = 0;
|
mHolderCount = 0;
|
||||||
mScanBox.scan(coords, tiles[0].zoomLevel);
|
mScanBox.scan(coords, tiles[0].zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
tileCnt += mHolderCount;
|
tileCnt += mHolderCount;
|
||||||
|
|
||||||
// // TODO get the right function: trying to accomodate for the
|
// Log.d(TAG, "visible: " + tileCnt);
|
||||||
// y-stretching introduced by the perspective transformation...
|
|
||||||
// float sw, sh;
|
|
||||||
// sw = MapViewPosition.VIEW_SCALE;
|
|
||||||
// sh = MapViewPosition.VIEW_SCALE;
|
|
||||||
// sh += (mMapViewPosition.mTilt / 150);
|
|
||||||
//
|
|
||||||
// Matrix.frustumM(mProjMatrix, 0, -sw * mWidth, sw * mWidth,
|
|
||||||
// sh * mHeight, -sh * mHeight, 1, 2);
|
|
||||||
//
|
|
||||||
// Matrix.translateM(mProjMatrix, 0, 0, 0,
|
|
||||||
// -MapViewPosition.VIEW_DISTANCE);
|
|
||||||
//
|
|
||||||
// mProjMatrix[10] = 0;
|
|
||||||
// mProjMatrix[14] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadCnt = 0;
|
uploadCnt = 0;
|
||||||
int updateTextures = 0;
|
int updateTextures = 0;
|
||||||
@ -579,28 +531,33 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
uploadTileData(tile);
|
uploadTileData(tile);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.holder != null) {
|
if (tile.holder != null) {
|
||||||
if (tile.holder.newData) {
|
// load tile that is referenced by this holder
|
||||||
|
if (tile.holder.newData)
|
||||||
uploadTileData(tile.holder);
|
uploadTileData(tile.holder);
|
||||||
}
|
|
||||||
tile.isReady = tile.holder.isReady;
|
tile.isReady = tile.holder.isReady;
|
||||||
|
|
||||||
} else if (!tile.isReady) {
|
} else if (!tile.isReady) {
|
||||||
// check near relatives if they can serve as proxy
|
// check near relatives than can serve as proxy
|
||||||
|
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
||||||
MapTile rel = tile.rel.parent.tile;
|
MapTile rel = tile.rel.parent.tile;
|
||||||
if (rel != null && rel.newData) {
|
if (rel.newData)
|
||||||
uploadTileData(rel);
|
uploadTileData(rel);
|
||||||
} else {
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (int c = 0; c < 4; c++) {
|
for (int c = 0; c < 4; c++) {
|
||||||
if (tile.rel.child[c] == null)
|
if ((tile.proxies & 1 << c) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rel = tile.rel.child[c].tile;
|
MapTile rel = tile.rel.child[c].tile;
|
||||||
if (rel != null && rel.newData)
|
if (rel != null && rel.newData)
|
||||||
uploadTileData(rel);
|
uploadTileData(rel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (uploadCnt > 0)
|
if (uploadCnt > 0)
|
||||||
checkBufferUsage();
|
checkBufferUsage();
|
||||||
@ -620,7 +577,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// proxies are clipped to the region where nothing was drawn to depth
|
// 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
|
||||||
|
// TODO draw proxies for placeholder...
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile t = tiles[i];
|
MapTile t = tiles[i];
|
||||||
if (t.isVisible && !t.isReady && (t.holder == null))
|
if (t.isVisible && !t.isReady && (t.holder == null))
|
||||||
@ -639,7 +598,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
int z = mapPosition.zoomLevel;
|
int z = mapPosition.zoomLevel;
|
||||||
float s = mapPosition.scale;
|
float s = mapPosition.scale;
|
||||||
|
|
||||||
int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL, 0);
|
int zoomLevelDiff = Math.max(z - TileGenerator.STROKE_MAX_ZOOM_LEVEL,
|
||||||
|
0);
|
||||||
float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
float scale = (float) Math.pow(1.4, zoomLevelDiff);
|
||||||
if (scale < 1)
|
if (scale < 1)
|
||||||
scale = 1;
|
scale = 1;
|
||||||
@ -647,7 +607,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
||||||
TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
||||||
else
|
else
|
||||||
TextRenderer.beginDraw(1 / s, mProjMatrix);
|
TextRenderer.beginDraw(1f / s, mProjMatrix);
|
||||||
|
|
||||||
for (int i = 0; i < tileCnt; i++) {
|
for (int i = 0; i < tileCnt; i++) {
|
||||||
MapTile t = tiles[i];
|
MapTile t = tiles[i];
|
||||||
@ -669,12 +629,53 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
TextRenderer.endDraw();
|
TextRenderer.endDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO call overlay renderer here
|
// call overlay renderer
|
||||||
|
for (Overlay overlay : mOverlays) {
|
||||||
|
if (overlay.newData) {
|
||||||
|
if (overlay.vbo == null)
|
||||||
|
overlay.vbo = BufferObject.get();
|
||||||
|
|
||||||
|
if (overlay.vbo == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (uploadOverlayData(overlay))
|
||||||
|
overlay.isReady = true;
|
||||||
|
}
|
||||||
|
if (!overlay.isReady)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// setMatrix(mMVPMatrix, overlay);
|
||||||
|
overlay.render(mMapPosition, mMVPMatrix, mProjMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
if (MapView.debugFrameTime) {
|
if (MapView.debugFrameTime) {
|
||||||
GLES20.glFinish();
|
GLES20.glFinish();
|
||||||
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
|
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debugView) {
|
||||||
|
float mm = 0.5f;
|
||||||
|
float min = -mm;
|
||||||
|
float max = mm;
|
||||||
|
float ymax = mm * mHeight / mWidth;
|
||||||
|
mDebugCoords[0] = min;
|
||||||
|
mDebugCoords[1] = ymax;
|
||||||
|
mDebugCoords[2] = max;
|
||||||
|
mDebugCoords[3] = ymax;
|
||||||
|
mDebugCoords[4] = min;
|
||||||
|
mDebugCoords[5] = -ymax;
|
||||||
|
mDebugCoords[6] = max;
|
||||||
|
mDebugCoords[7] = -ymax;
|
||||||
|
|
||||||
|
PolygonRenderer.debugDraw(mProjMatrix, mDebugCoords, 0);
|
||||||
|
|
||||||
|
mapPosition.zoomLevel = -1;
|
||||||
|
mMapViewPosition.getMapPosition(mapPosition, mDebugCoords);
|
||||||
|
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0,
|
||||||
|
mapPosition.viewMatrix, 0);
|
||||||
|
PolygonRenderer.debugDraw(mMVPMatrix, mDebugCoords, 1);
|
||||||
|
}
|
||||||
|
|
||||||
GLRenderer.drawlock.unlock();
|
GLRenderer.drawlock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -701,54 +702,49 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
||||||
|
|
||||||
LineLayer ll = tile.lineLayers;
|
|
||||||
PolygonLayer pl = tile.polygonLayers;
|
|
||||||
|
|
||||||
boolean clipped = false;
|
boolean clipped = false;
|
||||||
int simpleShader = mRotate ? 0 : 1;
|
int simpleShader = 0; // mRotate ? 0 : 1;
|
||||||
|
|
||||||
for (; pl != null || ll != null;) {
|
for (Layer l = tile.layers.layers; l != null;) {
|
||||||
int lnext = Integer.MAX_VALUE;
|
|
||||||
int pnext = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
if (ll != null)
|
switch (l.type) {
|
||||||
lnext = ll.layer;
|
case Layer.POLYGON:
|
||||||
|
|
||||||
if (pl != null)
|
|
||||||
pnext = pl.layer;
|
|
||||||
|
|
||||||
if (pl != null && pnext < lnext) {
|
|
||||||
GLES20.glDisable(GL_BLEND);
|
GLES20.glDisable(GL_BLEND);
|
||||||
pl = PolygonRenderer.drawPolygons(pos, pl, lnext, mvp, !clipped);
|
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
} else {
|
break;
|
||||||
// FIXME
|
|
||||||
|
case Layer.LINE:
|
||||||
if (!clipped) {
|
if (!clipped) {
|
||||||
PolygonRenderer.drawPolygons(pos, null, 0, mvp, true);
|
PolygonRenderer.draw(pos, null, mvp, true, true);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glEnable(GL_BLEND);
|
GLES20.glEnable(GL_BLEND);
|
||||||
ll = LineRenderer.drawLines(pos, ll, pnext, mvp, div,
|
l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
|
||||||
simpleShader, tile.lineOffset);
|
tile.layers.lineOffset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile.layers.symbolLayers != null) {
|
||||||
|
setMatrix(mvp, tile, div, false);
|
||||||
|
|
||||||
|
for (Layer l = tile.layers.symbolLayers; l != null;) {
|
||||||
|
l = TextureRenderer.draw(l, 1, mProjMatrix, mvp,
|
||||||
|
tile.layers.symbolOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should check tile.proxies here
|
|
||||||
private static boolean drawProxyChild(MapTile tile) {
|
private static boolean drawProxyChild(MapTile tile) {
|
||||||
int drawn = 0;
|
int drawn = 0;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (tile.rel.child[i] == null)
|
if ((tile.proxies & 1 << i) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MapTile c = tile.rel.child[i].tile;
|
MapTile c = tile.rel.child[i].tile;
|
||||||
if (c == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// if (!isVisible(c)) {
|
|
||||||
// drawn++;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (c.isReady) {
|
if (c.isReady) {
|
||||||
drawTile(c);
|
drawTile(c);
|
||||||
@ -812,13 +808,24 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
|
|
||||||
// use this to scale only the view to see better which tiles are
|
|
||||||
// rendered
|
|
||||||
float s = MapViewPosition.VIEW_SCALE;
|
float s = MapViewPosition.VIEW_SCALE;
|
||||||
Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
float aspect = mHeight / (float) mWidth;
|
||||||
s * height, -s * height, 1, 2);
|
|
||||||
|
|
||||||
Matrix.translateM(mProjMatrix, 0, 0, 0, -MapViewPosition.VIEW_DISTANCE);
|
Matrix.frustumM(mProjMatrix, 0, -1 * s, 1 * s,
|
||||||
|
aspect * s, -aspect * s, MapViewPosition.VIEW_NEAR,
|
||||||
|
MapViewPosition.VIEW_FAR);
|
||||||
|
|
||||||
|
Matrix.setIdentityM(mTmpMatrix, 0);
|
||||||
|
Matrix.translateM(mTmpMatrix, 0, 0, 0, -MapViewPosition.VIEW_DISTANCE);
|
||||||
|
Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mTmpMatrix, 0);
|
||||||
|
|
||||||
|
if (debugView) {
|
||||||
|
// modify this to scale only the view, to see better which tiles are
|
||||||
|
// rendered
|
||||||
|
Matrix.setIdentityM(mMVPMatrix, 0);
|
||||||
|
Matrix.scaleM(mMVPMatrix, 0, 0.5f, 0.5f, 1);
|
||||||
|
Matrix.multiplyMM(mProjMatrix, 0, mMVPMatrix, 0, mProjMatrix, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// set to zero: we modify the z value with polygon-offset for clipping
|
// set to zero: we modify the z value with polygon-offset for clipping
|
||||||
mProjMatrix[10] = 0;
|
mProjMatrix[10] = 0;
|
||||||
@ -830,8 +837,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mNewSurface = false;
|
|
||||||
|
|
||||||
|
mNewSurface = false;
|
||||||
mBufferMemoryUsage = 0;
|
mBufferMemoryUsage = 0;
|
||||||
|
|
||||||
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||||
@ -839,14 +846,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
// Set up vertex buffer objects
|
// Set up vertex buffer objects
|
||||||
int numVBO = (CACHE_TILES + (numTiles * 2));
|
int numVBO = (CACHE_TILES + (numTiles * 2));
|
||||||
int[] mVboIds = new int[numVBO];
|
BufferObject.init(numVBO);
|
||||||
GLES20.glGenBuffers(numVBO, mVboIds, 0);
|
|
||||||
GlUtils.checkGlError("glGenBuffers");
|
|
||||||
|
|
||||||
mVBOs = new ArrayList<VertexBufferObject>(numVBO);
|
|
||||||
|
|
||||||
for (int i = 1; i < numVBO; i++)
|
|
||||||
mVBOs.add(new VertexBufferObject(mVboIds[i]));
|
|
||||||
|
|
||||||
// Set up textures
|
// Set up textures
|
||||||
TextRenderer.setup(numTiles);
|
TextRenderer.setup(numTiles);
|
||||||
@ -854,6 +854,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
if (mClearColor != null)
|
if (mClearColor != null)
|
||||||
mUpdateColor = true;
|
mUpdateColor = true;
|
||||||
|
|
||||||
|
vertexArray[0] = false;
|
||||||
|
vertexArray[1] = false;
|
||||||
|
|
||||||
// FIXME this should be synchronized
|
// FIXME this should be synchronized
|
||||||
mMapView.redrawMap();
|
mMapView.redrawMap();
|
||||||
}
|
}
|
||||||
@ -862,20 +865,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
void clearTiles(int numTiles) {
|
void clearTiles(int numTiles) {
|
||||||
mDrawTiles = new TilesData(numTiles);
|
mDrawTiles = new TilesData(numTiles);
|
||||||
mNextTiles = new TilesData(numTiles);
|
mNextTiles = new TilesData(numTiles);
|
||||||
|
mMapPosition.zoomLevel = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||||
|
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
// Log.d(TAG, "Extensions: " + ext);
|
||||||
Log.d(TAG, "Extensions: " + ext);
|
|
||||||
|
|
||||||
LineRenderer.init();
|
LineRenderer.init();
|
||||||
PolygonRenderer.init();
|
PolygonRenderer.init();
|
||||||
TextRenderer.init();
|
TextRenderer.init();
|
||||||
|
TextureRenderer.init();
|
||||||
mNewSurface = true;
|
TextureObject.init(10);
|
||||||
// mUpdateColor = true;
|
|
||||||
|
|
||||||
// glEnable(GL_SCISSOR_TEST);
|
// glEnable(GL_SCISSOR_TEST);
|
||||||
// glScissor(0, 0, mWidth, mHeight);
|
// glScissor(0, 0, mWidth, mHeight);
|
||||||
@ -883,51 +885,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||||
GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
mNewSurface = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mNewSurface;
|
private boolean mNewSurface;
|
||||||
|
|
||||||
|
private static final boolean debugView = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
// }
|
|
@ -12,14 +12,15 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
|
|
||||||
|
import android.graphics.Paint.Cap;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -27,7 +28,7 @@ import android.util.Log;
|
|||||||
class LineRenderer {
|
class LineRenderer {
|
||||||
private final static String TAG = "LineRenderer";
|
private final static String TAG = "LineRenderer";
|
||||||
|
|
||||||
private static int NUM_VERTEX_SHORTS = 4;
|
// private static int NUM_VERTEX_SHORTS = 4;
|
||||||
|
|
||||||
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
|
private static final int LINE_VERTICES_DATA_POS_OFFSET = 0;
|
||||||
private static final int LINE_VERTICES_DATA_TEX_OFFSET = 4;
|
private static final int LINE_VERTICES_DATA_TEX_OFFSET = 4;
|
||||||
@ -40,6 +41,7 @@ class LineRenderer {
|
|||||||
private static int[] hLineMatrix = new int[2];
|
private static int[] hLineMatrix = new int[2];
|
||||||
private static int[] hLineScale = new int[2];
|
private static int[] hLineScale = new int[2];
|
||||||
private static int[] hLineWidth = new int[2];
|
private static int[] hLineWidth = new int[2];
|
||||||
|
private static int[] hLineMode = new int[2];
|
||||||
|
|
||||||
static boolean init() {
|
static boolean init() {
|
||||||
lineProgram[0] = GlUtils.createProgram(Shaders.lineVertexShader,
|
lineProgram[0] = GlUtils.createProgram(Shaders.lineVertexShader,
|
||||||
@ -53,6 +55,7 @@ class LineRenderer {
|
|||||||
hLineScale[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_wscale");
|
hLineScale[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_wscale");
|
||||||
hLineWidth[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_width");
|
hLineWidth[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_width");
|
||||||
hLineColor[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_color");
|
hLineColor[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_color");
|
||||||
|
hLineMode[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_mode");
|
||||||
|
|
||||||
hLineVertexPosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_position");
|
hLineVertexPosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_position");
|
||||||
hLineTexturePosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_st");
|
hLineTexturePosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_st");
|
||||||
@ -68,6 +71,7 @@ class LineRenderer {
|
|||||||
hLineScale[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_wscale");
|
hLineScale[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_wscale");
|
||||||
hLineWidth[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_width");
|
hLineWidth[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_width");
|
||||||
hLineColor[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_color");
|
hLineColor[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_color");
|
||||||
|
hLineMode[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_mode");
|
||||||
|
|
||||||
hLineVertexPosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_position");
|
hLineVertexPosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_position");
|
||||||
hLineTexturePosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_st");
|
hLineTexturePosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_st");
|
||||||
@ -75,8 +79,8 @@ class LineRenderer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LineLayer drawLines(MapPosition pos, LineLayer layer, int next,
|
static Layer draw(MapPosition pos, Layer layer, float[] matrix, float div,
|
||||||
float[] matrix, float div, int mode, int bufferOffset) {
|
int mode, int bufferOffset) {
|
||||||
|
|
||||||
int zoom = pos.zoomLevel;
|
int zoom = pos.zoomLevel;
|
||||||
float scale = pos.scale;
|
float scale = pos.scale;
|
||||||
@ -86,8 +90,20 @@ class LineRenderer {
|
|||||||
|
|
||||||
GLES20.glUseProgram(lineProgram[mode]);
|
GLES20.glUseProgram(lineProgram[mode]);
|
||||||
|
|
||||||
GLES20.glEnableVertexAttribArray(hLineVertexPosition[mode]);
|
int va = hLineVertexPosition[mode];
|
||||||
GLES20.glEnableVertexAttribArray(hLineTexturePosition[mode]);
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
va = hLineTexturePosition[mode];
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLES20.glEnableVertexAttribArray(hLineVertexPosition[mode]);
|
||||||
|
// GLES20.glEnableVertexAttribArray(hLineTexturePosition[mode]);
|
||||||
|
|
||||||
GLES20.glVertexAttribPointer(hLineVertexPosition[mode], 2, GLES20.GL_SHORT,
|
GLES20.glVertexAttribPointer(hLineVertexPosition[mode], 2, GLES20.GL_SHORT,
|
||||||
false, 8, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
false, 8, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
||||||
@ -100,12 +116,14 @@ class LineRenderer {
|
|||||||
// scale factor to map one pixel on tile to one pixel on screen:
|
// scale factor to map one pixel on tile to one pixel on screen:
|
||||||
// only works with orthographic projection
|
// only works with orthographic projection
|
||||||
float s = scale / div;
|
float s = scale / div;
|
||||||
float pixel = 2.0f / s;
|
float pixel = 0;
|
||||||
|
|
||||||
if (mode == 0)
|
if (mode == 1)
|
||||||
pixel = 0;
|
pixel = 1.5f / s;
|
||||||
|
|
||||||
GLES20.glUniform1f(hLineScale[mode], pixel);
|
GLES20.glUniform1f(hLineScale[mode], pixel);
|
||||||
|
int lineMode = 0;
|
||||||
|
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||||
|
|
||||||
// line scale factor (for non fixed lines)
|
// line scale factor (for non fixed lines)
|
||||||
float lineScale = FloatMath.sqrt(s);
|
float lineScale = FloatMath.sqrt(s);
|
||||||
@ -115,10 +133,11 @@ class LineRenderer {
|
|||||||
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||||
float width = 1;
|
float width = 1;
|
||||||
|
|
||||||
LineLayer l = layer;
|
Layer l = layer;
|
||||||
for (; l != null && l.layer < next; l = l.next) {
|
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
||||||
|
LineLayer ll = (LineLayer) l;
|
||||||
|
Line line = ll.line;
|
||||||
|
|
||||||
Line line = l.line;
|
|
||||||
if (line.fade != -1 && line.fade > zoom)
|
if (line.fade != -1 && line.fade > zoom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -134,23 +153,33 @@ class LineRenderer {
|
|||||||
blur = false;
|
blur = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (l.isOutline) {
|
if (line.outline) {
|
||||||
for (LineLayer o = l.outlines; o != null; o = o.outlines) {
|
for (LineLayer o = ll.outlines; o != null; o = o.outlines) {
|
||||||
|
|
||||||
if (o.line.fixed || strokeMaxZoom) {
|
if (o.line.fixed || strokeMaxZoom) {
|
||||||
width = (l.width + o.width) / s;
|
width = (ll.width + o.width) / s;
|
||||||
} else {
|
} else {
|
||||||
width = l.width / s + o.width / lineScale;
|
width = ll.width / s + o.width / lineScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glUniform1f(hLineWidth[mode], width);
|
GLES20.glUniform1f(hLineWidth[mode], width);
|
||||||
|
|
||||||
if (line.blur != 0) {
|
if (line.blur != 0) {
|
||||||
blurScale = (l.width + o.width) / s - (line.blur / s);
|
blurScale = (ll.width + o.width) / s - (line.blur / s);
|
||||||
GLES20.glUniform1f(hLineScale[mode], blurScale);
|
GLES20.glUniform1f(hLineScale[mode], blurScale);
|
||||||
blur = true;
|
blur = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line.cap == Cap.ROUND) {
|
||||||
|
if (lineMode != 1) {
|
||||||
|
lineMode = 1;
|
||||||
|
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||||
|
}
|
||||||
|
} else if (lineMode != 0) {
|
||||||
|
lineMode = 0;
|
||||||
|
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||||
|
}
|
||||||
|
|
||||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, o.offset, o.verticesCnt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -158,173 +187,37 @@ class LineRenderer {
|
|||||||
if (line.fixed || strokeMaxZoom) {
|
if (line.fixed || strokeMaxZoom) {
|
||||||
// invert scaling of extrusion vectors so that line width
|
// invert scaling of extrusion vectors so that line width
|
||||||
// stays the same.
|
// stays the same.
|
||||||
width = l.width / s;
|
width = ll.width / s;
|
||||||
} else {
|
} else {
|
||||||
width = l.width / lineScale;
|
width = ll.width / lineScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glUniform1f(hLineWidth[mode], width);
|
GLES20.glUniform1f(hLineWidth[mode], width);
|
||||||
|
|
||||||
if (line.blur != 0) {
|
if (line.blur != 0) {
|
||||||
blurScale = (l.width / lineScale) * line.blur;
|
blurScale = (ll.width / lineScale) * line.blur;
|
||||||
GLES20.glUniform1f(hLineScale[mode], blurScale);
|
GLES20.glUniform1f(hLineScale[mode], blurScale);
|
||||||
blur = true;
|
blur = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (line.cap == Cap.ROUND) {
|
||||||
|
if (lineMode != 1) {
|
||||||
|
lineMode = 1;
|
||||||
|
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||||
|
}
|
||||||
|
} else if (lineMode != 0) {
|
||||||
|
lineMode = 0;
|
||||||
|
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||||
|
}
|
||||||
|
|
||||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
|
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, l.offset, l.verticesCnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glDisableVertexAttribArray(hLineVertexPosition[mode]);
|
// GLES20.glDisableVertexAttribArray(hLineVertexPosition[mode]);
|
||||||
GLES20.glDisableVertexAttribArray(hLineTexturePosition[mode]);
|
// GLES20.glDisableVertexAttribArray(hLineTexturePosition[mode]);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sizeOf(LineLayer layers) {
|
|
||||||
int size = 0;
|
|
||||||
for (LineLayer l = layers; l != null; l = l.next)
|
|
||||||
size += l.verticesCnt;
|
|
||||||
|
|
||||||
size *= NUM_VERTEX_SHORTS;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compileLayerData(LineLayer layers, ShortBuffer sbuf) {
|
|
||||||
int pos = 0;
|
|
||||||
VertexPoolItem last = null, items = null;
|
|
||||||
|
|
||||||
for (LineLayer l = layers; l != null; l = l.next) {
|
|
||||||
if (l.isOutline)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (VertexPoolItem item = l.pool; item != null; item = item.next) {
|
|
||||||
|
|
||||||
if (item.next == null) {
|
|
||||||
sbuf.put(item.vertices, 0, item.used);
|
|
||||||
} else {
|
|
||||||
// item.used = VertexPoolItem.SIZE;
|
|
||||||
sbuf.put(item.vertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
last = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
l.offset = pos;
|
|
||||||
pos += l.verticesCnt;
|
|
||||||
|
|
||||||
if (last != null) {
|
|
||||||
last.next = items;
|
|
||||||
items = l.pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
l.pool = null;
|
|
||||||
l.curItem = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexPool.add(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @SuppressLint("UseValueOf")
|
|
||||||
// private static final Boolean lock = new Boolean(true);
|
|
||||||
// private static final int POOL_LIMIT = 1500;
|
|
||||||
//
|
|
||||||
// static private LineLayer pool = null;
|
|
||||||
// static private int count = 0;
|
|
||||||
// static private int countAll = 0;
|
|
||||||
//
|
|
||||||
// static void finish() {
|
|
||||||
// synchronized (lock) {
|
|
||||||
// count = 0;
|
|
||||||
// countAll = 0;
|
|
||||||
// pool = null;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static LineLayer get(int layer, Line line, float width, boolean outline)
|
|
||||||
// {
|
|
||||||
// synchronized (lock) {
|
|
||||||
//
|
|
||||||
// if (count == 0 && pool == null) {
|
|
||||||
// countAll++;
|
|
||||||
// return new LineLayer(layer, line, width, outline);
|
|
||||||
// }
|
|
||||||
// if (count > 0) {
|
|
||||||
// count--;
|
|
||||||
// } else {
|
|
||||||
// int c = 0;
|
|
||||||
// LineLayer tmp = pool;
|
|
||||||
//
|
|
||||||
// while (tmp != null) {
|
|
||||||
// c++;
|
|
||||||
// tmp = tmp.next;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Log.d("LineLayersl", "eek wrong count: " + c + " left");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// LineLayer it = pool;
|
|
||||||
// pool = pool.next;
|
|
||||||
// it.next = null;
|
|
||||||
// it.layer = layer;
|
|
||||||
// it.line = line;
|
|
||||||
// it.isOutline = outline;
|
|
||||||
// it.width = width;
|
|
||||||
// return it;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// static void add(LineLayer layers) {
|
|
||||||
// if (layers == null)
|
|
||||||
// return;
|
|
||||||
//
|
|
||||||
// synchronized (lock) {
|
|
||||||
//
|
|
||||||
// // limit pool items
|
|
||||||
// if (countAll < POOL_LIMIT) {
|
|
||||||
// LineLayer last = layers;
|
|
||||||
//
|
|
||||||
// while (true) {
|
|
||||||
// count++;
|
|
||||||
//
|
|
||||||
// if (last.next == null)
|
|
||||||
// break;
|
|
||||||
//
|
|
||||||
// last = last.next;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// last.next = pool;
|
|
||||||
// pool = layers;
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// int cleared = 0;
|
|
||||||
// LineLayer prev, tmp = layers;
|
|
||||||
// while (tmp != null) {
|
|
||||||
// prev = tmp;
|
|
||||||
// tmp = tmp.next;
|
|
||||||
//
|
|
||||||
// countAll--;
|
|
||||||
// cleared++;
|
|
||||||
//
|
|
||||||
// prev.next = null;
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// Log.d("LineLayers", "sum: " + countAll + " free: " + count + " freed "
|
|
||||||
// + cleared);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
static void clear(LineLayer layer) {
|
|
||||||
for (LineLayer l = layer; l != null; l = l.next) {
|
|
||||||
if (l.pool != null) {
|
|
||||||
VertexPool.add(l.pool);
|
|
||||||
l.pool = null;
|
|
||||||
l.curItem = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// LineLayers.add(layer);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -12,18 +12,19 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.generator.JobTile;
|
||||||
|
import org.oscim.renderer.layer.VertexPool;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.utils.GlConfigChooser;
|
import org.oscim.utils.GlConfigChooser;
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.MapViewPosition;
|
import org.oscim.view.MapViewPosition;
|
||||||
import org.oscim.view.generator.JobTile;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
@ -36,7 +37,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
private GLRenderer mRenderer;
|
private GLRenderer mRenderer;
|
||||||
|
|
||||||
private static final int MAX_TILES_IN_QUEUE = 40;
|
private static final int MAX_TILES_IN_QUEUE = 40;
|
||||||
private static final int CACHE_THRESHOLD = 50;
|
private static final int CACHE_THRESHOLD = 10;
|
||||||
|
|
||||||
private static MapView mMapView;
|
private static MapView mMapView;
|
||||||
|
|
||||||
@ -52,6 +53,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// tiles that have new data to upload, see passTile()
|
// tiles that have new data to upload, see passTile()
|
||||||
private static ArrayList<MapTile> mTilesLoaded;
|
private static ArrayList<MapTile> mTilesLoaded;
|
||||||
|
|
||||||
|
private static ArrayList<Overlay> mOverlays;
|
||||||
|
|
||||||
// TODO current boundary tiles, values used to check if position has
|
// TODO current boundary tiles, values used to check if position has
|
||||||
// changed for updating current tile list
|
// changed for updating current tile list
|
||||||
|
|
||||||
@ -65,7 +68,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// private static int[] mZoomLevels;
|
// private static int[] mZoomLevels;
|
||||||
|
|
||||||
private static float[] mTileCoords = new float[8];
|
private static float[] mTileCoords = new float[8];
|
||||||
private static int[] mBoundaryTiles = new int[8];
|
|
||||||
|
// private static int[] mBoundaryTiles = new int[8];
|
||||||
|
|
||||||
// used for passing tiles to be rendered from TileLoader(Main-Thread) to
|
// used for passing tiles to be rendered from TileLoader(Main-Thread) to
|
||||||
// GLThread
|
// GLThread
|
||||||
@ -90,14 +94,14 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
int xmax = 1 << mZoom;
|
int xmax = 1 << mZoom;
|
||||||
|
|
||||||
for (int x = x1; x < x2; x++) {
|
for (int x = x1; x < x2; x++) {
|
||||||
// MapTile holder = null;
|
|
||||||
MapTile tile = null;
|
MapTile tile = null;
|
||||||
|
|
||||||
// boolean found = false;
|
|
||||||
if (cnt == max) {
|
if (cnt == max) {
|
||||||
Log.d(TAG, "reached max currentTiles " + max);
|
Log.d(TAG, "reached maximum for currentTiles " + max);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE to myself: do not modify x, argh !!!
|
||||||
int xx = x;
|
int xx = x;
|
||||||
|
|
||||||
if (x < 0 || x >= xmax) {
|
if (x < 0 || x >= xmax) {
|
||||||
@ -107,12 +111,11 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
else
|
else
|
||||||
xx = x - xmax;
|
xx = x - xmax;
|
||||||
|
|
||||||
if (xx < 0 || xx >= xmax) {
|
if (xx < 0 || xx >= xmax)
|
||||||
// Log.d(TAG, "tile out of bounds " + y + " " + xx);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// check if tile is already added
|
||||||
for (int i = 0; i < cnt; i++)
|
for (int i = 0; i < cnt; i++)
|
||||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||||
tile = tiles[i];
|
tile = tiles[i];
|
||||||
@ -128,7 +131,28 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public MapRenderer(Context context, MapView mapView) {
|
// why not try a pattern every now and then?
|
||||||
|
// but should do the same for GLRenderer
|
||||||
|
private static MapRenderer SINGLETON;
|
||||||
|
|
||||||
|
public static MapRenderer create(Context context, MapView mapView) {
|
||||||
|
if (SINGLETON != null)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
|
||||||
|
return SINGLETON = new MapRenderer(context, mapView);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy() {
|
||||||
|
SINGLETON = null;
|
||||||
|
// mRenderer = null;
|
||||||
|
// mTiles = null;
|
||||||
|
// mTilesLoaded = null;
|
||||||
|
// mJobList = null;
|
||||||
|
// mOverlays = null;
|
||||||
|
// ... free pools
|
||||||
|
}
|
||||||
|
|
||||||
|
private MapRenderer(Context context, MapView mapView) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
mMapView = mapView;
|
mMapView = mapView;
|
||||||
@ -148,6 +172,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mJobList = new ArrayList<JobTile>();
|
mJobList = new ArrayList<JobTile>();
|
||||||
mTiles = new ArrayList<MapTile>();
|
mTiles = new ArrayList<MapTile>();
|
||||||
mTilesLoaded = new ArrayList<MapTile>(30);
|
mTilesLoaded = new ArrayList<MapTile>(30);
|
||||||
|
mOverlays = new ArrayList<Overlay>(5);
|
||||||
|
|
||||||
VertexPool.init();
|
VertexPool.init();
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
@ -163,7 +188,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
* @param clear
|
* @param clear
|
||||||
* whether to clear and reload all tiles
|
* whether to clear and reload all tiles
|
||||||
*/
|
*/
|
||||||
public void updateMap(boolean clear) {
|
public void updateMap(final boolean clear) {
|
||||||
boolean changedPos = false;
|
boolean changedPos = false;
|
||||||
|
|
||||||
if (mMapView == null)
|
if (mMapView == null)
|
||||||
@ -173,14 +198,24 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// make sure onDrawFrame is not running
|
// make sure onDrawFrame is not running
|
||||||
GLRenderer.drawlock.lock();
|
GLRenderer.drawlock.lock();
|
||||||
// remove all tiles references
|
// remove all tiles references
|
||||||
Log.d(TAG, "CLEAR");
|
Log.d(TAG, "CLEAR " + mInitial);
|
||||||
|
|
||||||
|
if (clear) {
|
||||||
for (MapTile t : mTiles)
|
for (MapTile t : mTiles)
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
|
} else {
|
||||||
|
VertexPool.init();
|
||||||
|
}
|
||||||
|
|
||||||
mTiles.clear();
|
mTiles.clear();
|
||||||
mTilesLoaded.clear();
|
mTilesLoaded.clear();
|
||||||
|
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
|
|
||||||
|
// TODO clear overlay items data
|
||||||
|
mOverlays.clear();
|
||||||
|
mOverlays.add(new Overlay());
|
||||||
|
|
||||||
// set up TileData arrays that are passed to gl-thread
|
// set up TileData arrays that are passed to gl-thread
|
||||||
int num = mWidth;
|
int num = mWidth;
|
||||||
if (mWidth < mHeight)
|
if (mWidth < mHeight)
|
||||||
@ -198,19 +233,25 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// mZoomLevels = mapInfo.zoomLevel;
|
// mZoomLevels = mapInfo.zoomLevel;
|
||||||
GLRenderer.drawlock.unlock();
|
GLRenderer.drawlock.unlock();
|
||||||
|
|
||||||
changedPos = true;
|
// .. make sure mMapPosition will be updated
|
||||||
|
mMapPosition.zoomLevel = -1;
|
||||||
|
|
||||||
mInitial = false;
|
mInitial = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapPosition mapPosition = mMapPosition;
|
MapPosition mapPosition = mMapPosition;
|
||||||
mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
float[] coords = mTileCoords;
|
||||||
|
changedPos = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||||
|
|
||||||
|
if (!changedPos)
|
||||||
|
return;
|
||||||
|
|
||||||
float s = Tile.TILE_SIZE;
|
float s = Tile.TILE_SIZE;
|
||||||
// load some additional tiles more than currently visible
|
// load some additional tiles more than currently visible
|
||||||
float scale = mapPosition.scale * 0.75f;
|
float scale = mapPosition.scale * 0.75f;
|
||||||
float px = (float) mapPosition.x;
|
float px = (float) mapPosition.x;
|
||||||
float py = (float) mapPosition.y;
|
float py = (float) mapPosition.y;
|
||||||
float[] coords = mTileCoords;
|
|
||||||
int zdir = 0;
|
int zdir = 0;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i += 2) {
|
for (int i = 0; i < 8; i += 2) {
|
||||||
@ -218,32 +259,30 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
coords[i + 1] = (py + coords[i + 1] / scale) / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
// this does not work reloably with tilt and rotation
|
||||||
if (mBoundaryTiles[i] != (int) coords[i]) {
|
// changedPos = false;
|
||||||
changedPos = true;
|
// for (int i = 0; i < 8; i++)
|
||||||
break;
|
// if (mBoundaryTiles[i] != (int) coords[i]) {
|
||||||
}
|
// changedPos = true;
|
||||||
|
// break;
|
||||||
for (int i = 0; i < 8; i++)
|
// }
|
||||||
mBoundaryTiles[i] = (int) coords[i];
|
// for (int i = 0; i < 8; i++)
|
||||||
|
// mBoundaryTiles[i] = (int) coords[i];
|
||||||
|
|
||||||
// TODO all following should probably be done in an idler instead
|
// TODO all following should probably be done in an idler instead
|
||||||
// to drain queued events. need to check how android handles things.
|
// to drain queued events. need to check how android handles things.
|
||||||
|
|
||||||
if (changedPos) {
|
boolean changed = updateVisibleList(mapPosition, zdir);
|
||||||
updateVisibleList(mapPosition, zdir);
|
|
||||||
|
|
||||||
if (!MapView.debugFrameTime)
|
if (!MapView.debugFrameTime)
|
||||||
requestRender();
|
requestRender();
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||||
if (remove > CACHE_THRESHOLD)
|
if (remove > CACHE_THRESHOLD)
|
||||||
limitCache(mapPosition, remove);
|
limitCache(mapPosition, remove);
|
||||||
|
|
||||||
limitLoadQueue();
|
limitLoadQueue();
|
||||||
} else {
|
|
||||||
if (!MapView.debugFrameTime)
|
|
||||||
requestRender();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,8 +294,9 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
* the current MapPosition
|
* the current MapPosition
|
||||||
* @param zdir
|
* @param zdir
|
||||||
* zoom direction
|
* zoom direction
|
||||||
|
* @return true if new tiles were loaded
|
||||||
*/
|
*/
|
||||||
private static void updateVisibleList(MapPosition mapPosition, int zdir) {
|
private static boolean updateVisibleList(MapPosition mapPosition, int zdir) {
|
||||||
|
|
||||||
mJobList.clear();
|
mJobList.clear();
|
||||||
// set non processed tiles to isLoading == false
|
// set non processed tiles to isLoading == false
|
||||||
@ -265,14 +305,16 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
||||||
// Log.d(TAG, "visible: " + mCurrentTiles.cnt + "/" +
|
// Log.d(TAG, "visible: " + mCurrentTiles.cnt + "/" +
|
||||||
// mCurrentTiles.tiles.length);
|
// mCurrentTiles.tiles.length);
|
||||||
GLRenderer.updateTiles(mCurrentTiles);
|
GLRenderer.updateTiles(mCurrentTiles, mOverlays);
|
||||||
|
|
||||||
// note: this sets isLoading == true for all job tiles
|
// note: this sets isLoading == true for all job tiles
|
||||||
if (mJobList.size() > 0) {
|
if (mJobList.size() > 0) {
|
||||||
updateTileDistances(mJobList, mapPosition);
|
updateTileDistances(mJobList, mapPosition);
|
||||||
Collections.sort(mJobList);
|
Collections.sort(mJobList);
|
||||||
mMapView.addJobs(mJobList);
|
mMapView.addJobs(mJobList);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */
|
/* package */
|
||||||
@ -342,15 +384,15 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
t.isLoading = false;
|
t.isLoading = false;
|
||||||
t.isReady = false;
|
t.isReady = false;
|
||||||
|
|
||||||
LineRenderer.clear(t.lineLayers);
|
if (t.layers != null) {
|
||||||
PolygonRenderer.clear(t.polygonLayers);
|
t.layers.clear();
|
||||||
|
t.layers = null;
|
||||||
|
}
|
||||||
|
|
||||||
t.labels = null;
|
t.labels = null;
|
||||||
t.lineLayers = null;
|
|
||||||
t.polygonLayers = null;
|
|
||||||
|
|
||||||
if (t.vbo != null) {
|
if (t.vbo != null) {
|
||||||
GLRenderer.addVBO(t.vbo);
|
BufferObject.release(t.vbo);
|
||||||
t.vbo = null;
|
t.vbo = null;
|
||||||
}
|
}
|
||||||
if (t.texture != null)
|
if (t.texture != null)
|
||||||
@ -364,7 +406,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
byte zoom = mapPosition.zoomLevel;
|
byte zoom = mapPosition.zoomLevel;
|
||||||
long x = (long) mapPosition.x;
|
long x = (long) mapPosition.x;
|
||||||
long y = (long) mapPosition.y;
|
long y = (long) mapPosition.y;
|
||||||
|
// long center = Tile.TILE_SIZE << (zoom - 1);
|
||||||
int diff;
|
int diff;
|
||||||
long dx, dy;
|
long dx, dy;
|
||||||
|
|
||||||
@ -380,6 +422,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
dy = (t.pixelY + h) - y;
|
dy = (t.pixelY + h) - y;
|
||||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
||||||
// 0.25f;
|
// 0.25f;
|
||||||
|
// dx %= center;
|
||||||
|
// dy %= center;
|
||||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
|
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
|
||||||
} else if (diff > 0) {
|
} else if (diff > 0) {
|
||||||
// tile zoom level is child of current
|
// tile zoom level is child of current
|
||||||
@ -392,6 +436,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
dx = ((t.pixelX + h) >> (diff >> 1)) - x;
|
dx = ((t.pixelX + h) >> (diff >> 1)) - x;
|
||||||
dy = ((t.pixelY + h) >> (diff >> 1)) - y;
|
dy = ((t.pixelY + h) >> (diff >> 1)) - y;
|
||||||
}
|
}
|
||||||
|
// dx %= center;
|
||||||
|
// dy %= center;
|
||||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
|
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy));
|
||||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy));
|
t.distance = FloatMath.sqrt((dx * dx + dy * dy));
|
||||||
|
|
||||||
@ -399,7 +445,8 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
// tile zoom level is parent of current
|
// tile zoom level is parent of current
|
||||||
dx = ((t.pixelX + h) << -diff) - x;
|
dx = ((t.pixelX + h) << -diff) - x;
|
||||||
dy = ((t.pixelY + h) << -diff) - y;
|
dy = ((t.pixelY + h) << -diff) - y;
|
||||||
|
// dx %= center;
|
||||||
|
// dy %= center;
|
||||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
||||||
// (-diff * 0.5f);
|
// (-diff * 0.5f);
|
||||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
|
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * (-diff * 0.5f);
|
||||||
@ -410,14 +457,13 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
private static void limitCache(MapPosition mapPosition, int remove) {
|
private static void limitCache(MapPosition mapPosition, int remove) {
|
||||||
int size = mTiles.size();
|
int size = mTiles.size();
|
||||||
|
|
||||||
// remove orphaned tiles
|
// remove tiles that were never loaded
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile t = mTiles.get(i);
|
MapTile t = mTiles.get(i);
|
||||||
// make sure tile cannot be used by GL or MapWorker Thread
|
// make sure tile cannot be used by GL or MapWorker Thread
|
||||||
if (t.isLocked() || t.isActive()) {
|
if (t.isLocked() || t.isActive()) {
|
||||||
i++;
|
i++;
|
||||||
} else {
|
} else {
|
||||||
// Log.d(TAG, "remove empty tile" + t);
|
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
mTiles.remove(i);
|
mTiles.remove(i);
|
||||||
remove--;
|
remove--;
|
||||||
@ -432,26 +478,25 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
Collections.sort(mTiles);
|
Collections.sort(mTiles);
|
||||||
|
|
||||||
for (int i = 1; i < remove; i++) {
|
for (int i = 1; i < remove; i++) {
|
||||||
|
|
||||||
MapTile t = mTiles.remove(size - i);
|
MapTile t = mTiles.remove(size - i);
|
||||||
|
|
||||||
synchronized (t) {
|
|
||||||
if (t.isLocked()) {
|
if (t.isLocked()) {
|
||||||
// dont remove tile used by renderthread
|
// dont remove tile used by GLRenderer
|
||||||
Log.d(TAG, "X not removing " + t
|
Log.d(TAG, "X not removing " + t + " " + t.distance);
|
||||||
// + " " + t.isLocked
|
|
||||||
+ " " + t.distance);
|
|
||||||
|
|
||||||
mTiles.add(t);
|
mTiles.add(t);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.isLoading) {
|
if (t.isLoading) {
|
||||||
// NOTE: if we add tile back then on next limitCache
|
// NOTE: if we add tile back and set loading=false, on next
|
||||||
// the tile will be removed. clearTile could interfere with
|
// limitCache the tile will be removed. clearTile could
|
||||||
// MapGenerator. so clear in passTile() instead.
|
// interfere with TileGenerator. so clear in passTile()
|
||||||
// mTiles.add(t);
|
// instead.
|
||||||
t.isLoading = false;
|
// ... no, this does not work either: when set loading to
|
||||||
|
// false tile could be added to load queue while still
|
||||||
|
// processed in TileGenerator => need tile.cancel flag.
|
||||||
|
// t.isLoading = false;
|
||||||
|
mTiles.add(t);
|
||||||
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -459,7 +504,6 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
clearTile(t);
|
clearTile(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static void limitLoadQueue() {
|
private static void limitLoadQueue() {
|
||||||
int size = mTilesLoaded.size();
|
int size = mTilesLoaded.size();
|
||||||
@ -469,11 +513,11 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
synchronized (mTilesLoaded) {
|
synchronized (mTilesLoaded) {
|
||||||
|
|
||||||
// remove tiles uploaded to vbo
|
// remove tiles already uploaded to vbo
|
||||||
for (int i = 0; i < size;) {
|
for (int i = 0; i < size;) {
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
// rel == null means tile is already removed by limitCache
|
|
||||||
if (!t.newData || t.rel == null) {
|
if (!t.newData) {
|
||||||
mTilesLoaded.remove(i);
|
mTilesLoaded.remove(i);
|
||||||
size--;
|
size--;
|
||||||
continue;
|
continue;
|
||||||
@ -484,20 +528,11 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
if (size < MAX_TILES_IN_QUEUE)
|
if (size < MAX_TILES_IN_QUEUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Log.d(TAG, "queue: " + mTilesLoaded.size() + " " + size + " "
|
|
||||||
// + (size - MAX_TILES_IN_QUEUE / 2));
|
|
||||||
|
|
||||||
// clear loaded but not used tiles
|
// clear loaded but not used tiles
|
||||||
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
||||||
|
|
||||||
MapTile t = mTilesLoaded.get(i);
|
MapTile t = mTilesLoaded.get(i);
|
||||||
|
|
||||||
synchronized (t) {
|
|
||||||
if (t.rel == null) {
|
|
||||||
mTilesLoaded.remove(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t.isLocked()) {
|
if (t.isLocked()) {
|
||||||
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
||||||
// t.isActive);
|
// t.isActive);
|
||||||
@ -512,7 +547,6 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called from MapWorker Thread when tile is loaded by TileGenerator
|
* called from MapWorker Thread when tile is loaded by TileGenerator
|
||||||
@ -534,7 +568,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRenderer.setVBO(tile);
|
tile.vbo = BufferObject.get();
|
||||||
|
|
||||||
if (tile.vbo == null) {
|
if (tile.vbo == null) {
|
||||||
Log.d(TAG, "no VBOs left for " + tile);
|
Log.d(TAG, "no VBOs left for " + tile);
|
||||||
@ -573,79 +607,4 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh);
|
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);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
@ -12,9 +12,10 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import org.oscim.view.generator.JobTile;
|
import org.oscim.generator.JobTile;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
|
|
||||||
class MapTile extends JobTile {
|
class MapTile extends JobTile {
|
||||||
|
|
||||||
@ -22,26 +23,15 @@ class MapTile extends JobTile {
|
|||||||
* VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m
|
* VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m
|
||||||
* bytes lines vertices
|
* bytes lines vertices
|
||||||
*/
|
*/
|
||||||
VertexBufferObject vbo;
|
BufferObject vbo;
|
||||||
|
|
||||||
/**
|
|
||||||
* polygonOffset in vbo is always 16 bytes,
|
|
||||||
*/
|
|
||||||
int lineOffset;
|
|
||||||
|
|
||||||
TextTexture texture;
|
TextTexture texture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tile data set by TileGenerator:
|
* Tile data set by TileGenerator:
|
||||||
*/
|
*/
|
||||||
LineLayer lineLayers;
|
|
||||||
PolygonLayer polygonLayers;
|
|
||||||
TextItem labels;
|
TextItem labels;
|
||||||
|
Layers layers;
|
||||||
/**
|
|
||||||
* tile is used by render thread. set by updateVisibleList (main thread).
|
|
||||||
*/
|
|
||||||
// boolean isLocked;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tile has new data to upload to gl
|
* tile has new data to upload to gl
|
||||||
@ -59,7 +49,7 @@ class MapTile extends JobTile {
|
|||||||
boolean isVisible;
|
boolean isVisible;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pointer to access relatives in TileTree
|
* pointer to access relatives in QuadTree
|
||||||
*/
|
*/
|
||||||
QuadTree rel;
|
QuadTree rel;
|
||||||
|
|
||||||
@ -74,12 +64,16 @@ class MapTile extends JobTile {
|
|||||||
|
|
||||||
// counting the tiles that use this tile as proxy
|
// counting the tiles that use this tile as proxy
|
||||||
byte refs;
|
byte refs;
|
||||||
|
|
||||||
byte locked;
|
byte locked;
|
||||||
|
|
||||||
// this tile sits in fo another tile. e.g. x:-1,y:0,z:1 for x:1,y:0
|
// used when this tile sits in fo another tile.
|
||||||
|
// e.g. x:-1,y:0,z:1 for x:1,y:0
|
||||||
MapTile holder;
|
MapTile holder;
|
||||||
|
|
||||||
|
MapTile(int tileX, int tileY, byte zoomLevel) {
|
||||||
|
super(tileX, tileY, zoomLevel);
|
||||||
|
}
|
||||||
|
|
||||||
boolean isActive() {
|
boolean isActive() {
|
||||||
return isLoading || newData || isReady;
|
return isLoading || newData || isReady;
|
||||||
}
|
}
|
||||||
@ -146,9 +140,4 @@ class MapTile extends JobTile {
|
|||||||
}
|
}
|
||||||
proxies = 0;
|
proxies = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapTile(int tileX, int tileY, byte zoomLevel) {
|
|
||||||
super(tileX, tileY, zoomLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
190
src/org/oscim/renderer/Overlay.java
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.renderer.layer.SymbolItem;
|
||||||
|
import org.oscim.renderer.layer.SymbolLayer;
|
||||||
|
import org.oscim.theme.renderinstruction.BitmapUtils;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint.Cap;
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
import android.opengl.Matrix;
|
||||||
|
|
||||||
|
public class Overlay {
|
||||||
|
|
||||||
|
BufferObject vbo;
|
||||||
|
Layers layers;
|
||||||
|
TextItem labels;
|
||||||
|
TextTexture texture;
|
||||||
|
// flag to set when data is ready for (re)compilation.
|
||||||
|
boolean newData;
|
||||||
|
boolean isReady;
|
||||||
|
MapPosition mMapPosition;
|
||||||
|
|
||||||
|
float drawScale;
|
||||||
|
|
||||||
|
private boolean first = true;
|
||||||
|
|
||||||
|
Overlay() {
|
||||||
|
mMapPosition = new MapPosition();
|
||||||
|
|
||||||
|
layers = new Layers();
|
||||||
|
|
||||||
|
LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||||
|
ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||||
|
ll.width = 2;
|
||||||
|
float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100,
|
||||||
|
-100 };
|
||||||
|
short[] index = { (short) points.length };
|
||||||
|
ll.addLine(points, index, false);
|
||||||
|
//
|
||||||
|
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
||||||
|
// pl.area = new Area(Color.argb(128, 255, 0, 0));
|
||||||
|
//
|
||||||
|
// float[] ppoints = {
|
||||||
|
// 0, 256,
|
||||||
|
// 0, 0,
|
||||||
|
// 256, 0,
|
||||||
|
// 256, 256,
|
||||||
|
// };
|
||||||
|
// short[] pindex = { (short) ppoints.length };
|
||||||
|
// pl.addPolygon(ppoints, pindex);
|
||||||
|
|
||||||
|
SymbolLayer sl = new SymbolLayer();
|
||||||
|
SymbolItem it = new SymbolItem();
|
||||||
|
|
||||||
|
it.x = 0;
|
||||||
|
it.y = 0;
|
||||||
|
// billboard always faces camera
|
||||||
|
it.billboard = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
sl.addSymbol(it);
|
||||||
|
|
||||||
|
SymbolItem it2 = new SymbolItem();
|
||||||
|
it2.bitmap = it.bitmap;
|
||||||
|
it2.x = 0;
|
||||||
|
it2.y = 0;
|
||||||
|
// billboard always faces camera
|
||||||
|
it2.billboard = false;
|
||||||
|
|
||||||
|
sl.addSymbol(it2);
|
||||||
|
|
||||||
|
layers.symbolLayers = sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized boolean onTouch() {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /////////////// called from GLRender Thread ////////////////////////
|
||||||
|
// use synchronized (this){} when updating 'layers' from another thread
|
||||||
|
|
||||||
|
synchronized void update(MapView mapView) {
|
||||||
|
// keep position constant (or update layer relative to new position)
|
||||||
|
// mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
// fix at initial position
|
||||||
|
mapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
// pass layers to be uploaded and drawn to GL Thread
|
||||||
|
// afterwards never modify 'layers' outside of this function!
|
||||||
|
newData = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] mvp = new float[16];
|
||||||
|
|
||||||
|
synchronized void render(MapPosition pos, float[] mv, float[] proj) {
|
||||||
|
float div = 1;
|
||||||
|
|
||||||
|
setMatrix(pos, mv);
|
||||||
|
|
||||||
|
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
|
||||||
|
|
||||||
|
for (Layer l = layers.layers; l != null;) {
|
||||||
|
if (l.type == Layer.POLYGON) {
|
||||||
|
GLES20.glDisable(GLES20.GL_BLEND);
|
||||||
|
l = PolygonRenderer.draw(pos, l, mvp, true, false);
|
||||||
|
} else {
|
||||||
|
GLES20.glEnable(GLES20.GL_BLEND);
|
||||||
|
l = LineRenderer.draw(pos, l, mvp, div, 0, layers.lineOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Layer l = layers.symbolLayers; l != null;) {
|
||||||
|
l = TextureRenderer.draw(l, 1, proj, mv, layers.symbolOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMatrix(MapPosition mPos, float[] matrix) {
|
||||||
|
|
||||||
|
MapPosition oPos = mMapPosition;
|
||||||
|
float div = 1;
|
||||||
|
byte z = oPos.zoomLevel;
|
||||||
|
int diff = mPos.zoomLevel - z;
|
||||||
|
|
||||||
|
if (diff < 0)
|
||||||
|
div = (1 << -diff);
|
||||||
|
else if (diff > 0)
|
||||||
|
div = (1.0f / (1 << diff));
|
||||||
|
|
||||||
|
float x = (float) (oPos.x - mPos.x * div);
|
||||||
|
float y = (float) (oPos.y - mPos.y * div);
|
||||||
|
|
||||||
|
// flip around date-line
|
||||||
|
float max = (Tile.TILE_SIZE << z);
|
||||||
|
if (x < -max / 2)
|
||||||
|
x = max + x;
|
||||||
|
else if (x > max / 2)
|
||||||
|
x = x - max;
|
||||||
|
|
||||||
|
float scale = mPos.scale / div;
|
||||||
|
|
||||||
|
Matrix.setIdentityM(matrix, 0);
|
||||||
|
|
||||||
|
// translate relative to map center
|
||||||
|
matrix[12] = x * scale;
|
||||||
|
matrix[13] = y * scale;
|
||||||
|
|
||||||
|
scale = (mPos.scale / oPos.scale) / div;
|
||||||
|
// scale to tile to world coordinates
|
||||||
|
scale /= GLRenderer.COORD_MULTIPLIER;
|
||||||
|
matrix[0] = scale;
|
||||||
|
matrix[5] = scale;
|
||||||
|
|
||||||
|
Matrix.multiplyMM(matrix, 0, mPos.viewMatrix, 0, matrix, 0);
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import static android.opengl.GLES20.GL_BLEND;
|
import static android.opengl.GLES20.GL_BLEND;
|
||||||
import static android.opengl.GLES20.GL_EQUAL;
|
import static android.opengl.GLES20.GL_EQUAL;
|
||||||
@ -38,17 +38,18 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.ShortBuffer;
|
|
||||||
|
|
||||||
|
import org.oscim.core.MapPosition;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.PolygonLayer;
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
import org.oscim.view.MapPosition;
|
|
||||||
|
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
|
|
||||||
class PolygonRenderer {
|
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 NUM_VERTEX_SHORTS = 2;
|
||||||
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
|
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
|
||||||
private static final int STENCIL_BITS = 8;
|
private static final int STENCIL_BITS = 8;
|
||||||
|
|
||||||
@ -88,9 +89,6 @@ class PolygonRenderer {
|
|||||||
/* do not modify stencil buffer */
|
/* do not modify stencil buffer */
|
||||||
glStencilMask(0);
|
glStencilMask(0);
|
||||||
|
|
||||||
/* only draw where nothing was drawn yet */
|
|
||||||
glEnable(GLES20.GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
for (int c = mStart; c < mCount; c++) {
|
for (int c = mStart; c < mCount; c++) {
|
||||||
PolygonLayer l = mFillPolys[c];
|
PolygonLayer l = mFillPolys[c];
|
||||||
|
|
||||||
@ -162,14 +160,25 @@ class PolygonRenderer {
|
|||||||
// stencil buffer index to start fill
|
// stencil buffer index to start fill
|
||||||
private static int mStart;
|
private static int mStart;
|
||||||
|
|
||||||
static PolygonLayer drawPolygons(MapPosition pos, PolygonLayer layer, int next,
|
static Layer draw(MapPosition pos, Layer layer,
|
||||||
float[] matrix, boolean first) {
|
float[] matrix, boolean first, boolean clip) {
|
||||||
|
|
||||||
int zoom = pos.zoomLevel;
|
int zoom = pos.zoomLevel;
|
||||||
float scale = pos.scale;
|
float scale = pos.scale;
|
||||||
|
|
||||||
glUseProgram(polygonProgram);
|
glUseProgram(polygonProgram);
|
||||||
GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
|
|
||||||
|
int va = hPolygonVertexPosition;
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
va = va == 0 ? 1 : 0;
|
||||||
|
if (GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glDisableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = false;
|
||||||
|
}
|
||||||
|
// GLES20.glEnableVertexAttribArray(hPolygonVertexPosition);
|
||||||
|
|
||||||
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_SHORT,
|
glVertexAttribPointer(hPolygonVertexPosition, 2, GLES20.GL_SHORT,
|
||||||
false, 0, POLYGON_VERTICES_DATA_POS_OFFSET);
|
false, 0, POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||||
@ -179,8 +188,6 @@ class PolygonRenderer {
|
|||||||
// use stencilbuffer method for polygon drawing
|
// use stencilbuffer method for polygon drawing
|
||||||
glEnable(GL_STENCIL_TEST);
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
PolygonLayer l = layer;
|
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
mCount = 0;
|
mCount = 0;
|
||||||
mStart = 0;
|
mStart = 0;
|
||||||
@ -188,12 +195,15 @@ class PolygonRenderer {
|
|||||||
mStart = mCount;
|
mStart = mCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; l != null && l.layer < next; l = l.next) {
|
Layer l = layer;
|
||||||
|
|
||||||
|
for (; l != null && l.type == Layer.POLYGON; l = l.next) {
|
||||||
|
PolygonLayer pl = (PolygonLayer) l;
|
||||||
// fade out polygon layers (set in RederTheme)
|
// fade out polygon layers (set in RederTheme)
|
||||||
if (l.area.fade > 0 && l.area.fade > zoom)
|
if (pl.area.fade > 0 && pl.area.fade > zoom)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mCount == 0) {
|
if (mCount == mStart) {
|
||||||
// clear stencilbuffer (tile region)
|
// clear stencilbuffer (tile region)
|
||||||
|
|
||||||
// disable drawing to framebuffer
|
// disable drawing to framebuffer
|
||||||
@ -205,7 +215,7 @@ class PolygonRenderer {
|
|||||||
|
|
||||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||||
|
|
||||||
if (first) {
|
if (clip) {
|
||||||
// draw clip-region into depth buffer:
|
// draw clip-region into depth buffer:
|
||||||
// this is used for lines and polygons
|
// this is used for lines and polygons
|
||||||
|
|
||||||
@ -214,14 +224,15 @@ class PolygonRenderer {
|
|||||||
|
|
||||||
// to prevent overdraw gl_less restricts
|
// to prevent overdraw gl_less restricts
|
||||||
// the clip to the area where no other
|
// the clip to the area where no other
|
||||||
// tile was drawn
|
// tile has drawn
|
||||||
GLES20.glDepthFunc(GLES20.GL_LESS);
|
GLES20.glDepthFunc(GLES20.GL_LESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
if (first) {
|
if (clip) {
|
||||||
first = false;
|
first = false;
|
||||||
|
clip = false;
|
||||||
// dont modify depth buffer
|
// dont modify depth buffer
|
||||||
GLES20.glDepthMask(false);
|
GLES20.glDepthMask(false);
|
||||||
// only draw to this tile
|
// only draw to this tile
|
||||||
@ -232,23 +243,26 @@ class PolygonRenderer {
|
|||||||
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
||||||
|
|
||||||
// no need for depth test while drawing stencil
|
// no need for depth test while drawing stencil
|
||||||
|
if (clip)
|
||||||
glDisable(GLES20.GL_DEPTH_TEST);
|
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);
|
|
||||||
}
|
}
|
||||||
|
// 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
|
||||||
|
// if (clip)
|
||||||
|
// glDisable(GLES20.GL_DEPTH_TEST);
|
||||||
|
// }
|
||||||
|
|
||||||
mFillPolys[mCount] = l;
|
mFillPolys[mCount] = pl;
|
||||||
|
|
||||||
// set stencil mask to draw to
|
// set stencil mask to draw to
|
||||||
glStencilMask(1 << mCount++);
|
glStencilMask(1 << mCount++);
|
||||||
@ -257,15 +271,23 @@ class PolygonRenderer {
|
|||||||
|
|
||||||
// draw up to 8 layers into stencil buffer
|
// draw up to 8 layers into stencil buffer
|
||||||
if (mCount == STENCIL_BITS) {
|
if (mCount == STENCIL_BITS) {
|
||||||
|
/* only draw where nothing was drawn yet */
|
||||||
|
if (clip)
|
||||||
|
glEnable(GLES20.GL_DEPTH_TEST);
|
||||||
|
|
||||||
fillPolygons(zoom, scale);
|
fillPolygons(zoom, scale);
|
||||||
mCount = 0;
|
mCount = 0;
|
||||||
mStart = 0;
|
mStart = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCount > 0)
|
if (mCount > 0) {
|
||||||
fillPolygons(zoom, scale);
|
/* only draw where nothing was drawn yet */
|
||||||
|
if (clip)
|
||||||
|
glEnable(GLES20.GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
fillPolygons(zoom, scale);
|
||||||
|
}
|
||||||
// maybe reset start when only few layers left in stencil buffer
|
// maybe reset start when only few layers left in stencil buffer
|
||||||
// if (mCount > 5){
|
// if (mCount > 5){
|
||||||
// mCount = 0;
|
// mCount = 0;
|
||||||
@ -274,19 +296,20 @@ class PolygonRenderer {
|
|||||||
|
|
||||||
glDisable(GL_STENCIL_TEST);
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
|
||||||
if (first)
|
if (clip && first)
|
||||||
drawDepthClip();
|
drawDepthClip();
|
||||||
|
|
||||||
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
// GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
|
private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
|
||||||
|
private static float[] debugFillColor2 = { 0.0f, 0.3f, 0.0f, 0.3f };
|
||||||
|
|
||||||
private static ByteBuffer mDebugFill;
|
private static ByteBuffer mDebugFill;
|
||||||
|
|
||||||
static void debugDraw(float[] matrix, float[] coords) {
|
static void debugDraw(float[] matrix, float[] coords, int color) {
|
||||||
|
|
||||||
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
|
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
|
||||||
FloatBuffer buf = mDebugFill.asFloatBuffer();
|
FloatBuffer buf = mDebugFill.asFloatBuffer();
|
||||||
@ -303,12 +326,15 @@ class PolygonRenderer {
|
|||||||
|
|
||||||
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
|
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
|
||||||
|
|
||||||
|
if (color == 0)
|
||||||
glUniform4fv(hPolygonColor, 1, debugFillColor, 0);
|
glUniform4fv(hPolygonColor, 1, debugFillColor, 0);
|
||||||
|
else
|
||||||
|
glUniform4fv(hPolygonColor, 1, debugFillColor2, 0);
|
||||||
|
|
||||||
glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
GlUtils.checkGlError("draw debug");
|
GlUtils.checkGlError("draw debug");
|
||||||
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
// GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawDepthClip() {
|
static void drawDepthClip() {
|
||||||
@ -322,55 +348,4 @@ class PolygonRenderer {
|
|||||||
glColorMask(true, true, true, true);
|
glColorMask(true, true, true, true);
|
||||||
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sizeOf(PolygonLayer layers) {
|
|
||||||
int size = 0;
|
|
||||||
|
|
||||||
for (PolygonLayer l = layers; l != null; l = l.next)
|
|
||||||
size += l.verticesCnt;
|
|
||||||
|
|
||||||
size *= NUM_VERTEX_SHORTS;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void compileLayerData(PolygonLayer layers, ShortBuffer sbuf) {
|
|
||||||
int pos = 4;
|
|
||||||
|
|
||||||
VertexPoolItem last = null, items = null;
|
|
||||||
|
|
||||||
for (PolygonLayer l = layers; l != null; l = l.next) {
|
|
||||||
|
|
||||||
for (VertexPoolItem item = l.pool; item != null; item = item.next) {
|
|
||||||
|
|
||||||
if (item.next == null) {
|
|
||||||
sbuf.put(item.vertices, 0, item.used);
|
|
||||||
} else {
|
|
||||||
// item.used = VertexPoolItem.SIZE;
|
|
||||||
sbuf.put(item.vertices);
|
|
||||||
}
|
|
||||||
|
|
||||||
last = item;
|
|
||||||
}
|
|
||||||
|
|
||||||
l.offset = pos;
|
|
||||||
pos += l.verticesCnt;
|
|
||||||
|
|
||||||
if (last != null) {
|
|
||||||
last.next = items;
|
|
||||||
items = l.pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
l.pool = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexPool.add(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear(PolygonLayer layers) {
|
|
||||||
for (PolygonLayer l = layers; l != null; l = l.next) {
|
|
||||||
if (l.pool != null)
|
|
||||||
VertexPool.add(l.pool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -37,17 +37,9 @@ class QuadTree {
|
|||||||
MapTile tile;
|
MapTile tile;
|
||||||
|
|
||||||
static void init() {
|
static void init() {
|
||||||
|
|
||||||
pool = null;
|
pool = null;
|
||||||
root = new QuadTree();
|
root = new QuadTree();
|
||||||
root.parent = root;
|
root.parent = root;
|
||||||
|
|
||||||
// QuadTree t;
|
|
||||||
// for (int i = 0; i < 200; i++) {
|
|
||||||
// t = new QuadTree();
|
|
||||||
// t.parent = pool;
|
|
||||||
// pool = t;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean remove(MapTile t) {
|
static boolean remove(MapTile t) {
|
||||||
@ -90,8 +82,6 @@ class QuadTree {
|
|||||||
int y = tile.tileY;
|
int y = tile.tileY;
|
||||||
int z = tile.zoomLevel;
|
int z = tile.zoomLevel;
|
||||||
|
|
||||||
QuadTree cur;
|
|
||||||
|
|
||||||
// if (x < 0 || x >= 1 << z) {
|
// if (x < 0 || x >= 1 << z) {
|
||||||
// Log.d(TAG, "invalid position");
|
// Log.d(TAG, "invalid position");
|
||||||
// return null;
|
// return null;
|
||||||
@ -109,7 +99,7 @@ class QuadTree {
|
|||||||
|
|
||||||
leaf.refs++;
|
leaf.refs++;
|
||||||
|
|
||||||
cur = leaf.child[id];
|
QuadTree cur = leaf.child[id];
|
||||||
|
|
||||||
if (cur != null) {
|
if (cur != null) {
|
||||||
leaf = cur;
|
leaf = cur;
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
/* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen Design */
|
/* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen Design */
|
||||||
|
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -103,6 +103,7 @@ public abstract class ScanBox {
|
|||||||
scanSpans(ca, bc);
|
scanSpans(ca, bc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME
|
||||||
private static final int MAX_SLOPE = 4;
|
private static final int MAX_SLOPE = 4;
|
||||||
|
|
||||||
private void scanSpans(Edge e0, Edge e1) {
|
private void scanSpans(Edge e0, Edge e1) {
|
@ -13,9 +13,9 @@
|
|||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
class Shaders {
|
public final class Shaders {
|
||||||
|
|
||||||
final static String lineVertexShader = ""
|
final static String lineVertexShader = ""
|
||||||
+ "precision mediump float;"
|
+ "precision mediump float;"
|
||||||
@ -54,40 +54,119 @@ class Shaders {
|
|||||||
+ "precision mediump float;"
|
+ "precision mediump float;"
|
||||||
+ "uniform float u_wscale;"
|
+ "uniform float u_wscale;"
|
||||||
+ "uniform float u_width;"
|
+ "uniform float u_width;"
|
||||||
|
+ "uniform int u_mode;"
|
||||||
+ "uniform vec4 u_color;"
|
+ "uniform vec4 u_color;"
|
||||||
+ "varying vec2 v_st;"
|
+ "varying vec2 v_st;"
|
||||||
+ "const float zero = 0.0;"
|
+ "const float zero = 0.0;"
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
+ " float len;"
|
+ " float len;"
|
||||||
+ " if (v_st.t == zero)"
|
+ " if (u_mode == 0)"
|
||||||
+ " len = abs(v_st.s);"
|
+ " len = u_width - abs(v_st.s);"
|
||||||
+ " else "
|
+ " else "
|
||||||
+ " len = length(v_st);"
|
+ " len = u_width - length(v_st);"
|
||||||
// fade to alpha. u_wscale is the width in pixel which should be
|
// fade to alpha. u_wscale is the width in pixel which should be
|
||||||
// faded, u_width - len the position of this fragment on the
|
// faded, u_width - len the position of this fragment on the
|
||||||
// perpendicular to this line segment
|
// perpendicular to this line segment
|
||||||
+ " gl_FragColor = smoothstep(zero, u_wscale, u_width - len) * u_color;"
|
+ " vec4 color = u_color;"
|
||||||
|
+ " if (len < u_wscale)"
|
||||||
|
+ " color *= len / u_wscale;"
|
||||||
|
+ " gl_FragColor = color;"
|
||||||
|
// smoothstep(zero, u_wscale, u_width - len) * u_color;"
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
|
// final static String lineFragmentShader = ""
|
||||||
|
// + "#extension GL_OES_standard_derivatives : enable\n"
|
||||||
|
// + "precision mediump float;\n"
|
||||||
|
// + "uniform float u_wscale;"
|
||||||
|
// + "uniform float u_width;"
|
||||||
|
// + "uniform vec4 u_color;"
|
||||||
|
// + "varying vec2 v_st;"
|
||||||
|
// + "const float zero = 0.0;"
|
||||||
|
// + "const vec4 col1 = vec4(0.5,0.0,0.0,0.5);"
|
||||||
|
// + "const vec4 col2 = vec4(0.0,0.0,0.5,0.5);"
|
||||||
|
// + "void main() {"
|
||||||
|
// + " vec4 color = u_color;"
|
||||||
|
// + " float width = u_width;"
|
||||||
|
// + " float len;"
|
||||||
|
// + " if (v_st.t == zero)"
|
||||||
|
// + " len = abs(v_st.s);"
|
||||||
|
// + " else "
|
||||||
|
// + " len = length(v_st);"
|
||||||
|
// + " vec2 st_width = fwidth(v_st);"
|
||||||
|
// + " float fuzz = max(st_width.s, st_width.t);"
|
||||||
|
// // + " if (v_st.s > 0.0){"
|
||||||
|
// // + " color = col1;"
|
||||||
|
// + " color *= (1.0 - len) / (fuzz + u_wscale);"
|
||||||
|
// // + " }else{"
|
||||||
|
// // + " color = col2;"
|
||||||
|
// // + " color *= 1.0 - (fuzz + u_wscale) / (len - 1.0);"
|
||||||
|
// // + " }"
|
||||||
|
// + " gl_FragColor = color;"
|
||||||
|
// + "}";
|
||||||
|
|
||||||
|
// final static String lineFragmentShader = ""
|
||||||
|
// + "#extension GL_OES_standard_derivatives : enable\n"
|
||||||
|
// + "precision mediump float;\n"
|
||||||
|
// + "uniform float u_wscale;"
|
||||||
|
// + "uniform float u_width;"
|
||||||
|
// + "uniform vec4 u_color;"
|
||||||
|
// + "varying vec2 v_st;"
|
||||||
|
// + "const float zero = 0.0;"
|
||||||
|
// + "const vec4 col1 = vec4(0.5,0.0,0.0,0.5);"
|
||||||
|
// + "const vec4 col2 = vec4(0.0,0.0,0.5,0.5);"
|
||||||
|
// + "void main() {"
|
||||||
|
// + " vec4 color = u_color;"
|
||||||
|
// + " float width = u_width;"
|
||||||
|
// + " float len;"
|
||||||
|
// + " if (v_st.t == zero)"
|
||||||
|
// + " len = abs(v_st.s);"
|
||||||
|
// + " else "
|
||||||
|
// + " len = length(v_st);"
|
||||||
|
// + " vec2 st_width = fwidth(v_st);"
|
||||||
|
// + " float fuzz = max(st_width.s, st_width.t);"
|
||||||
|
// + " if (u_width > 1.0) fuzz *= 1.2;"
|
||||||
|
// + " color *= (u_width - len) / (fuzz + u_wscale);"
|
||||||
|
// + " if (v_st.s > 0.0){"
|
||||||
|
// + " if (u_width - len < fuzz + u_wscale)"
|
||||||
|
// + " color = col1 * (u_width - len) / (fuzz + u_wscale);"
|
||||||
|
// + " }else{"
|
||||||
|
// + " if (u_width - len < fuzz + u_wscale)"
|
||||||
|
// + " color = col2 * (u_width - len) / (fuzz + u_wscale);"
|
||||||
|
// + "}"
|
||||||
|
// // + " color *= (fuzz + u_wscale);"
|
||||||
|
// // " color *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
|
||||||
|
// + " gl_FragColor = color;"
|
||||||
|
// + "}";
|
||||||
|
|
||||||
final static String lineFragmentShader = ""
|
final static String lineFragmentShader = ""
|
||||||
+ "#extension GL_OES_standard_derivatives : enable\n"
|
+ "#extension GL_OES_standard_derivatives : enable\n"
|
||||||
+ "precision mediump float;\n"
|
+ "precision mediump float;\n"
|
||||||
+ "uniform float u_wscale;"
|
+ "uniform float u_wscale;"
|
||||||
+ "uniform float u_width;"
|
+ "uniform float u_width;"
|
||||||
|
+ "uniform int u_mode;"
|
||||||
+ "uniform vec4 u_color;"
|
+ "uniform vec4 u_color;"
|
||||||
+ "varying vec2 v_st;"
|
+ "varying vec2 v_st;"
|
||||||
|
// + "const vec4 col1 = vec4(0.5,0.0,0.0,0.5);"
|
||||||
|
// + "const vec4 col2 = vec4(0.0,0.0,0.5,0.5);"
|
||||||
+ "const float zero = 0.0;"
|
+ "const float zero = 0.0;"
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
+ " vec4 color = u_color;"
|
+ " vec4 color = u_color;"
|
||||||
+ " float width = u_width;"
|
+ " float width = u_width;"
|
||||||
+ " float len;"
|
+ " float len;"
|
||||||
+ " if (v_st.t == zero)"
|
+ " if (u_mode == 0)"
|
||||||
+ " len = abs(v_st.s);"
|
+ " len = u_width - abs(v_st.s);"
|
||||||
+ " else "
|
+ " else "
|
||||||
+ " len = length(v_st);"
|
+ " len = u_width - length(v_st);"
|
||||||
+ " vec2 st_width = fwidth(v_st);"
|
+ " vec2 st_width = fwidth(v_st);"
|
||||||
+ " float fuzz = max(st_width.s, st_width.t) * 1.5;"
|
+ " float fuzz = max(st_width.s, st_width.t);"
|
||||||
+ " color *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
|
// + " if (u_width > 1.0) fuzz *= 1.2;"
|
||||||
|
+ " fuzz += u_wscale;"
|
||||||
|
+ " if (len < fuzz){"
|
||||||
|
// + " if (v_st.s > zero)"
|
||||||
|
+ " color *= len / fuzz;"
|
||||||
|
// + " else"
|
||||||
|
// + " color = col2 * (u_width - len) / fuzz;"
|
||||||
|
+ " }"
|
||||||
+ " gl_FragColor = color;"
|
+ " gl_FragColor = color;"
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
@ -113,17 +192,18 @@ class Shaders {
|
|||||||
+ "uniform mat4 u_mv;"
|
+ "uniform mat4 u_mv;"
|
||||||
+ "uniform mat4 u_proj;"
|
+ "uniform mat4 u_proj;"
|
||||||
+ "uniform float u_scale;"
|
+ "uniform float u_scale;"
|
||||||
|
+ "uniform float u_swidth;"
|
||||||
+ "varying vec2 tex_c;"
|
+ "varying vec2 tex_c;"
|
||||||
+ "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
+ "const vec2 div = vec2(1.0/2048.0,1.0/2048.0);"
|
||||||
+ "const float coord_scale = 0.125;"
|
+ "const float coord_scale = 0.125;"
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
+ " vec4 pos;"
|
+ " vec4 pos;"
|
||||||
+ " if (mod(vertex.x, 2.0) == 0.0){"
|
+ " if (mod(vertex.x, 2.0) == 0.0){"
|
||||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + vertex.zw * u_scale, 0.0, 1.0));"
|
+ " pos = u_proj * (u_mv * vec4(vertex.xy + vertex.zw * u_scale, 0.0, 1.0));"
|
||||||
+ " } else {"
|
+ " } else {"
|
||||||
// place as billboard
|
// // place as billboard
|
||||||
+ " vec4 dir = u_mv * vec4(vertex.xy, 0.0, 1.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));"
|
+ " pos = u_proj * (dir + vec4(vertex.zw * (coord_scale * u_swidth), 0.0, 0.0));"
|
||||||
+ " }"
|
+ " }"
|
||||||
+ " gl_Position = pos;"
|
+ " gl_Position = pos;"
|
||||||
+ " tex_c = tex_coord * div;"
|
+ " tex_c = tex_coord * div;"
|
||||||
@ -134,7 +214,7 @@ class Shaders {
|
|||||||
// + "attribute vec4 vertex;"
|
// + "attribute vec4 vertex;"
|
||||||
// + "attribute vec2 tex_coord;"
|
// + "attribute vec2 tex_coord;"
|
||||||
// + "uniform mat4 mvp;"
|
// + "uniform mat4 mvp;"
|
||||||
// + "uniform mat4 rotation;"
|
// + "uniform mat4 viewMatrix;"
|
||||||
// + "uniform float scale;"
|
// + "uniform float scale;"
|
||||||
// + "varying vec2 tex_c;"
|
// + "varying vec2 tex_c;"
|
||||||
// + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
// + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
||||||
@ -143,7 +223,7 @@ class Shaders {
|
|||||||
// + " if (mod(vertex.x, 2.0) == 0.0){"
|
// + " if (mod(vertex.x, 2.0) == 0.0){"
|
||||||
// + " pos = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
|
// + " pos = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
|
||||||
// + " } else {"
|
// + " } else {"
|
||||||
// + " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
|
// + " vec4 dir = viewMatrix * vec4(vertex.zw / scale, 0.0, 1.0);"
|
||||||
// + " pos = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
|
// + " pos = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
|
||||||
// + " }"
|
// + " }"
|
||||||
// + " pos.z = 0.0;"
|
// + " pos.z = 0.0;"
|
||||||
@ -156,7 +236,7 @@ class Shaders {
|
|||||||
// + "attribute vec4 vertex;"
|
// + "attribute vec4 vertex;"
|
||||||
// + "attribute vec2 tex_coord;"
|
// + "attribute vec2 tex_coord;"
|
||||||
// + "uniform mat4 mvp;"
|
// + "uniform mat4 mvp;"
|
||||||
// + "uniform mat4 rotation;"
|
// + "uniform mat4 viewMatrix;"
|
||||||
// + "uniform float scale;"
|
// + "uniform float scale;"
|
||||||
// + "varying vec2 tex_c;"
|
// + "varying vec2 tex_c;"
|
||||||
// + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
// + "const vec2 div = vec2(1.0/4096.0,1.0/2048.0);"
|
||||||
@ -165,7 +245,7 @@ class Shaders {
|
|||||||
// +
|
// +
|
||||||
// " gl_Position = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
|
// " gl_Position = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
|
||||||
// + " } else {"
|
// + " } else {"
|
||||||
// + " vec4 dir = rotation * vec4(vertex.zw / scale, 0.0, 1.0);"
|
// + " vec4 dir = viewMatrix * vec4(vertex.zw / scale, 0.0, 1.0);"
|
||||||
// + " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
|
// + " gl_Position = mvp * vec4(vertex.xy + dir.xy, 0.0, 1.0);"
|
||||||
// + " }"
|
// + " }"
|
||||||
// + " tex_c = tex_coord * div;"
|
// + " tex_c = tex_coord * div;"
|
@ -12,37 +12,33 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
|
||||||
|
|
||||||
public class TextItem {
|
public class TextItem {
|
||||||
TextItem next;
|
TextItem next;
|
||||||
|
|
||||||
final float x, y;
|
final float x, y;
|
||||||
final String text;
|
final String string;
|
||||||
final Caption caption;
|
final Text text;
|
||||||
final PathText path;
|
|
||||||
final float width;
|
final float width;
|
||||||
|
|
||||||
short x1, y1, x2, y2;
|
short x1, y1, x2, y2;
|
||||||
|
|
||||||
public TextItem(float x, float y, String text, Caption caption) {
|
public TextItem(float x, float y, String string, Text text) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
|
this.string = string;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.caption = caption;
|
this.width = text.paint.measureText(string);
|
||||||
this.width = caption.paint.measureText(text);
|
|
||||||
this.path = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextItem(float x, float y, String text, PathText pathText, float width) {
|
public TextItem(float x, float y, String string, Text text, float width) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
|
this.string = string;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.path = pathText;
|
|
||||||
this.caption = null;
|
|
||||||
this.width = width;
|
this.width = width;
|
||||||
}
|
}
|
||||||
|
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
@ -30,7 +30,9 @@ import android.util.FloatMath;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class TextRenderer {
|
public class TextRenderer {
|
||||||
private final static int TEXTURE_WIDTH = 512;
|
private static String TAG = "TextRenderer";
|
||||||
|
|
||||||
|
private final static int TEXTURE_WIDTH = 256;
|
||||||
private final static int TEXTURE_HEIGHT = 256;
|
private final static int TEXTURE_HEIGHT = 256;
|
||||||
private final static float SCALE = 8.0f;
|
private final static float SCALE = 8.0f;
|
||||||
private final static int LBIT_MASK = 0xfffffffe;
|
private final static int LBIT_MASK = 0xfffffffe;
|
||||||
@ -58,6 +60,7 @@ public class TextRenderer {
|
|||||||
private static int hTextProjectionMatrix;
|
private static int hTextProjectionMatrix;
|
||||||
private static int hTextVertex;
|
private static int hTextVertex;
|
||||||
private static int hTextScale;
|
private static int hTextScale;
|
||||||
|
private static int hTextScreenScale;
|
||||||
private static int hTextTextureCoord;
|
private static int hTextTextureCoord;
|
||||||
|
|
||||||
private static Paint mPaint = new Paint(Color.BLACK);
|
private static Paint mPaint = new Paint(Color.BLACK);
|
||||||
@ -86,6 +89,7 @@ public class TextRenderer {
|
|||||||
hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
||||||
hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
||||||
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
||||||
|
hTextScreenScale = GLES20.glGetUniformLocation(mTextProgram, "u_swidth");
|
||||||
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
||||||
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
||||||
|
|
||||||
@ -235,16 +239,10 @@ public class TextRenderer {
|
|||||||
|
|
||||||
TextItem t = tile.labels;
|
TextItem t = tile.labels;
|
||||||
float yy;
|
float yy;
|
||||||
short x1, x2, x3, x4, y1, y2, y3, y4;
|
|
||||||
|
|
||||||
for (int i = 0; t != null && i < max; t = t.next, i++) {
|
for (int i = 0; t != null && i < max; t = t.next, i++) {
|
||||||
|
|
||||||
if (t.caption != null) {
|
height = (int) (t.text.fontHeight) + 2 * mFontPadY;
|
||||||
height = (int) (t.caption.fontHeight) + 2 * mFontPadY;
|
|
||||||
} else {
|
|
||||||
height = (int) (t.path.fontHeight) + 2 * mFontPadY;
|
|
||||||
}
|
|
||||||
|
|
||||||
width = t.width + 2 * mFontPadX;
|
width = t.width + 2 * mFontPadX;
|
||||||
|
|
||||||
if (height > advanceY)
|
if (height > advanceY)
|
||||||
@ -256,35 +254,26 @@ public class TextRenderer {
|
|||||||
advanceY = (int) height;
|
advanceY = (int) height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.caption != null) {
|
yy = y + (height - 1) - t.text.fontDescent - mFontPadY;
|
||||||
yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
|
|
||||||
} else {
|
|
||||||
yy = y + (height - 1) - t.path.fontDescent - mFontPadY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (yy > TEXTURE_HEIGHT) {
|
if (yy > TEXTURE_HEIGHT) {
|
||||||
Log.d(TAG, "reached max labels");
|
Log.d(TAG, "reached max labels");
|
||||||
continue;
|
break;
|
||||||
|
// continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.caption != null) {
|
if (t.text.stroke != null)
|
||||||
if (t.caption.stroke != null)
|
mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.stroke);
|
||||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.caption.stroke);
|
|
||||||
|
|
||||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.caption.paint);
|
mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.paint);
|
||||||
} else {
|
|
||||||
if (t.path.stroke != null)
|
|
||||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.path.stroke);
|
|
||||||
|
|
||||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.path.paint);
|
|
||||||
}
|
|
||||||
if (width > TEXTURE_WIDTH)
|
if (width > TEXTURE_WIDTH)
|
||||||
width = TEXTURE_WIDTH;
|
width = TEXTURE_WIDTH;
|
||||||
|
|
||||||
float hw = width / 2.0f;
|
float hw = width / 2.0f;
|
||||||
float hh = height / 2.0f;
|
float hh = height / 2.0f;
|
||||||
|
short x1, x2, x3, x4, y1, y2, y3, y4;
|
||||||
|
|
||||||
if (t.caption != null) {
|
if (t.text.caption) {
|
||||||
x1 = x3 = (short) (SCALE * (-hw));
|
x1 = x3 = (short) (SCALE * (-hw));
|
||||||
y1 = y3 = (short) (SCALE * (hh));
|
y1 = y3 = (short) (SCALE * (hh));
|
||||||
x2 = x4 = (short) (SCALE * (hw));
|
x2 = x4 = (short) (SCALE * (hw));
|
||||||
@ -330,11 +319,8 @@ public class TextRenderer {
|
|||||||
short v2 = (short) (SCALE * (y + height));
|
short v2 = (short) (SCALE * (y + height));
|
||||||
|
|
||||||
// pack caption/way-text info in lowest bit
|
// pack caption/way-text info in lowest bit
|
||||||
short tx;
|
int tmp = (int) (SCALE * t.x) & LBIT_MASK;
|
||||||
if (t.caption == null)
|
short tx = (short) (tmp | (t.text.caption ? 1 : 0));
|
||||||
tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 0);
|
|
||||||
else
|
|
||||||
tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 1);
|
|
||||||
|
|
||||||
short ty = (short) (SCALE * t.y);
|
short ty = (short) (SCALE * t.y);
|
||||||
|
|
||||||
@ -393,8 +379,6 @@ public class TextRenderer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String TAG = "TextRenderer";
|
|
||||||
|
|
||||||
static void compileTextures() {
|
static void compileTextures() {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
TextTexture tex;
|
TextTexture tex;
|
||||||
@ -422,32 +406,34 @@ public class TextRenderer {
|
|||||||
static void beginDraw(float scale, float[] projection) {
|
static void beginDraw(float scale, float[] projection) {
|
||||||
GLES20.glUseProgram(mTextProgram);
|
GLES20.glUseProgram(mTextProgram);
|
||||||
|
|
||||||
GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
// GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
||||||
GLES20.glEnableVertexAttribArray(hTextVertex);
|
// GLES20.glEnableVertexAttribArray(hTextVertex);
|
||||||
|
|
||||||
|
int va = hTextTextureCoord;
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
va = hTextVertex;
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
GLES20.glUniform1f(hTextScale, scale);
|
GLES20.glUniform1f(hTextScale, scale);
|
||||||
|
GLES20.glUniform1f(hTextScreenScale, 1f / GLRenderer.mWidth);
|
||||||
GLES20.glUniformMatrix4fv(hTextProjectionMatrix, 1, false, projection, 0);
|
GLES20.glUniformMatrix4fv(hTextProjectionMatrix, 1, false, projection, 0);
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
|
||||||
mShortBuffer.clear();
|
|
||||||
mShortBuffer.put(debugVertices, 0, 16);
|
|
||||||
mShortBuffer.flip();
|
|
||||||
GLES20.glVertexAttribPointer(hTextVertex, 2,
|
|
||||||
GLES20.GL_SHORT, false, 8, mShortBuffer);
|
|
||||||
mShortBuffer.position(2);
|
|
||||||
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
|
|
||||||
GLES20.GL_SHORT, false, 8, mShortBuffer);
|
|
||||||
} else {
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void endDraw() {
|
static void endDraw() {
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
// GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
||||||
GLES20.glDisableVertexAttribArray(hTextVertex);
|
// GLES20.glDisableVertexAttribArray(hTextVertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawTile(MapTile tile, float[] matrix) {
|
static void drawTile(MapTile tile, float[] matrix) {
|
||||||
@ -456,10 +442,6 @@ public class TextRenderer {
|
|||||||
|
|
||||||
GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
GLES20.glVertexAttribPointer(hTextVertex, 4,
|
GLES20.glVertexAttribPointer(hTextVertex, 4,
|
||||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
||||||
|
|
||||||
@ -470,5 +452,4 @@ public class TextRenderer {
|
|||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
||||||
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
public class TextTexture {
|
public class TextTexture {
|
||||||
|
|
||||||
@ -22,12 +22,11 @@ public class TextTexture {
|
|||||||
int offset;
|
int offset;
|
||||||
MapTile tile;
|
MapTile tile;
|
||||||
|
|
||||||
String[] text;
|
|
||||||
|
|
||||||
TextTexture(int textureID) {
|
TextTexture(int textureID) {
|
||||||
vertices = new short[TextRenderer.MAX_LABELS *
|
vertices = new short[TextRenderer.MAX_LABELS *
|
||||||
TextRenderer.VERTICES_PER_SPRITE *
|
TextRenderer.VERTICES_PER_SPRITE *
|
||||||
TextRenderer.SHORTS_PER_VERTICE];
|
TextRenderer.SHORTS_PER_VERTICE];
|
||||||
|
|
||||||
id = textureID;
|
id = textureID;
|
||||||
}
|
}
|
||||||
|
|
97
src/org/oscim/renderer/TextureObject.java
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
import android.opengl.GLUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class TextureObject {
|
||||||
|
private static TextureObject pool;
|
||||||
|
|
||||||
|
public static synchronized TextureObject get() {
|
||||||
|
TextureObject to;
|
||||||
|
|
||||||
|
if (pool == null) {
|
||||||
|
init(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
to = pool;
|
||||||
|
pool = pool.next;
|
||||||
|
to.next = null;
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized void release(TextureObject to) {
|
||||||
|
to.next = pool;
|
||||||
|
pool = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void uploadTexture(TextureObject to, Bitmap bitmap,
|
||||||
|
int format, int type, int w, int h) {
|
||||||
|
|
||||||
|
if (to == null) {
|
||||||
|
Log.d("...", "no fckn texture!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
|
||||||
|
if (to.width == w && to.height == h)
|
||||||
|
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap, format, type);
|
||||||
|
else {
|
||||||
|
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, format, bitmap, type, 0);
|
||||||
|
to.width = w;
|
||||||
|
to.height = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init(int num) {
|
||||||
|
TextureObject to;
|
||||||
|
|
||||||
|
int[] textureIds = new int[num];
|
||||||
|
GLES20.glGenTextures(num, textureIds, 0);
|
||||||
|
|
||||||
|
for (int i = 1; i < num; i++) {
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[i]);
|
||||||
|
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
|
||||||
|
GLES20.GL_LINEAR);
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
|
||||||
|
GLES20.GL_LINEAR);
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
|
||||||
|
GLES20.GL_CLAMP_TO_EDGE); // Set U Wrapping
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
|
||||||
|
GLES20.GL_CLAMP_TO_EDGE); // Set V Wrapping
|
||||||
|
|
||||||
|
to = new TextureObject(textureIds[i]);
|
||||||
|
to.next = pool;
|
||||||
|
pool = to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureObject next;
|
||||||
|
|
||||||
|
int id;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
// vertex offset from which this texture is referenced
|
||||||
|
// or store texture id with vertex?
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
TextureObject(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
139
src/org/oscim/renderer/TextureRenderer.java
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.TextureLayer;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
|
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
|
||||||
|
public class TextureRenderer {
|
||||||
|
private static int mTextureProgram;
|
||||||
|
private static int hTextureMVMatrix;
|
||||||
|
private static int hTextureProjMatrix;
|
||||||
|
private static int hTextureVertex;
|
||||||
|
private static int hTextureScale;
|
||||||
|
private static int hTextureScreenScale;
|
||||||
|
private static int hTextureTexCoord;
|
||||||
|
private static int mIndicesVBO;
|
||||||
|
|
||||||
|
final static int INDICES_PER_SPRITE = 6;
|
||||||
|
final static int VERTICES_PER_SPRITE = 4;
|
||||||
|
final static int SHORTS_PER_VERTICE = 6;
|
||||||
|
// per texture
|
||||||
|
public final static int MAX_ITEMS = 40;
|
||||||
|
|
||||||
|
static void init() {
|
||||||
|
mTextureProgram = GlUtils.createProgram(Shaders.textVertexShader,
|
||||||
|
Shaders.textFragmentShader);
|
||||||
|
|
||||||
|
hTextureMVMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_mv");
|
||||||
|
hTextureProjMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_proj");
|
||||||
|
hTextureScale = GLES20.glGetUniformLocation(mTextureProgram, "u_scale");
|
||||||
|
hTextureScreenScale = GLES20.glGetUniformLocation(mTextureProgram, "u_swidth");
|
||||||
|
hTextureVertex = GLES20.glGetAttribLocation(mTextureProgram, "vertex");
|
||||||
|
hTextureTexCoord = GLES20.glGetAttribLocation(mTextureProgram, "tex_coord");
|
||||||
|
|
||||||
|
int bufferSize = MAX_ITEMS * VERTICES_PER_SPRITE
|
||||||
|
* SHORTS_PER_VERTICE * (Short.SIZE / 8);
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize)
|
||||||
|
.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
ShortBuffer mShortBuffer = buf.asShortBuffer();
|
||||||
|
|
||||||
|
// Setup triangle indices
|
||||||
|
short[] indices = new short[MAX_ITEMS * INDICES_PER_SPRITE];
|
||||||
|
int len = indices.length;
|
||||||
|
short j = 0;
|
||||||
|
for (int i = 0; i < len; i += INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE) {
|
||||||
|
indices[i + 0] = (short) (j + 0);
|
||||||
|
indices[i + 1] = (short) (j + 1);
|
||||||
|
indices[i + 2] = (short) (j + 2);
|
||||||
|
indices[i + 3] = (short) (j + 2);
|
||||||
|
indices[i + 4] = (short) (j + 3);
|
||||||
|
indices[i + 5] = (short) (j + 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mShortBuffer.clear();
|
||||||
|
mShortBuffer.put(indices, 0, len);
|
||||||
|
mShortBuffer.flip();
|
||||||
|
|
||||||
|
int[] mVboIds = new int[1];
|
||||||
|
GLES20.glGenBuffers(1, mVboIds, 0);
|
||||||
|
mIndicesVBO = mVboIds[0];
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
|
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, len * (Short.SIZE / 8),
|
||||||
|
mShortBuffer, GLES20.GL_STATIC_DRAW);
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Layer draw(Layer layer, float scale, float[] projection,
|
||||||
|
float matrix[], int offset) {
|
||||||
|
GLES20.glUseProgram(mTextureProgram);
|
||||||
|
GlUtils.checkGlError("draw texture1");
|
||||||
|
|
||||||
|
int va = hTextureTexCoord;
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
va = hTextureVertex;
|
||||||
|
if (!GLRenderer.vertexArray[va]) {
|
||||||
|
GLES20.glEnableVertexAttribArray(va);
|
||||||
|
GLRenderer.vertexArray[va] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureLayer tl = (TextureLayer) layer;
|
||||||
|
GlUtils.checkGlError("draw texture2.");
|
||||||
|
GLES20.glUniform1f(hTextureScale, scale);
|
||||||
|
GLES20.glUniform1f(hTextureScreenScale, 1f / GLRenderer.mWidth);
|
||||||
|
|
||||||
|
GLES20.glUniformMatrix4fv(hTextureProjMatrix, 1, false, projection, 0);
|
||||||
|
GLES20.glUniformMatrix4fv(hTextureMVMatrix, 1, false, matrix, 0);
|
||||||
|
GlUtils.checkGlError("draw texture2");
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||||
|
GlUtils.checkGlError("draw texture3");
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tl.textures.id);
|
||||||
|
GlUtils.checkGlError("draw texture4");
|
||||||
|
|
||||||
|
GlUtils.checkGlError("draw texture5");
|
||||||
|
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
||||||
|
GLES20.GL_SHORT, false, 12, offset);
|
||||||
|
GlUtils.checkGlError("draw texture..");
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hTextureTexCoord, 2,
|
||||||
|
GLES20.GL_SHORT, false, 12, offset + 8);
|
||||||
|
GlUtils.checkGlError("draw texture...");
|
||||||
|
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tl.verticesCnt / 4)
|
||||||
|
* INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
GlUtils.checkGlError("draw texture");
|
||||||
|
|
||||||
|
return layer.next;
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
@ -21,16 +21,21 @@ import org.oscim.core.WebMercator;
|
|||||||
import org.oscim.database.IMapDatabase;
|
import org.oscim.database.IMapDatabase;
|
||||||
import org.oscim.database.IMapDatabaseCallback;
|
import org.oscim.database.IMapDatabaseCallback;
|
||||||
import org.oscim.database.QueryResult;
|
import org.oscim.database.QueryResult;
|
||||||
|
import org.oscim.generator.JobTile;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.renderer.layer.PolygonLayer;
|
||||||
|
import org.oscim.renderer.layer.SymbolItem;
|
||||||
|
import org.oscim.renderer.layer.SymbolLayer;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
import org.oscim.theme.RenderTheme;
|
import org.oscim.theme.RenderTheme;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
|
||||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.oscim.view.DebugSettings;
|
import org.oscim.view.DebugSettings;
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
import org.oscim.view.generator.JobTile;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@ -45,9 +50,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
||||||
private static final double PIx4 = Math.PI * 4;
|
private static final double PIx4 = Math.PI * 4;
|
||||||
|
|
||||||
private static final double STROKE_INCREASE = Math.sqrt(2);
|
private static final double STROKE_INCREASE = Math.sqrt(2);
|
||||||
private static final byte LAYERS = 11;
|
private static final byte LAYERS = 11;
|
||||||
private static final double f900913 = 20037508.342789244;
|
|
||||||
|
|
||||||
static final byte STROKE_MIN_ZOOM_LEVEL = 12;
|
static final byte STROKE_MIN_ZOOM_LEVEL = 12;
|
||||||
static final byte STROKE_MAX_ZOOM_LEVEL = 17;
|
static final byte STROKE_MAX_ZOOM_LEVEL = 17;
|
||||||
@ -58,13 +63,15 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private MapTile mCurrentTile;
|
private MapTile mCurrentTile;
|
||||||
|
|
||||||
|
// coordinates of the currently processed way
|
||||||
private float[] mCoords;
|
private float[] mCoords;
|
||||||
private short[] mIndices;
|
private short[] mIndices;
|
||||||
|
|
||||||
private LineLayer mLineLayers;
|
// current line layer, will be added to outline layers
|
||||||
private PolygonLayer mPolyLayers;
|
|
||||||
private LineLayer mCurLineLayer;
|
private LineLayer mCurLineLayer;
|
||||||
private PolygonLayer mCurPolyLayer;
|
|
||||||
|
// layer data prepared for rendering
|
||||||
|
private Layers mLayers;
|
||||||
|
|
||||||
private TextItem mLabels;
|
private TextItem mLabels;
|
||||||
|
|
||||||
@ -74,10 +81,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
private float mStrokeScale = 1.0f;
|
private float mStrokeScale = 1.0f;
|
||||||
|
|
||||||
private boolean mProjected;
|
private boolean mProjected;
|
||||||
// private boolean mProjectedResult;
|
|
||||||
private float mSimplify;
|
private float mSimplify;
|
||||||
// private boolean firstMatch;
|
|
||||||
// private boolean prevClosed;
|
|
||||||
|
|
||||||
private RenderInstruction[] mRenderInstructions = null;
|
private RenderInstruction[] mRenderInstructions = null;
|
||||||
|
|
||||||
@ -126,8 +130,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
mTagName = null;
|
mTagName = null;
|
||||||
|
|
||||||
if (mMapProjection != null)
|
if (mMapProjection != null) {
|
||||||
{
|
|
||||||
long x = mCurrentTile.pixelX;
|
long x = mCurrentTile.pixelX;
|
||||||
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
|
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
|
||||||
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
||||||
@ -137,7 +140,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
long dy = (y - (z >> 1));
|
long dy = (y - (z >> 1));
|
||||||
|
|
||||||
if (mMapProjection == WebMercator.NAME) {
|
if (mMapProjection == WebMercator.NAME) {
|
||||||
double div = f900913 / (z >> 1);
|
double div = WebMercator.f900913 / (z >> 1);
|
||||||
// divy = f900913 / (z >> 1);
|
// divy = f900913 / (z >> 1);
|
||||||
mPoiX = (float) (longitude / div - dx);
|
mPoiX = (float) (longitude / div - dx);
|
||||||
mPoiY = (float) (latitude / div + dy);
|
mPoiY = (float) (latitude / div + dy);
|
||||||
@ -147,6 +150,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mPoiX = (float) (longitude / divx - dx);
|
mPoiX = (float) (longitude / divx - dx);
|
||||||
double sinLat = Math.sin(latitude * PI180);
|
double sinLat = Math.sin(latitude * PI180);
|
||||||
mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
|
mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
|
||||||
|
|
||||||
|
// TODO remove this, only used for mapsforge maps
|
||||||
if (mPoiX < -10 || mPoiX > Tile.TILE_SIZE + 10 || mPoiY < -10
|
if (mPoiX < -10 || mPoiX > Tile.TILE_SIZE + 10 || mPoiY < -10
|
||||||
|| mPoiY > Tile.TILE_SIZE + 10)
|
|| mPoiY > Tile.TILE_SIZE + 10)
|
||||||
return;
|
return;
|
||||||
@ -230,45 +235,45 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderAreaCaption(Caption caption) {
|
public void renderAreaCaption(Text text) {
|
||||||
// Log.d(TAG, "renderAreaCaption: " + mTagName);
|
// Log.d(TAG, "renderAreaCaption: " + mTagName);
|
||||||
|
|
||||||
if (mTagName == null)
|
if (mTagName == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (caption.textKey == mTagEmptyName.key) {
|
if (text.textKey == mTagEmptyName.key) {
|
||||||
|
|
||||||
TextItem t = new TextItem(mCoords[0], mCoords[1], mTagName.value, caption);
|
TextItem t = new TextItem(mCoords[0], mCoords[1], mTagName.value, text);
|
||||||
t.next = mLabels;
|
t.next = mLabels;
|
||||||
mLabels = t;
|
mLabels = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderPointOfInterestCaption(Caption caption) {
|
public void renderPointOfInterestCaption(Text text) {
|
||||||
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY +
|
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY +
|
||||||
// " " + mTagName);
|
// " " + mTagName);
|
||||||
|
|
||||||
if (mTagName == null)
|
if (mTagName == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (caption.textKey == mTagEmptyName.key) {
|
if (text.textKey == mTagEmptyName.key) {
|
||||||
TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, caption);
|
TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text);
|
||||||
t.next = mLabels;
|
t.next = mLabels;
|
||||||
mLabels = t;
|
mLabels = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWayText(PathText pathText) {
|
public void renderWayText(Text text) {
|
||||||
// Log.d(TAG, "renderWayText: " + mTagName);
|
// Log.d(TAG, "renderWayText: " + mTagName);
|
||||||
|
|
||||||
if (mTagName == null)
|
if (mTagName == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (pathText.textKey == mTagEmptyName.key && mTagName.value != null) {
|
if (text.textKey == mTagEmptyName.key && mTagName.value != null) {
|
||||||
|
|
||||||
mLabels = WayDecorator.renderText(mCoords, mTagName.value, pathText, 0,
|
mLabels = WayDecorator.renderText(mCoords, mTagName.value, text, 0,
|
||||||
mIndices[0], mLabels);
|
mIndices[0], mLabels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,67 +291,47 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderPointOfInterestSymbol(Bitmap symbol) {
|
public void renderPointOfInterestSymbol(Bitmap bitmap) {
|
||||||
// TODO Auto-generated method stub
|
// Log.d(TAG, "add symbol");
|
||||||
|
|
||||||
|
if (mLayers.symbolLayers == null)
|
||||||
|
mLayers.symbolLayers = new SymbolLayer();
|
||||||
|
|
||||||
|
SymbolLayer sl = (SymbolLayer) mLayers.symbolLayers;
|
||||||
|
|
||||||
|
SymbolItem it = new SymbolItem();
|
||||||
|
it.x = mPoiX;
|
||||||
|
it.y = mPoiY;
|
||||||
|
it.bitmap = bitmap;
|
||||||
|
it.billboard = true;
|
||||||
|
|
||||||
|
sl.addSymbol(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int countLines;
|
|
||||||
private int countNodes;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void renderWay(Line line, int level) {
|
public void renderWay(Line line, int level) {
|
||||||
|
|
||||||
projectToTile();
|
projectToTile();
|
||||||
|
|
||||||
if (line.outline && mCurLineLayer == null)
|
if (line.outline && mCurLineLayer == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float w = line.width;
|
int numLayer = (mDrawingLayer * 2) + level;
|
||||||
|
|
||||||
|
LineLayer lineLayer = (LineLayer) mLayers.getLayer(numLayer, Layer.LINE);
|
||||||
|
if (lineLayer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (lineLayer.line == null) {
|
||||||
|
lineLayer.line = line;
|
||||||
|
|
||||||
|
float w = line.width;
|
||||||
if (!line.fixed) {
|
if (!line.fixed) {
|
||||||
w *= mStrokeScale;
|
w *= mStrokeScale;
|
||||||
w *= mProjectionScaleFactor;
|
w *= mProjectionScaleFactor;
|
||||||
}
|
}
|
||||||
|
lineLayer.width = w;
|
||||||
LineLayer lineLayer = null;
|
|
||||||
|
|
||||||
int numLayer = mDrawingLayer + level;
|
|
||||||
|
|
||||||
LineLayer l = mLineLayers;
|
|
||||||
|
|
||||||
if (mCurLineLayer != null && mCurLineLayer.layer == numLayer) {
|
|
||||||
lineLayer = mCurLineLayer;
|
|
||||||
} else if (l == null || l.layer > numLayer) {
|
|
||||||
// insert new layer at start
|
|
||||||
lineLayer = new LineLayer(numLayer, line, w, line.outline);
|
|
||||||
// lineLayer = LineLayers.get(numLayer, line, w, false);
|
|
||||||
|
|
||||||
lineLayer.next = l;
|
|
||||||
mLineLayers = lineLayer;
|
|
||||||
} else {
|
|
||||||
while (l != null) {
|
|
||||||
// found layer
|
|
||||||
if (l.layer == numLayer) {
|
|
||||||
lineLayer = l;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// insert new layer between current and next layer
|
|
||||||
if (l.next == null || l.next.layer > numLayer) {
|
|
||||||
lineLayer = new LineLayer(numLayer, line, w, line.outline);
|
|
||||||
// lineLayer = LineLayers.get(numLayer, line, w, false);
|
|
||||||
lineLayer.next = l.next;
|
|
||||||
l.next = lineLayer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
l = l.next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineLayer == null) {
|
|
||||||
mCurLineLayer = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (line.outline) {
|
if (line.outline) {
|
||||||
lineLayer.addOutline(mCurLineLayer);
|
lineLayer.addOutline(mCurLineLayer);
|
||||||
return;
|
return;
|
||||||
@ -367,38 +352,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
int numLayer = mDrawingLayer + level;
|
int numLayer = mDrawingLayer + level;
|
||||||
|
|
||||||
PolygonLayer layer = null;
|
PolygonLayer layer = (PolygonLayer) mLayers.getLayer(numLayer, Layer.POLYGON);
|
||||||
PolygonLayer l = mPolyLayers;
|
|
||||||
|
|
||||||
if (mCurPolyLayer != null && mCurPolyLayer.layer == numLayer) {
|
|
||||||
layer = mCurPolyLayer;
|
|
||||||
} else if (l == null || l.layer > numLayer) {
|
|
||||||
// insert new layer at start
|
|
||||||
layer = new PolygonLayer(numLayer, area);
|
|
||||||
layer.next = l;
|
|
||||||
mPolyLayers = layer;
|
|
||||||
} else {
|
|
||||||
while (l != null) {
|
|
||||||
|
|
||||||
if (l.layer == numLayer) {
|
|
||||||
layer = l;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert new layer between current and next layer
|
|
||||||
if (l.next == null || l.next.layer > numLayer) {
|
|
||||||
layer = new PolygonLayer(numLayer, area);
|
|
||||||
layer.next = l.next;
|
|
||||||
l.next = layer;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
l = l.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (layer == null)
|
if (layer == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mCurPolyLayer = layer;
|
if (layer.area == null)
|
||||||
|
layer.area = area;
|
||||||
|
|
||||||
layer.addPolygon(mCoords, mIndices);
|
layer.addPolygon(mCoords, mIndices);
|
||||||
}
|
}
|
||||||
@ -430,7 +389,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
|
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
|
||||||
|
|
||||||
if (tile.newData || tile.isReady) {
|
if (tile.newData || tile.isReady) {
|
||||||
// fixed now....
|
// should be fixed now.
|
||||||
Log.d(TAG, "XXX tile already loaded "
|
Log.d(TAG, "XXX tile already loaded "
|
||||||
+ tile + " "
|
+ tile + " "
|
||||||
+ tile.newData + " "
|
+ tile.newData + " "
|
||||||
@ -446,22 +405,19 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
else
|
else
|
||||||
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
|
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
|
||||||
|
|
||||||
// firstMatch = true;
|
|
||||||
countLines = 0;
|
|
||||||
countNodes = 0;
|
|
||||||
|
|
||||||
// acount for area changes with latitude
|
// acount for area changes with latitude
|
||||||
mProjectionScaleFactor = 0.5f + (float) (0.5 / Math.cos(MercatorProjection
|
mProjectionScaleFactor = 0.5f + (float) (0.5 / Math.cos(MercatorProjection
|
||||||
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)
|
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)
|
||||||
* (Math.PI / 180)));
|
* (Math.PI / 180)));
|
||||||
|
|
||||||
|
mLayers = new Layers();
|
||||||
|
|
||||||
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
||||||
Log.d(TAG, "Failed loading: " + tile);
|
Log.d(TAG, "Failed loading: " + tile);
|
||||||
LineRenderer.clear(mLineLayers);
|
mLayers.clear();
|
||||||
PolygonRenderer.clear(mPolyLayers);
|
mLayers = null;
|
||||||
mLineLayers = null;
|
|
||||||
mPolyLayers = null;
|
|
||||||
mLabels = null;
|
mLabels = null;
|
||||||
|
mCurLineLayer = null;
|
||||||
tile.isLoading = false;
|
tile.isLoading = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -478,15 +434,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
TileGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
|
TileGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
tile.lineLayers = mLineLayers;
|
tile.layers = mLayers;
|
||||||
tile.polygonLayers = mPolyLayers;
|
|
||||||
tile.labels = mLabels;
|
tile.labels = mLabels;
|
||||||
|
|
||||||
mCurPolyLayer = null;
|
mLayers = null;
|
||||||
mCurLineLayer = null;
|
|
||||||
mLineLayers = null;
|
|
||||||
mPolyLayers = null;
|
|
||||||
mLabels = null;
|
mLabels = null;
|
||||||
|
mCurLineLayer = null;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -542,6 +495,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
return mRenderInstructions != null;
|
return mRenderInstructions != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO move this to Projection classes
|
||||||
private boolean projectToTile() {
|
private boolean projectToTile() {
|
||||||
if (mProjected || mMapProjection == null)
|
if (mProjected || mMapProjection == null)
|
||||||
return true;
|
return true;
|
||||||
@ -558,13 +512,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
||||||
float min = mSimplify;
|
float min = mSimplify;
|
||||||
|
|
||||||
double divx, divy;
|
double divx, divy = 0;
|
||||||
long dx = (x - (z >> 1));
|
long dx = (x - (z >> 1));
|
||||||
long dy = (y - (z >> 1));
|
long dy = (y - (z >> 1));
|
||||||
|
|
||||||
if (useWebMercator) {
|
if (useWebMercator) {
|
||||||
divx = f900913 / (z >> 1);
|
divx = WebMercator.f900913 / (z >> 1);
|
||||||
divy = f900913 / (z >> 1);
|
|
||||||
} else {
|
} else {
|
||||||
divx = 180000000.0 / (z >> 1);
|
divx = 180000000.0 / (z >> 1);
|
||||||
divy = z / PIx4;
|
divy = z / PIx4;
|
||||||
@ -584,7 +537,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
if (useWebMercator) {
|
if (useWebMercator) {
|
||||||
lon = (float) (coords[pos] / divx - dx);
|
lon = (float) (coords[pos] / divx - dx);
|
||||||
lat = (float) (coords[pos + 1] / divy + dy);
|
lat = (float) (coords[pos + 1] / divx + dy);
|
||||||
} else {
|
} else {
|
||||||
lon = (float) ((coords[pos]) / divx - dx);
|
lon = (float) ((coords[pos]) / divx - dx);
|
||||||
double sinLat = Math.sin(coords[pos + 1] * PI180);
|
double sinLat = Math.sin(coords[pos + 1] * PI180);
|
@ -12,9 +12,9 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.oscim.utils.GeometryUtils;
|
import org.oscim.utils.GeometryUtils;
|
||||||
|
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
@ -99,7 +99,7 @@ final class WayDecorator {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static TextItem renderText(float[] coordinates, String text, PathText pathText,
|
static TextItem renderText(float[] coordinates, String string, Text text,
|
||||||
int pos, int len, TextItem textItems) {
|
int pos, int len, TextItem textItems) {
|
||||||
TextItem items = textItems;
|
TextItem items = textItems;
|
||||||
TextItem t = null;
|
TextItem t = null;
|
||||||
@ -175,7 +175,7 @@ final class WayDecorator {
|
|||||||
} else if (segmentLengthInPixel > minWidth) {
|
} else if (segmentLengthInPixel > minWidth) {
|
||||||
|
|
||||||
if (wayNameWidth < 0) {
|
if (wayNameWidth < 0) {
|
||||||
wayNameWidth = pathText.paint.measureText(text);
|
wayNameWidth = text.paint.measureText(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segmentLengthInPixel > wayNameWidth + 25) {
|
if (segmentLengthInPixel > wayNameWidth + 25) {
|
||||||
@ -227,7 +227,7 @@ final class WayDecorator {
|
|||||||
if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
||||||
&& top2 - 10 < bot) {
|
&& top2 - 10 < bot) {
|
||||||
|
|
||||||
if (t2.text.equals(text)) {
|
if (t2.string.equals(string)) {
|
||||||
intersects = true;
|
intersects = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -256,8 +256,8 @@ final class WayDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if (t == null)
|
// if (t == null)
|
||||||
t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2, text,
|
t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2, string,
|
||||||
pathText, wayNameWidth);
|
text, wayNameWidth);
|
||||||
|
|
||||||
t.x1 = (short) x1;
|
t.x1 = (short) x1;
|
||||||
t.y1 = (short) y1;
|
t.y1 = (short) y1;
|
37
src/org/oscim/renderer/layer/Layer.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer.layer;
|
||||||
|
|
||||||
|
public class Layer {
|
||||||
|
public final static byte LINE = 0;
|
||||||
|
public final static byte POLYGON = 1;
|
||||||
|
public final static byte WAYTEXT = 2;
|
||||||
|
public final static byte POITEXT = 3;
|
||||||
|
public final static byte SYMBOL = 4;
|
||||||
|
public final static byte BITMAP = 5;
|
||||||
|
|
||||||
|
public byte type;
|
||||||
|
|
||||||
|
public Layer next;
|
||||||
|
|
||||||
|
int layer;
|
||||||
|
// number of vertices this layer holds
|
||||||
|
public int verticesCnt;
|
||||||
|
// vertices offset of this layer in VBO
|
||||||
|
public int offset;
|
||||||
|
|
||||||
|
VertexPoolItem pool;
|
||||||
|
protected VertexPoolItem curItem;
|
||||||
|
}
|
166
src/org/oscim/renderer/layer/Layers.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.TextureObject;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class Layers {
|
||||||
|
|
||||||
|
public Layer layers;
|
||||||
|
public int lineOffset;
|
||||||
|
|
||||||
|
public Layer symbolLayers;
|
||||||
|
public int symbolOffset;
|
||||||
|
|
||||||
|
private Layer mCurLayer;
|
||||||
|
|
||||||
|
public Layer getLayer(int level, byte type) {
|
||||||
|
Layer l = layers;
|
||||||
|
Layer ret = null;
|
||||||
|
|
||||||
|
if (mCurLayer != null && mCurLayer.layer == level) {
|
||||||
|
ret = mCurLayer;
|
||||||
|
} else if (l == null || l.layer > level) {
|
||||||
|
// insert new layer at start
|
||||||
|
l = null;
|
||||||
|
} else {
|
||||||
|
while (true) {
|
||||||
|
if (l.layer == level) {
|
||||||
|
// found layer
|
||||||
|
ret = l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l.next == null || l.next.layer > level) {
|
||||||
|
// insert new layer between current and next layer
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
l = l.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == null) {
|
||||||
|
if (type == Layer.LINE)
|
||||||
|
ret = new LineLayer(level);
|
||||||
|
else
|
||||||
|
ret = new PolygonLayer(level);
|
||||||
|
|
||||||
|
if (l == null) {
|
||||||
|
ret.next = layers;
|
||||||
|
layers = ret;
|
||||||
|
} else {
|
||||||
|
ret.next = l.next;
|
||||||
|
l.next = ret;
|
||||||
|
}
|
||||||
|
} else if (ret.type != type) {
|
||||||
|
Log.d("...", "wrong layer type " + ret.type + " " + type);
|
||||||
|
// FIXME thorw exception
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int LINE_VERTEX_SHORTS = 4;
|
||||||
|
private static int POLY_VERTEX_SHORTS = 2;
|
||||||
|
private static int TEXTURE_VERTEX_SHORTS = 6;
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
int size = 0;
|
||||||
|
for (Layer l = layers; l != null; l = l.next) {
|
||||||
|
if (l.type == Layer.LINE)
|
||||||
|
size += l.verticesCnt * LINE_VERTEX_SHORTS;
|
||||||
|
else
|
||||||
|
size += l.verticesCnt * POLY_VERTEX_SHORTS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Layer l = symbolLayers; l != null; l = l.next) {
|
||||||
|
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void compile(ShortBuffer sbuf, boolean addFill) {
|
||||||
|
// offset from fill coordinates
|
||||||
|
int pos = 0;
|
||||||
|
if (addFill)
|
||||||
|
pos = 4;
|
||||||
|
|
||||||
|
// add polygons first, needed to get the offsets right...
|
||||||
|
addLayerItems(sbuf, layers, Layer.POLYGON, pos);
|
||||||
|
|
||||||
|
lineOffset = sbuf.position() * 2; // * short-bytes
|
||||||
|
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
||||||
|
|
||||||
|
symbolOffset = sbuf.position() * 2; // * short-bytes
|
||||||
|
|
||||||
|
for (Layer l = symbolLayers; l != null; l = l.next) {
|
||||||
|
SymbolLayer sl = (SymbolLayer) l;
|
||||||
|
sl.compile(sbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addLayerItems(ShortBuffer sbuf, Layer l, byte type, int pos) {
|
||||||
|
VertexPoolItem last = null, items = null;
|
||||||
|
|
||||||
|
for (; l != null; l = l.next) {
|
||||||
|
if (l.type != type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
||||||
|
if (it.next == null)
|
||||||
|
sbuf.put(it.vertices, 0, it.used);
|
||||||
|
else
|
||||||
|
sbuf.put(it.vertices);
|
||||||
|
last = it;
|
||||||
|
}
|
||||||
|
if (last == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
l.offset = pos;
|
||||||
|
pos += l.verticesCnt;
|
||||||
|
|
||||||
|
last.next = items;
|
||||||
|
items = l.pool;
|
||||||
|
last = null;
|
||||||
|
|
||||||
|
l.pool = null;
|
||||||
|
l.curItem = null;
|
||||||
|
}
|
||||||
|
VertexPool.release(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
// FIXME collect pool and add as a whole
|
||||||
|
for (Layer l = layers; l != null; l = l.next) {
|
||||||
|
if (l.pool != null) {
|
||||||
|
VertexPool.release(l.pool);
|
||||||
|
l.pool = null;
|
||||||
|
l.curItem = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Layer l = symbolLayers; l != null; l = l.next) {
|
||||||
|
SymbolLayer sl = (SymbolLayer) l;
|
||||||
|
if (sl.textures != null)
|
||||||
|
TextureObject.release(sl.textures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,15 +12,16 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
|
||||||
import android.graphics.Paint.Cap;
|
import android.graphics.Paint.Cap;
|
||||||
import android.util.FloatMath;
|
import android.util.FloatMath;
|
||||||
|
|
||||||
class LineLayer {
|
public final class LineLayer extends Layer {
|
||||||
|
|
||||||
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||||
// scale factor mapping extrusion vector to short values
|
// scale factor mapping extrusion vector to short values
|
||||||
@ -29,33 +30,26 @@ class LineLayer {
|
|||||||
// coordinates
|
// coordinates
|
||||||
private static final int DIR_MASK = 0xFFFFFFFC;
|
private static final int DIR_MASK = 0xFFFFFFFC;
|
||||||
|
|
||||||
// next layer
|
|
||||||
LineLayer next;
|
|
||||||
|
|
||||||
// lines referenced by this outline layer
|
// lines referenced by this outline layer
|
||||||
LineLayer outlines;
|
public LineLayer outlines;
|
||||||
|
public Line line;
|
||||||
|
public float width;
|
||||||
|
|
||||||
Line line;
|
// boolean isOutline;
|
||||||
float width;
|
|
||||||
boolean isOutline;
|
|
||||||
int layer;
|
|
||||||
|
|
||||||
VertexPoolItem pool;
|
LineLayer(int layer) {
|
||||||
protected VertexPoolItem curItem;
|
|
||||||
|
|
||||||
// number of vertices this layer holds
|
|
||||||
int verticesCnt;
|
|
||||||
// vertices offset of this layer in VBO
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
LineLayer(int layer, Line line, float width, boolean outline) {
|
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.width = width;
|
this.type = Layer.LINE;
|
||||||
this.line = line;
|
|
||||||
this.isOutline = outline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addOutline(LineLayer link) {
|
// LineLayer(int layer, Line line, float width, boolean outline) {
|
||||||
|
// this.layer = layer;
|
||||||
|
// this.width = width;
|
||||||
|
// this.line = line;
|
||||||
|
// // this.isOutline = outline;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void addOutline(LineLayer link) {
|
||||||
for (LineLayer l = outlines; l != null; l = l.outlines)
|
for (LineLayer l = outlines; l != null; l = l.outlines)
|
||||||
if (link == l)
|
if (link == l)
|
||||||
return;
|
return;
|
||||||
@ -69,7 +63,7 @@ class LineLayer {
|
|||||||
* (https://github.com/olofsj/GLMap/) by olofsj
|
* (https://github.com/olofsj/GLMap/) by olofsj
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void addLine(float[] points, short[] index, boolean closed) {
|
public void addLine(float[] points, short[] index, boolean closed) {
|
||||||
float x, y, nextX, nextY, prevX, prevY;
|
float x, y, nextX, nextY, prevX, prevY;
|
||||||
float a, ux, uy, vx, vy, wx, wy;
|
float a, ux, uy, vx, vy, wx, wy;
|
||||||
|
|
||||||
@ -108,7 +102,6 @@ class LineLayer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
closed = false;
|
closed = false;
|
||||||
|
|
||||||
// amount of vertices used
|
// amount of vertices used
|
@ -12,32 +12,25 @@
|
|||||||
* You should have received a copy of the GNU Lesser General License along with
|
* You should have received a copy of the GNU Lesser General License along with
|
||||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
|
|
||||||
class PolygonLayer {
|
public final class PolygonLayer extends Layer {
|
||||||
private static final float S = GLRenderer.COORD_MULTIPLIER;
|
private static final float S = GLRenderer.COORD_MULTIPLIER;
|
||||||
|
|
||||||
PolygonLayer next;
|
public Area area;
|
||||||
Area area;
|
|
||||||
|
|
||||||
VertexPoolItem pool;
|
PolygonLayer(int layer) {
|
||||||
protected VertexPoolItem curItem;
|
|
||||||
int verticesCnt;
|
|
||||||
int offset;
|
|
||||||
|
|
||||||
final int layer;
|
|
||||||
|
|
||||||
PolygonLayer(int layer, Area area) {
|
|
||||||
this.layer = layer;
|
this.layer = layer;
|
||||||
this.area = area;
|
this.type = Layer.POLYGON;
|
||||||
curItem = VertexPool.get();
|
curItem = VertexPool.get();
|
||||||
pool = curItem;
|
pool = curItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPolygon(float[] points, short[] index) {
|
public void addPolygon(float[] points, short[] index) {
|
||||||
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
|
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
|
||||||
|
|
||||||
VertexPoolItem si = curItem;
|
VertexPoolItem si = curItem;
|
29
src/org/oscim/renderer/layer/SymbolItem.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer.layer;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
|
public class SymbolItem {
|
||||||
|
SymbolItem next;
|
||||||
|
|
||||||
|
public Bitmap bitmap;
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public boolean billboard;
|
||||||
|
|
||||||
|
// center, top, bottom, left, right, top-left...
|
||||||
|
byte placement;
|
||||||
|
}
|
200
src/org/oscim/renderer/layer/SymbolLayer.java
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.TextureObject;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.opengl.GLUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
// TODO share one static texture for all poi map symabols
|
||||||
|
|
||||||
|
public final class SymbolLayer extends TextureLayer {
|
||||||
|
private static String TAG = SymbolLayer.class.getSimpleName();
|
||||||
|
|
||||||
|
private final static int TEXTURE_WIDTH = 256;
|
||||||
|
private final static int TEXTURE_HEIGHT = 256;
|
||||||
|
private final static float SCALE = 8.0f;
|
||||||
|
|
||||||
|
private static short[] mVertices;
|
||||||
|
private static Bitmap mBitmap;
|
||||||
|
private static Canvas mCanvas;
|
||||||
|
private static int mBitmapFormat;
|
||||||
|
private static int mBitmapType;
|
||||||
|
|
||||||
|
SymbolItem symbols;
|
||||||
|
|
||||||
|
public SymbolLayer() {
|
||||||
|
if (mBitmap == null) {
|
||||||
|
mBitmap = Bitmap.createBitmap(TEXTURE_WIDTH, TEXTURE_HEIGHT,
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
mCanvas = new Canvas(mBitmap);
|
||||||
|
mBitmapFormat = GLUtils.getInternalFormat(mBitmap);
|
||||||
|
mBitmapType = GLUtils.getType(mBitmap);
|
||||||
|
//
|
||||||
|
mVertices = new short[40 * 24];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSymbol(SymbolItem item) {
|
||||||
|
|
||||||
|
verticesCnt += 4;
|
||||||
|
|
||||||
|
SymbolItem it = symbols;
|
||||||
|
|
||||||
|
for (; it != null; it = it.next) {
|
||||||
|
if (it.bitmap == item.bitmap) {
|
||||||
|
item.next = it.next;
|
||||||
|
it.next = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.next = symbols;
|
||||||
|
symbols = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static int LBIT_MASK = 0xfffffffe;
|
||||||
|
private final RectF mRect = new RectF();
|
||||||
|
|
||||||
|
// TODO ... reuse texture when only symbol position changed
|
||||||
|
public void compile(ShortBuffer sbuf) {
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
short buf[] = mVertices;
|
||||||
|
|
||||||
|
int advanceY = 0;
|
||||||
|
float x = 0;
|
||||||
|
float y = 0;
|
||||||
|
|
||||||
|
mBitmap.eraseColor(Color.TRANSPARENT);
|
||||||
|
|
||||||
|
for (SymbolItem it = symbols; it != null;) {
|
||||||
|
|
||||||
|
// add bitmap
|
||||||
|
float width = it.bitmap.getWidth();
|
||||||
|
float height = it.bitmap.getHeight();
|
||||||
|
|
||||||
|
if (height > advanceY)
|
||||||
|
advanceY = (int) height;
|
||||||
|
|
||||||
|
if (x + width > TEXTURE_WIDTH) {
|
||||||
|
x = 0;
|
||||||
|
y += advanceY;
|
||||||
|
advanceY = (int) (height + 0.5f);
|
||||||
|
|
||||||
|
if (y + height > TEXTURE_HEIGHT) {
|
||||||
|
Log.d(TAG, "reached max symbols");
|
||||||
|
// need to sync bitmap upload somehow???
|
||||||
|
TextureObject to = TextureObject.get();
|
||||||
|
TextureObject.uploadTexture(to, mBitmap,
|
||||||
|
mBitmapFormat, mBitmapType,
|
||||||
|
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||||
|
to.next = textures;
|
||||||
|
textures = to;
|
||||||
|
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRect.left = x;
|
||||||
|
mRect.top = y;
|
||||||
|
mRect.right = x + width;
|
||||||
|
mRect.bottom = y + height;
|
||||||
|
// Log.d("...", "draw " + x + " " + y + " " + width + " " + height);
|
||||||
|
|
||||||
|
mCanvas.drawBitmap(it.bitmap, null, mRect, null);
|
||||||
|
// mCanvas.drawBitmap(it.bitmap, x, y, null);
|
||||||
|
|
||||||
|
float hw = width / 2.0f;
|
||||||
|
float hh = height / 2.0f;
|
||||||
|
short x1, x2, x3, x4, y1, y2, y3, y4;
|
||||||
|
x1 = x3 = (short) (SCALE * (-hw));
|
||||||
|
x2 = x4 = (short) (SCALE * (hw));
|
||||||
|
|
||||||
|
y1 = y3 = (short) (SCALE * (hh));
|
||||||
|
y2 = y4 = (short) (SCALE * (-hh));
|
||||||
|
|
||||||
|
short u1 = (short) (SCALE * x);
|
||||||
|
short v1 = (short) (SCALE * y);
|
||||||
|
short u2 = (short) (SCALE * (x + width));
|
||||||
|
short v2 = (short) (SCALE * (y + height));
|
||||||
|
|
||||||
|
// add symbol items referencing the same bitmap
|
||||||
|
for (SymbolItem it2 = it;; it2 = it2.next) {
|
||||||
|
|
||||||
|
if (it2 == null || it2.bitmap != it.bitmap) {
|
||||||
|
it = it2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add vertices
|
||||||
|
short tx = (short) ((int) (SCALE * it2.x) & LBIT_MASK | (it2.billboard ? 1 : 0));
|
||||||
|
short ty = (short) (SCALE * it2.y);
|
||||||
|
|
||||||
|
// top-left
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x1;
|
||||||
|
buf[pos++] = y1;
|
||||||
|
buf[pos++] = u1;
|
||||||
|
buf[pos++] = v2;
|
||||||
|
|
||||||
|
// top-right
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x2;
|
||||||
|
buf[pos++] = y3;
|
||||||
|
buf[pos++] = u2;
|
||||||
|
buf[pos++] = v2;
|
||||||
|
|
||||||
|
// bot-right
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x4;
|
||||||
|
buf[pos++] = y4;
|
||||||
|
buf[pos++] = u2;
|
||||||
|
buf[pos++] = v1;
|
||||||
|
|
||||||
|
// bot-left
|
||||||
|
buf[pos++] = tx;
|
||||||
|
buf[pos++] = ty;
|
||||||
|
buf[pos++] = x3;
|
||||||
|
buf[pos++] = y2;
|
||||||
|
buf[pos++] = u1;
|
||||||
|
buf[pos++] = v1;
|
||||||
|
|
||||||
|
x += width + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureObject to = TextureObject.get();
|
||||||
|
|
||||||
|
TextureObject.uploadTexture(to, mBitmap,
|
||||||
|
mBitmapFormat, mBitmapType,
|
||||||
|
TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||||
|
|
||||||
|
to.next = textures;
|
||||||
|
textures = to;
|
||||||
|
|
||||||
|
sbuf.put(buf, 0, pos);
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
* 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
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
@ -12,8 +12,11 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
public class SymbolLayer {
|
import org.oscim.renderer.TextItem;
|
||||||
|
|
||||||
|
public final class TextLayer extends TextureLayer {
|
||||||
|
TextItem labels;
|
||||||
|
|
||||||
}
|
}
|
@ -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
|
* 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
|
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||||
@ -12,8 +12,11 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
public class TextureLayer {
|
import org.oscim.renderer.TextureObject;
|
||||||
|
|
||||||
|
public abstract class TextureLayer extends Layer {
|
||||||
|
public TextureObject textures;
|
||||||
|
|
||||||
}
|
}
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ public class VertexPool {
|
|||||||
static private int count = 0;
|
static private int count = 0;
|
||||||
static private int countAll = 0;
|
static private int countAll = 0;
|
||||||
|
|
||||||
static synchronized void init() {
|
public static synchronized void init() {
|
||||||
count = 0;
|
count = 0;
|
||||||
countAll = 0;
|
countAll = 0;
|
||||||
pool = null;
|
pool = null;
|
||||||
@ -61,7 +61,7 @@ public class VertexPool {
|
|||||||
// private static float load = 1.0f;
|
// private static float load = 1.0f;
|
||||||
// private static int loadCount = 0;
|
// private static int loadCount = 0;
|
||||||
|
|
||||||
static synchronized void add(VertexPoolItem items) {
|
static synchronized void release(VertexPoolItem items) {
|
||||||
if (items == null)
|
if (items == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -86,7 +86,8 @@ public class VertexPool {
|
|||||||
|
|
||||||
last.next = pool;
|
last.next = pool;
|
||||||
pool = items;
|
pool = items;
|
||||||
// Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " + countAll
|
// Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " +
|
||||||
|
// countAll
|
||||||
// + " load: " + (load / loadCount));
|
// + " load: " + (load / loadCount));
|
||||||
|
|
||||||
} else {
|
} else {
|
@ -12,7 +12,7 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public License along with
|
* 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/>.
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package org.oscim.view.renderer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
public class VertexPoolItem {
|
public class VertexPoolItem {
|
||||||
final short[] vertices;
|
final short[] vertices;
|
@ -15,9 +15,8 @@
|
|||||||
package org.oscim.theme;
|
package org.oscim.theme;
|
||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@ -36,14 +35,6 @@ public interface IRenderCallback {
|
|||||||
*/
|
*/
|
||||||
void renderArea(Area area, int level);
|
void renderArea(Area area, int level);
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders an area caption with the given text.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* the text to be rendered.
|
|
||||||
*/
|
|
||||||
void renderAreaCaption(Caption caption);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders an area symbol with the given bitmap.
|
* Renders an area symbol with the given bitmap.
|
||||||
*
|
*
|
||||||
@ -52,14 +43,6 @@ public interface IRenderCallback {
|
|||||||
*/
|
*/
|
||||||
void renderAreaSymbol(Bitmap symbol);
|
void renderAreaSymbol(Bitmap symbol);
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a point of interest caption with the given text.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* the text to be rendered.
|
|
||||||
*/
|
|
||||||
void renderPointOfInterestCaption(Caption caption);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a point of interest circle with the given parameters.
|
* Renders a point of interest circle with the given parameters.
|
||||||
*
|
*
|
||||||
@ -105,8 +88,25 @@ public interface IRenderCallback {
|
|||||||
/**
|
/**
|
||||||
* Renders a way with the given text along the way path.
|
* Renders a way with the given text along the way path.
|
||||||
*
|
*
|
||||||
* @param pathText
|
* @param text
|
||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
void renderWayText(PathText pathText);
|
void renderWayText(Text text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders an area caption with the given text.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* the text to be rendered.
|
||||||
|
*/
|
||||||
|
void renderAreaCaption(Text text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a point of interest caption with the given text.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* the text to be rendered.
|
||||||
|
*/
|
||||||
|
void renderPointOfInterestCaption(Text text);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -26,13 +26,12 @@ import javax.xml.parsers.SAXParserFactory;
|
|||||||
|
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
import org.oscim.theme.renderinstruction.AreaLevel;
|
import org.oscim.theme.renderinstruction.AreaLevel;
|
||||||
import org.oscim.theme.renderinstruction.Caption;
|
|
||||||
import org.oscim.theme.renderinstruction.Circle;
|
import org.oscim.theme.renderinstruction.Circle;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.theme.renderinstruction.LineSymbol;
|
import org.oscim.theme.renderinstruction.LineSymbol;
|
||||||
import org.oscim.theme.renderinstruction.PathText;
|
|
||||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||||
import org.oscim.theme.renderinstruction.Symbol;
|
import org.oscim.theme.renderinstruction.Symbol;
|
||||||
|
import org.oscim.theme.renderinstruction.Text;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
@ -55,7 +54,7 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
|
|
||||||
private static final String ELEMENT_NAME_RENDER_THEME = "rendertheme";
|
private static final String ELEMENT_NAME_RENDER_THEME = "rendertheme";
|
||||||
private static final String ELEMENT_NAME_RULE = "rule";
|
private static final String ELEMENT_NAME_RULE = "rule";
|
||||||
private static final String ELEMENT_NAME_STYPE_PATH_TEXT = "style-pathtext";
|
private static final String ELEMENT_NAME_STYLE_TEXT = "style-text";
|
||||||
private static final String ELEMENT_NAME_STYLE_AREA = "style-area";
|
private static final String ELEMENT_NAME_STYLE_AREA = "style-area";
|
||||||
private static final String ELEMENT_NAME_STYLE_LINE = "style-line";
|
private static final String ELEMENT_NAME_STYLE_LINE = "style-line";
|
||||||
private static final String ELEMENT_NAME_STYLE_OUTLINE = "style-outline";
|
private static final String ELEMENT_NAME_STYLE_OUTLINE = "style-outline";
|
||||||
@ -68,7 +67,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
/**
|
/**
|
||||||
* @param inputStream
|
* @param inputStream
|
||||||
* an input stream containing valid render theme XML data.
|
* an input stream containing valid render theme XML data.
|
||||||
* @return a new RenderTheme which is created by parsing the XML data from the input stream.
|
* @return a new RenderTheme which is created by parsing the XML data from
|
||||||
|
* the input stream.
|
||||||
* @throws SAXException
|
* @throws SAXException
|
||||||
* if an error occurs while parsing the render theme XML.
|
* if an error occurs while parsing the render theme XML.
|
||||||
* @throws ParserConfigurationException
|
* @throws ParserConfigurationException
|
||||||
@ -171,11 +171,11 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
mRuleStack.push(mCurrentRule);
|
mRuleStack.push(mCurrentRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ELEMENT_NAME_STYPE_PATH_TEXT.equals(localName)) {
|
else if (ELEMENT_NAME_STYLE_TEXT.equals(localName)) {
|
||||||
checkState(localName, Element.STYLE);
|
checkState(localName, Element.STYLE);
|
||||||
PathText pathText = PathText.create(localName, attributes);
|
Text text = Text.create(localName, attributes, false);
|
||||||
tmpStyleHash.put("t" + pathText.style, pathText);
|
tmpStyleHash.put("t" + text.style, text);
|
||||||
// System.out.println("add style: " + pathText.style);
|
// System.out.println("add style: " + text.style);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ELEMENT_NAME_STYLE_AREA.equals(localName)) {
|
else if (ELEMENT_NAME_STYLE_AREA.equals(localName)) {
|
||||||
@ -194,7 +194,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
Line line = Line.create((Line) ri, localName, attributes, 0,
|
Line line = Line.create((Line) ri, localName, attributes, 0,
|
||||||
false);
|
false);
|
||||||
tmpStyleHash.put("l" + line.style, line);
|
tmpStyleHash.put("l" + line.style, line);
|
||||||
// System.out.println("add style: " + line.style + " from " + style);
|
// System.out.println("add style: " + line.style +
|
||||||
|
// " from " + style);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.d("...", "this aint no style! " + style);
|
Log.d("...", "this aint no style! " + style);
|
||||||
@ -222,8 +223,11 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
|
|
||||||
else if ("caption".equals(localName)) {
|
else if ("caption".equals(localName)) {
|
||||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||||
Caption caption = Caption.create(localName, attributes);
|
Text text = Text.create(localName, attributes, true);
|
||||||
mCurrentRule.addRenderingInstruction(caption);
|
mCurrentRule.addRenderingInstruction(text);
|
||||||
|
|
||||||
|
// Caption caption = Caption.create(localName, attributes);
|
||||||
|
// mCurrentRule.addRenderingInstruction(caption);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ("circle".equals(localName)) {
|
else if ("circle".equals(localName)) {
|
||||||
@ -244,10 +248,10 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
mCurrentRule.addRenderingInstruction(lineSymbol);
|
mCurrentRule.addRenderingInstruction(lineSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ("pathText".equals(localName)) {
|
else if ("text".equals(localName)) {
|
||||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||||
PathText pathText = PathText.create(localName, attributes);
|
Text text = Text.create(localName, attributes, false);
|
||||||
mCurrentRule.addRenderingInstruction(pathText);
|
mCurrentRule.addRenderingInstruction(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ("symbol".equals(localName)) {
|
else if ("symbol".equals(localName)) {
|
||||||
@ -262,7 +266,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
if (style != null) {
|
if (style != null) {
|
||||||
Line line = (Line) tmpStyleHash.get("l" + style);
|
Line line = (Line) tmpStyleHash.get("l" + style);
|
||||||
if (line != null) {
|
if (line != null) {
|
||||||
// System.out.println("found style line : " + line.style);
|
// System.out.println("found style line : " +
|
||||||
|
// line.style);
|
||||||
Line newLine = Line.create(line, localName, attributes,
|
Line newLine = Line.create(line, localName, attributes,
|
||||||
mLevel++, false);
|
mLevel++, false);
|
||||||
|
|
||||||
@ -290,13 +295,13 @@ public class RenderThemeHandler extends DefaultHandler {
|
|||||||
mCurrentRule.addRenderingInstruction(new AreaLevel(area,
|
mCurrentRule.addRenderingInstruction(new AreaLevel(area,
|
||||||
mLevel++));
|
mLevel++));
|
||||||
else
|
else
|
||||||
Log.d("...", "this aint no style inna di area! " + style);
|
Log.d("...", "this aint no style inna d'area! " + style);
|
||||||
}
|
}
|
||||||
} else if (ELEMENT_NAME_USE_STYLE_PATH_TEXT.equals(localName)) {
|
} else if (ELEMENT_NAME_USE_STYLE_PATH_TEXT.equals(localName)) {
|
||||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||||
String style = attributes.getValue("name");
|
String style = attributes.getValue("name");
|
||||||
if (style != null) {
|
if (style != null) {
|
||||||
PathText pt = (PathText) tmpStyleHash.get("t" + style);
|
Text pt = (Text) tmpStyleHash.get("t" + style);
|
||||||
if (pt != null)
|
if (pt != null)
|
||||||
mCurrentRule.addRenderingInstruction(pt);
|
mCurrentRule.addRenderingInstruction(pt);
|
||||||
else
|
else
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
xsi:schemaLocation="http://mapsforge.org/renderTheme ../renderTheme.xsd"
|
xsi:schemaLocation="http://mapsforge.org/renderTheme ../renderTheme.xsd"
|
||||||
version="1" map-background="#fcfcfa">
|
version="1" map-background="#fcfcfa">
|
||||||
|
|
||||||
<style-pathtext name="road" k="name" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
<style-text name="road" k="name" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
||||||
<style-pathtext name="major-road" k="name" font-style="bold" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
<style-text name="major-road" k="name" font-style="bold" font-size="16" fill="#101010" stroke="#ffffff" stroke-width="2.0" />
|
||||||
|
|
||||||
<style-area name="residential" fill="#f0eee8" fade="10"/>
|
<style-area name="residential" fill="#f0eee8" fade="10"/>
|
||||||
|
|
||||||
@ -65,14 +65,14 @@
|
|||||||
<style-line name="steps" stroke="#f1f0f4" width="0.25" cap="butt" />
|
<style-line name="steps" stroke="#f1f0f4" width="0.25" cap="butt" />
|
||||||
|
|
||||||
<style-line name="water:outline" stroke="#a4bbcc" width="1.0" fixed="true" cap="butt" />
|
<style-line name="water:outline" stroke="#a4bbcc" width="1.0" fixed="true" cap="butt" />
|
||||||
<style-line name="water" stroke="#b4cbdc" width="1.0" cap="butt" />
|
<style-line name="water" stroke="#afcbf3" width="1.0" cap="butt" />
|
||||||
<style-area name="water" fill="#afcbf3" />
|
<style-area name="water" fill="#afcbf3" />
|
||||||
<!-- no-go area boundary -->
|
<!-- no-go area boundary -->
|
||||||
<style-line name="fence" stroke="#444444" width="1.2" fixed="true" cap="butt"/>
|
<style-line name="fence" stroke="#444444" width="1.2" fixed="true" cap="butt"/>
|
||||||
|
|
||||||
<style-line name="aeroway:runway" stroke="#c8ccbe" width="1.8" cap="butt" />
|
<style-line name="aeroway:runway" stroke="#c8ccbe" width="1.8" cap="butt" />
|
||||||
|
|
||||||
<style-line name="building" stroke="#c9c3c1" width="1.2" fixed="true" cap="butt" fade="15"/>
|
<style-line name="building" stroke="#c9c3c1" width="1.0" fixed="true" cap="butt" fade="15"/>
|
||||||
<style-area name="building" fill="#e9e6e3" fade="15"/>
|
<style-area name="building" fill="#e9e6e3" fade="15"/>
|
||||||
|
|
||||||
<!-- ways -->
|
<!-- ways -->
|
||||||
@ -487,11 +487,11 @@
|
|||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<!-- outline 1 - 4 -->
|
<!-- outline 1 - 4 -->
|
||||||
<style-outline name="1" stroke="#ee605020" width="0.02"/>
|
<style-outline name="1" stroke="#aa807040" width="0.1"/>
|
||||||
<!-- <style-outline name="1" stroke="#404030"/> -->
|
<!-- <style-outline name="1" stroke="#404030"/> -->
|
||||||
<style-outline name="2" stroke="#c0c0c0" />
|
<style-outline name="2" stroke="#c0c0c0" />
|
||||||
<style-outline name="primary" stroke="#7f7700" width="0.025"/>
|
<style-outline name="primary" stroke="#aa7f7700" width="0.1"/>
|
||||||
<style-outline name="motorway" stroke="#805f2e" width="0.025"/>
|
<style-outline name="motorway" stroke="#aa805f2e" width="0.1"/>
|
||||||
|
|
||||||
|
|
||||||
<!-- highway -->
|
<!-- highway -->
|
||||||
@ -499,23 +499,23 @@
|
|||||||
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
|
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
|
||||||
<rule e="way" k="area" v="~|no|false">
|
<rule e="way" k="area" v="~|no|false">
|
||||||
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
|
<rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
|
||||||
<line stroke="#f2df6d" width="1.8" cap="butt" fixed="true" fade="9"/>
|
<line stroke="#f2df6d" width="1.3" cap="butt" fixed="true" fade="9"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
|
<rule e="way" k="*" v="trunk_link|motorway_link" zoom-min="8">
|
||||||
<line stroke="#fed6a3" width="1.8" cap="butt" fixed="true" fade="8"/>
|
<line stroke="#fed6a3" width="1.4" cap="butt" fixed="true" fade="8"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule e="way" k="*" v="primary" zoom-min="5">
|
<rule e="way" k="*" v="primary" zoom-min="5">
|
||||||
<line stroke="#f2df6d" width="1.8" cap="butt" fixed="true" fade="5"/>
|
<line stroke="#f2df6d" width="1.4" cap="butt" fixed="true" fade="5"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule e="way" k="*" v="trunk" zoom-min="5">
|
<rule e="way" k="*" v="trunk" zoom-min="5">
|
||||||
<line stroke="#fed6a3" width="2.0" cap="butt" fixed="true" fade="5"/>
|
<line stroke="#fed6a3" width="1.4" cap="butt" fixed="true" fade="5"/>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
<rule e="way" k="*" v="motorway">
|
<rule e="way" k="*" v="motorway">
|
||||||
<line stroke="#eec693" width="2.2" cap="butt" fixed="true" fade="5"/>
|
<line stroke="#eec693" width="1.5" cap="butt" fixed="true" fade="5"/>
|
||||||
</rule>
|
</rule>
|
||||||
</rule>
|
</rule>
|
||||||
</rule>
|
</rule>
|
||||||
@ -790,7 +790,7 @@
|
|||||||
src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/cable_car.png"
|
src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/cable_car.png"
|
||||||
/> </rule> <rule e="way" k="aerialway" v="chair_lift"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/chair_lift_2.png"
|
/> </rule> <rule e="way" k="aerialway" v="chair_lift"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/chair_lift_2.png"
|
||||||
/> </rule> <rule e="way" k="aerialway" v="gondola"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/gondola.png"
|
/> </rule> <rule e="way" k="aerialway" v="gondola"> <lineSymbol src="jar:/org/mapsforge/android/maps/rendertheme/osmarender/symbols/gondola.png"
|
||||||
/> </rule> <rule e="way" k="*" v="*" zoom-min="14"> <pathText k="name" font-style="bold"
|
/> </rule> <rule e="way" k="*" v="*" zoom-min="14"> <text k="name" font-style="bold"
|
||||||
font-size="10" fill="#606060" stroke="#ffffff" width="2.0" /> </rule>
|
font-size="10" fill="#606060" stroke="#ffffff" width="2.0" /> </rule>
|
||||||
</rule> -->
|
</rule> -->
|
||||||
|
|
||||||
@ -831,7 +831,7 @@
|
|||||||
|
|
||||||
</rule>
|
</rule>
|
||||||
<rule e="way" k="railway" v="rail|turntable" >
|
<rule e="way" k="railway" v="rail|turntable" >
|
||||||
<line stroke="#887766" width="0.8" cap="butt" fixed="true" fade="12"/>
|
<line stroke="#ccaa9988" width="1.0" cap="butt" fixed="true" fade="12"/>
|
||||||
</rule>
|
</rule>
|
||||||
<!-- <rule e="way" k="railway" v="rail" zoom-max="14" zoom-min="13">
|
<!-- <rule e="way" k="railway" v="rail" zoom-max="14" zoom-min="13">
|
||||||
<line stroke="#8888aa" width="0.6" cap="butt"
|
<line stroke="#8888aa" width="0.6" cap="butt"
|
||||||
@ -969,6 +969,165 @@
|
|||||||
stroke="#ffffff" stroke-width="2.0" /> -->
|
stroke="#ffffff" stroke-width="2.0" /> -->
|
||||||
</rule>
|
</rule>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
|
<!-- aeroway -->
|
||||||
|
<rule e="node" k="aeroway" v="*">
|
||||||
|
<rule e="node" k="aeroway" v="helipad" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/helipad.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="aeroway" v="aerodrome|airport" zoom-max="13">
|
||||||
|
<symbol src="jar:symbols/airport.png" />
|
||||||
|
</rule>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- amenity -->
|
||||||
|
<rule e="node" k="amenity" v="*">
|
||||||
|
<rule e="node" k="amenity" v="atm" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/atm.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="bank" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/bank.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="bench" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/bench.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="bicycle_rental" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/bicycle_rental.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="bus_station" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/bus_sta.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="cafe" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/cafe.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="cinema" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/cinema.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="drinking_water" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/drinking_water.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="fast_food" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/fastfood.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="fire_station" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/firebrigade.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="fountain" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/fountain.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="fuel" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/petrolStation.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="hospital" zoom-min="15">
|
||||||
|
<symbol src="jar:symbols/hospital.png" />
|
||||||
|
</rule>
|
||||||
|
<!-- <rule e="node" k="amenity" v="kindergarten" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/kindergarten.png" />
|
||||||
|
</rule>-->
|
||||||
|
<rule e="node" k="amenity" v="library" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/library.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="parking" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/parking.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="pharmacy" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/pharmacy.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="place_of_worship" zoom-min="17">
|
||||||
|
<rule e="node" k="denomination|religion" v="jewish">
|
||||||
|
<symbol src="jar:symbols/synagogue.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="denomination|religion" v="muslim|moslem">
|
||||||
|
<symbol src="jar:symbols/mosque.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="denomination|religion" v="christian">
|
||||||
|
<symbol src="jar:symbols/church.png" />
|
||||||
|
</rule>
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="post_box" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/postbox.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="post_office" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/postoffice.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="pub|bar" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/pub.png" />
|
||||||
|
</rule>
|
||||||
|
<!-- <rule e="node" k="amenity" v="recycling" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/recycling.png" />
|
||||||
|
</rule> -->
|
||||||
|
<rule e="node" k="amenity" v="restaurant" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/restaurant.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="school" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/school.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="shelter" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/shelter.png" />
|
||||||
|
</rule>
|
||||||
|
<!-- <rule e="node" k="amenity" v="telephone" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/telephone.png" />
|
||||||
|
</rule> -->
|
||||||
|
<rule e="node" k="amenity" v="theatre" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/theatre.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="toilets" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/toilets.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="amenity" v="university|college" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/university.png" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- <rule e="node" k="*" v="*" zoom-min="17">
|
||||||
|
<caption k="name" font-style="bold" font-size="10" fill="#4040ff" stroke="#ffffff" stroke-width="2.0" />
|
||||||
|
</rule>-->
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<!-- shop -->
|
||||||
|
<rule e="node" k="shop" v="*">
|
||||||
|
<rule e="node" k="shop" v="bakery" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/bakery.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="shop" v="florist" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/florist.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="shop" v="supermarket|organic" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/supermarket.png" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule e="node" k="*" v="*" zoom-min="17">
|
||||||
|
<caption k="name" font-style="bold" font-size="10" fill="#4040ff" stroke="#ffffff" stroke-width="2.0" />
|
||||||
|
</rule>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- tourism -->
|
||||||
|
<rule e="node" k="tourism" v="*">
|
||||||
|
<rule e="node" k="tourism" v="alpine_hut" zoom-min="16">
|
||||||
|
<symbol src="jar:symbols/alpine_hut.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="tourism" v="camp_site" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/campSite.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="tourism" v="hostel" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/hostel.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="tourism" v="hotel" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/hotel.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="tourism" v="information" zoom-min="17">
|
||||||
|
<symbol src="jar:symbols/information.png" />
|
||||||
|
</rule>
|
||||||
|
<rule e="node" k="tourism" v="viewpoint" zoom-min="15">
|
||||||
|
<symbol src="jar:symbols/viewpoint.png" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule e="node" k="*" v="*" zoom-min="17">
|
||||||
|
<caption k="name" font-style="bold" font-size="10" fill="#4040ff" stroke="#ffffff" stroke-width="2.0" />
|
||||||
|
</rule>
|
||||||
|
</rule>
|
||||||
|
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
</rendertheme>
|
</rendertheme>
|
BIN
src/org/oscim/theme/osmarender/symbols/_bench.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
src/org/oscim/theme/osmarender/symbols/_cafe.png
Normal file
After Width: | Height: | Size: 388 B |
BIN
src/org/oscim/theme/osmarender/symbols/_fastfood.png
Normal file
After Width: | Height: | Size: 742 B |
BIN
src/org/oscim/theme/osmarender/symbols/_pub.png
Normal file
After Width: | Height: | Size: 398 B |
BIN
src/org/oscim/theme/osmarender/symbols/_restaurant.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
src/org/oscim/theme/osmarender/symbols/_school.png
Normal file
After Width: | Height: | Size: 717 B |
BIN
src/org/oscim/theme/osmarender/symbols/_theatre.png
Normal file
After Width: | Height: | Size: 997 B |
BIN
src/org/oscim/theme/osmarender/symbols/airport.png
Normal file
After Width: | Height: | Size: 423 B |
BIN
src/org/oscim/theme/osmarender/symbols/alpine_hut.png
Normal file
After Width: | Height: | Size: 398 B |
BIN
src/org/oscim/theme/osmarender/symbols/atm.png
Normal file
After Width: | Height: | Size: 511 B |
BIN
src/org/oscim/theme/osmarender/symbols/bakery.png
Normal file
After Width: | Height: | Size: 658 B |
BIN
src/org/oscim/theme/osmarender/symbols/bank.png
Normal file
After Width: | Height: | Size: 549 B |
BIN
src/org/oscim/theme/osmarender/symbols/bench.png
Normal file
After Width: | Height: | Size: 197 B |
BIN
src/org/oscim/theme/osmarender/symbols/bicycle_rental.png
Normal file
After Width: | Height: | Size: 604 B |
BIN
src/org/oscim/theme/osmarender/symbols/bus.png
Normal file
After Width: | Height: | Size: 492 B |
BIN
src/org/oscim/theme/osmarender/symbols/bus_sta.png
Normal file
After Width: | Height: | Size: 961 B |
BIN
src/org/oscim/theme/osmarender/symbols/cable_car.png
Normal file
After Width: | Height: | Size: 454 B |
BIN
src/org/oscim/theme/osmarender/symbols/cafe.png
Normal file
After Width: | Height: | Size: 374 B |
BIN
src/org/oscim/theme/osmarender/symbols/campSite.png
Normal file
After Width: | Height: | Size: 410 B |
BIN
src/org/oscim/theme/osmarender/symbols/cave_entrance.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
src/org/oscim/theme/osmarender/symbols/chair_lift_2.png
Normal file
After Width: | Height: | Size: 443 B |
BIN
src/org/oscim/theme/osmarender/symbols/church.png
Normal file
After Width: | Height: | Size: 234 B |
BIN
src/org/oscim/theme/osmarender/symbols/cinema.png
Normal file
After Width: | Height: | Size: 708 B |
BIN
src/org/oscim/theme/osmarender/symbols/drinking_water.png
Normal file
After Width: | Height: | Size: 602 B |
BIN
src/org/oscim/theme/osmarender/symbols/fastfood.png
Normal file
After Width: | Height: | Size: 356 B |
BIN
src/org/oscim/theme/osmarender/symbols/firebrigade.png
Normal file
After Width: | Height: | Size: 733 B |
BIN
src/org/oscim/theme/osmarender/symbols/florist.png
Normal file
After Width: | Height: | Size: 615 B |
BIN
src/org/oscim/theme/osmarender/symbols/fountain.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
src/org/oscim/theme/osmarender/symbols/gondola.png
Normal file
After Width: | Height: | Size: 387 B |
BIN
src/org/oscim/theme/osmarender/symbols/helipad.png
Normal file
After Width: | Height: | Size: 896 B |
BIN
src/org/oscim/theme/osmarender/symbols/hospital.png
Normal file
After Width: | Height: | Size: 477 B |
BIN
src/org/oscim/theme/osmarender/symbols/hostel.png
Normal file
After Width: | Height: | Size: 499 B |
BIN
src/org/oscim/theme/osmarender/symbols/hotel.png
Normal file
After Width: | Height: | Size: 462 B |
BIN
src/org/oscim/theme/osmarender/symbols/information.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
src/org/oscim/theme/osmarender/symbols/kindergarten.png
Normal file
After Width: | Height: | Size: 539 B |
BIN
src/org/oscim/theme/osmarender/symbols/library.png
Normal file
After Width: | Height: | Size: 575 B |
BIN
src/org/oscim/theme/osmarender/symbols/mosque.png
Normal file
After Width: | Height: | Size: 515 B |
BIN
src/org/oscim/theme/osmarender/symbols/oneway.png
Normal file
After Width: | Height: | Size: 244 B |
BIN
src/org/oscim/theme/osmarender/symbols/parking.png
Normal file
After Width: | Height: | Size: 303 B |
BIN
src/org/oscim/theme/osmarender/symbols/peak.png
Normal file
After Width: | Height: | Size: 309 B |
BIN
src/org/oscim/theme/osmarender/symbols/petrolStation.png
Normal file
After Width: | Height: | Size: 421 B |
BIN
src/org/oscim/theme/osmarender/symbols/pharmacy.png
Normal file
After Width: | Height: | Size: 419 B |
BIN
src/org/oscim/theme/osmarender/symbols/playground.png
Normal file
After Width: | Height: | Size: 705 B |
BIN
src/org/oscim/theme/osmarender/symbols/postbox.png
Normal file
After Width: | Height: | Size: 426 B |
BIN
src/org/oscim/theme/osmarender/symbols/postoffice.png
Normal file
After Width: | Height: | Size: 467 B |
BIN
src/org/oscim/theme/osmarender/symbols/pub.png
Normal file
After Width: | Height: | Size: 395 B |
After Width: | Height: | Size: 385 B |
BIN
src/org/oscim/theme/osmarender/symbols/railway-crossing.png
Normal file
After Width: | Height: | Size: 806 B |
BIN
src/org/oscim/theme/osmarender/symbols/recycling.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
src/org/oscim/theme/osmarender/symbols/restaurant.png
Normal file
After Width: | Height: | Size: 452 B |
BIN
src/org/oscim/theme/osmarender/symbols/school.png
Normal file
After Width: | Height: | Size: 564 B |
BIN
src/org/oscim/theme/osmarender/symbols/shelter.png
Normal file
After Width: | Height: | Size: 715 B |
BIN
src/org/oscim/theme/osmarender/symbols/soccer-borderless.png
Normal file
After Width: | Height: | Size: 658 B |