- 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" -->
|
||||
<activity
|
||||
android:name="org.oscim.app.TileMap"
|
||||
android:name="TileMap"
|
||||
android:configChanges="orientation|screenSize" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -15,4 +15,4 @@
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# 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;
|
||||
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.view.MapPosition;
|
||||
import org.oscim.core.MapPosition;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Criteria;
|
||||
|
@ -4,21 +4,18 @@ import java.io.FileFilter;
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import org.oscim.app.filefilter.FilterByFileExtension;
|
||||
import org.oscim.app.filefilter.ValidMapFile;
|
||||
import org.oscim.app.filefilter.ValidRenderTheme;
|
||||
import org.oscim.app.filepicker.FilePicker;
|
||||
import org.oscim.app.preferences.EditPreferences;
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.database.MapDatabases;
|
||||
import org.oscim.theme.InternalRenderTheme;
|
||||
import org.oscim.utils.AndroidUtils;
|
||||
import org.oscim.view.DebugSettings;
|
||||
import org.oscim.view.MapActivity;
|
||||
import org.oscim.view.MapPosition;
|
||||
import org.oscim.view.MapView;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
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_INFO_MAP_FILE = 1;
|
||||
private static final int DIALOG_LOCATION_PROVIDER_DISABLED = 2;
|
||||
private static final FileFilter FILE_FILTER_EXTENSION_MAP =
|
||||
new FilterByFileExtension(".map");
|
||||
// private static final FileFilter FILE_FILTER_EXTENSION_MAP =
|
||||
// new FilterByFileExtension(".map");
|
||||
private static final FileFilter FILE_FILTER_EXTENSION_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;
|
||||
|
||||
LocationHandler mLocation;
|
||||
@ -232,11 +229,12 @@ public class TileMap extends MapActivity {
|
||||
return mMapView.onTrackballEvent(event);
|
||||
}
|
||||
|
||||
private void startMapFilePicker() {
|
||||
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
||||
FilePicker.setFileSelectFilter(new ValidMapFile());
|
||||
startActivityForResult(new Intent(this, FilePicker.class), SELECT_MAP_FILE);
|
||||
}
|
||||
// private void startMapFilePicker() {
|
||||
// FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_MAP);
|
||||
// FilePicker.setFileSelectFilter(new ValidMapFile());
|
||||
// startActivityForResult(new Intent(this, FilePicker.class),
|
||||
// SELECT_MAP_FILE);
|
||||
// }
|
||||
|
||||
private void startRenderThemePicker() {
|
||||
FilePicker.setFileDisplayFilter(FILE_FILTER_EXTENSION_XML);
|
||||
@ -598,12 +596,12 @@ public class TileMap extends MapActivity {
|
||||
// }
|
||||
}
|
||||
|
||||
static class VersionHelper {
|
||||
@TargetApi(11)
|
||||
static void refreshActionBarMenu(Activity activity) {
|
||||
activity.invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
// static class VersionHelper {
|
||||
// @TargetApi(11)
|
||||
// static void refreshActionBarMenu(Activity activity) {
|
||||
// activity.invalidateOptionsMenu();
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
|
@ -12,10 +12,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view;
|
||||
|
||||
import org.oscim.core.GeoPoint;
|
||||
import org.oscim.core.MercatorProjection;
|
||||
package org.oscim.core;
|
||||
|
||||
import android.opengl.Matrix;
|
||||
|
||||
@ -30,11 +27,13 @@ public class MapPosition {
|
||||
public byte zoomLevel;
|
||||
public float scale;
|
||||
public float angle;
|
||||
public float tilt;
|
||||
|
||||
public double x;
|
||||
public double y;
|
||||
|
||||
public float[] rotation;
|
||||
public float[] viewMatrix;
|
||||
public float[] rotateMatrix;
|
||||
|
||||
public MapPosition() {
|
||||
this.zoomLevel = (byte) 1;
|
||||
@ -46,9 +45,13 @@ public class MapPosition {
|
||||
this.y = MercatorProjection.latitudeToPixelY(this.lat, zoomLevel);
|
||||
}
|
||||
|
||||
// FIXME remove this here
|
||||
public void init() {
|
||||
rotation = new float[16];
|
||||
Matrix.setIdentityM(rotation, 0);
|
||||
viewMatrix = new float[16];
|
||||
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) {
|
||||
// this.geoPoint = geoPoint;
|
||||
this.zoomLevel = zoomLevel;
|
||||
this.scale = scale;
|
||||
this.lat = geoPoint.getLatitude();
|
||||
@ -84,10 +86,10 @@ public class MapPosition {
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("MapPosition [geoPoint=");
|
||||
builder.append("lat");
|
||||
builder.append("MapPosition [");
|
||||
builder.append("lat=");
|
||||
builder.append(this.lat);
|
||||
builder.append("lon");
|
||||
builder.append(", lon=");
|
||||
builder.append(this.lon);
|
||||
builder.append(", zoomLevel=");
|
||||
builder.append(this.zoomLevel);
|
@ -14,7 +14,6 @@
|
||||
*/
|
||||
package org.oscim.core;
|
||||
|
||||
import org.oscim.view.MapPosition;
|
||||
|
||||
/**
|
||||
* An implementation of the spherical Mercator projection.
|
||||
|
@ -24,7 +24,8 @@ public class WebMercator {
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,7 @@ package org.oscim.database;
|
||||
|
||||
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.MapFileInfo;
|
||||
import org.oscim.database.mapfile.header.SubFileParameter;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
import org.oscim.generator.JobTile;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
@ -819,7 +819,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
Tag[] wayTags = sMapFileHeader.getMapFileInfo().wayTags;
|
||||
int[] textPos = new int[3];
|
||||
// float[] labelPosition;
|
||||
boolean skippedWays = false;
|
||||
// boolean skippedWays = false;
|
||||
int wayDataBlocks;
|
||||
|
||||
// skip string block
|
||||
@ -858,7 +858,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
if (tags == null)
|
||||
return false;
|
||||
|
||||
skippedWays = true;
|
||||
// skippedWays = true;
|
||||
|
||||
mReadBuffer.setBufferPosition(pos);
|
||||
}
|
||||
@ -885,12 +885,12 @@ public class MapDatabase implements IMapDatabase {
|
||||
// bit 5-8 represent the number of tag IDs
|
||||
byte numberOfTags = (byte) (specialByte & WAY_NUMBER_OF_TAGS_BITMASK);
|
||||
|
||||
boolean changed = skippedWays;
|
||||
skippedWays = false;
|
||||
// boolean changed = skippedWays;
|
||||
// skippedWays = false;
|
||||
|
||||
if (numberOfTags != 0) {
|
||||
tags = mReadBuffer.readTags(wayTags, numberOfTags);
|
||||
changed = true;
|
||||
// changed = true;
|
||||
}
|
||||
if (tags == null)
|
||||
return false;
|
||||
@ -904,8 +904,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
// check if the way has a name
|
||||
if ((featureByte & WAY_FEATURE_NAME) != 0) {
|
||||
textPos[0] = mReadBuffer.readUnsignedInt();
|
||||
String str = mReadBuffer.readUTF8EncodedStringAt(stringOffset
|
||||
+ textPos[0]);
|
||||
// String str =
|
||||
mReadBuffer.readUTF8EncodedStringAt(stringOffset + textPos[0]);
|
||||
// if (changed) {
|
||||
// Tag[] tmp = tags;
|
||||
// tags = new Tag[tmp.length + 1];
|
||||
|
@ -39,7 +39,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
||||
import org.oscim.database.MapInfo;
|
||||
import org.oscim.database.OpenResult;
|
||||
import org.oscim.database.QueryResult;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
import org.oscim.generator.JobTile;
|
||||
|
||||
import android.os.Environment;
|
||||
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 SERVER_ADDR = "city.informatik.uni-bremen.de";
|
||||
// private static final String URL = "/osci/map-live/";
|
||||
private static final String URL = "/osci/oscim/";
|
||||
private static final String URL = "/osci/map-live/";
|
||||
// private static final String URL = "/osci/oscim/";
|
||||
|
||||
private final static float REF_TILE_SIZE = 4096.0f;
|
||||
|
||||
|
@ -62,7 +62,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
||||
import org.oscim.database.MapInfo;
|
||||
import org.oscim.database.OpenResult;
|
||||
import org.oscim.database.QueryResult;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
import org.oscim.generator.JobTile;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.os.SystemClock;
|
||||
|
@ -33,7 +33,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
||||
import org.oscim.database.MapInfo;
|
||||
import org.oscim.database.OpenResult;
|
||||
import org.oscim.database.QueryResult;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
import org.oscim.generator.JobTile;
|
||||
import org.postgresql.PGConnection;
|
||||
|
||||
import android.util.Log;
|
||||
|
@ -24,7 +24,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
||||
import org.oscim.database.MapInfo;
|
||||
import org.oscim.database.OpenResult;
|
||||
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[] mTagsWay = { new Tag("highway", "primary"), new Tag("name", "Highway Rd") };
|
||||
|
||||
private Tag[] mNameTags;
|
||||
// private Tag[] mNameTags;
|
||||
|
||||
private final MapInfo mMapInfo =
|
||||
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
|
||||
* 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;
|
||||
|
@ -12,7 +12,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.generator;
|
||||
package org.oscim.generator;
|
||||
|
||||
import org.oscim.core.Tile;
|
||||
|
@ -12,11 +12,11 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.generator;
|
||||
package org.oscim.generator;
|
||||
|
||||
import org.oscim.renderer.MapRenderer;
|
||||
import org.oscim.renderer.TileGenerator;
|
||||
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
|
@ -12,7 +12,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.generator;
|
||||
package org.oscim.generator;
|
||||
|
||||
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
|
||||
* 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_BLEND;
|
||||
@ -31,13 +31,14 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
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.utils.GlUtils;
|
||||
import org.oscim.view.MapPosition;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.MapViewPosition;
|
||||
import org.oscim.view.renderer.MapRenderer.TilesData;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
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 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;
|
||||
|
||||
@ -64,9 +65,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
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 ShortBuffer shortBuffer[];
|
||||
@ -77,7 +78,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
private static float[] mMVPMatrix = 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[] mDebugCoords = new float[8];
|
||||
|
||||
// mNextTiles is set by TileLoader and swapped with
|
||||
// mDrawTiles in onDrawFrame in GL thread.
|
||||
@ -99,8 +102,22 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
static ReentrantLock tilelock = 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;
|
||||
|
||||
static boolean[] vertexArray = { false, false };
|
||||
|
||||
// TODO
|
||||
final class GLState {
|
||||
boolean blend = false;
|
||||
boolean depth = false;
|
||||
}
|
||||
|
||||
// scanline fill class used to check tile visibility
|
||||
private static ScanBox mScanBox = new ScanBox() {
|
||||
@Override
|
||||
@ -120,33 +137,35 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
return;
|
||||
|
||||
// add placeholder tiles to show both sides
|
||||
// of date line...
|
||||
// of date line. a little too complicated...
|
||||
for (int x = x1; x < x2; x++) {
|
||||
MapTile holder = null;
|
||||
MapTile tile = null;
|
||||
boolean found = false;
|
||||
|
||||
int xx = x;
|
||||
|
||||
if (x >= 0 && x < xmax)
|
||||
continue;
|
||||
|
||||
int xx = x;
|
||||
if (x < 0)
|
||||
xx = xmax + x;
|
||||
else
|
||||
xx = x - xmax;
|
||||
|
||||
if (xx < 0 || xx >= xmax)
|
||||
if (xx < 0 || xx >= xmax) {
|
||||
// Log.d(TAG, "out of bounds " + y + " " + x + "/" + xx);
|
||||
continue;
|
||||
|
||||
}
|
||||
for (int i = cnt; i < cnt + mHolderCount; i++)
|
||||
if (tiles[i].tileX == x && tiles[i].tileY == y) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found)
|
||||
if (found) {
|
||||
// Log.d(TAG, "already added " + y + " " + x + "/" + xx);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cnt; i++)
|
||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||
@ -154,11 +173,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
break;
|
||||
}
|
||||
|
||||
if (tile == null)
|
||||
if (tile == null) {
|
||||
// Log.d(TAG, "not found " + y + " " + x + "/" + xx);
|
||||
continue;
|
||||
|
||||
// Log.d(TAG, "add placeholder " + y + " " + x + ">>" + xx + " "
|
||||
// + tile);
|
||||
}
|
||||
|
||||
holder = new MapTile(x, y, mZoom);
|
||||
holder.isVisible = true;
|
||||
@ -173,7 +191,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
* the MapView
|
||||
*/
|
||||
public GLRenderer(MapView mapView) {
|
||||
Log.d(TAG, "init MapRenderer");
|
||||
|
||||
mMapView = mapView;
|
||||
mMapViewPosition = mapView.getMapViewPosition();
|
||||
@ -208,14 +225,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mUpdateTiles = false;
|
||||
}
|
||||
|
||||
private static ArrayList<Overlay> mOverlays;
|
||||
|
||||
/**
|
||||
* Called by TileLoader when list of active tiles changed. the list is
|
||||
* copied to mNextTiles to be used in next call to onDrawFrame
|
||||
*
|
||||
* @param tiles
|
||||
* active tiles
|
||||
* @param overlays
|
||||
* ...
|
||||
*/
|
||||
static void updateTiles(TilesData tiles) {
|
||||
static void updateTiles(TilesData tiles, ArrayList<Overlay> overlays) {
|
||||
|
||||
MapTile[] newTiles = tiles.tiles;
|
||||
|
||||
@ -223,6 +244,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
for (int i = 0, n = tiles.cnt; i < n; i++)
|
||||
newTiles[i].lock();
|
||||
|
||||
mOverlays = overlays;
|
||||
|
||||
// dont flip next/drawTiles while copying
|
||||
GLRenderer.tilelock.lock();
|
||||
|
||||
@ -243,28 +266,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
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) {
|
||||
int bg = t.getMapBackground();
|
||||
float[] c = new float[4];
|
||||
@ -276,161 +277,121 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mUpdateColor = true;
|
||||
}
|
||||
|
||||
private int uploadCnt = 0;
|
||||
private static int uploadCnt = 0;
|
||||
|
||||
private boolean uploadTileData(MapTile tile) {
|
||||
// Upload line data to vertex buffer object
|
||||
// Log.d(TAG, "uploadTileData, " + tile);
|
||||
private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) {
|
||||
|
||||
int lineSize = LineRenderer.sizeOf(tile.lineLayers);
|
||||
int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
|
||||
int newSize = lineSize + polySize;
|
||||
|
||||
if (newSize == 0) {
|
||||
LineRenderer.clear(tile.lineLayers);
|
||||
PolygonRenderer.clear(tile.polygonLayers);
|
||||
tile.lineLayers = null;
|
||||
tile.polygonLayers = null;
|
||||
tile.newData = false;
|
||||
int newSize = layers.getSize();
|
||||
if (newSize == 0)
|
||||
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
|
||||
// data is uploaded (or rather the blocking which is probably done to
|
||||
// avoid overwriting)
|
||||
if (uploadCnt >= rotateBuffers) {
|
||||
uploadCnt = 0;
|
||||
// GLES20.glFlush();
|
||||
}
|
||||
|
||||
ShortBuffer sbuf = shortBuffer[uploadCnt];
|
||||
|
||||
// add fill coordinates
|
||||
newSize += 8;
|
||||
if (addFill)
|
||||
newSize += 8;
|
||||
|
||||
// probably not a good idea to do this in gl thread...
|
||||
if (sbuf.capacity() < newSize) {
|
||||
ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
sbuf = bbuf.asShortBuffer();
|
||||
sbuf = ByteBuffer
|
||||
.allocateDirect(newSize * SHORT_BYTES)
|
||||
.order(ByteOrder.nativeOrder())
|
||||
.asShortBuffer();
|
||||
|
||||
shortBuffer[uploadCnt] = sbuf;
|
||||
sbuf.put(mFillCoords, 0, 8);
|
||||
if (addFill)
|
||||
sbuf.put(mFillCoords, 0, 8);
|
||||
} else {
|
||||
sbuf.clear();
|
||||
if (addFill)
|
||||
sbuf.put(mFillCoords, 0, 8);
|
||||
// if (addFill)
|
||||
// sbuf.position(8);
|
||||
}
|
||||
|
||||
sbuf.clear();
|
||||
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);
|
||||
|
||||
layers.compile(sbuf, addFill);
|
||||
sbuf.flip();
|
||||
|
||||
if (newSize != sbuf.remaining()) {
|
||||
Log.d(TAG, "tiles wrong: " + tile + " "
|
||||
Log.d(TAG, "wrong size: "
|
||||
+ newSize + " "
|
||||
+ sbuf.position() + " "
|
||||
+ sbuf.limit() + " "
|
||||
+ sbuf.remaining() + " "
|
||||
+ LineRenderer.sizeOf(tile.lineLayers)
|
||||
+ tile.isLoading + " "
|
||||
+ tile.rel);
|
||||
+ sbuf.remaining());
|
||||
|
||||
tile.newData = false;
|
||||
// tile.newData = false;
|
||||
return false;
|
||||
}
|
||||
newSize *= SHORT_BYTES;
|
||||
|
||||
// reuse memory allocated for vbo when possible and allocated
|
||||
// memory is less then four times the new data
|
||||
if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
|
||||
if (vbo.size > newSize && vbo.size < newSize * 4
|
||||
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
|
||||
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
||||
} else {
|
||||
mBufferMemoryUsage -= tile.vbo.size;
|
||||
tile.vbo.size = newSize;
|
||||
GLES20.glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||
mBufferMemoryUsage += tile.vbo.size;
|
||||
mBufferMemoryUsage -= vbo.size;
|
||||
vbo.size = newSize;
|
||||
GLES20.glBufferData(GL_ARRAY_BUFFER, vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||
mBufferMemoryUsage += vbo.size;
|
||||
}
|
||||
|
||||
uploadCnt++;
|
||||
|
||||
tile.isReady = true;
|
||||
tile.newData = false;
|
||||
|
||||
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() {
|
||||
// try to clear some unused vbo when exceding limit
|
||||
|
||||
if (mBufferMemoryUsage < LIMIT_BUFFERS) {
|
||||
if (CACHE_TILES < CACHE_TILES_MAX)
|
||||
CACHE_TILES += 50;
|
||||
return;
|
||||
}
|
||||
|
||||
// try to clear some unused vbo when exceding limit
|
||||
Log.d(TAG, "buffer object usage: " + mBufferMemoryUsage / MB + "MB");
|
||||
|
||||
int vboIds[] = new int[10];
|
||||
VertexBufferObject[] tmp = new VertexBufferObject[10];
|
||||
mBufferMemoryUsage -= BufferObject.limitUsage(2 * MB);
|
||||
|
||||
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)
|
||||
CACHE_TILES -= 50;
|
||||
}
|
||||
|
||||
private static boolean mRotate = false;
|
||||
|
||||
private static void setMatrix(float[] matrix, MapTile tile,
|
||||
float div, boolean project) {
|
||||
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
|
||||
float x = (float) (tile.pixelX - mapPosition.x * div);
|
||||
@ -448,12 +409,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
matrix[0] = scale;
|
||||
matrix[5] = scale;
|
||||
|
||||
if (mRotate)
|
||||
Matrix.multiplyMM(matrix, 0, mapPosition.rotation, 0, matrix, 0);
|
||||
Matrix.multiplyMM(matrix, 0, mapPosition.viewMatrix, 0, matrix, 0);
|
||||
|
||||
if (project)
|
||||
Matrix.multiplyMM(matrix, 0, mProjMatrix, 0, matrix, 0);
|
||||
|
||||
}
|
||||
|
||||
private static float scaleDiv(MapTile t) {
|
||||
@ -492,14 +451,18 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
| GLES20.GL_DEPTH_BUFFER_BIT
|
||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// get current tiles to draw
|
||||
if (mUpdateTiles) {
|
||||
// get current tiles to draw
|
||||
GLRenderer.tilelock.lock();
|
||||
mUpdateTiles = false;
|
||||
|
||||
TilesData tmp = mDrawTiles;
|
||||
mDrawTiles = mNextTiles;
|
||||
mNextTiles = tmp;
|
||||
mUpdateTiles = false;
|
||||
GLRenderer.tilelock.unlock();
|
||||
|
||||
// force update of mapPosition
|
||||
mMapPosition.zoomLevel = -1;
|
||||
}
|
||||
|
||||
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||
@ -507,14 +470,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
return;
|
||||
}
|
||||
|
||||
mRotate = mMapView.enableRotation || mMapView.enableCompass;
|
||||
|
||||
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||
// coordinates)
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
float[] coords = mTileCoords;
|
||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||
|
||||
for (Overlay overlay : mOverlays) {
|
||||
overlay.update(mMapView);
|
||||
}
|
||||
|
||||
int tileCnt = mDrawTiles.cnt;
|
||||
MapTile[] tiles = mDrawTiles.tiles;
|
||||
|
||||
@ -539,25 +504,12 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
mHolderCount = 0;
|
||||
mScanBox.scan(coords, tiles[0].zoomLevel);
|
||||
tileCnt += mHolderCount;
|
||||
|
||||
// // TODO get the right function: trying to accomodate for the
|
||||
// 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;
|
||||
}
|
||||
|
||||
tileCnt += mHolderCount;
|
||||
|
||||
// Log.d(TAG, "visible: " + tileCnt);
|
||||
|
||||
uploadCnt = 0;
|
||||
int updateTextures = 0;
|
||||
|
||||
@ -579,25 +531,30 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
uploadTileData(tile);
|
||||
continue;
|
||||
}
|
||||
if (tile.holder != null) {
|
||||
if (tile.holder.newData) {
|
||||
uploadTileData(tile.holder);
|
||||
}
|
||||
tile.isReady = tile.holder.isReady;
|
||||
} else if (!tile.isReady) {
|
||||
// check near relatives if they can serve as proxy
|
||||
MapTile rel = tile.rel.parent.tile;
|
||||
if (rel != null && rel.newData) {
|
||||
uploadTileData(rel);
|
||||
} else {
|
||||
for (int c = 0; c < 4; c++) {
|
||||
if (tile.rel.child[c] == null)
|
||||
continue;
|
||||
|
||||
rel = tile.rel.child[c].tile;
|
||||
if (rel != null && rel.newData)
|
||||
uploadTileData(rel);
|
||||
}
|
||||
if (tile.holder != null) {
|
||||
// load tile that is referenced by this holder
|
||||
if (tile.holder.newData)
|
||||
uploadTileData(tile.holder);
|
||||
|
||||
tile.isReady = tile.holder.isReady;
|
||||
|
||||
} else if (!tile.isReady) {
|
||||
// check near relatives than can serve as proxy
|
||||
if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
|
||||
MapTile rel = tile.rel.parent.tile;
|
||||
if (rel.newData)
|
||||
uploadTileData(rel);
|
||||
|
||||
continue;
|
||||
}
|
||||
for (int c = 0; c < 4; c++) {
|
||||
if ((tile.proxies & 1 << c) == 0)
|
||||
continue;
|
||||
|
||||
MapTile rel = tile.rel.child[c].tile;
|
||||
if (rel != null && rel.newData)
|
||||
uploadTileData(rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -620,7 +577,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
MapTile t = tiles[i];
|
||||
if (t.isVisible && !t.isReady && (t.holder == null))
|
||||
@ -639,7 +598,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
int z = mapPosition.zoomLevel;
|
||||
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);
|
||||
if (scale < 1)
|
||||
scale = 1;
|
||||
@ -647,7 +607,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (z >= TileGenerator.STROKE_MAX_ZOOM_LEVEL)
|
||||
TextRenderer.beginDraw(scale / FloatMath.sqrt(s), mProjMatrix);
|
||||
else
|
||||
TextRenderer.beginDraw(1 / s, mProjMatrix);
|
||||
TextRenderer.beginDraw(1f / s, mProjMatrix);
|
||||
|
||||
for (int i = 0; i < tileCnt; i++) {
|
||||
MapTile t = tiles[i];
|
||||
@ -669,12 +629,53 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
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) {
|
||||
GLES20.glFinish();
|
||||
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();
|
||||
}
|
||||
|
||||
@ -701,54 +702,49 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
||||
|
||||
LineLayer ll = tile.lineLayers;
|
||||
PolygonLayer pl = tile.polygonLayers;
|
||||
|
||||
boolean clipped = false;
|
||||
int simpleShader = mRotate ? 0 : 1;
|
||||
int simpleShader = 0; // mRotate ? 0 : 1;
|
||||
|
||||
for (; pl != null || ll != null;) {
|
||||
int lnext = Integer.MAX_VALUE;
|
||||
int pnext = Integer.MAX_VALUE;
|
||||
for (Layer l = tile.layers.layers; l != null;) {
|
||||
|
||||
if (ll != null)
|
||||
lnext = ll.layer;
|
||||
switch (l.type) {
|
||||
case Layer.POLYGON:
|
||||
|
||||
if (pl != null)
|
||||
pnext = pl.layer;
|
||||
|
||||
if (pl != null && pnext < lnext) {
|
||||
GLES20.glDisable(GL_BLEND);
|
||||
pl = PolygonRenderer.drawPolygons(pos, pl, lnext, mvp, !clipped);
|
||||
clipped = true;
|
||||
} else {
|
||||
// FIXME
|
||||
if (!clipped) {
|
||||
PolygonRenderer.drawPolygons(pos, null, 0, mvp, true);
|
||||
GLES20.glDisable(GL_BLEND);
|
||||
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
|
||||
clipped = true;
|
||||
}
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
ll = LineRenderer.drawLines(pos, ll, pnext, mvp, div,
|
||||
simpleShader, tile.lineOffset);
|
||||
break;
|
||||
|
||||
case Layer.LINE:
|
||||
if (!clipped) {
|
||||
PolygonRenderer.draw(pos, null, mvp, true, true);
|
||||
clipped = true;
|
||||
}
|
||||
|
||||
GLES20.glEnable(GL_BLEND);
|
||||
l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
|
||||
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) {
|
||||
int drawn = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (tile.rel.child[i] == null)
|
||||
if ((tile.proxies & 1 << i) == 0)
|
||||
continue;
|
||||
|
||||
MapTile c = tile.rel.child[i].tile;
|
||||
if (c == null)
|
||||
continue;
|
||||
|
||||
// if (!isVisible(c)) {
|
||||
// drawn++;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
if (c.isReady) {
|
||||
drawTile(c);
|
||||
@ -812,13 +808,24 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
// use this to scale only the view to see better which tiles are
|
||||
// rendered
|
||||
float s = MapViewPosition.VIEW_SCALE;
|
||||
Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
||||
s * height, -s * height, 1, 2);
|
||||
float aspect = mHeight / (float) mWidth;
|
||||
|
||||
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
|
||||
mProjMatrix[10] = 0;
|
||||
@ -830,8 +837,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
mMapView.redrawMap();
|
||||
return;
|
||||
}
|
||||
mNewSurface = false;
|
||||
|
||||
mNewSurface = false;
|
||||
mBufferMemoryUsage = 0;
|
||||
|
||||
int numTiles = (mWidth / (Tile.TILE_SIZE / 2) + 2)
|
||||
@ -839,14 +846,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
// Set up vertex buffer objects
|
||||
int numVBO = (CACHE_TILES + (numTiles * 2));
|
||||
int[] mVboIds = new int[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]));
|
||||
BufferObject.init(numVBO);
|
||||
|
||||
// Set up textures
|
||||
TextRenderer.setup(numTiles);
|
||||
@ -854,6 +854,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
if (mClearColor != null)
|
||||
mUpdateColor = true;
|
||||
|
||||
vertexArray[0] = false;
|
||||
vertexArray[1] = false;
|
||||
|
||||
// FIXME this should be synchronized
|
||||
mMapView.redrawMap();
|
||||
}
|
||||
@ -862,20 +865,19 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
void clearTiles(int numTiles) {
|
||||
mDrawTiles = new TilesData(numTiles);
|
||||
mNextTiles = new TilesData(numTiles);
|
||||
mMapPosition.zoomLevel = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
|
||||
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||
Log.d(TAG, "Extensions: " + ext);
|
||||
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||
// Log.d(TAG, "Extensions: " + ext);
|
||||
|
||||
LineRenderer.init();
|
||||
PolygonRenderer.init();
|
||||
TextRenderer.init();
|
||||
|
||||
mNewSurface = true;
|
||||
// mUpdateColor = true;
|
||||
TextureRenderer.init();
|
||||
TextureObject.init(10);
|
||||
|
||||
// glEnable(GL_SCISSOR_TEST);
|
||||
// glScissor(0, 0, mWidth, mHeight);
|
||||
@ -883,51 +885,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||
GLES20.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
mNewSurface = true;
|
||||
}
|
||||
|
||||
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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
package org.oscim.renderer;
|
||||
|
||||
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.utils.GlUtils;
|
||||
import org.oscim.view.MapPosition;
|
||||
|
||||
import android.graphics.Paint.Cap;
|
||||
import android.opengl.GLES20;
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
@ -27,7 +28,7 @@ import android.util.Log;
|
||||
class 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_TEX_OFFSET = 4;
|
||||
@ -40,6 +41,7 @@ class LineRenderer {
|
||||
private static int[] hLineMatrix = new int[2];
|
||||
private static int[] hLineScale = new int[2];
|
||||
private static int[] hLineWidth = new int[2];
|
||||
private static int[] hLineMode = new int[2];
|
||||
|
||||
static boolean init() {
|
||||
lineProgram[0] = GlUtils.createProgram(Shaders.lineVertexShader,
|
||||
@ -53,6 +55,7 @@ class LineRenderer {
|
||||
hLineScale[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_wscale");
|
||||
hLineWidth[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_width");
|
||||
hLineColor[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_color");
|
||||
hLineMode[0] = GLES20.glGetUniformLocation(lineProgram[0], "u_mode");
|
||||
|
||||
hLineVertexPosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_position");
|
||||
hLineTexturePosition[0] = GLES20.glGetAttribLocation(lineProgram[0], "a_st");
|
||||
@ -68,6 +71,7 @@ class LineRenderer {
|
||||
hLineScale[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_wscale");
|
||||
hLineWidth[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_width");
|
||||
hLineColor[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_color");
|
||||
hLineMode[1] = GLES20.glGetUniformLocation(lineProgram[1], "u_mode");
|
||||
|
||||
hLineVertexPosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_position");
|
||||
hLineTexturePosition[1] = GLES20.glGetAttribLocation(lineProgram[1], "a_st");
|
||||
@ -75,8 +79,8 @@ class LineRenderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
static LineLayer drawLines(MapPosition pos, LineLayer layer, int next,
|
||||
float[] matrix, float div, int mode, int bufferOffset) {
|
||||
static Layer draw(MapPosition pos, Layer layer, float[] matrix, float div,
|
||||
int mode, int bufferOffset) {
|
||||
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
@ -86,8 +90,20 @@ class LineRenderer {
|
||||
|
||||
GLES20.glUseProgram(lineProgram[mode]);
|
||||
|
||||
GLES20.glEnableVertexAttribArray(hLineVertexPosition[mode]);
|
||||
GLES20.glEnableVertexAttribArray(hLineTexturePosition[mode]);
|
||||
int va = hLineVertexPosition[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,
|
||||
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:
|
||||
// only works with orthographic projection
|
||||
float s = scale / div;
|
||||
float pixel = 2.0f / s;
|
||||
float pixel = 0;
|
||||
|
||||
if (mode == 0)
|
||||
pixel = 0;
|
||||
if (mode == 1)
|
||||
pixel = 1.5f / s;
|
||||
|
||||
GLES20.glUniform1f(hLineScale[mode], pixel);
|
||||
int lineMode = 0;
|
||||
GLES20.glUniform1i(hLineMode[mode], lineMode);
|
||||
|
||||
// line scale factor (for non fixed lines)
|
||||
float lineScale = FloatMath.sqrt(s);
|
||||
@ -115,10 +133,11 @@ class LineRenderer {
|
||||
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||
float width = 1;
|
||||
|
||||
LineLayer l = layer;
|
||||
for (; l != null && l.layer < next; l = l.next) {
|
||||
Layer l = layer;
|
||||
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)
|
||||
continue;
|
||||
|
||||
@ -134,23 +153,33 @@ class LineRenderer {
|
||||
blur = false;
|
||||
}
|
||||
|
||||
if (l.isOutline) {
|
||||
for (LineLayer o = l.outlines; o != null; o = o.outlines) {
|
||||
if (line.outline) {
|
||||
for (LineLayer o = ll.outlines; o != null; o = o.outlines) {
|
||||
|
||||
if (o.line.fixed || strokeMaxZoom) {
|
||||
width = (l.width + o.width) / s;
|
||||
width = (ll.width + o.width) / s;
|
||||
} else {
|
||||
width = l.width / s + o.width / lineScale;
|
||||
width = ll.width / s + o.width / lineScale;
|
||||
}
|
||||
|
||||
GLES20.glUniform1f(hLineWidth[mode], width);
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
@ -158,173 +187,37 @@ class LineRenderer {
|
||||
if (line.fixed || strokeMaxZoom) {
|
||||
// invert scaling of extrusion vectors so that line width
|
||||
// stays the same.
|
||||
width = l.width / s;
|
||||
width = ll.width / s;
|
||||
} else {
|
||||
width = l.width / lineScale;
|
||||
width = ll.width / lineScale;
|
||||
}
|
||||
|
||||
GLES20.glUniform1f(hLineWidth[mode], width);
|
||||
|
||||
if (line.blur != 0) {
|
||||
blurScale = (l.width / lineScale) * line.blur;
|
||||
blurScale = (ll.width / lineScale) * line.blur;
|
||||
GLES20.glUniform1f(hLineScale[mode], blurScale);
|
||||
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.glDisableVertexAttribArray(hLineVertexPosition[mode]);
|
||||
GLES20.glDisableVertexAttribArray(hLineTexturePosition[mode]);
|
||||
// GLES20.glDisableVertexAttribArray(hLineVertexPosition[mode]);
|
||||
// GLES20.glDisableVertexAttribArray(hLineTexturePosition[mode]);
|
||||
|
||||
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
|
||||
* 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.Collections;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.generator.JobTile;
|
||||
import org.oscim.renderer.layer.VertexPool;
|
||||
import org.oscim.theme.RenderTheme;
|
||||
import org.oscim.utils.GlConfigChooser;
|
||||
import org.oscim.view.MapPosition;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.MapViewPosition;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
|
||||
import android.content.Context;
|
||||
import android.opengl.GLSurfaceView;
|
||||
@ -36,7 +37,7 @@ public class MapRenderer extends GLSurfaceView {
|
||||
private GLRenderer mRenderer;
|
||||
|
||||
private static final int MAX_TILES_IN_QUEUE = 40;
|
||||
private static final int CACHE_THRESHOLD = 50;
|
||||
private static final int CACHE_THRESHOLD = 10;
|
||||
|
||||
private static MapView mMapView;
|
||||
|
||||
@ -52,6 +53,8 @@ public class MapRenderer extends GLSurfaceView {
|
||||
// tiles that have new data to upload, see passTile()
|
||||
private static ArrayList<MapTile> mTilesLoaded;
|
||||
|
||||
private static ArrayList<Overlay> mOverlays;
|
||||
|
||||
// TODO current boundary tiles, values used to check if position has
|
||||
// changed for updating current tile list
|
||||
|
||||
@ -65,7 +68,8 @@ public class MapRenderer extends GLSurfaceView {
|
||||
// private static int[] mZoomLevels;
|
||||
|
||||
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
|
||||
// GLThread
|
||||
@ -90,14 +94,14 @@ public class MapRenderer extends GLSurfaceView {
|
||||
int xmax = 1 << mZoom;
|
||||
|
||||
for (int x = x1; x < x2; x++) {
|
||||
// MapTile holder = null;
|
||||
MapTile tile = null;
|
||||
|
||||
// boolean found = false;
|
||||
if (cnt == max) {
|
||||
Log.d(TAG, "reached max currentTiles " + max);
|
||||
Log.d(TAG, "reached maximum for currentTiles " + max);
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE to myself: do not modify x, argh !!!
|
||||
int xx = x;
|
||||
|
||||
if (x < 0 || x >= xmax) {
|
||||
@ -107,12 +111,11 @@ public class MapRenderer extends GLSurfaceView {
|
||||
else
|
||||
xx = x - xmax;
|
||||
|
||||
if (xx < 0 || xx >= xmax) {
|
||||
// Log.d(TAG, "tile out of bounds " + y + " " + xx);
|
||||
if (xx < 0 || xx >= xmax)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check if tile is already added
|
||||
for (int i = 0; i < cnt; i++)
|
||||
if (tiles[i].tileX == xx && tiles[i].tileY == y) {
|
||||
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);
|
||||
|
||||
mMapView = mapView;
|
||||
@ -148,6 +172,7 @@ public class MapRenderer extends GLSurfaceView {
|
||||
mJobList = new ArrayList<JobTile>();
|
||||
mTiles = new ArrayList<MapTile>();
|
||||
mTilesLoaded = new ArrayList<MapTile>(30);
|
||||
mOverlays = new ArrayList<Overlay>(5);
|
||||
|
||||
VertexPool.init();
|
||||
QuadTree.init();
|
||||
@ -163,7 +188,7 @@ public class MapRenderer extends GLSurfaceView {
|
||||
* @param clear
|
||||
* whether to clear and reload all tiles
|
||||
*/
|
||||
public void updateMap(boolean clear) {
|
||||
public void updateMap(final boolean clear) {
|
||||
boolean changedPos = false;
|
||||
|
||||
if (mMapView == null)
|
||||
@ -173,14 +198,24 @@ public class MapRenderer extends GLSurfaceView {
|
||||
// make sure onDrawFrame is not running
|
||||
GLRenderer.drawlock.lock();
|
||||
// remove all tiles references
|
||||
Log.d(TAG, "CLEAR");
|
||||
for (MapTile t : mTiles)
|
||||
clearTile(t);
|
||||
Log.d(TAG, "CLEAR " + mInitial);
|
||||
|
||||
if (clear) {
|
||||
for (MapTile t : mTiles)
|
||||
clearTile(t);
|
||||
} else {
|
||||
VertexPool.init();
|
||||
}
|
||||
|
||||
mTiles.clear();
|
||||
mTilesLoaded.clear();
|
||||
|
||||
QuadTree.init();
|
||||
|
||||
// TODO clear overlay items data
|
||||
mOverlays.clear();
|
||||
mOverlays.add(new Overlay());
|
||||
|
||||
// set up TileData arrays that are passed to gl-thread
|
||||
int num = mWidth;
|
||||
if (mWidth < mHeight)
|
||||
@ -198,19 +233,25 @@ public class MapRenderer extends GLSurfaceView {
|
||||
// mZoomLevels = mapInfo.zoomLevel;
|
||||
GLRenderer.drawlock.unlock();
|
||||
|
||||
changedPos = true;
|
||||
// .. make sure mMapPosition will be updated
|
||||
mMapPosition.zoomLevel = -1;
|
||||
|
||||
mInitial = false;
|
||||
}
|
||||
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
||||
float[] coords = mTileCoords;
|
||||
changedPos = mMapViewPosition.getMapPosition(mapPosition, coords);
|
||||
|
||||
if (!changedPos)
|
||||
return;
|
||||
|
||||
float s = Tile.TILE_SIZE;
|
||||
// load some additional tiles more than currently visible
|
||||
float scale = mapPosition.scale * 0.75f;
|
||||
float px = (float) mapPosition.x;
|
||||
float py = (float) mapPosition.y;
|
||||
float[] coords = mTileCoords;
|
||||
|
||||
int zdir = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (mBoundaryTiles[i] != (int) coords[i]) {
|
||||
changedPos = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
mBoundaryTiles[i] = (int) coords[i];
|
||||
// this does not work reloably with tilt and rotation
|
||||
// changedPos = false;
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// if (mBoundaryTiles[i] != (int) coords[i]) {
|
||||
// changedPos = true;
|
||||
// break;
|
||||
// }
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// mBoundaryTiles[i] = (int) coords[i];
|
||||
|
||||
// TODO all following should probably be done in an idler instead
|
||||
// to drain queued events. need to check how android handles things.
|
||||
|
||||
if (changedPos) {
|
||||
updateVisibleList(mapPosition, zdir);
|
||||
boolean changed = updateVisibleList(mapPosition, zdir);
|
||||
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
|
||||
if (changed) {
|
||||
int remove = mTiles.size() - GLRenderer.CACHE_TILES;
|
||||
if (remove > CACHE_THRESHOLD)
|
||||
limitCache(mapPosition, remove);
|
||||
|
||||
limitLoadQueue();
|
||||
} else {
|
||||
if (!MapView.debugFrameTime)
|
||||
requestRender();
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,8 +294,9 @@ public class MapRenderer extends GLSurfaceView {
|
||||
* the current MapPosition
|
||||
* @param zdir
|
||||
* 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();
|
||||
// set non processed tiles to isLoading == false
|
||||
@ -265,14 +305,16 @@ public class MapRenderer extends GLSurfaceView {
|
||||
mScanBox.scan(mTileCoords, mapPosition.zoomLevel);
|
||||
// Log.d(TAG, "visible: " + mCurrentTiles.cnt + "/" +
|
||||
// mCurrentTiles.tiles.length);
|
||||
GLRenderer.updateTiles(mCurrentTiles);
|
||||
GLRenderer.updateTiles(mCurrentTiles, mOverlays);
|
||||
|
||||
// note: this sets isLoading == true for all job tiles
|
||||
if (mJobList.size() > 0) {
|
||||
updateTileDistances(mJobList, mapPosition);
|
||||
Collections.sort(mJobList);
|
||||
mMapView.addJobs(mJobList);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* package */
|
||||
@ -342,15 +384,15 @@ public class MapRenderer extends GLSurfaceView {
|
||||
t.isLoading = false;
|
||||
t.isReady = false;
|
||||
|
||||
LineRenderer.clear(t.lineLayers);
|
||||
PolygonRenderer.clear(t.polygonLayers);
|
||||
if (t.layers != null) {
|
||||
t.layers.clear();
|
||||
t.layers = null;
|
||||
}
|
||||
|
||||
t.labels = null;
|
||||
t.lineLayers = null;
|
||||
t.polygonLayers = null;
|
||||
|
||||
if (t.vbo != null) {
|
||||
GLRenderer.addVBO(t.vbo);
|
||||
BufferObject.release(t.vbo);
|
||||
t.vbo = null;
|
||||
}
|
||||
if (t.texture != null)
|
||||
@ -364,7 +406,7 @@ public class MapRenderer extends GLSurfaceView {
|
||||
byte zoom = mapPosition.zoomLevel;
|
||||
long x = (long) mapPosition.x;
|
||||
long y = (long) mapPosition.y;
|
||||
|
||||
// long center = Tile.TILE_SIZE << (zoom - 1);
|
||||
int diff;
|
||||
long dx, dy;
|
||||
|
||||
@ -380,6 +422,8 @@ public class MapRenderer extends GLSurfaceView {
|
||||
dy = (t.pixelY + h) - y;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)) *
|
||||
// 0.25f;
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
t.distance = FloatMath.sqrt((dx * dx + dy * dy)) * 0.25f;
|
||||
} else if (diff > 0) {
|
||||
// tile zoom level is child of current
|
||||
@ -392,6 +436,8 @@ public class MapRenderer extends GLSurfaceView {
|
||||
dx = ((t.pixelX + h) >> (diff >> 1)) - x;
|
||||
dy = ((t.pixelY + h) >> (diff >> 1)) - y;
|
||||
}
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? 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
|
||||
dx = ((t.pixelX + h) << -diff) - x;
|
||||
dy = ((t.pixelY + h) << -diff) - y;
|
||||
|
||||
// dx %= center;
|
||||
// dy %= center;
|
||||
// t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? 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) {
|
||||
int size = mTiles.size();
|
||||
|
||||
// remove orphaned tiles
|
||||
// remove tiles that were never loaded
|
||||
for (int i = 0; i < size;) {
|
||||
MapTile t = mTiles.get(i);
|
||||
// make sure tile cannot be used by GL or MapWorker Thread
|
||||
if (t.isLocked() || t.isActive()) {
|
||||
i++;
|
||||
} else {
|
||||
// Log.d(TAG, "remove empty tile" + t);
|
||||
clearTile(t);
|
||||
mTiles.remove(i);
|
||||
remove--;
|
||||
@ -432,32 +478,30 @@ public class MapRenderer extends GLSurfaceView {
|
||||
Collections.sort(mTiles);
|
||||
|
||||
for (int i = 1; i < remove; i++) {
|
||||
|
||||
MapTile t = mTiles.remove(size - i);
|
||||
|
||||
synchronized (t) {
|
||||
if (t.isLocked()) {
|
||||
// dont remove tile used by renderthread
|
||||
Log.d(TAG, "X not removing " + t
|
||||
// + " " + t.isLocked
|
||||
+ " " + t.distance);
|
||||
|
||||
mTiles.add(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t.isLoading) {
|
||||
// NOTE: if we add tile back then on next limitCache
|
||||
// the tile will be removed. clearTile could interfere with
|
||||
// MapGenerator. so clear in passTile() instead.
|
||||
// mTiles.add(t);
|
||||
t.isLoading = false;
|
||||
Log.d(TAG, "X cancel loading " + t + " " + t.distance);
|
||||
continue;
|
||||
}
|
||||
|
||||
clearTile(t);
|
||||
if (t.isLocked()) {
|
||||
// dont remove tile used by GLRenderer
|
||||
Log.d(TAG, "X not removing " + t + " " + t.distance);
|
||||
mTiles.add(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t.isLoading) {
|
||||
// NOTE: if we add tile back and set loading=false, on next
|
||||
// limitCache the tile will be removed. clearTile could
|
||||
// interfere with TileGenerator. so clear in passTile()
|
||||
// instead.
|
||||
// ... 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);
|
||||
continue;
|
||||
}
|
||||
|
||||
clearTile(t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -469,11 +513,11 @@ public class MapRenderer extends GLSurfaceView {
|
||||
|
||||
synchronized (mTilesLoaded) {
|
||||
|
||||
// remove tiles uploaded to vbo
|
||||
// remove tiles already uploaded to vbo
|
||||
for (int i = 0; i < size;) {
|
||||
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);
|
||||
size--;
|
||||
continue;
|
||||
@ -484,32 +528,22 @@ public class MapRenderer extends GLSurfaceView {
|
||||
if (size < MAX_TILES_IN_QUEUE)
|
||||
return;
|
||||
|
||||
// Log.d(TAG, "queue: " + mTilesLoaded.size() + " " + size + " "
|
||||
// + (size - MAX_TILES_IN_QUEUE / 2));
|
||||
|
||||
// clear loaded but not used tiles
|
||||
for (int i = 0, n = size - MAX_TILES_IN_QUEUE / 2; i < n; n--) {
|
||||
|
||||
MapTile t = mTilesLoaded.get(i);
|
||||
|
||||
synchronized (t) {
|
||||
if (t.rel == null) {
|
||||
mTilesLoaded.remove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t.isLocked()) {
|
||||
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
||||
// t.isActive);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Log.d(TAG, "remove unused tile data: " + t);
|
||||
mTilesLoaded.remove(i);
|
||||
mTiles.remove(t);
|
||||
clearTile(t);
|
||||
if (t.isLocked()) {
|
||||
// Log.d(TAG, "keep unused tile data: " + t + " " +
|
||||
// t.isActive);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Log.d(TAG, "remove unused tile data: " + t);
|
||||
mTilesLoaded.remove(i);
|
||||
mTiles.remove(t);
|
||||
clearTile(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,7 +568,7 @@ public class MapRenderer extends GLSurfaceView {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRenderer.setVBO(tile);
|
||||
tile.vbo = BufferObject.get();
|
||||
|
||||
if (tile.vbo == null) {
|
||||
Log.d(TAG, "no VBOs left for " + tile);
|
||||
@ -573,79 +607,4 @@ public class MapRenderer extends GLSurfaceView {
|
||||
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
}
|
||||
|
||||
// private static void updateVisibleList(MapPosition mapPosition, int zdir)
|
||||
// {
|
||||
// double x = mapPosition.x;
|
||||
// double y = mapPosition.y;
|
||||
// byte zoomLevel = mapPosition.zoomLevel;
|
||||
// float scale = mapPosition.scale;
|
||||
//
|
||||
// double add = 1.0f / scale;
|
||||
// int offsetX = (int) ((mWidth >> 1) * add) + Tile.TILE_SIZE;
|
||||
// int offsetY = (int) ((mHeight >> 1) * add) + Tile.TILE_SIZE;
|
||||
//
|
||||
// long pixelRight = (long) x + offsetX;
|
||||
// long pixelBottom = (long) y + offsetY;
|
||||
// long pixelLeft = (long) x - offsetX;
|
||||
// long pixelTop = (long) y - offsetY;
|
||||
//
|
||||
// int tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel);
|
||||
// int tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel);
|
||||
// int tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel);
|
||||
// int tileBottom = MercatorProjection.pixelYToTileY(pixelBottom,
|
||||
// zoomLevel);
|
||||
//
|
||||
// mJobList.clear();
|
||||
//
|
||||
// // set non processed tiles to isLoading == false
|
||||
// mMapView.addJobs(null);
|
||||
//
|
||||
// int tiles = 0;
|
||||
// int max = mCurrentTiles.tiles.length - 1;
|
||||
//
|
||||
// // boolean fetchChildren = false;
|
||||
// // boolean fetchParent = false;
|
||||
// // boolean fetchProxy = false;
|
||||
// // if (mZoomLevels != null) {
|
||||
// // // check MapDatabase zoom-level-mapping
|
||||
// // if (mZoomLevels[zoomLevel] == 0) {
|
||||
// // mCurrentTiles.cnt = 0;
|
||||
// // mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
// // return;
|
||||
// // }
|
||||
// //
|
||||
// // if (mZoomLevels[zoomLevel] > zoomLevel) {
|
||||
// // fetchChildren = true;
|
||||
// // fetchProxy = true;
|
||||
// //
|
||||
// // } else if (mZoomLevels[zoomLevel] < zoomLevel) {
|
||||
// // fetchParent = true;
|
||||
// // fetchProxy = true;
|
||||
// // }
|
||||
// // }
|
||||
//
|
||||
// for (int yy = tileTop; yy <= tileBottom; yy++) {
|
||||
// for (int xx = tileLeft; xx <= tileRight; xx++) {
|
||||
//
|
||||
// if (tiles == max)
|
||||
// break;
|
||||
//
|
||||
// // MapTile tile =
|
||||
// addTile(xx, yy, zoomLevel, zdir);
|
||||
// // mCurrentTiles.tiles[tiles++] = tile;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // pass new tile list to glThread
|
||||
// mCurrentTiles.cnt = tiles;
|
||||
// mCurrentTiles = GLRenderer.updateTiles(mCurrentTiles);
|
||||
//
|
||||
// // note: this sets isLoading == true for all job tiles
|
||||
// if (mJobList.size() > 0) {
|
||||
// updateTileDistances(mJobList, mapPosition);
|
||||
// Collections.sort(mJobList);
|
||||
// mMapView.addJobs(mJobList);
|
||||
// }
|
||||
// }
|
||||
}
|
@ -12,9 +12,10 @@
|
||||
* 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.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 {
|
||||
|
||||
@ -22,26 +23,15 @@ class MapTile extends JobTile {
|
||||
* VBO layout: - 16 bytes fill coordinates, n bytes polygon vertices, m
|
||||
* bytes lines vertices
|
||||
*/
|
||||
VertexBufferObject vbo;
|
||||
|
||||
/**
|
||||
* polygonOffset in vbo is always 16 bytes,
|
||||
*/
|
||||
int lineOffset;
|
||||
BufferObject vbo;
|
||||
|
||||
TextTexture texture;
|
||||
|
||||
/**
|
||||
* Tile data set by TileGenerator:
|
||||
*/
|
||||
LineLayer lineLayers;
|
||||
PolygonLayer polygonLayers;
|
||||
TextItem labels;
|
||||
|
||||
/**
|
||||
* tile is used by render thread. set by updateVisibleList (main thread).
|
||||
*/
|
||||
// boolean isLocked;
|
||||
Layers layers;
|
||||
|
||||
/**
|
||||
* tile has new data to upload to gl
|
||||
@ -59,7 +49,7 @@ class MapTile extends JobTile {
|
||||
boolean isVisible;
|
||||
|
||||
/**
|
||||
* pointer to access relatives in TileTree
|
||||
* pointer to access relatives in QuadTree
|
||||
*/
|
||||
QuadTree rel;
|
||||
|
||||
@ -74,12 +64,16 @@ class MapTile extends JobTile {
|
||||
|
||||
// counting the tiles that use this tile as proxy
|
||||
byte refs;
|
||||
|
||||
byte locked;
|
||||
|
||||
// this tile sits in fo another tile. e.g. x:-1,y:0,z:1 for x:1,y:0
|
||||
// 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(int tileX, int tileY, byte zoomLevel) {
|
||||
super(tileX, tileY, zoomLevel);
|
||||
}
|
||||
|
||||
boolean isActive() {
|
||||
return isLoading || newData || isReady;
|
||||
}
|
||||
@ -146,9 +140,4 @@ class MapTile extends JobTile {
|
||||
}
|
||||
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
|
||||
* 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_EQUAL;
|
||||
@ -38,17 +38,18 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
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.view.MapPosition;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
class 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 STENCIL_BITS = 8;
|
||||
|
||||
@ -88,9 +89,6 @@ class PolygonRenderer {
|
||||
/* do not modify stencil buffer */
|
||||
glStencilMask(0);
|
||||
|
||||
/* only draw where nothing was drawn yet */
|
||||
glEnable(GLES20.GL_DEPTH_TEST);
|
||||
|
||||
for (int c = mStart; c < mCount; c++) {
|
||||
PolygonLayer l = mFillPolys[c];
|
||||
|
||||
@ -162,14 +160,25 @@ class PolygonRenderer {
|
||||
// stencil buffer index to start fill
|
||||
private static int mStart;
|
||||
|
||||
static PolygonLayer drawPolygons(MapPosition pos, PolygonLayer layer, int next,
|
||||
float[] matrix, boolean first) {
|
||||
static Layer draw(MapPosition pos, Layer layer,
|
||||
float[] matrix, boolean first, boolean clip) {
|
||||
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
|
||||
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,
|
||||
false, 0, POLYGON_VERTICES_DATA_POS_OFFSET);
|
||||
@ -179,8 +188,6 @@ class PolygonRenderer {
|
||||
// use stencilbuffer method for polygon drawing
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
|
||||
PolygonLayer l = layer;
|
||||
|
||||
if (first) {
|
||||
mCount = 0;
|
||||
mStart = 0;
|
||||
@ -188,12 +195,15 @@ class PolygonRenderer {
|
||||
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)
|
||||
if (l.area.fade > 0 && l.area.fade > zoom)
|
||||
if (pl.area.fade > 0 && pl.area.fade > zoom)
|
||||
continue;
|
||||
|
||||
if (mCount == 0) {
|
||||
if (mCount == mStart) {
|
||||
// clear stencilbuffer (tile region)
|
||||
|
||||
// disable drawing to framebuffer
|
||||
@ -205,7 +215,7 @@ class PolygonRenderer {
|
||||
|
||||
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
|
||||
|
||||
if (first) {
|
||||
if (clip) {
|
||||
// draw clip-region into depth buffer:
|
||||
// this is used for lines and polygons
|
||||
|
||||
@ -214,14 +224,15 @@ class PolygonRenderer {
|
||||
|
||||
// to prevent overdraw gl_less restricts
|
||||
// the clip to the area where no other
|
||||
// tile was drawn
|
||||
// tile has drawn
|
||||
GLES20.glDepthFunc(GLES20.GL_LESS);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
if (first) {
|
||||
if (clip) {
|
||||
first = false;
|
||||
clip = false;
|
||||
// dont modify depth buffer
|
||||
GLES20.glDepthMask(false);
|
||||
// only draw to this tile
|
||||
@ -232,23 +243,26 @@ class PolygonRenderer {
|
||||
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
|
||||
|
||||
// no need for depth test while drawing stencil
|
||||
glDisable(GLES20.GL_DEPTH_TEST);
|
||||
if (clip)
|
||||
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
|
||||
glStencilMask(1 << mCount++);
|
||||
@ -257,15 +271,23 @@ class PolygonRenderer {
|
||||
|
||||
// draw up to 8 layers into stencil buffer
|
||||
if (mCount == STENCIL_BITS) {
|
||||
/* only draw where nothing was drawn yet */
|
||||
if (clip)
|
||||
glEnable(GLES20.GL_DEPTH_TEST);
|
||||
|
||||
fillPolygons(zoom, scale);
|
||||
mCount = 0;
|
||||
mStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mCount > 0)
|
||||
fillPolygons(zoom, scale);
|
||||
if (mCount > 0) {
|
||||
/* 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
|
||||
// if (mCount > 5){
|
||||
// mCount = 0;
|
||||
@ -274,19 +296,20 @@ class PolygonRenderer {
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
if (first)
|
||||
if (clip && first)
|
||||
drawDepthClip();
|
||||
|
||||
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||
// GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
static void debugDraw(float[] matrix, float[] coords) {
|
||||
static void debugDraw(float[] matrix, float[] coords, int color) {
|
||||
|
||||
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder());
|
||||
FloatBuffer buf = mDebugFill.asFloatBuffer();
|
||||
@ -303,12 +326,15 @@ class PolygonRenderer {
|
||||
|
||||
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
|
||||
|
||||
glUniform4fv(hPolygonColor, 1, debugFillColor, 0);
|
||||
if (color == 0)
|
||||
glUniform4fv(hPolygonColor, 1, debugFillColor, 0);
|
||||
else
|
||||
glUniform4fv(hPolygonColor, 1, debugFillColor2, 0);
|
||||
|
||||
glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
GlUtils.checkGlError("draw debug");
|
||||
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||
// GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
|
||||
}
|
||||
|
||||
static void drawDepthClip() {
|
||||
@ -322,55 +348,4 @@ class PolygonRenderer {
|
||||
glColorMask(true, true, true, true);
|
||||
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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@ -37,17 +37,9 @@ class QuadTree {
|
||||
MapTile tile;
|
||||
|
||||
static void init() {
|
||||
|
||||
pool = null;
|
||||
root = new QuadTree();
|
||||
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) {
|
||||
@ -90,8 +82,6 @@ class QuadTree {
|
||||
int y = tile.tileY;
|
||||
int z = tile.zoomLevel;
|
||||
|
||||
QuadTree cur;
|
||||
|
||||
// if (x < 0 || x >= 1 << z) {
|
||||
// Log.d(TAG, "invalid position");
|
||||
// return null;
|
||||
@ -109,7 +99,7 @@ class QuadTree {
|
||||
|
||||
leaf.refs++;
|
||||
|
||||
cur = leaf.child[id];
|
||||
QuadTree cur = leaf.child[id];
|
||||
|
||||
if (cur != null) {
|
||||
leaf = cur;
|
@ -15,7 +15,7 @@
|
||||
|
||||
/* 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.Log;
|
||||
@ -103,6 +103,7 @@ public abstract class ScanBox {
|
||||
scanSpans(ca, bc);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
private static final int MAX_SLOPE = 4;
|
||||
|
||||
private void scanSpans(Edge e0, Edge e1) {
|
@ -13,9 +13,9 @@
|
||||
* 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 = ""
|
||||
+ "precision mediump float;"
|
||||
@ -54,40 +54,119 @@ class Shaders {
|
||||
+ "precision mediump float;"
|
||||
+ "uniform float u_wscale;"
|
||||
+ "uniform float u_width;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "const float zero = 0.0;"
|
||||
+ "void main() {"
|
||||
+ " float len;"
|
||||
+ " if (v_st.t == zero)"
|
||||
+ " len = abs(v_st.s);"
|
||||
+ " if (u_mode == 0)"
|
||||
+ " len = u_width - abs(v_st.s);"
|
||||
+ " else "
|
||||
+ " len = length(v_st);"
|
||||
+ " len = u_width - length(v_st);"
|
||||
// fade to alpha. u_wscale is the width in pixel which should be
|
||||
// faded, u_width - len the position of this fragment on the
|
||||
// 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 = ""
|
||||
+ "#extension GL_OES_standard_derivatives : enable\n"
|
||||
+ "precision mediump float;\n"
|
||||
+ "uniform float u_wscale;"
|
||||
+ "uniform float u_width;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "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;"
|
||||
+ "void main() {"
|
||||
+ " vec4 color = u_color;"
|
||||
+ " float width = u_width;"
|
||||
+ " float len;"
|
||||
+ " if (v_st.t == zero)"
|
||||
+ " len = abs(v_st.s);"
|
||||
+ " if (u_mode == 0)"
|
||||
+ " len = u_width - abs(v_st.s);"
|
||||
+ " else "
|
||||
+ " len = length(v_st);"
|
||||
+ " vec2 st_width = fwidth(v_st);"
|
||||
+ " float fuzz = max(st_width.s, st_width.t) * 1.5;"
|
||||
+ " color *= smoothstep(zero, fuzz + u_wscale, u_width - len);"
|
||||
+ " len = u_width - 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;"
|
||||
+ " fuzz += u_wscale;"
|
||||
+ " if (len < fuzz){"
|
||||
// + " if (v_st.s > zero)"
|
||||
+ " color *= len / fuzz;"
|
||||
// + " else"
|
||||
// + " color = col2 * (u_width - len) / fuzz;"
|
||||
+ " }"
|
||||
+ " gl_FragColor = color;"
|
||||
+ "}";
|
||||
|
||||
@ -113,17 +192,18 @@ class Shaders {
|
||||
+ "uniform mat4 u_mv;"
|
||||
+ "uniform mat4 u_proj;"
|
||||
+ "uniform float u_scale;"
|
||||
+ "uniform float u_swidth;"
|
||||
+ "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;"
|
||||
+ "void main() {"
|
||||
+ " vec4 pos;"
|
||||
+ " if (mod(vertex.x, 2.0) == 0.0){"
|
||||
+ " pos = u_proj * (u_mv * vec4(vertex.xy + vertex.zw * u_scale, 0.0, 1.0));"
|
||||
+ " } else {"
|
||||
// place as billboard
|
||||
// // place as billboard
|
||||
+ " 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;"
|
||||
+ " tex_c = tex_coord * div;"
|
||||
@ -134,7 +214,7 @@ class Shaders {
|
||||
// + "attribute vec4 vertex;"
|
||||
// + "attribute vec2 tex_coord;"
|
||||
// + "uniform mat4 mvp;"
|
||||
// + "uniform mat4 rotation;"
|
||||
// + "uniform mat4 viewMatrix;"
|
||||
// + "uniform float scale;"
|
||||
// + "varying vec2 tex_c;"
|
||||
// + "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){"
|
||||
// + " pos = mvp * vec4(vertex.xy + vertex.zw / scale, 0.0, 1.0);"
|
||||
// + " } 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.z = 0.0;"
|
||||
@ -156,7 +236,7 @@ class Shaders {
|
||||
// + "attribute vec4 vertex;"
|
||||
// + "attribute vec2 tex_coord;"
|
||||
// + "uniform mat4 mvp;"
|
||||
// + "uniform mat4 rotation;"
|
||||
// + "uniform mat4 viewMatrix;"
|
||||
// + "uniform float scale;"
|
||||
// + "varying vec2 tex_c;"
|
||||
// + "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);"
|
||||
// + " } 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);"
|
||||
// + " }"
|
||||
// + " tex_c = tex_coord * div;"
|
@ -12,37 +12,33 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer;
|
||||
|
||||
import org.oscim.theme.renderinstruction.Caption;
|
||||
import org.oscim.theme.renderinstruction.PathText;
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
|
||||
public class TextItem {
|
||||
TextItem next;
|
||||
|
||||
final float x, y;
|
||||
final String text;
|
||||
final Caption caption;
|
||||
final PathText path;
|
||||
final String string;
|
||||
final Text text;
|
||||
final float width;
|
||||
|
||||
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.y = y;
|
||||
this.string = string;
|
||||
this.text = text;
|
||||
this.caption = caption;
|
||||
this.width = caption.paint.measureText(text);
|
||||
this.path = null;
|
||||
this.width = text.paint.measureText(string);
|
||||
}
|
||||
|
||||
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.y = y;
|
||||
this.string = string;
|
||||
this.text = text;
|
||||
this.path = pathText;
|
||||
this.caption = null;
|
||||
this.width = width;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@ -30,7 +30,9 @@ import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
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 float SCALE = 8.0f;
|
||||
private final static int LBIT_MASK = 0xfffffffe;
|
||||
@ -58,6 +60,7 @@ public class TextRenderer {
|
||||
private static int hTextProjectionMatrix;
|
||||
private static int hTextVertex;
|
||||
private static int hTextScale;
|
||||
private static int hTextScreenScale;
|
||||
private static int hTextTextureCoord;
|
||||
|
||||
private static Paint mPaint = new Paint(Color.BLACK);
|
||||
@ -86,6 +89,7 @@ public class TextRenderer {
|
||||
hTextMVMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_mv");
|
||||
hTextProjectionMatrix = GLES20.glGetUniformLocation(mTextProgram, "u_proj");
|
||||
hTextScale = GLES20.glGetUniformLocation(mTextProgram, "u_scale");
|
||||
hTextScreenScale = GLES20.glGetUniformLocation(mTextProgram, "u_swidth");
|
||||
hTextVertex = GLES20.glGetAttribLocation(mTextProgram, "vertex");
|
||||
hTextTextureCoord = GLES20.glGetAttribLocation(mTextProgram, "tex_coord");
|
||||
|
||||
@ -235,16 +239,10 @@ public class TextRenderer {
|
||||
|
||||
TextItem t = tile.labels;
|
||||
float yy;
|
||||
short x1, x2, x3, x4, y1, y2, y3, y4;
|
||||
|
||||
for (int i = 0; t != null && i < max; t = t.next, i++) {
|
||||
|
||||
if (t.caption != null) {
|
||||
height = (int) (t.caption.fontHeight) + 2 * mFontPadY;
|
||||
} else {
|
||||
height = (int) (t.path.fontHeight) + 2 * mFontPadY;
|
||||
}
|
||||
|
||||
height = (int) (t.text.fontHeight) + 2 * mFontPadY;
|
||||
width = t.width + 2 * mFontPadX;
|
||||
|
||||
if (height > advanceY)
|
||||
@ -256,35 +254,26 @@ public class TextRenderer {
|
||||
advanceY = (int) height;
|
||||
}
|
||||
|
||||
if (t.caption != null) {
|
||||
yy = y + (height - 1) - t.caption.fontDescent - mFontPadY;
|
||||
} else {
|
||||
yy = y + (height - 1) - t.path.fontDescent - mFontPadY;
|
||||
}
|
||||
|
||||
yy = y + (height - 1) - t.text.fontDescent - mFontPadY;
|
||||
if (yy > TEXTURE_HEIGHT) {
|
||||
Log.d(TAG, "reached max labels");
|
||||
continue;
|
||||
break;
|
||||
// continue;
|
||||
}
|
||||
|
||||
if (t.caption != null) {
|
||||
if (t.caption.stroke != null)
|
||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.caption.stroke);
|
||||
if (t.text.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.paint);
|
||||
} else {
|
||||
if (t.path.stroke != null)
|
||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.path.stroke);
|
||||
mCanvas.drawText(t.string, x + t.width / 2, yy, t.text.paint);
|
||||
|
||||
mCanvas.drawText(t.text, x + t.width / 2, yy, t.path.paint);
|
||||
}
|
||||
if (width > TEXTURE_WIDTH)
|
||||
width = TEXTURE_WIDTH;
|
||||
|
||||
float hw = width / 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));
|
||||
y1 = y3 = (short) (SCALE * (hh));
|
||||
x2 = x4 = (short) (SCALE * (hw));
|
||||
@ -330,11 +319,8 @@ public class TextRenderer {
|
||||
short v2 = (short) (SCALE * (y + height));
|
||||
|
||||
// pack caption/way-text info in lowest bit
|
||||
short tx;
|
||||
if (t.caption == null)
|
||||
tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 0);
|
||||
else
|
||||
tx = (short) ((int) (SCALE * t.x) & LBIT_MASK | 1);
|
||||
int tmp = (int) (SCALE * t.x) & LBIT_MASK;
|
||||
short tx = (short) (tmp | (t.text.caption ? 1 : 0));
|
||||
|
||||
short ty = (short) (SCALE * t.y);
|
||||
|
||||
@ -393,8 +379,6 @@ public class TextRenderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String TAG = "TextRenderer";
|
||||
|
||||
static void compileTextures() {
|
||||
int offset = 0;
|
||||
TextTexture tex;
|
||||
@ -422,32 +406,34 @@ public class TextRenderer {
|
||||
static void beginDraw(float scale, float[] projection) {
|
||||
GLES20.glUseProgram(mTextProgram);
|
||||
|
||||
GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
||||
GLES20.glEnableVertexAttribArray(hTextVertex);
|
||||
// GLES20.glEnableVertexAttribArray(hTextTextureCoord);
|
||||
// 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(hTextScreenScale, 1f / GLRenderer.mWidth);
|
||||
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_ARRAY_BUFFER, mVerticesVBO);
|
||||
}
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesVBO);
|
||||
}
|
||||
|
||||
static void endDraw() {
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
||||
GLES20.glDisableVertexAttribArray(hTextVertex);
|
||||
// GLES20.glDisableVertexAttribArray(hTextTextureCoord);
|
||||
// GLES20.glDisableVertexAttribArray(hTextVertex);
|
||||
}
|
||||
|
||||
static void drawTile(MapTile tile, float[] matrix) {
|
||||
@ -456,19 +442,14 @@ public class TextRenderer {
|
||||
|
||||
GLES20.glUniformMatrix4fv(hTextMVMatrix, 1, false, matrix, 0);
|
||||
|
||||
if (debug) {
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
||||
} else {
|
||||
GLES20.glVertexAttribPointer(hTextVertex, 4,
|
||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
||||
|
||||
GLES20.glVertexAttribPointer(hTextVertex, 4,
|
||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8));
|
||||
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
|
||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
|
||||
+ 8);
|
||||
|
||||
GLES20.glVertexAttribPointer(hTextTextureCoord, 2,
|
||||
GLES20.GL_SHORT, false, 12, tile.texture.offset * (Short.SIZE / 8)
|
||||
+ 8);
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
||||
INDICES_PER_SPRITE, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, (tile.texture.length / 24) *
|
||||
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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer;
|
||||
|
||||
public class TextTexture {
|
||||
|
||||
@ -22,12 +22,11 @@ public class TextTexture {
|
||||
int offset;
|
||||
MapTile tile;
|
||||
|
||||
String[] text;
|
||||
|
||||
TextTexture(int textureID) {
|
||||
vertices = new short[TextRenderer.MAX_LABELS *
|
||||
TextRenderer.VERTICES_PER_SPRITE *
|
||||
TextRenderer.SHORTS_PER_VERTICE];
|
||||
|
||||
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
|
||||
* 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.Tag;
|
||||
@ -21,16 +21,21 @@ import org.oscim.core.WebMercator;
|
||||
import org.oscim.database.IMapDatabase;
|
||||
import org.oscim.database.IMapDatabaseCallback;
|
||||
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.RenderTheme;
|
||||
import org.oscim.theme.renderinstruction.Area;
|
||||
import org.oscim.theme.renderinstruction.Caption;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.theme.renderinstruction.PathText;
|
||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
import org.oscim.view.DebugSettings;
|
||||
import org.oscim.view.MapView;
|
||||
import org.oscim.view.generator.JobTile;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
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 PIx4 = Math.PI * 4;
|
||||
|
||||
private static final double STROKE_INCREASE = Math.sqrt(2);
|
||||
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_MAX_ZOOM_LEVEL = 17;
|
||||
@ -58,13 +63,15 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
private MapTile mCurrentTile;
|
||||
|
||||
// coordinates of the currently processed way
|
||||
private float[] mCoords;
|
||||
private short[] mIndices;
|
||||
|
||||
private LineLayer mLineLayers;
|
||||
private PolygonLayer mPolyLayers;
|
||||
// current line layer, will be added to outline layers
|
||||
private LineLayer mCurLineLayer;
|
||||
private PolygonLayer mCurPolyLayer;
|
||||
|
||||
// layer data prepared for rendering
|
||||
private Layers mLayers;
|
||||
|
||||
private TextItem mLabels;
|
||||
|
||||
@ -74,10 +81,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
private float mStrokeScale = 1.0f;
|
||||
|
||||
private boolean mProjected;
|
||||
// private boolean mProjectedResult;
|
||||
private float mSimplify;
|
||||
// private boolean firstMatch;
|
||||
// private boolean prevClosed;
|
||||
|
||||
private RenderInstruction[] mRenderInstructions = null;
|
||||
|
||||
@ -126,8 +130,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
mTagName = null;
|
||||
|
||||
if (mMapProjection != null)
|
||||
{
|
||||
if (mMapProjection != null) {
|
||||
long x = mCurrentTile.pixelX;
|
||||
long y = mCurrentTile.pixelY + Tile.TILE_SIZE;
|
||||
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
||||
@ -137,7 +140,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
long dy = (y - (z >> 1));
|
||||
|
||||
if (mMapProjection == WebMercator.NAME) {
|
||||
double div = f900913 / (z >> 1);
|
||||
double div = WebMercator.f900913 / (z >> 1);
|
||||
// divy = f900913 / (z >> 1);
|
||||
mPoiX = (float) (longitude / div - dx);
|
||||
mPoiY = (float) (latitude / div + dy);
|
||||
@ -147,6 +150,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
mPoiX = (float) (longitude / divx - dx);
|
||||
double sinLat = Math.sin(latitude * PI180);
|
||||
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
|
||||
|| mPoiY > Tile.TILE_SIZE + 10)
|
||||
return;
|
||||
@ -230,45 +235,45 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAreaCaption(Caption caption) {
|
||||
public void renderAreaCaption(Text text) {
|
||||
// Log.d(TAG, "renderAreaCaption: " + mTagName);
|
||||
|
||||
if (mTagName == null)
|
||||
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;
|
||||
mLabels = t;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderPointOfInterestCaption(Caption caption) {
|
||||
public void renderPointOfInterestCaption(Text text) {
|
||||
// Log.d(TAG, "renderPointOfInterestCaption: " + mPoiX + " " + mPoiY +
|
||||
// " " + mTagName);
|
||||
|
||||
if (mTagName == null)
|
||||
return;
|
||||
|
||||
if (caption.textKey == mTagEmptyName.key) {
|
||||
TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, caption);
|
||||
if (text.textKey == mTagEmptyName.key) {
|
||||
TextItem t = new TextItem(mPoiX, mPoiY, mTagName.value, text);
|
||||
t.next = mLabels;
|
||||
mLabels = t;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderWayText(PathText pathText) {
|
||||
public void renderWayText(Text text) {
|
||||
// Log.d(TAG, "renderWayText: " + mTagName);
|
||||
|
||||
if (mTagName == null)
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -286,67 +291,47 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderPointOfInterestSymbol(Bitmap symbol) {
|
||||
// TODO Auto-generated method stub
|
||||
public void renderPointOfInterestSymbol(Bitmap bitmap) {
|
||||
// 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
|
||||
public void renderWay(Line line, int level) {
|
||||
|
||||
projectToTile();
|
||||
|
||||
if (line.outline && mCurLineLayer == null)
|
||||
return;
|
||||
|
||||
float w = line.width;
|
||||
int numLayer = (mDrawingLayer * 2) + level;
|
||||
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mProjectionScaleFactor;
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
w *= mStrokeScale;
|
||||
w *= mProjectionScaleFactor;
|
||||
}
|
||||
lineLayer.width = w;
|
||||
}
|
||||
|
||||
if (line.outline) {
|
||||
lineLayer.addOutline(mCurLineLayer);
|
||||
return;
|
||||
@ -367,38 +352,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
int numLayer = mDrawingLayer + level;
|
||||
|
||||
PolygonLayer layer = null;
|
||||
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;
|
||||
}
|
||||
}
|
||||
PolygonLayer layer = (PolygonLayer) mLayers.getLayer(numLayer, Layer.POLYGON);
|
||||
if (layer == null)
|
||||
return;
|
||||
|
||||
mCurPolyLayer = layer;
|
||||
if (layer.area == null)
|
||||
layer.area = area;
|
||||
|
||||
layer.addPolygon(mCoords, mIndices);
|
||||
}
|
||||
@ -430,7 +389,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
mDebugDrawUnmatched = debugSettings.mDrawUnmatchted;
|
||||
|
||||
if (tile.newData || tile.isReady) {
|
||||
// fixed now....
|
||||
// should be fixed now.
|
||||
Log.d(TAG, "XXX tile already loaded "
|
||||
+ tile + " "
|
||||
+ tile.newData + " "
|
||||
@ -446,22 +405,19 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
else
|
||||
setScaleStrokeWidth(STROKE_MAX_ZOOM_LEVEL);
|
||||
|
||||
// firstMatch = true;
|
||||
countLines = 0;
|
||||
countNodes = 0;
|
||||
|
||||
// acount for area changes with latitude
|
||||
mProjectionScaleFactor = 0.5f + (float) (0.5 / Math.cos(MercatorProjection
|
||||
.pixelYToLatitude(tile.pixelY, tile.zoomLevel)
|
||||
* (Math.PI / 180)));
|
||||
|
||||
mLayers = new Layers();
|
||||
|
||||
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
||||
Log.d(TAG, "Failed loading: " + tile);
|
||||
LineRenderer.clear(mLineLayers);
|
||||
PolygonRenderer.clear(mPolyLayers);
|
||||
mLineLayers = null;
|
||||
mPolyLayers = null;
|
||||
mLayers.clear();
|
||||
mLayers = null;
|
||||
mLabels = null;
|
||||
mCurLineLayer = null;
|
||||
tile.isLoading = false;
|
||||
return false;
|
||||
}
|
||||
@ -478,15 +434,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
TileGenerator.renderTheme.matchWay(this, debugTagBox, (byte) 0, false, true);
|
||||
}
|
||||
|
||||
tile.lineLayers = mLineLayers;
|
||||
tile.polygonLayers = mPolyLayers;
|
||||
tile.layers = mLayers;
|
||||
tile.labels = mLabels;
|
||||
|
||||
mCurPolyLayer = null;
|
||||
mCurLineLayer = null;
|
||||
mLineLayers = null;
|
||||
mPolyLayers = null;
|
||||
mLayers = null;
|
||||
mLabels = null;
|
||||
mCurLineLayer = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -542,6 +495,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
return mRenderInstructions != null;
|
||||
}
|
||||
|
||||
// TODO move this to Projection classes
|
||||
private boolean projectToTile() {
|
||||
if (mProjected || mMapProjection == null)
|
||||
return true;
|
||||
@ -558,13 +512,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
long z = Tile.TILE_SIZE << mCurrentTile.zoomLevel;
|
||||
float min = mSimplify;
|
||||
|
||||
double divx, divy;
|
||||
double divx, divy = 0;
|
||||
long dx = (x - (z >> 1));
|
||||
long dy = (y - (z >> 1));
|
||||
|
||||
if (useWebMercator) {
|
||||
divx = f900913 / (z >> 1);
|
||||
divy = f900913 / (z >> 1);
|
||||
divx = WebMercator.f900913 / (z >> 1);
|
||||
} else {
|
||||
divx = 180000000.0 / (z >> 1);
|
||||
divy = z / PIx4;
|
||||
@ -584,7 +537,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
if (useWebMercator) {
|
||||
lon = (float) (coords[pos] / divx - dx);
|
||||
lat = (float) (coords[pos + 1] / divy + dy);
|
||||
lat = (float) (coords[pos + 1] / divx + dy);
|
||||
} else {
|
||||
lon = (float) ((coords[pos]) / divx - dx);
|
||||
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
|
||||
* 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 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) {
|
||||
TextItem items = textItems;
|
||||
TextItem t = null;
|
||||
@ -175,7 +175,7 @@ final class WayDecorator {
|
||||
} else if (segmentLengthInPixel > minWidth) {
|
||||
|
||||
if (wayNameWidth < 0) {
|
||||
wayNameWidth = pathText.paint.measureText(text);
|
||||
wayNameWidth = text.paint.measureText(string);
|
||||
}
|
||||
|
||||
if (segmentLengthInPixel > wayNameWidth + 25) {
|
||||
@ -227,7 +227,7 @@ final class WayDecorator {
|
||||
if (x1 - 10 < t2.x2 && t2.x1 - 10 < x2 && top - 10 < bot2
|
||||
&& top2 - 10 < bot) {
|
||||
|
||||
if (t2.text.equals(text)) {
|
||||
if (t2.string.equals(string)) {
|
||||
intersects = true;
|
||||
break;
|
||||
}
|
||||
@ -256,8 +256,8 @@ final class WayDecorator {
|
||||
}
|
||||
|
||||
// if (t == null)
|
||||
t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2, text,
|
||||
pathText, wayNameWidth);
|
||||
t = new TextItem(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2, string,
|
||||
text, wayNameWidth);
|
||||
|
||||
t.x1 = (short) x1;
|
||||
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
|
||||
* 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.renderer.GLRenderer;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
|
||||
import android.graphics.Paint.Cap;
|
||||
import android.util.FloatMath;
|
||||
|
||||
class LineLayer {
|
||||
public final class LineLayer extends Layer {
|
||||
|
||||
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||
// scale factor mapping extrusion vector to short values
|
||||
@ -29,33 +30,26 @@ class LineLayer {
|
||||
// coordinates
|
||||
private static final int DIR_MASK = 0xFFFFFFFC;
|
||||
|
||||
// next layer
|
||||
LineLayer next;
|
||||
|
||||
// lines referenced by this outline layer
|
||||
LineLayer outlines;
|
||||
public LineLayer outlines;
|
||||
public Line line;
|
||||
public float width;
|
||||
|
||||
Line line;
|
||||
float width;
|
||||
boolean isOutline;
|
||||
int layer;
|
||||
// boolean isOutline;
|
||||
|
||||
VertexPoolItem pool;
|
||||
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) {
|
||||
LineLayer(int layer) {
|
||||
this.layer = layer;
|
||||
this.width = width;
|
||||
this.line = line;
|
||||
this.isOutline = outline;
|
||||
this.type = Layer.LINE;
|
||||
}
|
||||
|
||||
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)
|
||||
if (link == l)
|
||||
return;
|
||||
@ -69,7 +63,7 @@ class LineLayer {
|
||||
* (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 a, ux, uy, vx, vy, wx, wy;
|
||||
|
||||
@ -108,7 +102,6 @@ class LineLayer {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
closed = false;
|
||||
|
||||
// amount of vertices used
|
@ -12,32 +12,25 @@
|
||||
* 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.view.renderer;
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.theme.renderinstruction.Area;
|
||||
|
||||
class PolygonLayer {
|
||||
public final class PolygonLayer extends Layer {
|
||||
private static final float S = GLRenderer.COORD_MULTIPLIER;
|
||||
|
||||
PolygonLayer next;
|
||||
Area area;
|
||||
public Area area;
|
||||
|
||||
VertexPoolItem pool;
|
||||
protected VertexPoolItem curItem;
|
||||
int verticesCnt;
|
||||
int offset;
|
||||
|
||||
final int layer;
|
||||
|
||||
PolygonLayer(int layer, Area area) {
|
||||
PolygonLayer(int layer) {
|
||||
this.layer = layer;
|
||||
this.area = area;
|
||||
this.type = Layer.POLYGON;
|
||||
curItem = VertexPool.get();
|
||||
pool = curItem;
|
||||
}
|
||||
|
||||
void addPolygon(float[] points, short[] index) {
|
||||
public void addPolygon(float[] points, short[] index) {
|
||||
short center = (short) ((Tile.TILE_SIZE >> 1) * S);
|
||||
|
||||
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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
@ -23,7 +23,7 @@ public class VertexPool {
|
||||
static private int count = 0;
|
||||
static private int countAll = 0;
|
||||
|
||||
static synchronized void init() {
|
||||
public static synchronized void init() {
|
||||
count = 0;
|
||||
countAll = 0;
|
||||
pool = null;
|
||||
@ -61,7 +61,7 @@ public class VertexPool {
|
||||
// private static float load = 1.0f;
|
||||
// private static int loadCount = 0;
|
||||
|
||||
static synchronized void add(VertexPoolItem items) {
|
||||
static synchronized void release(VertexPoolItem items) {
|
||||
if (items == null)
|
||||
return;
|
||||
|
||||
@ -86,7 +86,8 @@ public class VertexPool {
|
||||
|
||||
last.next = pool;
|
||||
pool = items;
|
||||
// Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " + countAll
|
||||
// Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " +
|
||||
// countAll
|
||||
// + " load: " + (load / loadCount));
|
||||
|
||||
} else {
|
@ -12,7 +12,7 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.oscim.view.renderer;
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
public class VertexPoolItem {
|
||||
final short[] vertices;
|
@ -15,9 +15,8 @@
|
||||
package org.oscim.theme;
|
||||
|
||||
import org.oscim.theme.renderinstruction.Area;
|
||||
import org.oscim.theme.renderinstruction.Caption;
|
||||
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.Paint;
|
||||
@ -36,14 +35,6 @@ public interface IRenderCallback {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -52,14 +43,6 @@ public interface IRenderCallback {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@ -105,8 +88,25 @@ public interface IRenderCallback {
|
||||
/**
|
||||
* 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.AreaLevel;
|
||||
import org.oscim.theme.renderinstruction.Caption;
|
||||
import org.oscim.theme.renderinstruction.Circle;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.theme.renderinstruction.LineSymbol;
|
||||
import org.oscim.theme.renderinstruction.PathText;
|
||||
import org.oscim.theme.renderinstruction.RenderInstruction;
|
||||
import org.oscim.theme.renderinstruction.Symbol;
|
||||
import org.oscim.theme.renderinstruction.Text;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
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_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_LINE = "style-line";
|
||||
private static final String ELEMENT_NAME_STYLE_OUTLINE = "style-outline";
|
||||
@ -68,7 +67,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
/**
|
||||
* @param inputStream
|
||||
* 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
|
||||
* if an error occurs while parsing the render theme XML.
|
||||
* @throws ParserConfigurationException
|
||||
@ -171,11 +171,11 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
mRuleStack.push(mCurrentRule);
|
||||
}
|
||||
|
||||
else if (ELEMENT_NAME_STYPE_PATH_TEXT.equals(localName)) {
|
||||
else if (ELEMENT_NAME_STYLE_TEXT.equals(localName)) {
|
||||
checkState(localName, Element.STYLE);
|
||||
PathText pathText = PathText.create(localName, attributes);
|
||||
tmpStyleHash.put("t" + pathText.style, pathText);
|
||||
// System.out.println("add style: " + pathText.style);
|
||||
Text text = Text.create(localName, attributes, false);
|
||||
tmpStyleHash.put("t" + text.style, text);
|
||||
// System.out.println("add style: " + text.style);
|
||||
}
|
||||
|
||||
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,
|
||||
false);
|
||||
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 {
|
||||
Log.d("...", "this aint no style! " + style);
|
||||
@ -222,8 +223,11 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
|
||||
else if ("caption".equals(localName)) {
|
||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||
Caption caption = Caption.create(localName, attributes);
|
||||
mCurrentRule.addRenderingInstruction(caption);
|
||||
Text text = Text.create(localName, attributes, true);
|
||||
mCurrentRule.addRenderingInstruction(text);
|
||||
|
||||
// Caption caption = Caption.create(localName, attributes);
|
||||
// mCurrentRule.addRenderingInstruction(caption);
|
||||
}
|
||||
|
||||
else if ("circle".equals(localName)) {
|
||||
@ -244,10 +248,10 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
mCurrentRule.addRenderingInstruction(lineSymbol);
|
||||
}
|
||||
|
||||
else if ("pathText".equals(localName)) {
|
||||
else if ("text".equals(localName)) {
|
||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||
PathText pathText = PathText.create(localName, attributes);
|
||||
mCurrentRule.addRenderingInstruction(pathText);
|
||||
Text text = Text.create(localName, attributes, false);
|
||||
mCurrentRule.addRenderingInstruction(text);
|
||||
}
|
||||
|
||||
else if ("symbol".equals(localName)) {
|
||||
@ -262,7 +266,8 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
if (style != null) {
|
||||
Line line = (Line) tmpStyleHash.get("l" + style);
|
||||
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,
|
||||
mLevel++, false);
|
||||
|
||||
@ -290,13 +295,13 @@ public class RenderThemeHandler extends DefaultHandler {
|
||||
mCurrentRule.addRenderingInstruction(new AreaLevel(area,
|
||||
mLevel++));
|
||||
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)) {
|
||||
checkState(localName, Element.RENDERING_INSTRUCTION);
|
||||
String style = attributes.getValue("name");
|
||||
if (style != null) {
|
||||
PathText pt = (PathText) tmpStyleHash.get("t" + style);
|
||||
Text pt = (Text) tmpStyleHash.get("t" + style);
|
||||
if (pt != null)
|
||||
mCurrentRule.addRenderingInstruction(pt);
|
||||
else
|
||||
|
@ -4,8 +4,8 @@
|
||||
xsi:schemaLocation="http://mapsforge.org/renderTheme ../renderTheme.xsd"
|
||||
version="1" map-background="#fcfcfa">
|
||||
|
||||
<style-pathtext 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="road" k="name" 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"/>
|
||||
|
||||
@ -65,14 +65,14 @@
|
||||
<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" stroke="#b4cbdc" width="1.0" cap="butt" />
|
||||
<style-line name="water" stroke="#afcbf3" width="1.0" cap="butt" />
|
||||
<style-area name="water" fill="#afcbf3" />
|
||||
<!-- no-go area boundary -->
|
||||
<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="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"/>
|
||||
|
||||
<!-- ways -->
|
||||
@ -487,11 +487,11 @@
|
||||
</rule>
|
||||
|
||||
<!-- 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="2" stroke="#c0c0c0" />
|
||||
<style-outline name="primary" stroke="#7f7700" width="0.025"/>
|
||||
<style-outline name="motorway" stroke="#805f2e" width="0.025"/>
|
||||
<style-outline name="primary" stroke="#aa7f7700" width="0.1"/>
|
||||
<style-outline name="motorway" stroke="#aa805f2e" width="0.1"/>
|
||||
|
||||
|
||||
<!-- highway -->
|
||||
@ -499,23 +499,23 @@
|
||||
<rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
|
||||
<rule e="way" k="area" v="~|no|false">
|
||||
<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 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 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 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 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>
|
||||
@ -790,7 +790,7 @@
|
||||
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="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>
|
||||
</rule> -->
|
||||
|
||||
@ -831,7 +831,7 @@
|
||||
|
||||
</rule>
|
||||
<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 e="way" k="railway" v="rail" zoom-max="14" zoom-min="13">
|
||||
<line stroke="#8888aa" width="0.6" cap="butt"
|
||||
@ -969,6 +969,165 @@
|
||||
stroke="#ffffff" stroke-width="2.0" /> -->
|
||||
</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>
|
||||
|
||||
</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 |