- add initial version of line stipple renderer
- 'vbo' moved to 'Layers'
This commit is contained in:
parent
a0083ae484
commit
7cf4ca27f3
@ -16,6 +16,8 @@ package org.oscim.generator;
|
|||||||
|
|
||||||
import static org.oscim.generator.JobTile.STATE_NONE;
|
import static org.oscim.generator.JobTile.STATE_NONE;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.oscim.core.MercatorProjection;
|
import org.oscim.core.MercatorProjection;
|
||||||
import org.oscim.core.Tag;
|
import org.oscim.core.Tag;
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
@ -27,6 +29,7 @@ import org.oscim.renderer.layer.ExtrusionLayer;
|
|||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.Layers;
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.renderer.layer.LineLayer;
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
|
import org.oscim.renderer.layer.LineTexLayer;
|
||||||
import org.oscim.renderer.layer.PolygonLayer;
|
import org.oscim.renderer.layer.PolygonLayer;
|
||||||
import org.oscim.renderer.layer.TextItem;
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.theme.IRenderCallback;
|
import org.oscim.theme.IRenderCallback;
|
||||||
@ -132,7 +135,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
*/
|
*/
|
||||||
public TileGenerator(MapView mapView) {
|
public TileGenerator(MapView mapView) {
|
||||||
// mMapView = mapView;
|
// mMapView = mapView;
|
||||||
mClipper = new LineClipper(0,0,Tile.TILE_SIZE, Tile.TILE_SIZE, true);
|
mClipper = new LineClipper(0, 0, Tile.TILE_SIZE, Tile.TILE_SIZE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
@ -254,6 +257,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mTagHouseNr = tags[i];
|
mTagHouseNr = tags[i];
|
||||||
tags[i] = mTagEmptyHouseNr;
|
tags[i] = mTagEmptyHouseNr;
|
||||||
} else if (mTile.zoomLevel >= 17 &&
|
} else if (mTile.zoomLevel >= 17 &&
|
||||||
|
// FIXME, allow overlays to intercept
|
||||||
|
// this, or use a theme option for this
|
||||||
key == Tag.TAG_KEY_BUILDING) {
|
key == Tag.TAG_KEY_BUILDING) {
|
||||||
mRenderBuildingModel = true;
|
mRenderBuildingModel = true;
|
||||||
}
|
}
|
||||||
@ -270,38 +275,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
mTagName = null;
|
mTagName = null;
|
||||||
mTagHouseNr = null;
|
mTagHouseNr = null;
|
||||||
|
|
||||||
//if (mMapProjection != null) {
|
|
||||||
// long x = mTile.pixelX;
|
|
||||||
// long y = mTile.pixelY + Tile.TILE_SIZE;
|
|
||||||
// long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
|
||||||
//
|
|
||||||
// double divx, divy;
|
|
||||||
// long dx = (x - (z >> 1));
|
|
||||||
// long dy = (y - (z >> 1));
|
|
||||||
//
|
|
||||||
// if (mMapProjection == WebMercator.NAME) {
|
|
||||||
// double div = WebMercator.f900913 / (z >> 1);
|
|
||||||
// // divy = f900913 / (z >> 1);
|
|
||||||
// mPoiX = (float) (longitude / div - dx);
|
|
||||||
// mPoiY = (float) (latitude / div + dy);
|
|
||||||
// } else {
|
|
||||||
// divx = 180000000.0 / (z >> 1);
|
|
||||||
// divy = z / PIx4;
|
|
||||||
// mPoiX = (float) (longitude / divx - dx);
|
|
||||||
// double sinLat = Math.sin(latitude * PI180);
|
|
||||||
// mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
//} else {
|
|
||||||
mPoiX = longitude;
|
mPoiX = longitude;
|
||||||
mPoiY = latitude;
|
mPoiY = latitude;
|
||||||
//}
|
|
||||||
|
|
||||||
// remove tags that should not be cached in Rendertheme
|
// remove tags that should not be cached in Rendertheme
|
||||||
filterTags(tags);
|
filterTags(tags);
|
||||||
// Log.d(TAG, "renderPointOfInterest: " + mTagName);
|
|
||||||
|
|
||||||
// mNodeRenderInstructions =
|
|
||||||
TileGenerator.renderTheme.matchNode(this, tags, mTile.zoomLevel);
|
TileGenerator.renderTheme.matchNode(this, tags, mTile.zoomLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,8 +317,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
private void debugUnmatched(boolean closed, Tag[] tags) {
|
private void debugUnmatched(boolean closed, Tag[] tags) {
|
||||||
|
|
||||||
Log.d(TAG, "way not matched: " + tags[0] + " "
|
Log.d(TAG, "DBG way not matched: " + closed + " " + Arrays.deepToString(tags));
|
||||||
+ (tags.length > 1 ? tags[1] : "") + " " + closed);
|
|
||||||
|
|
||||||
mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false);
|
mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false);
|
||||||
|
|
||||||
@ -366,37 +344,62 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
// ----------------- RenderThemeCallback -----------------
|
// ----------------- RenderThemeCallback -----------------
|
||||||
@Override
|
@Override
|
||||||
public void renderWay(Line line, int level) {
|
public void renderWay(Line line, int level) {
|
||||||
// projectToTile();
|
// TODO projectToTile();
|
||||||
|
|
||||||
if (line.outline && mCurLineLayer == null) {
|
|
||||||
// TODO fix this in RenderTheme
|
|
||||||
Log.e(TAG, "theme issue, cannot add outline: line must come before outline!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int numLayer = (mDrawingLayer * 2) + level;
|
int numLayer = (mDrawingLayer * 2) + level;
|
||||||
|
|
||||||
LineLayer lineLayer = (LineLayer) mLayers.getLayer(numLayer, Layer.LINE);
|
if (line.stipple == 0) {
|
||||||
if (lineLayer == null)
|
if (line.outline && mCurLineLayer == null) {
|
||||||
return;
|
// FIXME in RenderTheme
|
||||||
|
Log.e(TAG, "BUG in theme: line must come before outline!");
|
||||||
if (lineLayer.line == null) {
|
return;
|
||||||
lineLayer.line = line;
|
|
||||||
|
|
||||||
float w = line.width;
|
|
||||||
if (!line.fixed) {
|
|
||||||
w *= mStrokeScale;
|
|
||||||
w *= mProjectionScaleFactor;
|
|
||||||
}
|
}
|
||||||
lineLayer.width = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.outline) {
|
LineLayer lineLayer = (LineLayer)
|
||||||
lineLayer.addOutline(mCurLineLayer);
|
mLayers.getLayer(numLayer, Layer.LINE);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lineLayer.addLine(mCoords, mIndices, mClosed);
|
if (lineLayer == null)
|
||||||
mCurLineLayer = lineLayer;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineLayer.addLine(mCoords, mIndices, mClosed);
|
||||||
|
mCurLineLayer = lineLayer;
|
||||||
|
} else {
|
||||||
|
LineTexLayer lineLayer = (LineTexLayer)
|
||||||
|
mLayers.getLayer(numLayer, Layer.TEXLINE);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lineLayer.addLine(mCoords, mIndices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -480,8 +483,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
int length = mIndices[i];
|
int length = mIndices[i];
|
||||||
if (length < 4)
|
if (length < 4)
|
||||||
break;
|
break;
|
||||||
mLabels = WayDecorator.renderText(mClipper,mCoords, mTagName.value, text,
|
mLabels = WayDecorator.renderText(mClipper, mCoords, mTagName.value, text,
|
||||||
offset, length, mLabels);
|
offset, length, mLabels);
|
||||||
offset += length;
|
offset += length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,6 +523,31 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
|||||||
|
|
||||||
// // TODO move this to Projection classes
|
// // TODO move this to Projection classes
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//if (mMapProjection != null) {
|
||||||
|
// long x = mTile.pixelX;
|
||||||
|
// long y = mTile.pixelY + Tile.TILE_SIZE;
|
||||||
|
// long z = Tile.TILE_SIZE << mTile.zoomLevel;
|
||||||
|
//
|
||||||
|
// double divx, divy;
|
||||||
|
// long dx = (x - (z >> 1));
|
||||||
|
// long dy = (y - (z >> 1));
|
||||||
|
//
|
||||||
|
// if (mMapProjection == WebMercator.NAME) {
|
||||||
|
// double div = WebMercator.f900913 / (z >> 1);
|
||||||
|
// // divy = f900913 / (z >> 1);
|
||||||
|
// mPoiX = (float) (longitude / div - dx);
|
||||||
|
// mPoiY = (float) (latitude / div + dy);
|
||||||
|
// } else {
|
||||||
|
// divx = 180000000.0 / (z >> 1);
|
||||||
|
// divy = z / PIx4;
|
||||||
|
// mPoiX = (float) (longitude / divx - dx);
|
||||||
|
// double sinLat = Math.sin(latitude * PI180);
|
||||||
|
// mPoiY = (float) (Math.log((1.0 + sinLat) / (1.0 - sinLat)) * divy + dy);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//} else {
|
||||||
|
|
||||||
// private String mMapProjection;
|
// private String mMapProjection;
|
||||||
// private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
// private static final double PI180 = (Math.PI / 180) / 1000000.0;
|
||||||
// private static final double PIx4 = Math.PI * 4;
|
// private static final double PIx4 = Math.PI * 4;
|
||||||
|
|||||||
@ -28,7 +28,8 @@ import android.opengl.GLES20;
|
|||||||
import android.opengl.Matrix;
|
import android.opengl.Matrix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is for rendering the Line- and PolygonLayers of visible MapTiles. For
|
* This class is for rendering the Line- and PolygonLayers of visible MapTiles.
|
||||||
|
* For
|
||||||
* visible tiles that do not have data available yet its parent in children
|
* visible tiles that do not have data available yet its parent in children
|
||||||
* tiles are rendered when available.
|
* tiles are rendered when available.
|
||||||
*
|
*
|
||||||
@ -107,12 +108,12 @@ public class BaseMap {
|
|||||||
if (t.holder != null)
|
if (t.holder != null)
|
||||||
t = t.holder;
|
t = t.holder;
|
||||||
|
|
||||||
if (t.layers == null || t.vbo == null) {
|
if (t.layers == null || t.layers.vbo == null) {
|
||||||
//Log.d(TAG, "missing data " + (t.layers == null) + " " + (t.vbo == null));
|
//Log.d(TAG, "missing data " + (t.layers == null) + " " + (t.vbo == null));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.layers.vbo.id);
|
||||||
|
|
||||||
// place tile relative to map position
|
// place tile relative to map position
|
||||||
float div = FastMath.pow(tile.zoomLevel - pos.zoomLevel);
|
float div = FastMath.pow(tile.zoomLevel - pos.zoomLevel);
|
||||||
@ -135,8 +136,9 @@ public class BaseMap {
|
|||||||
int simpleShader = (pos.tilt < 1 ? 1 : 0);
|
int simpleShader = (pos.tilt < 1 ? 1 : 0);
|
||||||
|
|
||||||
boolean clipped = false;
|
boolean clipped = false;
|
||||||
|
boolean lineTexture = true;
|
||||||
|
|
||||||
for (Layer l = t.layers.layers; l != null;) {
|
for (Layer l = t.layers.baseLayers; l != null;) {
|
||||||
switch (l.type) {
|
switch (l.type) {
|
||||||
case Layer.POLYGON:
|
case Layer.POLYGON:
|
||||||
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
|
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
|
||||||
@ -144,16 +146,38 @@ public class BaseMap {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Layer.LINE:
|
case Layer.LINE:
|
||||||
|
//if (!lineTexture) {
|
||||||
|
LineRenderer.beginLines();
|
||||||
|
// lineTexture = true;
|
||||||
|
//}
|
||||||
if (!clipped) {
|
if (!clipped) {
|
||||||
|
// draw stencil buffer clip region
|
||||||
PolygonRenderer.draw(pos, null, mvp, true, true);
|
PolygonRenderer.draw(pos, null, mvp, true, true);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
}
|
}
|
||||||
l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
|
l = LineRenderer.draw(t.layers, l, pos, mvp, div, simpleShader);
|
||||||
t.layers.lineOffset);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Layer.TEXLINE:
|
||||||
|
LineRenderer.endLines();
|
||||||
|
|
||||||
|
if (!clipped) {
|
||||||
|
// draw stencil buffer clip region
|
||||||
|
PolygonRenderer.draw(pos, null, mvp, true, true);
|
||||||
|
clipped = true;
|
||||||
|
}
|
||||||
|
l = LineTexRenderer.draw(t.layers, l, pos, mvp, div);
|
||||||
|
lineTexture = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// just in case
|
||||||
|
l = l.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear clip-region and could also draw 'fade-effect'
|
||||||
PolygonRenderer.drawOver(mvp);
|
PolygonRenderer.drawOver(mvp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -74,7 +74,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// bytes currently loaded in VBOs
|
// bytes currently loaded in VBOs
|
||||||
private static int mBufferMemoryUsage;
|
private static int mBufferMemoryUsage;
|
||||||
|
|
||||||
|
|
||||||
private static float[] mTileCoords = new float[8];
|
private static float[] mTileCoords = new float[8];
|
||||||
private static float[] mDebugCoords = new float[8];
|
private static float[] mDebugCoords = new float[8];
|
||||||
|
|
||||||
@ -211,10 +210,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
private static int uploadCnt = 0;
|
private static int uploadCnt = 0;
|
||||||
|
|
||||||
public static boolean uploadLayers(Layers layers, BufferObject vbo, int newSize,
|
public static boolean uploadLayers(Layers layers, int newSize,
|
||||||
boolean addFill) {
|
boolean addFill) {
|
||||||
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
|
|
||||||
// add fill coordinates
|
// add fill coordinates
|
||||||
if (addFill)
|
if (addFill)
|
||||||
@ -241,23 +240,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
if (newSize != sbuf.remaining()) {
|
if (newSize != sbuf.remaining()) {
|
||||||
Log.d(TAG, "wrong size: "
|
Log.d(TAG, "wrong size: "
|
||||||
+ newSize + " "
|
+ " new size: " + newSize
|
||||||
+ sbuf.position() + " "
|
+ " buffer pos: " + sbuf.position()
|
||||||
+ sbuf.limit() + " "
|
+ " buffer limit: " + sbuf.limit()
|
||||||
+ sbuf.remaining());
|
+ " buffer fill: " + sbuf.remaining());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
newSize *= SHORT_BYTES;
|
newSize *= SHORT_BYTES;
|
||||||
|
|
||||||
// reuse memory allocated for vbo when possible and allocated
|
// reuse memory allocated for vbo when possible and allocated
|
||||||
// memory is less then four times the new data
|
// memory is less then four times the new data
|
||||||
if (vbo.size > newSize && vbo.size < newSize * 4
|
if (layers.vbo.size > newSize && layers.vbo.size < newSize * 4
|
||||||
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
|
&& mBufferMemoryUsage < LIMIT_BUFFERS) {
|
||||||
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
||||||
} else {
|
} else {
|
||||||
mBufferMemoryUsage += newSize - vbo.size;
|
mBufferMemoryUsage += newSize - layers.vbo.size;
|
||||||
vbo.size = newSize;
|
layers.vbo.size = newSize;
|
||||||
GLES20.glBufferData(GL_ARRAY_BUFFER, vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
GLES20.glBufferData(GL_ARRAY_BUFFER, layers.vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -272,15 +271,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
int newSize = tile.layers.getSize();
|
int newSize = tile.layers.getSize();
|
||||||
if (newSize > 0) {
|
if (newSize > 0) {
|
||||||
|
|
||||||
if (tile.vbo == null)
|
if (tile.layers.vbo == null)
|
||||||
tile.vbo = BufferObject.get(newSize);
|
tile.layers.vbo = BufferObject.get(newSize);
|
||||||
|
|
||||||
if (!uploadLayers(tile.layers, tile.vbo, newSize, true)) {
|
if (!uploadLayers(tile.layers, newSize, true)) {
|
||||||
Log.d(TAG, "BUG uploadTileData " + tile + " failed!");
|
Log.d(TAG, "BUG uploadTileData " + tile + " failed!");
|
||||||
|
|
||||||
|
BufferObject.release(tile.layers.vbo);
|
||||||
|
tile.layers.vbo = null;
|
||||||
tile.layers.clear();
|
tile.layers.clear();
|
||||||
tile.layers = null;
|
tile.layers = null;
|
||||||
BufferObject.release(tile.vbo);
|
|
||||||
tile.vbo = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,7 +376,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
MapPosition pos = mMapPosition;
|
MapPosition pos = mMapPosition;
|
||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
boolean changed;
|
boolean changed;
|
||||||
synchronized(mMapViewPosition){
|
synchronized (mMapViewPosition) {
|
||||||
changed = mMapViewPosition.getMapPosition(pos);
|
changed = mMapViewPosition.getMapPosition(pos);
|
||||||
mMapViewPosition.getMapViewProjection(coords);
|
mMapViewPosition.getMapViewProjection(coords);
|
||||||
mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj);
|
mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj);
|
||||||
@ -621,7 +621,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
// Log.d(TAG, "Extensions: " + ext);
|
// Log.d(TAG, "Extensions: " + ext);
|
||||||
|
|
||||||
|
// classes that require GL context for initialization
|
||||||
LineRenderer.init();
|
LineRenderer.init();
|
||||||
|
LineTexRenderer.init();
|
||||||
PolygonRenderer.init();
|
PolygonRenderer.init();
|
||||||
TextureRenderer.init();
|
TextureRenderer.init();
|
||||||
TextureObject.init(10);
|
TextureObject.init(10);
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
|||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.generator.TileGenerator;
|
import org.oscim.generator.TileGenerator;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
import org.oscim.renderer.layer.LineLayer;
|
import org.oscim.renderer.layer.LineLayer;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
import org.oscim.utils.GlUtils;
|
import org.oscim.utils.GlUtils;
|
||||||
@ -34,10 +35,6 @@ import org.oscim.utils.GlUtils;
|
|||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Hannes Janetzek
|
|
||||||
*/
|
|
||||||
|
|
||||||
public final class LineRenderer {
|
public final class LineRenderer {
|
||||||
private final static String TAG = LineRenderer.class.getName();
|
private final static String TAG = LineRenderer.class.getName();
|
||||||
|
|
||||||
@ -97,6 +94,7 @@ public final class LineRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mTexID = GlUtils.loadTexture(pixel, 128, 128, GLES20.GL_ALPHA,
|
mTexID = GlUtils.loadTexture(pixel, 128, 128, GLES20.GL_ALPHA,
|
||||||
|
GLES20.GL_NEAREST, GLES20.GL_NEAREST,
|
||||||
GLES20.GL_MIRRORED_REPEAT, GLES20.GL_MIRRORED_REPEAT);
|
GLES20.GL_MIRRORED_REPEAT, GLES20.GL_MIRRORED_REPEAT);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -110,13 +108,13 @@ public final class LineRenderer {
|
|||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Layer draw(MapPosition pos, Layer layer, float[] matrix, float div,
|
public static Layer draw(Layers layers, Layer curLayer, MapPosition pos,
|
||||||
int mode, int bufferOffset) {
|
float[] matrix, float div, int mode) {
|
||||||
|
|
||||||
int zoom = pos.zoomLevel;
|
int zoom = pos.zoomLevel;
|
||||||
float scale = pos.scale;
|
float scale = pos.scale;
|
||||||
|
|
||||||
if (layer == null)
|
if (curLayer == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
GLState.blend(true);
|
GLState.blend(true);
|
||||||
@ -131,13 +129,13 @@ public final class LineRenderer {
|
|||||||
GLState.enableVertexArrays(hLineVertexPosition[mode], -1);
|
GLState.enableVertexArrays(hLineVertexPosition[mode], -1);
|
||||||
|
|
||||||
glVertexAttribPointer(hLineVertexPosition[mode], 4, GL_SHORT,
|
glVertexAttribPointer(hLineVertexPosition[mode], 4, GL_SHORT,
|
||||||
false, 0, bufferOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
false, 0, layers.lineOffset + LINE_VERTICES_DATA_POS_OFFSET);
|
||||||
|
|
||||||
glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
|
glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0);
|
||||||
|
|
||||||
// line scale factor for non fixed lines: within a zoom-
|
// Line scale factor for non fixed lines: Within a zoom-
|
||||||
// level lines would be scaled by the factor 2 via projection.
|
// level lines would be scaled by the factor 2 by view-matrix.
|
||||||
// though lines should only scale by sqrt(2). this is achieved
|
// Though lines should only scale by sqrt(2). This is achieved
|
||||||
// by inverting scaling of extrusion vector with: width/sqrt(s).
|
// by inverting scaling of extrusion vector with: width/sqrt(s).
|
||||||
// within one zoom-level: 1 <= s <= 2
|
// within one zoom-level: 1 <= s <= 2
|
||||||
float s = scale / div;
|
float s = scale / div;
|
||||||
@ -158,7 +156,7 @@ public final class LineRenderer {
|
|||||||
// dont increase scale when max is reached
|
// dont increase scale when max is reached
|
||||||
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||||
|
|
||||||
Layer l = layer;
|
Layer l = curLayer;
|
||||||
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
||||||
LineLayer ll = (LineLayer) l;
|
LineLayer ll = (LineLayer) l;
|
||||||
Line line = ll.line;
|
Line line = ll.line;
|
||||||
@ -187,7 +185,7 @@ public final class LineRenderer {
|
|||||||
} else {
|
} else {
|
||||||
width = ll.width / s + o.width / lineScale;
|
width = ll.width / s + o.width / lineScale;
|
||||||
|
|
||||||
// check min size for outline
|
// check min-size for outline
|
||||||
if (o.line.min > 0 && o.width * lineScale < o.line.min * 2)
|
if (o.line.min > 0 && o.width * lineScale < o.line.min * 2)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -223,7 +221,9 @@ public final class LineRenderer {
|
|||||||
// line width increases by sqrt(2.2).
|
// line width increases by sqrt(2.2).
|
||||||
width = ll.width / lineScale;
|
width = ll.width / lineScale;
|
||||||
|
|
||||||
if (ll.line.min > 0 && ll.width * lineScale < ll.line.min * 2)
|
// min-size hack to omit outline when line becomes
|
||||||
|
// very thin
|
||||||
|
if ((ll.line.min > 0) && (ll.width * lineScale < ll.line.min * 2))
|
||||||
width = (ll.width - 0.2f) / lineScale;
|
width = (ll.width - 0.2f) / lineScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +262,6 @@ public final class LineRenderer {
|
|||||||
+ "attribute vec4 a_pos;"
|
+ "attribute vec4 a_pos;"
|
||||||
+ "uniform float u_mode;"
|
+ "uniform float u_mode;"
|
||||||
+ "varying vec2 v_st;"
|
+ "varying vec2 v_st;"
|
||||||
+ "varying vec2 v_mode;"
|
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
// scale extrusion to u_width pixel
|
// scale extrusion to u_width pixel
|
||||||
// just ignore the two most insignificant bits of a_st :)
|
// just ignore the two most insignificant bits of a_st :)
|
||||||
@ -271,26 +270,24 @@ public final class LineRenderer {
|
|||||||
// last two bits of a_st hold the texture coordinates
|
// last two bits of a_st hold the texture coordinates
|
||||||
// ..maybe one could wrap texture so that `abs` is not required
|
// ..maybe one could wrap texture so that `abs` is not required
|
||||||
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
|
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
|
||||||
+ " v_mode = vec2(1.0 - u_mode, u_mode);"
|
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
private final static String lineSimpleFragmentShader = ""
|
private final static String lineSimpleFragmentShader = ""
|
||||||
+ "precision mediump float;"
|
+ "precision mediump float;"
|
||||||
+ "uniform sampler2D tex;"
|
+ "uniform sampler2D tex;"
|
||||||
+ "uniform float u_wscale;"
|
+ "uniform float u_wscale;"
|
||||||
|
+ "uniform float u_mode;"
|
||||||
+ "uniform vec4 u_color;"
|
+ "uniform vec4 u_color;"
|
||||||
+ "varying vec2 v_st;"
|
+ "varying vec2 v_st;"
|
||||||
+ "varying vec2 v_mode;"
|
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
//+ " float len;"
|
//+ " float len;"
|
||||||
// some say one should not use conditionals
|
// (currently required as overlay line renderers dont load the texture)
|
||||||
// (FIXME currently required as overlay line renderers dont load the texture)
|
|
||||||
//+ " if (u_mode == 0)"
|
//+ " if (u_mode == 0)"
|
||||||
//+ " len = abs(v_st.s);"
|
//+ " len = abs(v_st.s);"
|
||||||
//+ " else"
|
//+ " else"
|
||||||
//+ " len = texture2D(tex, v_st).a;"
|
//+ " len = texture2D(tex, v_st).a;"
|
||||||
// one trick to avoid branching, need to check performance
|
// this avoids branching, need to check performance
|
||||||
+ " float len = max(v_mode[0] * abs(v_st.s), v_mode[1] * texture2D(tex, v_st).a);"
|
+ " float len = max((1.0 - u_mode) * abs(v_st.s), u_mode * texture2D(tex, v_st).a);"
|
||||||
// interpolate alpha between: 0.0 < 1.0 - len < u_wscale
|
// interpolate alpha between: 0.0 < 1.0 - len < u_wscale
|
||||||
// where wscale is 'filter width' / 'line width' and 0 <= len <= sqrt(2)
|
// where wscale is 'filter width' / 'line width' and 0 <= len <= sqrt(2)
|
||||||
+ " gl_FragColor = u_color * smoothstep(0.0, u_wscale, 1.0 - len);"
|
+ " gl_FragColor = u_color * smoothstep(0.0, u_wscale, 1.0 - len);"
|
||||||
|
|||||||
287
src/org/oscim/renderer/LineTexRenderer.java
Normal file
287
src/org/oscim/renderer/LineTexRenderer.java
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.core.MapPosition;
|
||||||
|
import org.oscim.renderer.layer.Layer;
|
||||||
|
import org.oscim.renderer.layer.Layers;
|
||||||
|
import org.oscim.renderer.layer.LineTexLayer;
|
||||||
|
import org.oscim.utils.GlUtils;
|
||||||
|
|
||||||
|
import android.opengl.GLES20;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class LineTexRenderer {
|
||||||
|
private final static String TAG = LineTexRenderer.class.getName();
|
||||||
|
|
||||||
|
private static int shader;
|
||||||
|
private static int hVertexPosition0;
|
||||||
|
private static int hVertexPosition1;
|
||||||
|
private static int hVertexLength0;
|
||||||
|
private static int hVertexLength1;
|
||||||
|
private static int hVertexFlip;
|
||||||
|
private static int hMatrix;
|
||||||
|
private static int hTexColor;
|
||||||
|
private static int hBgColor;
|
||||||
|
private static int hScale;
|
||||||
|
|
||||||
|
private static int mIndicesBufferID;
|
||||||
|
private static int mVertexFlipID;
|
||||||
|
|
||||||
|
// draw up to 100 quads in one pass
|
||||||
|
|
||||||
|
private static int maxQuads = 100;
|
||||||
|
private static int maxIndices = maxQuads * 6;
|
||||||
|
private static int mTexID;
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
shader = GlUtils.createProgram(vertexShader,
|
||||||
|
fragmentShader);
|
||||||
|
if (shader == 0) {
|
||||||
|
Log.e(TAG, "Could not create program.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hMatrix = GLES20.glGetUniformLocation(shader, "u_mvp");
|
||||||
|
hTexColor = GLES20.glGetUniformLocation(shader, "u_color");
|
||||||
|
hBgColor = GLES20.glGetUniformLocation(shader, "u_bgcolor");
|
||||||
|
hScale = GLES20.glGetUniformLocation(shader, "u_scale");
|
||||||
|
|
||||||
|
hVertexPosition0 = GLES20.glGetAttribLocation(shader, "a_pos0");
|
||||||
|
hVertexPosition1 = GLES20.glGetAttribLocation(shader, "a_pos1");
|
||||||
|
hVertexLength0 = GLES20.glGetAttribLocation(shader, "a_len0");
|
||||||
|
hVertexLength1 = GLES20.glGetAttribLocation(shader, "a_len1");
|
||||||
|
hVertexFlip = GLES20.glGetAttribLocation(shader, "a_flip");
|
||||||
|
|
||||||
|
int[] mVboIds = new int[2];
|
||||||
|
GLES20.glGenBuffers(2, mVboIds, 0);
|
||||||
|
mIndicesBufferID = mVboIds[0];
|
||||||
|
mVertexFlipID = mVboIds[1];
|
||||||
|
|
||||||
|
// 0, 1, 0, 1
|
||||||
|
byte[] flip = new byte[maxQuads * 4];
|
||||||
|
for (int i = 0; i < flip.length; i++)
|
||||||
|
flip[i] = (byte) (i % 2);
|
||||||
|
|
||||||
|
short j = 0;
|
||||||
|
//mNumIndices = ((points.length) >> 2) * 6;
|
||||||
|
|
||||||
|
short[] indices = new short[maxIndices];
|
||||||
|
for (int i = 0; i < maxIndices; i += 6, j += 4) {
|
||||||
|
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 + 1);
|
||||||
|
indices[i + 5] = (short) (j + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer buf = ByteBuffer.allocateDirect(maxIndices * 2)
|
||||||
|
.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
ShortBuffer sbuf = buf.asShortBuffer();
|
||||||
|
sbuf.put(indices);
|
||||||
|
sbuf.flip();
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
|
||||||
|
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length * 2, sbuf,
|
||||||
|
GLES20.GL_STATIC_DRAW);
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
buf.clear();
|
||||||
|
buf.put(flip);
|
||||||
|
buf.flip();
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID);
|
||||||
|
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, flip.length, buf,
|
||||||
|
GLES20.GL_STATIC_DRAW);
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
byte[] stipple = new byte[2];
|
||||||
|
stipple[0] = 8;
|
||||||
|
stipple[1] = 8;
|
||||||
|
//stipple[2] = 16;
|
||||||
|
//stipple[3] = 48;
|
||||||
|
|
||||||
|
mTexID = GlUtils.loadStippleTexture(stipple);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static int STRIDE = 12;
|
||||||
|
private final static int LEN_OFFSET = 8;
|
||||||
|
|
||||||
|
public static Layer draw(Layers layers, Layer curLayer,
|
||||||
|
MapPosition pos, float[] matrix, float div) {
|
||||||
|
|
||||||
|
GLState.blend(true);
|
||||||
|
GLState.useProgram(shader);
|
||||||
|
|
||||||
|
GLState.enableVertexArrays(-1, -1);
|
||||||
|
|
||||||
|
GLES20.glEnableVertexAttribArray(hVertexPosition0);
|
||||||
|
GLES20.glEnableVertexAttribArray(hVertexPosition1);
|
||||||
|
GLES20.glEnableVertexAttribArray(hVertexLength0);
|
||||||
|
GLES20.glEnableVertexAttribArray(hVertexLength1);
|
||||||
|
GLES20.glEnableVertexAttribArray(hVertexFlip);
|
||||||
|
|
||||||
|
GLES20.glUniformMatrix4fv(hMatrix, 1, false, matrix, 0);
|
||||||
|
GLES20.glUniform1f(hScale, pos.scale / div);
|
||||||
|
|
||||||
|
GLES20.glUniform4f(hTexColor, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
//aa9988
|
||||||
|
|
||||||
|
GLES20.glUniform4f(hBgColor, 0x99 / 255f, 0x96 / 255f, 0x93 / 255f, 0.95f);
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
mIndicesBufferID);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID);
|
||||||
|
GLES20.glVertexAttribPointer(hVertexFlip, 1,
|
||||||
|
GLES20.GL_BYTE, false, 0, 0);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
|
|
||||||
|
int offset = layers.texLineOffset;
|
||||||
|
|
||||||
|
Layer l = curLayer;
|
||||||
|
while (l != null && l.type == Layer.TEXLINE) {
|
||||||
|
LineTexLayer ll = (LineTexLayer) l;
|
||||||
|
//Line line = ll.line;
|
||||||
|
|
||||||
|
// first pass
|
||||||
|
int allIndices = (ll.evenQuads * 6);
|
||||||
|
for (int i = 0; i < allIndices; i += maxIndices) {
|
||||||
|
int numIndices = allIndices - i;
|
||||||
|
if (numIndices > maxIndices)
|
||||||
|
numIndices = maxIndices;
|
||||||
|
|
||||||
|
// i / 6 * (24 shorts per block * 2 short bytes)
|
||||||
|
int add = offset + i * 8;
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexPosition0,
|
||||||
|
4, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + STRIDE);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexLength0,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + STRIDE + LEN_OFFSET);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexPosition1,
|
||||||
|
4, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexLength1,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + LEN_OFFSET);
|
||||||
|
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numIndices,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// second pass
|
||||||
|
allIndices = (ll.oddQuads * 6);
|
||||||
|
for (int i = 0; i < allIndices; i += maxIndices) {
|
||||||
|
int numIndices = allIndices - i;
|
||||||
|
if (numIndices > maxIndices)
|
||||||
|
numIndices = maxIndices;
|
||||||
|
// i / 6 * (24 shorts per block * 2 short bytes)
|
||||||
|
int add = offset + i * 8;
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexPosition0,
|
||||||
|
4, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + 2 * STRIDE);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexLength0,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + 2 * STRIDE + LEN_OFFSET);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexPosition1,
|
||||||
|
4, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + STRIDE);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(hVertexLength1,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE,
|
||||||
|
add + STRIDE + LEN_OFFSET);
|
||||||
|
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numIndices,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
l = l.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
GLES20.glDisableVertexAttribArray(hVertexPosition0);
|
||||||
|
GLES20.glDisableVertexAttribArray(hVertexPosition1);
|
||||||
|
GLES20.glDisableVertexAttribArray(hVertexLength0);
|
||||||
|
GLES20.glDisableVertexAttribArray(hVertexLength1);
|
||||||
|
GLES20.glDisableVertexAttribArray(hVertexFlip);
|
||||||
|
GlUtils.checkGlError("...");
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
final static String vertexShader = ""
|
||||||
|
+ "precision mediump float;"
|
||||||
|
+ "uniform mat4 u_mvp;"
|
||||||
|
+ "uniform vec4 u_color;"
|
||||||
|
+ "uniform float u_scale;"
|
||||||
|
+ "attribute vec4 a_pos0;"
|
||||||
|
+ "attribute vec4 a_pos1;"
|
||||||
|
+ "attribute vec2 a_len0;"
|
||||||
|
+ "attribute vec2 a_len1;"
|
||||||
|
+ "attribute float a_flip;"
|
||||||
|
+ "varying vec2 v_st;"
|
||||||
|
+ "void main() {"
|
||||||
|
+ " float div = (8.0 * 16.0) / max(ceil(log(u_scale)),1.0);"
|
||||||
|
+ " if (a_flip == 0.0){"
|
||||||
|
+ " vec2 dir = a_pos0.zw/16.0;"
|
||||||
|
+ " gl_Position = u_mvp * vec4(a_pos0.xy + dir / u_scale, 0.0, 1.0);"
|
||||||
|
+ " v_st = vec2(a_len0.x/div, 1.0);"
|
||||||
|
+ " }else {"
|
||||||
|
+ " vec2 dir = a_pos1.zw/16.0;"
|
||||||
|
+ " gl_Position = u_mvp * vec4(a_pos1.xy - dir / u_scale, 0.0, 1.0);"
|
||||||
|
+ " v_st = vec2(a_len1.x/div, -1.0);"
|
||||||
|
+ " }"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
final static String fragmentShader = ""
|
||||||
|
+ "#extension GL_OES_standard_derivatives : enable\n"
|
||||||
|
+ "precision mediump float;"
|
||||||
|
+ "uniform sampler2D tex;"
|
||||||
|
+ " uniform vec4 u_color;"
|
||||||
|
+ " uniform vec4 u_bgcolor;"
|
||||||
|
+ "varying vec2 v_st;"
|
||||||
|
+ "void main() {"
|
||||||
|
+ " float len = texture2D(tex, v_st).a;"
|
||||||
|
+ " float tex_w = abs(v_st.t);"
|
||||||
|
+ " vec2 st_width = fwidth(v_st);"
|
||||||
|
+ " float fuzz = max(st_width.s, st_width.t);"
|
||||||
|
+ " float line_w = (1.0 - smoothstep(1.0 - fuzz, 1.0, tex_w));"
|
||||||
|
+ " float stipple_w = (1.0 - smoothstep(0.7 - fuzz, 0.7, tex_w));"
|
||||||
|
+ " float stipple_p = smoothstep(0.495, 0.505, len);"
|
||||||
|
+ " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));"
|
||||||
|
|
||||||
|
//+ " gl_FragColor = u_color * min(abs(1.0 - mod(v_len, 20.0)/10.0), (1.0 - abs(v_st.x)));"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
}
|
||||||
@ -37,15 +37,6 @@ public final class MapTile extends JobTile {
|
|||||||
*/
|
*/
|
||||||
public boolean isVisible;
|
public boolean isVisible;
|
||||||
|
|
||||||
/**
|
|
||||||
* VBO holds all vertex data to draw lines and polygons when
|
|
||||||
* 'layers' are compiled. layout:
|
|
||||||
* 16 bytes fill coordinates,
|
|
||||||
* n bytes polygon vertices,
|
|
||||||
* m bytes lines vertices
|
|
||||||
*/
|
|
||||||
BufferObject vbo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to access relatives in QuadTree
|
* Pointer to access relatives in QuadTree
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -162,7 +162,7 @@ public class TileManager {
|
|||||||
MapPosition mapPosition = mMapPosition;
|
MapPosition mapPosition = mMapPosition;
|
||||||
float[] coords = mTileCoords;
|
float[] coords = mTileCoords;
|
||||||
|
|
||||||
synchronized(mMapViewPosition){
|
synchronized (mMapViewPosition) {
|
||||||
changedPos = mMapViewPosition.getMapPosition(mapPosition);
|
changedPos = mMapViewPosition.getMapPosition(mapPosition);
|
||||||
mMapViewPosition.getMapViewProjection(coords);
|
mMapViewPosition.getMapViewProjection(coords);
|
||||||
}
|
}
|
||||||
@ -390,17 +390,18 @@ public class TileManager {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (t.layers != null) {
|
if (t.layers != null) {
|
||||||
|
// TODO move this to layers clear
|
||||||
|
if (t.layers.vbo != null) {
|
||||||
|
BufferObject.release(t.layers.vbo);
|
||||||
|
t.layers.vbo = null;
|
||||||
|
}
|
||||||
|
|
||||||
t.layers.clear();
|
t.layers.clear();
|
||||||
t.layers = null;
|
t.layers = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextItem.release(t.labels);
|
TextItem.release(t.labels);
|
||||||
|
|
||||||
if (t.vbo != null) {
|
|
||||||
BufferObject.release(t.vbo);
|
|
||||||
t.vbo = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
QuadTree.remove(t);
|
QuadTree.remove(t);
|
||||||
t.state = STATE_NONE;
|
t.state = STATE_NONE;
|
||||||
|
|
||||||
@ -522,19 +523,19 @@ public class TileManager {
|
|||||||
tiles[i] = null;
|
tiles[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (locked) {
|
//if (locked) {
|
||||||
// Log.d(TAG, "------------ "
|
// Log.d(TAG, "------------ "
|
||||||
// + remove + " / " + r + " "
|
// + remove + " / " + r + " "
|
||||||
// + mMapPosition.zoomLevel
|
// + mMapPosition.zoomLevel
|
||||||
// + " ----------");
|
// + " ----------");
|
||||||
// for (int i = 0; i < size; i++) {
|
// for (int i = 0; i < size; i++) {
|
||||||
// MapTile t = tiles[i];
|
// MapTile t = tiles[i];
|
||||||
// if (t == null)
|
// if (t == null)
|
||||||
// continue;
|
// continue;
|
||||||
// Log.d(TAG, "limitCache: " + t + " " + t.distance);
|
// Log.d(TAG, "limitCache: " + t + " " + t.distance);
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
// }
|
//}
|
||||||
remove = (newTileCnt - MAX_TILES_IN_QUEUE) + 10;
|
remove = (newTileCnt - MAX_TILES_IN_QUEUE) + 10;
|
||||||
//int r = remove;
|
//int r = remove;
|
||||||
for (int i = size - 1; i >= 0 && remove > 0; i--) {
|
for (int i = size - 1; i >= 0 && remove > 0; i--) {
|
||||||
@ -572,11 +573,11 @@ public class TileManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile.vbo != null) {
|
//if (tile.vbo != null) {
|
||||||
// BAD Things(tm) happend: tile is already loaded
|
// // BAD Things(tm) happend: tile is already loaded
|
||||||
Log.d(TAG, "BUG: tile loaded before " + tile);
|
// Log.d(TAG, "BUG: tile loaded before " + tile);
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
|
|
||||||
tile.state = STATE_NEW_DATA;
|
tile.state = STATE_NEW_DATA;
|
||||||
mTilesForUpload++;
|
mTilesForUpload++;
|
||||||
|
|||||||
@ -64,7 +64,7 @@ public class ExtrusionLayer extends Layer {
|
|||||||
|
|
||||||
public ExtrusionLayer(int level) {
|
public ExtrusionLayer(int level) {
|
||||||
this.type = Layer.EXTRUSION;
|
this.type = Layer.EXTRUSION;
|
||||||
this.layer = level;
|
this.level = level;
|
||||||
|
|
||||||
mVertices = mCurVertices = VertexPool.get();
|
mVertices = mCurVertices = VertexPool.get();
|
||||||
|
|
||||||
@ -346,6 +346,7 @@ public class ExtrusionLayer extends Layer {
|
|||||||
return convex;
|
return convex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void compile(ShortBuffer sbuf) {
|
public void compile(ShortBuffer sbuf) {
|
||||||
|
|
||||||
if (mNumVertices == 0 || compiled)
|
if (mNumVertices == 0 || compiled)
|
||||||
|
|||||||
@ -14,24 +14,28 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @authorHannes Janetzek
|
* @authorHannes Janetzek
|
||||||
*/
|
*/
|
||||||
public abstract class Layer {
|
public abstract class Layer {
|
||||||
public final static byte LINE = 0;
|
public final static byte LINE = 0;
|
||||||
public final static byte POLYGON = 1;
|
public final static byte POLYGON = 1;
|
||||||
public final static byte WAYTEXT = 2;
|
public final static byte TEXLINE = 2;
|
||||||
public final static byte POITEXT = 3;
|
public final static byte WAYTEXT = 3;
|
||||||
public final static byte SYMBOL = 4;
|
public final static byte POITEXT = 4;
|
||||||
public final static byte BITMAP = 5;
|
public final static byte SYMBOL = 5;
|
||||||
public final static byte TEXLINE = 6;
|
public final static byte BITMAP = 6;
|
||||||
public final static byte EXTRUSION = 7;
|
public final static byte EXTRUSION = 7;
|
||||||
|
|
||||||
public byte type = -1;
|
public byte type = -1;
|
||||||
|
|
||||||
public Layer next;
|
public Layer next;
|
||||||
|
|
||||||
int layer;
|
// drawing order from bottom to top
|
||||||
|
int level;
|
||||||
|
|
||||||
// number of vertices for this layer
|
// number of vertices for this layer
|
||||||
public int verticesCnt;
|
public int verticesCnt;
|
||||||
|
|
||||||
@ -44,5 +48,6 @@ public abstract class Layer {
|
|||||||
VertexPoolItem pool;
|
VertexPoolItem pool;
|
||||||
protected VertexPoolItem curItem;
|
protected VertexPoolItem curItem;
|
||||||
|
|
||||||
|
abstract protected void compile(ShortBuffer sbuf);
|
||||||
abstract protected void clear();
|
abstract protected void clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,22 +16,33 @@ package org.oscim.renderer.layer;
|
|||||||
|
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.oscim.renderer.BufferObject;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Hannes Janetzek
|
|
||||||
*/
|
|
||||||
public class Layers {
|
public class Layers {
|
||||||
// mixed Polygon and Line layers
|
private final static String TAG = Layers.class.getName();
|
||||||
public Layer layers;
|
|
||||||
|
// mixed Polygon- and LineLayer
|
||||||
|
public Layer baseLayers;
|
||||||
public Layer textureLayers;
|
public Layer textureLayers;
|
||||||
public Layer extrusionLayers;
|
public Layer extrusionLayers;
|
||||||
|
|
||||||
|
// VBO holds all vertex data to draw lines and polygons
|
||||||
|
// after are compilation.
|
||||||
|
// Layout:
|
||||||
|
// 16 bytes fill coordinates,
|
||||||
|
// n bytes polygon vertices,
|
||||||
|
// m bytes lines vertices
|
||||||
|
// ...
|
||||||
|
public BufferObject vbo;
|
||||||
|
|
||||||
// To not need to switch VertexAttribPointer positions all the time:
|
// To not need to switch VertexAttribPointer positions all the time:
|
||||||
// 1. polygons are packed in VBO at offset 0
|
// 1. polygons are packed in VBO at offset 0
|
||||||
// 2. lines afterwards at lineOffset
|
// 2. lines afterwards at lineOffset
|
||||||
// 3. other layers keep their byte offset in Layer.offset
|
// 3. other layers keep their byte offset in Layer.offset
|
||||||
public int lineOffset;
|
public int lineOffset;
|
||||||
|
public int texLineOffset;
|
||||||
|
|
||||||
// time when layers became first rendered (in uptime)
|
// time when layers became first rendered (in uptime)
|
||||||
// used for animations
|
// used for animations
|
||||||
@ -39,93 +50,109 @@ public class Layers {
|
|||||||
|
|
||||||
private Layer mCurLayer;
|
private Layer mCurLayer;
|
||||||
|
|
||||||
// get or add the line- or polygon-layer for a level.
|
// get or add the Line- or PolygonLayer for a level.
|
||||||
public Layer getLayer(int level, byte type) {
|
public Layer getLayer(int level, byte type) {
|
||||||
Layer l = layers;
|
Layer l = baseLayers;
|
||||||
Layer ret = null;
|
Layer layer = null;
|
||||||
|
|
||||||
if (mCurLayer != null && mCurLayer.layer == level) {
|
if (mCurLayer != null && mCurLayer.level == level) {
|
||||||
ret = mCurLayer;
|
layer = mCurLayer;
|
||||||
} else if (l == null || l.layer > level) {
|
|
||||||
// insert new layer at start
|
|
||||||
l = null;
|
|
||||||
} else {
|
} else {
|
||||||
while (true) {
|
|
||||||
if (l.layer == level) {
|
|
||||||
// found layer
|
|
||||||
ret = l;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (l.next == null || l.next.layer > level) {
|
if (l == null || l.level > level) {
|
||||||
|
// insert new layer at start
|
||||||
|
l = null;
|
||||||
|
} else {
|
||||||
|
while (true) {
|
||||||
|
// found layer
|
||||||
|
if (l.level == level) {
|
||||||
|
layer = l;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// insert new layer between current and next layer
|
// insert new layer between current and next layer
|
||||||
break;
|
if (l.next == null || l.next.level > level)
|
||||||
|
break;
|
||||||
|
|
||||||
|
l = l.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layer == null) {
|
||||||
|
// add a new Layer
|
||||||
|
if (type == Layer.LINE)
|
||||||
|
layer = new LineLayer(level);
|
||||||
|
else if (type == Layer.POLYGON)
|
||||||
|
layer = new PolygonLayer(level);
|
||||||
|
else if (type == Layer.TEXLINE)
|
||||||
|
layer = new LineTexLayer(level);
|
||||||
|
else
|
||||||
|
// TODO throw execption
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (l == null) {
|
||||||
|
// insert at start
|
||||||
|
layer.next = baseLayers;
|
||||||
|
baseLayers = layer;
|
||||||
|
} else {
|
||||||
|
layer.next = l.next;
|
||||||
|
l.next = layer;
|
||||||
}
|
}
|
||||||
l = l.next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret == null) {
|
|
||||||
if (type == Layer.LINE)
|
|
||||||
ret = new LineLayer(level);
|
|
||||||
else if (type == Layer.POLYGON)
|
|
||||||
ret = new PolygonLayer(level);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (l == null) {
|
if (layer.type != type) {
|
||||||
// insert at start
|
// check if found layer matches requested type
|
||||||
ret.next = layers;
|
Log.d(TAG, "BUG wrong layer " + layer.type + " " + type);
|
||||||
layers = ret;
|
// TODO throw exception
|
||||||
} 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 null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
mCurLayer = layer;
|
||||||
|
|
||||||
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int LINE_VERTEX_SHORTS = 4;
|
private final static int[] VERTEX_SHORT_CNT = {
|
||||||
private static int POLY_VERTEX_SHORTS = 2;
|
4, // LINE_VERTEX_SHORTS
|
||||||
private static int TEXTURE_VERTEX_SHORTS = 6;
|
2, // POLY_VERTEX_SHORTS
|
||||||
|
6, // TEXLINE_VERTEX_SHORTS
|
||||||
|
};
|
||||||
|
|
||||||
//private static int EXTRUSION_VERTEX_SHORTS = 4;
|
private final static int TEXTURE_VERTEX_SHORTS = 6;
|
||||||
|
|
||||||
|
private final static int SHORT_BYTES = 2;
|
||||||
|
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
for (Layer l = layers; l != null; l = l.next) {
|
for (Layer l = baseLayers; l != null; l = l.next)
|
||||||
if (l.type == Layer.LINE)
|
size += l.verticesCnt * VERTEX_SHORT_CNT[l.type];
|
||||||
size += l.verticesCnt * LINE_VERTEX_SHORTS;
|
|
||||||
else
|
|
||||||
size += l.verticesCnt * POLY_VERTEX_SHORTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Layer l = textureLayers; l != null; l = l.next)
|
for (Layer l = textureLayers; l != null; l = l.next)
|
||||||
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
||||||
|
|
||||||
//for (Layer l = extrusionLayers; l != null; l = l.next)
|
|
||||||
// size += l.verticesCnt * EXTRUSION_VERTEX_SHORTS;
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void compile(ShortBuffer sbuf, boolean addFill) {
|
public void compile(ShortBuffer sbuf, boolean addFill) {
|
||||||
// offset from fill coordinates
|
// offset from fill coordinates
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
if (addFill)
|
int size = 0;
|
||||||
|
|
||||||
|
if (addFill){
|
||||||
pos = 4;
|
pos = 4;
|
||||||
|
size = 8;
|
||||||
|
}
|
||||||
|
|
||||||
// add polygons first, needed to get the offsets right...
|
size += addLayerItems(sbuf, baseLayers, Layer.POLYGON, pos);
|
||||||
addLayerItems(sbuf, layers, Layer.POLYGON, pos);
|
|
||||||
|
|
||||||
lineOffset = sbuf.position() * 2; // * short-bytes
|
lineOffset = size * SHORT_BYTES;
|
||||||
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
size += addLayerItems(sbuf, baseLayers, Layer.LINE, 0);
|
||||||
|
|
||||||
|
|
||||||
|
texLineOffset = size * SHORT_BYTES;
|
||||||
|
size += addLayerItems(sbuf, baseLayers, Layer.TEXLINE, 0);
|
||||||
|
|
||||||
for (Layer l = textureLayers; l != null; l = l.next) {
|
for (Layer l = textureLayers; l != null; l = l.next) {
|
||||||
TextureLayer tl = (TextureLayer) l;
|
TextureLayer tl = (TextureLayer) l;
|
||||||
@ -139,20 +166,33 @@ public class Layers {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// optimization for lines and polygon: collect all pool items and add back in one go
|
// optimization for Line- and PolygonLayer:
|
||||||
private static void addLayerItems(ShortBuffer sbuf, Layer l, byte type, int pos) {
|
// collect all pool items and add back in one go
|
||||||
|
private static int addLayerItems(ShortBuffer sbuf, Layer l, byte type, int pos) {
|
||||||
VertexPoolItem last = null, items = null;
|
VertexPoolItem last = null, items = null;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
// HACK, see LineTexLayer
|
||||||
|
boolean addOffset = (type == Layer.TEXLINE);
|
||||||
|
|
||||||
for (; l != null; l = l.next) {
|
for (; l != null; l = l.next) {
|
||||||
if (l.type != type)
|
if (l.type != type)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
if (addOffset){
|
||||||
if (it.next == null)
|
sbuf.position(sbuf.position() + 6);
|
||||||
sbuf.put(it.vertices, 0, it.used);
|
addOffset = false;
|
||||||
else
|
}
|
||||||
sbuf.put(it.vertices, 0, VertexPoolItem.SIZE);
|
|
||||||
|
|
||||||
|
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
||||||
|
if (it.next == null){
|
||||||
|
size += it.used;
|
||||||
|
sbuf.put(it.vertices, 0, it.used);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
size += VertexPoolItem.SIZE;
|
||||||
|
sbuf.put(it.vertices, 0, VertexPoolItem.SIZE);
|
||||||
|
}
|
||||||
last = it;
|
last = it;
|
||||||
}
|
}
|
||||||
if (last == null)
|
if (last == null)
|
||||||
@ -169,11 +209,13 @@ public class Layers {
|
|||||||
l.curItem = null;
|
l.curItem = null;
|
||||||
}
|
}
|
||||||
VertexPool.release(items);
|
VertexPool.release(items);
|
||||||
|
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addPoolItems(Layer l, ShortBuffer sbuf) {
|
static void addPoolItems(Layer l, ShortBuffer sbuf) {
|
||||||
// offset of layer data in vbo
|
// offset of layer data in vbo
|
||||||
l.offset = sbuf.position() * 2; // (* short-bytes)
|
l.offset = sbuf.position() * SHORT_BYTES;
|
||||||
|
|
||||||
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
||||||
if (it.next == null)
|
if (it.next == null)
|
||||||
@ -190,7 +232,7 @@ public class Layers {
|
|||||||
public void clear() {
|
public void clear() {
|
||||||
|
|
||||||
// clear line and polygon layers directly
|
// clear line and polygon layers directly
|
||||||
Layer l = layers;
|
Layer l = baseLayers;
|
||||||
while (l != null) {
|
while (l != null) {
|
||||||
if (l.pool != null) {
|
if (l.pool != null) {
|
||||||
VertexPool.release(l.pool);
|
VertexPool.release(l.pool);
|
||||||
@ -207,8 +249,13 @@ public class Layers {
|
|||||||
for (l = extrusionLayers; l != null; l = l.next) {
|
for (l = extrusionLayers; l != null; l = l.next) {
|
||||||
l.clear();
|
l.clear();
|
||||||
}
|
}
|
||||||
layers = null;
|
baseLayers = null;
|
||||||
textureLayers = null;
|
textureLayers = null;
|
||||||
extrusionLayers = null;
|
extrusionLayers = null;
|
||||||
|
|
||||||
|
// if (vbo != null){
|
||||||
|
// BufferObject.release(vbo);
|
||||||
|
// vbo = null;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.theme.renderinstruction.Line;
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
@ -26,7 +28,6 @@ import android.graphics.Paint.Cap;
|
|||||||
* @author Hannes Janetzek
|
* @author Hannes Janetzek
|
||||||
*/
|
*/
|
||||||
public final class LineLayer extends Layer {
|
public final class LineLayer extends Layer {
|
||||||
|
|
||||||
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||||
// scale factor mapping extrusion vector to short values
|
// scale factor mapping extrusion vector to short values
|
||||||
public static final float DIR_SCALE = 2048;
|
public static final float DIR_SCALE = 2048;
|
||||||
@ -42,7 +43,7 @@ public final class LineLayer extends Layer {
|
|||||||
public boolean roundCap;
|
public boolean roundCap;
|
||||||
|
|
||||||
LineLayer(int layer) {
|
LineLayer(int layer) {
|
||||||
this.layer = layer;
|
this.level = layer;
|
||||||
this.type = Layer.LINE;
|
this.type = Layer.LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,11 +313,13 @@ public final class LineLayer extends Layer {
|
|||||||
vx *= -1;
|
vx *= -1;
|
||||||
vy *= -1;
|
vy *= -1;
|
||||||
|
|
||||||
|
int end = pos + length;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ipos < pos + length) {
|
if (ipos < end) {
|
||||||
nextX = points[ipos++];
|
nextX = points[ipos++];
|
||||||
nextY = points[ipos++];
|
nextY = points[ipos++];
|
||||||
} else if (closed && ipos < pos + length + 2) {
|
} else if (closed && ipos < end + 2) {
|
||||||
// add startpoint == endpoint
|
// add startpoint == endpoint
|
||||||
nextX = points[pos];
|
nextX = points[pos];
|
||||||
nextY = points[pos + 1];
|
nextY = points[pos + 1];
|
||||||
@ -543,4 +546,8 @@ public final class LineLayer extends Layer {
|
|||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compile(ShortBuffer sbuf) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
229
src/org/oscim/renderer/layer/LineTexLayer.java
Normal file
229
src/org/oscim/renderer/layer/LineTexLayer.java
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 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.GLRenderer;
|
||||||
|
import org.oscim.theme.renderinstruction.Line;
|
||||||
|
import org.oscim.utils.FastMath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layer for textured or stippled lines
|
||||||
|
*/
|
||||||
|
public final class LineTexLayer extends Layer {
|
||||||
|
// Interleave two segment quads in one block to be able to use
|
||||||
|
// vertices twice. pos0 and pos1 use the same vertex array where
|
||||||
|
// pos1 has an offset of one vertex. The vertex shader will use
|
||||||
|
// pos0 when the vertexId is even, pos1 when the Id is odd.
|
||||||
|
//
|
||||||
|
// As there is no gl_VertexId in gles 2.0 an additional 'flip'
|
||||||
|
// array is used. Depending on 'flip' extrusion is inverted.
|
||||||
|
//
|
||||||
|
// Indices and flip buffers can be static.
|
||||||
|
//
|
||||||
|
// First pass: using even vertex array positions
|
||||||
|
// (used vertices are in braces)
|
||||||
|
// vertex id 0 1 2 3 4 5 6 7
|
||||||
|
// pos0 x (0) 1 (2) 3 (4) 5 (6) 7 x
|
||||||
|
// pos1 x (0) 1 (2) 3 (4) 5 (6) 7 x
|
||||||
|
// flip 0 1 0 1 0 1 0 1
|
||||||
|
//
|
||||||
|
// Second pass: using odd vertex array positions
|
||||||
|
// vertex id 0 1 2 3 4 5 6 7
|
||||||
|
// pos0 x 0 (1) 2 (3) 4 (5) 6 (7) x
|
||||||
|
// pos1 x 0 (1) 2 (3) 4 (5) 6 (7) x
|
||||||
|
// flip 0 1 0 1 0 1 0 1
|
||||||
|
//
|
||||||
|
// Vertex layout:
|
||||||
|
// [2 short] position,
|
||||||
|
// [2 short] extrusion,
|
||||||
|
// [1 short] line length
|
||||||
|
// [1 short] unused
|
||||||
|
//
|
||||||
|
// indices, for two blocks:
|
||||||
|
// 0, 1, 2,
|
||||||
|
// 2, 1, 3,
|
||||||
|
// 4, 5, 6,
|
||||||
|
// 6, 5, 7,
|
||||||
|
|
||||||
|
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||||
|
// scale factor mapping extrusion vector to short values
|
||||||
|
public static final float DIR_SCALE = 255; //2048;
|
||||||
|
|
||||||
|
// lines referenced by this outline layer
|
||||||
|
public LineLayer outlines;
|
||||||
|
public Line line;
|
||||||
|
public float width;
|
||||||
|
|
||||||
|
public boolean roundCap;
|
||||||
|
|
||||||
|
public int evenQuads;
|
||||||
|
public int oddQuads;
|
||||||
|
|
||||||
|
private boolean evenSegment;
|
||||||
|
|
||||||
|
LineTexLayer(int layer) {
|
||||||
|
this.level = layer;
|
||||||
|
this.type = Layer.TEXLINE;
|
||||||
|
this.evenSegment = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLine(float[] points, short[] index) {
|
||||||
|
|
||||||
|
if (pool == null) {
|
||||||
|
curItem = pool = VertexPool.get();
|
||||||
|
// need to make sure there is one unused
|
||||||
|
// vertex in front for interleaving.
|
||||||
|
|
||||||
|
// HACK add this offset when compiling
|
||||||
|
// otherwise one cant use the full
|
||||||
|
// VertexItem
|
||||||
|
//curItem.used = 6;
|
||||||
|
|
||||||
|
verticesCnt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexPoolItem si = curItem;
|
||||||
|
|
||||||
|
short v[] = si.vertices;
|
||||||
|
int opos = si.used;
|
||||||
|
|
||||||
|
boolean even = evenSegment;
|
||||||
|
|
||||||
|
// reset offset to last written position
|
||||||
|
if (!even)
|
||||||
|
opos -= 12;
|
||||||
|
|
||||||
|
int n;
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
if (index == null) {
|
||||||
|
n = 1;
|
||||||
|
length = points.length;
|
||||||
|
} else {
|
||||||
|
n = index.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0, pos = 0; i < n; i++) {
|
||||||
|
if (index != null)
|
||||||
|
length = index[i];
|
||||||
|
|
||||||
|
// check end-marker in indices
|
||||||
|
if (length < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// need at least two points
|
||||||
|
if (length < 4) {
|
||||||
|
pos += length;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipos = pos;
|
||||||
|
|
||||||
|
float x = points[ipos++] * COORD_SCALE;
|
||||||
|
float y = points[ipos++] * COORD_SCALE;
|
||||||
|
|
||||||
|
// randomize a bit
|
||||||
|
float lineLength = FastMath.abs(x * y) % 20;
|
||||||
|
|
||||||
|
int end = pos + length;
|
||||||
|
|
||||||
|
for (; ipos < end;) {
|
||||||
|
float nx = points[ipos++] * COORD_SCALE;
|
||||||
|
float ny = points[ipos++] * COORD_SCALE;
|
||||||
|
|
||||||
|
// Calculate triangle corners for the given width
|
||||||
|
float vx = nx - x;
|
||||||
|
float vy = ny - y;
|
||||||
|
|
||||||
|
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||||
|
|
||||||
|
// normal vector
|
||||||
|
vx /= a;
|
||||||
|
vy /= a;
|
||||||
|
|
||||||
|
// perpendicular to line segment
|
||||||
|
float ux = -vy;
|
||||||
|
float uy = vx;
|
||||||
|
|
||||||
|
short dx = (short) (ux * DIR_SCALE);
|
||||||
|
short dy = (short) (uy * DIR_SCALE);
|
||||||
|
|
||||||
|
if (opos == VertexPoolItem.SIZE) {
|
||||||
|
si = si.next = VertexPool.get();
|
||||||
|
v = si.vertices;
|
||||||
|
opos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
v[opos + 0] = (short) x;
|
||||||
|
v[opos + 1] = (short) y;
|
||||||
|
v[opos + 2] = dx;
|
||||||
|
v[opos + 3] = dy;
|
||||||
|
v[opos + 4] = (short) lineLength;
|
||||||
|
v[opos + 5] = 0;
|
||||||
|
|
||||||
|
lineLength += a;
|
||||||
|
v[opos + 12] = (short) nx;
|
||||||
|
v[opos + 13] = (short) ny;
|
||||||
|
v[opos + 14] = dx;
|
||||||
|
v[opos + 15] = dy;
|
||||||
|
v[opos + 16] = (short) lineLength;
|
||||||
|
v[opos + 17] = 0;
|
||||||
|
|
||||||
|
x = nx;
|
||||||
|
y = ny;
|
||||||
|
|
||||||
|
if (even) {
|
||||||
|
// go to second segment
|
||||||
|
opos += 6;
|
||||||
|
even = false;
|
||||||
|
|
||||||
|
// vertex 0 and 2 were added
|
||||||
|
verticesCnt += 3;
|
||||||
|
evenQuads++;
|
||||||
|
} else {
|
||||||
|
// go to next block
|
||||||
|
even = true;
|
||||||
|
opos += 18;
|
||||||
|
|
||||||
|
// vertex 1 and 3 were added
|
||||||
|
verticesCnt += 1;
|
||||||
|
oddQuads++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance offset to last written position
|
||||||
|
if (!even)
|
||||||
|
opos += 12;
|
||||||
|
|
||||||
|
si.used = opos;
|
||||||
|
curItem = si;
|
||||||
|
|
||||||
|
evenSegment = even;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void clear() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compile(ShortBuffer sbuf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.layer;
|
package org.oscim.renderer.layer;
|
||||||
|
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
import org.oscim.core.Tile;
|
import org.oscim.core.Tile;
|
||||||
import org.oscim.renderer.GLRenderer;
|
import org.oscim.renderer.GLRenderer;
|
||||||
import org.oscim.theme.renderinstruction.Area;
|
import org.oscim.theme.renderinstruction.Area;
|
||||||
@ -24,7 +26,7 @@ public final class PolygonLayer extends Layer {
|
|||||||
public Area area;
|
public Area area;
|
||||||
|
|
||||||
PolygonLayer(int layer) {
|
PolygonLayer(int layer) {
|
||||||
this.layer = layer;
|
this.level = layer;
|
||||||
this.type = Layer.POLYGON;
|
this.type = Layer.POLYGON;
|
||||||
curItem = VertexPool.get();
|
curItem = VertexPool.get();
|
||||||
pool = curItem;
|
pool = curItem;
|
||||||
@ -87,6 +89,10 @@ public final class PolygonLayer extends Layer {
|
|||||||
curItem = si;
|
curItem = si;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void compile(ShortBuffer sbuf) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void clear() {
|
protected void clear() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,8 @@ public abstract class TextureLayer extends Layer {
|
|||||||
* @param sbuf
|
* @param sbuf
|
||||||
* buffer to add vertices
|
* buffer to add vertices
|
||||||
*/
|
*/
|
||||||
void compile(ShortBuffer sbuf) {
|
@Override
|
||||||
|
protected void compile(ShortBuffer sbuf) {
|
||||||
|
|
||||||
for (TextureObject to = textures; to != null; to = to.next)
|
for (TextureObject to = textures; to != null; to = to.next)
|
||||||
TextureObject.uploadTexture(to);
|
TextureObject.uploadTexture(to);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ public class VertexPoolItem {
|
|||||||
|
|
||||||
// must be multiple of
|
// must be multiple of
|
||||||
// 4 (LineLayer/PolygonLayer),
|
// 4 (LineLayer/PolygonLayer),
|
||||||
// 6 (TexLineLayer)
|
// 24 (TexLineLayer - one block, i.e. two segments)
|
||||||
// 24 (TextureLayer)
|
// 24 (TextureLayer)
|
||||||
public static final int SIZE = 360;
|
public static final int SIZE = 360;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import org.oscim.renderer.GLRenderer;
|
|||||||
import org.oscim.renderer.GLRenderer.Matrices;
|
import org.oscim.renderer.GLRenderer.Matrices;
|
||||||
import org.oscim.renderer.GLState;
|
import org.oscim.renderer.GLState;
|
||||||
import org.oscim.renderer.LineRenderer;
|
import org.oscim.renderer.LineRenderer;
|
||||||
|
import org.oscim.renderer.LineTexRenderer;
|
||||||
import org.oscim.renderer.PolygonRenderer;
|
import org.oscim.renderer.PolygonRenderer;
|
||||||
import org.oscim.renderer.TextureRenderer;
|
import org.oscim.renderer.TextureRenderer;
|
||||||
import org.oscim.renderer.layer.Layer;
|
import org.oscim.renderer.layer.Layer;
|
||||||
@ -34,8 +35,6 @@ public abstract class BasicOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
public final Layers layers;
|
public final Layers layers;
|
||||||
|
|
||||||
public BufferObject vbo;
|
|
||||||
|
|
||||||
protected float[] mvp = new float[16];
|
protected float[] mvp = new float[16];
|
||||||
|
|
||||||
public BasicOverlay(MapView mapView) {
|
public BasicOverlay(MapView mapView) {
|
||||||
@ -51,17 +50,23 @@ public abstract class BasicOverlay extends RenderOverlay {
|
|||||||
|
|
||||||
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
GLState.test(false, false);
|
GLState.test(false, false);
|
||||||
|
|
||||||
if (layers.layers != null) {
|
if (layers.baseLayers != null) {
|
||||||
setMatrix(pos, m, true);
|
setMatrix(pos, m, true);
|
||||||
|
|
||||||
for (Layer l = layers.layers; l != null;) {
|
for (Layer l = layers.baseLayers; l != null;) {
|
||||||
if (l.type == Layer.POLYGON) {
|
switch (l.type) {
|
||||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
case Layer.POLYGON:
|
||||||
} else {
|
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||||
l = LineRenderer.draw(pos, l, m.mvp, div, 0, layers.lineOffset);
|
break;
|
||||||
|
case Layer.LINE:
|
||||||
|
l = LineRenderer.draw(layers, l, pos, m.mvp, div, 0);
|
||||||
|
break;
|
||||||
|
case Layer.TEXLINE:
|
||||||
|
l = LineTexRenderer.draw(layers, l, pos, m.mvp, div);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,21 +86,21 @@ public abstract class BasicOverlay extends RenderOverlay {
|
|||||||
public void compile() {
|
public void compile() {
|
||||||
int newSize = layers.getSize();
|
int newSize = layers.getSize();
|
||||||
if (newSize == 0) {
|
if (newSize == 0) {
|
||||||
BufferObject.release(vbo);
|
BufferObject.release(layers.vbo);
|
||||||
vbo = null;
|
layers.vbo = null;
|
||||||
isReady = false;
|
isReady = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbo == null) {
|
if (layers.vbo == null) {
|
||||||
vbo = BufferObject.get(0);
|
layers.vbo = BufferObject.get(0);
|
||||||
|
|
||||||
if (vbo == null)
|
if (layers.vbo == null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newSize > 0) {
|
if (newSize > 0) {
|
||||||
if (GLRenderer.uploadLayers(layers, vbo, newSize, true))
|
if (GLRenderer.uploadLayers(layers, newSize, true))
|
||||||
isReady = true;
|
isReady = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,85 +40,51 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
super(mapView);
|
super(mapView);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interleave two quads to be able to use vertices
|
// Interleave two segment quads in one block to be able to use
|
||||||
// twice. pos0 and pos1 use the same vertex array
|
// vertices twice. pos0 and pos1 use the same vertex array where
|
||||||
// where pos1 is off-setted by one vertex. The
|
// pos1 is off-setted by one vertex. The vertex shader will use
|
||||||
// vertex shader will use pos0 when the vertexId
|
// pos0 when the vertexId is even, pos1 when the Id is odd.
|
||||||
// is even, pos1 when the Id is odd.
|
|
||||||
//
|
//
|
||||||
// As there is no gl_VertexId in gles 2.0 an
|
// As there is no gl_VertexId in gles 2.0 an additional 'flip'
|
||||||
// additional 'flip' array is used.
|
// array is used. Depending on 'flip' extrusion is inverted.
|
||||||
// Depending on 'flip' extrusion is inverted.
|
|
||||||
//
|
//
|
||||||
// Indices and flip buffers can be static.
|
// Indices and flip buffers can be static.
|
||||||
//
|
//
|
||||||
// First pass: using even vertex array positions
|
// First pass: using even vertex array positions
|
||||||
// (used vertices are in braces)
|
// (used vertices are in braces)
|
||||||
// vertex id 0, 1, 2, 3
|
// vertex id 0 1 2 3 4 5 6 7
|
||||||
// pos0 - (0) 1 (2) 3 -
|
// pos0 - (0) 1 (2) 3 (4) 5 (6) 7 -
|
||||||
// pos1 - (0) 1 (2) 3 -
|
// pos1 - (0) 1 (2) 3 (4) 5 (6) 7 -
|
||||||
// flip 0 1 0 1
|
// flip 0 1 0 1 0 1 0 1
|
||||||
//
|
//
|
||||||
// Second pass: using odd vertex array positions
|
// Second pass: using odd vertex array positions
|
||||||
// vertex id 0, 1, 2, 3
|
// vertex id 0 1 2 3 4 5 6 7
|
||||||
// pos0 - 0 (1) 2 (3) -
|
// pos0 - 0 (1) 2 (3) 4 (5) 6 (7) -
|
||||||
// pos1 - 0 (1) 2 (3) -
|
// pos1 - 0 (1) 2 (3) 4 (5) 6 (7) -
|
||||||
// flip 0 1 0 1
|
// flip 0 1 0 1 0 1 0 1
|
||||||
//
|
//
|
||||||
// Vertex layout:
|
// Vertex layout:
|
||||||
// x/y pos[16][16], dir_x[8]|dir_y[8], start[4]|length[12]
|
// [2 short] position,
|
||||||
// - 'direction' precision 1/16, maximum line width is 2*16
|
// [2 short] extrusion,
|
||||||
// - texture 'start' prescision 1
|
// [1 short] line length
|
||||||
// -> max tex width is 32
|
// [1 short] unused
|
||||||
// - segment 'length' prescision 1/4
|
|
||||||
// -> max line length is 2^12/4=1024
|
|
||||||
// - texture 'end' is 'length'-'start'
|
|
||||||
|
|
||||||
// private final short[] box = {
|
|
||||||
// // '-' start
|
|
||||||
// 0, 0, 0, 0,
|
|
||||||
// // 0.
|
|
||||||
// -800, 0, 255, 0,
|
|
||||||
// // 2.
|
|
||||||
// 100, 0, 255, 0,
|
|
||||||
// // 1.
|
|
||||||
// 0, 0, 255, 1,
|
|
||||||
// // 3.
|
|
||||||
// 800, 0, 255, 1,
|
|
||||||
//
|
//
|
||||||
// -800, 200, 127, 0,
|
// indices: (two indice blocks)
|
||||||
// 0, 200, 127, 0,
|
// 0, 1, 2,
|
||||||
// 0, 200, 127, 1,
|
// 2, 1, 3,
|
||||||
// 800, 200, 127, 1,
|
// 4, 5, 6,
|
||||||
//
|
// 6, 5, 7,
|
||||||
// -800, 400, 255, 0,
|
|
||||||
// 0, 400, 255, 0,
|
|
||||||
// 0, 400, 255, 1,
|
|
||||||
// 800, 400, 255, 1,
|
|
||||||
//
|
|
||||||
// // '-' end
|
|
||||||
// 0, 0, 0, 0,
|
|
||||||
// };
|
|
||||||
|
|
||||||
private short[] indices = {
|
|
||||||
0, 1, 2,
|
|
||||||
2, 1, 3,
|
|
||||||
|
|
||||||
4, 5, 6,
|
|
||||||
6, 5, 7,
|
|
||||||
|
|
||||||
8, 9, 10,
|
|
||||||
10, 9, 11,
|
|
||||||
};
|
|
||||||
|
|
||||||
private byte[] flip;
|
|
||||||
|
|
||||||
private static int testProgram;
|
private static int testProgram;
|
||||||
private static int htestVertexPosition0;
|
private static int htestVertexPosition0;
|
||||||
private static int htestVertexPosition1;
|
private static int htestVertexPosition1;
|
||||||
|
private static int htestVertexLength0;
|
||||||
|
private static int htestVertexLength1;
|
||||||
private static int htestVertexFlip;
|
private static int htestVertexFlip;
|
||||||
private static int htestMatrix;
|
private static int htestMatrix;
|
||||||
private static int htestColor;
|
private static int htestTexColor;
|
||||||
|
private static int htestBgColor;
|
||||||
|
private static int htestScale;
|
||||||
|
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
|
||||||
@ -126,38 +92,52 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
+ "precision mediump float;"
|
+ "precision mediump float;"
|
||||||
+ "uniform mat4 u_mvp;"
|
+ "uniform mat4 u_mvp;"
|
||||||
+ "uniform vec4 u_color;"
|
+ "uniform vec4 u_color;"
|
||||||
|
+ "uniform float u_scale;"
|
||||||
+ "attribute vec4 a_pos0;"
|
+ "attribute vec4 a_pos0;"
|
||||||
+ "attribute vec4 a_pos1;"
|
+ "attribute vec4 a_pos1;"
|
||||||
|
+ "attribute vec2 a_len0;"
|
||||||
|
+ "attribute vec2 a_len1;"
|
||||||
+ "attribute float a_flip;"
|
+ "attribute float a_flip;"
|
||||||
+ "varying vec4 color;"
|
+ "varying vec2 v_st;"
|
||||||
+ "const float ff = 256.0;"
|
|
||||||
+ "const float ffff = 65536.0;"
|
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
|
+ " float div = (8.0 * 16.0) / max(ceil(log(u_scale)),1.0);"
|
||||||
+ " if (a_flip == 0.0){"
|
+ " if (a_flip == 0.0){"
|
||||||
// extract 8 bit direction vector
|
|
||||||
+ " vec2 dir = a_pos0.zw/16.0;"
|
+ " vec2 dir = a_pos0.zw/16.0;"
|
||||||
+ " gl_Position = u_mvp * vec4(a_pos0.xy + dir, 0.0, 1.0);"
|
+ " gl_Position = u_mvp * vec4(a_pos0.xy + dir / u_scale, 0.0, 1.0);"
|
||||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.0);"
|
+ " v_st = vec2(a_len0.x/div, 1.0);"
|
||||||
+ " }else {"
|
+ " }else {"
|
||||||
+ " vec2 dir = a_pos1.zw/16.0;"
|
+ " vec2 dir = a_pos1.zw/16.0;"
|
||||||
+ " gl_Position = u_mvp * vec4(a_pos1.xy - dir, 0.0, 1.0);"
|
+ " gl_Position = u_mvp * vec4(a_pos1.xy - dir / u_scale, 0.0, 1.0);"
|
||||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.0);"
|
+ " v_st = vec2(a_len1.x/div, -1.0);"
|
||||||
+ "}}";
|
+ " }"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
final static String testFragmentShader = ""
|
final static String testFragmentShader = ""
|
||||||
+ "precision mediump float;"
|
+ "precision mediump float;"
|
||||||
+ "varying vec4 color;"
|
+ "uniform sampler2D tex;"
|
||||||
|
+ " uniform vec4 u_color;"
|
||||||
|
+ " uniform vec4 u_bgcolor;"
|
||||||
|
+ "varying vec2 v_st;"
|
||||||
+ "void main() {"
|
+ "void main() {"
|
||||||
+ " gl_FragColor = color;"
|
+ " float len = texture2D(tex, v_st).a;"
|
||||||
|
+ " float tex_w = abs(v_st.t);"
|
||||||
|
+ " float line_w = (1.0 - smoothstep(0.7, 1.0, tex_w));"
|
||||||
|
+ " float stipple_w = (1.0 - smoothstep(0.1, 0.6, tex_w));"
|
||||||
|
+ " float stipple_p = smoothstep(0.495, 0.505, len);"
|
||||||
|
+ " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));"
|
||||||
|
|
||||||
|
//+ " gl_FragColor = u_color * min(abs(1.0 - mod(v_len, 20.0)/10.0), (1.0 - abs(v_st.x)));"
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
private int mIndicesBufferID;
|
private int mIndicesBufferID;
|
||||||
private int mVertexBufferID;
|
private int mVertexBufferID;
|
||||||
private int mVertexFlipID;
|
private int mVertexFlipID;
|
||||||
|
|
||||||
private int mNumVertices;
|
//private int mNumVertices;
|
||||||
private int mNumIndices;
|
private int mNumIndices;
|
||||||
|
|
||||||
|
private int mTexID;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
||||||
boolean tilesChanged) {
|
boolean tilesChanged) {
|
||||||
@ -174,9 +154,14 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
htestMatrix = GLES20.glGetUniformLocation(testProgram, "u_mvp");
|
htestMatrix = GLES20.glGetUniformLocation(testProgram, "u_mvp");
|
||||||
htestColor = GLES20.glGetUniformLocation(testProgram, "u_color");
|
htestTexColor = GLES20.glGetUniformLocation(testProgram, "u_color");
|
||||||
|
htestBgColor = GLES20.glGetUniformLocation(testProgram, "u_bgcolor");
|
||||||
|
htestScale = GLES20.glGetUniformLocation(testProgram, "u_scale");
|
||||||
|
|
||||||
htestVertexPosition0 = GLES20.glGetAttribLocation(testProgram, "a_pos0");
|
htestVertexPosition0 = GLES20.glGetAttribLocation(testProgram, "a_pos0");
|
||||||
htestVertexPosition1 = GLES20.glGetAttribLocation(testProgram, "a_pos1");
|
htestVertexPosition1 = GLES20.glGetAttribLocation(testProgram, "a_pos1");
|
||||||
|
htestVertexLength0 = GLES20.glGetAttribLocation(testProgram, "a_len0");
|
||||||
|
htestVertexLength1 = GLES20.glGetAttribLocation(testProgram, "a_len1");
|
||||||
htestVertexFlip = GLES20.glGetAttribLocation(testProgram, "a_flip");
|
htestVertexFlip = GLES20.glGetAttribLocation(testProgram, "a_flip");
|
||||||
|
|
||||||
int[] mVboIds = new int[3];
|
int[] mVboIds = new int[3];
|
||||||
@ -186,34 +171,37 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
mVertexFlipID = mVboIds[2];
|
mVertexFlipID = mVboIds[2];
|
||||||
|
|
||||||
float points[] = {
|
float points[] = {
|
||||||
800, 0,
|
-800, -800,
|
||||||
0, 0,
|
800, -800,
|
||||||
//-400, 100,
|
800, 800,
|
||||||
//-600, 200,
|
-800, 800,
|
||||||
//-800, 100,
|
-800, -800,
|
||||||
};
|
};
|
||||||
|
|
||||||
// float[] points = new float[12 * 2];
|
// float[] points = new float[12 * 2];
|
||||||
// for (int i = 0; i < 24; i += 2) {
|
// for (int i = 0; i < 24; i += 2) {
|
||||||
// points[i + 0] = (float) Math.sin(-i / 11f * Math.PI) * 400;
|
// points[i + 0] = (float) Math.sin(-i / 11f * Math.PI) * 8*400;
|
||||||
// points[i + 1] = (float) Math.cos(-i / 11f * Math.PI) * 400;
|
// points[i + 1] = (float) Math.cos(-i / 11f * Math.PI) * 8*400;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
mNumVertices = (points.length - 2) * 2;
|
boolean oddSegments = points.length % 4 == 0;
|
||||||
|
|
||||||
short[] vertices = new short[(mNumVertices + 2) * 4];
|
int numVertices = points.length + (oddSegments ? 2 : 0);
|
||||||
|
|
||||||
int opos = 4;
|
short[] vertices = new short[numVertices * 6];
|
||||||
|
|
||||||
|
int opos = 6;
|
||||||
|
|
||||||
float x = points[0];
|
float x = points[0];
|
||||||
float y = points[1];
|
float y = points[1];
|
||||||
|
|
||||||
float scale = 127;
|
float scale = 255;
|
||||||
boolean even = true;
|
boolean even = true;
|
||||||
|
float len = 0;
|
||||||
|
|
||||||
for (int i = 2; i < points.length;) {
|
for (int i = 2; i < points.length; i += 2) {
|
||||||
float nx = points[i++];
|
float nx = points[i + 0];
|
||||||
float ny = points[i++];
|
float ny = points[i + 1];
|
||||||
|
|
||||||
// Calculate triangle corners for the given width
|
// Calculate triangle corners for the given width
|
||||||
float vx = nx - x;
|
float vx = nx - x;
|
||||||
@ -225,7 +213,7 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
vx /= a;
|
vx /= a;
|
||||||
vy /= a;
|
vy /= a;
|
||||||
|
|
||||||
// perpendicular
|
// perpendicular to line segment
|
||||||
float ux = -vy;
|
float ux = -vy;
|
||||||
float uy = vx;
|
float uy = vx;
|
||||||
|
|
||||||
@ -236,33 +224,41 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
vertices[opos + 1] = (short) y;
|
vertices[opos + 1] = (short) y;
|
||||||
vertices[opos + 2] = dx;
|
vertices[opos + 2] = dx;
|
||||||
vertices[opos + 3] = dy;
|
vertices[opos + 3] = dy;
|
||||||
|
vertices[opos + 4] = (short) len;
|
||||||
|
vertices[opos + 5] = 0;
|
||||||
|
|
||||||
vertices[opos + 8] = (short) nx;
|
len += a;
|
||||||
vertices[opos + 9] = (short) ny;
|
vertices[opos + 12] = (short) nx;
|
||||||
vertices[opos + 10] = dx;
|
vertices[opos + 13] = (short) ny;
|
||||||
vertices[opos + 11] = dy;
|
vertices[opos + 14] = dx;
|
||||||
|
vertices[opos + 15] = dy;
|
||||||
|
vertices[opos + 16] = (short) len;
|
||||||
|
vertices[opos + 17] = 0;
|
||||||
|
|
||||||
x = nx;
|
x = nx;
|
||||||
y = ny;
|
y = ny;
|
||||||
|
|
||||||
if (even) {
|
if (even) {
|
||||||
opos += 4;
|
// go to second segment
|
||||||
|
opos += 6;
|
||||||
even = false;
|
even = false;
|
||||||
} else {
|
} else {
|
||||||
|
// go to next block
|
||||||
even = true;
|
even = true;
|
||||||
opos += 12;
|
opos += 18;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flip = new byte[(points.length - 2)];
|
// 0, 1, 0, 1
|
||||||
|
byte[] flip = new byte[points.length];
|
||||||
for (int i = 0; i < flip.length; i++)
|
for (int i = 0; i < flip.length; i++)
|
||||||
flip[i] = (byte) (i % 2);
|
flip[i] = (byte) (i % 2);
|
||||||
|
|
||||||
short j = 0;
|
short j = 0;
|
||||||
mNumIndices = ((points.length) >> 2) * 6;
|
mNumIndices = ((points.length) >> 2) * 6;
|
||||||
|
|
||||||
indices = new short[mNumIndices];
|
short[] indices = new short[mNumIndices];
|
||||||
for (int i = 0; i < mNumIndices; i += 6, j += 4) {
|
for (int i = 0; i < mNumIndices; i += 6, j += 4) {
|
||||||
indices[i + 0] = (short) (j + 0);
|
indices[i + 0] = (short) (j + 0);
|
||||||
indices[i + 1] = (short) (j + 1);
|
indices[i + 1] = (short) (j + 1);
|
||||||
@ -273,7 +269,7 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
indices[i + 5] = (short) (j + 3);
|
indices[i + 5] = (short) (j + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.allocateDirect(128 * 4)
|
ByteBuffer buf = ByteBuffer.allocateDirect(numVertices * 6 * 2)
|
||||||
.order(ByteOrder.nativeOrder());
|
.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
ShortBuffer sbuf = buf.asShortBuffer();
|
ShortBuffer sbuf = buf.asShortBuffer();
|
||||||
@ -285,7 +281,6 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
sbuf.clear();
|
sbuf.clear();
|
||||||
//sbuf.put(box);
|
|
||||||
sbuf.put(vertices);
|
sbuf.put(vertices);
|
||||||
sbuf.flip();
|
sbuf.flip();
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||||
@ -300,12 +295,23 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
GLES20.GL_STATIC_DRAW);
|
GLES20.GL_STATIC_DRAW);
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
byte[] stipple = new byte[2];
|
||||||
|
stipple[0] = 8;
|
||||||
|
stipple[1] = 8;
|
||||||
|
//stipple[2] = 16;
|
||||||
|
//stipple[3] = 48;
|
||||||
|
|
||||||
|
mTexID = GlUtils.loadStippleTexture(stipple);
|
||||||
|
|
||||||
mMapView.getMapViewPosition().getMapPosition(mMapPosition);
|
mMapView.getMapViewPosition().getMapPosition(mMapPosition);
|
||||||
|
|
||||||
// tell GLRenderer to call 'render'
|
// tell GLRenderer to call 'render'
|
||||||
isReady = true;
|
isReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static int STRIDE = 12;
|
||||||
|
private final static int LEN_OFFSET = 8;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void render(MapPosition pos, Matrices m) {
|
public synchronized void render(MapPosition pos, Matrices m) {
|
||||||
|
|
||||||
@ -318,42 +324,79 @@ public class TestLineOverlay extends RenderOverlay {
|
|||||||
GLState.enableVertexArrays(-1, -1);
|
GLState.enableVertexArrays(-1, -1);
|
||||||
GLES20.glEnableVertexAttribArray(htestVertexPosition0);
|
GLES20.glEnableVertexAttribArray(htestVertexPosition0);
|
||||||
GLES20.glEnableVertexAttribArray(htestVertexPosition1);
|
GLES20.glEnableVertexAttribArray(htestVertexPosition1);
|
||||||
|
GlUtils.checkGlError("-4");
|
||||||
|
GLES20.glEnableVertexAttribArray(htestVertexLength0);
|
||||||
|
GlUtils.checkGlError("-3");
|
||||||
|
GLES20.glEnableVertexAttribArray(htestVertexLength1);
|
||||||
|
GlUtils.checkGlError("-2");
|
||||||
GLES20.glEnableVertexAttribArray(htestVertexFlip);
|
GLES20.glEnableVertexAttribArray(htestVertexFlip);
|
||||||
|
|
||||||
GLES20.glUniformMatrix4fv(htestMatrix, 1, false, m.mvp, 0);
|
GLES20.glUniformMatrix4fv(htestMatrix, 1, false, m.mvp, 0);
|
||||||
|
float div = FastMath.pow(pos.zoomLevel - mMapPosition.zoomLevel);
|
||||||
|
GLES20.glUniform1f(htestScale, pos.scale / mMapPosition.scale * div);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
|
GLES20.glUniform4f(htestTexColor, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
GLES20.glUniform4f(htestBgColor, 0.3f, 0.3f, 0.3f, 1.0f);
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID);
|
||||||
|
|
||||||
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER,
|
||||||
|
mIndicesBufferID);
|
||||||
|
GlUtils.checkGlError("-1");
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID);
|
||||||
GLES20.glVertexAttribPointer(htestVertexFlip, 1, GLES20.GL_BYTE, false, 0, 0);
|
GLES20.glVertexAttribPointer(htestVertexFlip, 1,
|
||||||
|
GLES20.GL_BYTE, false, 0, 0);
|
||||||
|
GlUtils.checkGlError("0");
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||||
|
GlUtils.checkGlError("1");
|
||||||
|
|
||||||
|
// first pass
|
||||||
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
||||||
4, GLES20.GL_SHORT, false, 0, 8);
|
4, GLES20.GL_SHORT, false, STRIDE, STRIDE);
|
||||||
|
GlUtils.checkGlError("2");
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(htestVertexLength0,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE, STRIDE + LEN_OFFSET);
|
||||||
|
GlUtils.checkGlError("3");
|
||||||
|
|
||||||
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
||||||
4, GLES20.GL_SHORT, false, 0, 0);
|
4, GLES20.GL_SHORT, false, STRIDE, 0);
|
||||||
|
GlUtils.checkGlError("4");
|
||||||
|
|
||||||
GLES20.glUniform4f(htestColor, 0.5f, 0.5f, 1.0f, 1.0f);
|
GLES20.glVertexAttribPointer(htestVertexLength1,
|
||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
2, GLES20.GL_SHORT, false, STRIDE, LEN_OFFSET);
|
||||||
|
GlUtils.checkGlError("5");
|
||||||
|
|
||||||
|
//GLES20.glUniform4f(htestColor, 0.5f, 0.5f, 1.0f, 1.0f);
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
|
// second pass
|
||||||
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
GLES20.glVertexAttribPointer(htestVertexPosition0,
|
||||||
4, GLES20.GL_SHORT, false, 0, 16);
|
4, GLES20.GL_SHORT, false, STRIDE, 2 * STRIDE);
|
||||||
|
|
||||||
|
GLES20.glVertexAttribPointer(htestVertexLength0,
|
||||||
|
2, GLES20.GL_SHORT, false, STRIDE, 2 * STRIDE + LEN_OFFSET);
|
||||||
|
|
||||||
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
GLES20.glVertexAttribPointer(htestVertexPosition1,
|
||||||
4, GLES20.GL_SHORT, false, 0, 8);
|
4, GLES20.GL_SHORT, false, STRIDE, STRIDE);
|
||||||
|
|
||||||
GLES20.glUniform4f(htestColor, 0.5f, 1.0f, 0.5f, 1.0f);
|
GLES20.glVertexAttribPointer(htestVertexLength1,
|
||||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
2, GLES20.GL_SHORT, false, STRIDE, STRIDE + LEN_OFFSET);
|
||||||
|
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
GLES20.glDisableVertexAttribArray(htestVertexPosition0);
|
GLES20.glDisableVertexAttribArray(htestVertexPosition0);
|
||||||
GLES20.glDisableVertexAttribArray(htestVertexPosition1);
|
GLES20.glDisableVertexAttribArray(htestVertexPosition1);
|
||||||
|
GLES20.glDisableVertexAttribArray(htestVertexLength0);
|
||||||
|
GLES20.glDisableVertexAttribArray(htestVertexLength1);
|
||||||
GLES20.glDisableVertexAttribArray(htestVertexFlip);
|
GLES20.glDisableVertexAttribArray(htestVertexFlip);
|
||||||
GlUtils.checkGlError("...");
|
GlUtils.checkGlError("...");
|
||||||
|
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -14,13 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.oscim.renderer.overlays;
|
package org.oscim.renderer.overlays;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.oscim.core.MapPosition;
|
import org.oscim.core.MapPosition;
|
||||||
import org.oscim.renderer.layer.SymbolItem;
|
import org.oscim.renderer.layer.Layer;
|
||||||
import org.oscim.renderer.layer.SymbolLayer;
|
import org.oscim.renderer.layer.LineTexLayer;
|
||||||
import org.oscim.renderer.layer.TextItem;
|
import org.oscim.renderer.layer.TextItem;
|
||||||
import org.oscim.theme.renderinstruction.BitmapUtils;
|
|
||||||
import org.oscim.view.MapView;
|
import org.oscim.view.MapView;
|
||||||
|
|
||||||
public class TestOverlay extends BasicOverlay {
|
public class TestOverlay extends BasicOverlay {
|
||||||
@ -34,12 +31,33 @@ public class TestOverlay extends BasicOverlay {
|
|||||||
public TestOverlay(MapView mapView) {
|
public TestOverlay(MapView mapView) {
|
||||||
super(mapView);
|
super(mapView);
|
||||||
|
|
||||||
// LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
// draw a rectangle
|
||||||
// ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
//LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||||
// ll.width = 2;
|
//ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||||
// float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100, -100 };
|
//ll.width = 2;
|
||||||
// short[] index = { (short) points.length };
|
float[] points = {
|
||||||
// ll.addLine(points, index, false);
|
-100, -100,
|
||||||
|
100, -100,
|
||||||
|
100, 100,
|
||||||
|
-100, 100,
|
||||||
|
-100, -100
|
||||||
|
};
|
||||||
|
//short[] index = { (short) points.length };
|
||||||
|
//ll.addLine(points, index, true);
|
||||||
|
|
||||||
|
|
||||||
|
LineTexLayer lt = (LineTexLayer) layers.getLayer(2, Layer.TEXLINE);
|
||||||
|
lt.addLine(points, null);
|
||||||
|
|
||||||
|
float[] points2 = {
|
||||||
|
-200, -200,
|
||||||
|
200, -200,
|
||||||
|
200, 200,
|
||||||
|
-200, 200,
|
||||||
|
-200, -200
|
||||||
|
};
|
||||||
|
|
||||||
|
lt.addLine(points2, null);
|
||||||
|
|
||||||
//
|
//
|
||||||
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
// PolygonLayer pl = (PolygonLayer) layers.getLayer(0, Layer.POLYGON);
|
||||||
@ -54,33 +72,33 @@ public class TestOverlay extends BasicOverlay {
|
|||||||
// short[] pindex = { (short) ppoints.length };
|
// short[] pindex = { (short) ppoints.length };
|
||||||
// pl.addPolygon(ppoints, pindex);
|
// pl.addPolygon(ppoints, pindex);
|
||||||
|
|
||||||
SymbolLayer sl = new SymbolLayer();
|
//SymbolLayer sl = new SymbolLayer();
|
||||||
SymbolItem it = new SymbolItem();
|
//SymbolItem it = new SymbolItem();
|
||||||
|
//
|
||||||
it.x = 0;
|
//it.x = 0;
|
||||||
it.y = 0;
|
//it.y = 0;
|
||||||
// billboard always faces camera
|
//// billboard always faces camera
|
||||||
it.billboard = true;
|
//it.billboard = true;
|
||||||
|
//
|
||||||
try {
|
//try {
|
||||||
it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
// it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||||
} catch (IOException e) {
|
//} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// // TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
//}
|
||||||
sl.addSymbol(it);
|
//sl.addSymbol(it);
|
||||||
|
//
|
||||||
SymbolItem it2 = new SymbolItem();
|
//SymbolItem it2 = new SymbolItem();
|
||||||
it2.bitmap = it.bitmap;
|
//it2.bitmap = it.bitmap;
|
||||||
it2.x = 0;
|
//it2.x = 0;
|
||||||
it2.y = 0;
|
//it2.y = 0;
|
||||||
// billboard always faces camera
|
//// billboard always faces camera
|
||||||
it2.billboard = false;
|
//it2.billboard = false;
|
||||||
|
//
|
||||||
sl.addSymbol(it2);
|
//sl.addSymbol(it2);
|
||||||
sl.fixed = false;
|
//sl.fixed = false;
|
||||||
|
//
|
||||||
layers.textureLayers = sl;
|
//layers.textureLayers = sl;
|
||||||
|
|
||||||
// TextLayer tl = new TextLayer();
|
// TextLayer tl = new TextLayer();
|
||||||
// Text t = Text.createText(20, 2, Color.WHITE, Color.BLACK, false);
|
// Text t = Text.createText(20, 2, Color.WHITE, Color.BLACK, false);
|
||||||
@ -106,7 +124,7 @@ public class TestOverlay extends BasicOverlay {
|
|||||||
updateMapPosition();
|
updateMapPosition();
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
((SymbolLayer) (layers.textureLayers)).prepare();
|
//((SymbolLayer) (layers.textureLayers)).prepare();
|
||||||
|
|
||||||
// pass layers to be uploaded and drawn to GL Thread
|
// pass layers to be uploaded and drawn to GL Thread
|
||||||
// afterwards never modify 'layers' outside of this function!
|
// afterwards never modify 'layers' outside of this function!
|
||||||
|
|||||||
@ -386,8 +386,8 @@ public class TextOverlay extends BasicOverlay {
|
|||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
if (mDebugLayer != null) {
|
if (mDebugLayer != null) {
|
||||||
layers.layers = mDebugLayer.layers;
|
layers.baseLayers = mDebugLayer.baseLayers;
|
||||||
mDebugLayer.layers = null;
|
mDebugLayer.baseLayers = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set new TextLayer to be uploaded and used
|
// set new TextLayer to be uploaded and used
|
||||||
|
|||||||
@ -627,7 +627,7 @@ public class TextOverlayExp extends BasicOverlay {
|
|||||||
layers.clear();
|
layers.clear();
|
||||||
|
|
||||||
if (mDebugLayer != null) {
|
if (mDebugLayer != null) {
|
||||||
layers.layers = mDebugLayer.layers;
|
layers.baseLayers = mDebugLayer.baseLayers;
|
||||||
mDebugLayer = null;
|
mDebugLayer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,12 +665,12 @@ public class TextOverlayExp extends BasicOverlay {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vbo == null) {
|
if (layers.vbo == null) {
|
||||||
vbo = BufferObject.get(0);
|
layers.vbo = BufferObject.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newSize > 0) {
|
if (newSize > 0) {
|
||||||
if (GLRenderer.uploadLayers(layers, vbo, newSize, true))
|
if (GLRenderer.uploadLayers(layers, newSize, true))
|
||||||
isReady = true;
|
isReady = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -679,19 +679,19 @@ public class TextOverlayExp extends BasicOverlay {
|
|||||||
public synchronized void render(MapPosition pos, Matrices m) {
|
public synchronized void render(MapPosition pos, Matrices m) {
|
||||||
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
float div = FastMath.pow(mMapPosition.zoomLevel - pos.zoomLevel);
|
||||||
|
|
||||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
|
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, layers.vbo.id);
|
||||||
GLState.test(false, false);
|
GLState.test(false, false);
|
||||||
|
|
||||||
if (layers.layers != null) {
|
if (layers.baseLayers != null) {
|
||||||
setMatrix(pos, m, true);
|
setMatrix(pos, m, true);
|
||||||
|
|
||||||
//Matrix.multiplyMM(m.mvp, 0, m.proj, 0, m.mvp,0);
|
//Matrix.multiplyMM(m.mvp, 0, m.proj, 0, m.mvp,0);
|
||||||
for (Layer l = layers.layers; l != null;) {
|
for (Layer l = layers.baseLayers; l != null;) {
|
||||||
if (l.type == Layer.POLYGON) {
|
if (l.type == Layer.POLYGON) {
|
||||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||||
} else {
|
} else {
|
||||||
float scale = pos.scale * div;
|
float scale = pos.scale * div;
|
||||||
l = LineRenderer.draw(pos, l, m.mvp, scale, 0, layers.lineOffset);
|
l = LineRenderer.draw(layers, l, pos, m.mvp, scale, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -229,35 +229,13 @@ public final class Line extends RenderInstruction {
|
|||||||
this.fade = fade;
|
this.fade = fade;
|
||||||
this.stipple = stipple;
|
this.stipple = stipple;
|
||||||
this.min = min;
|
this.min = min;
|
||||||
|
|
||||||
|
if (stipple != 0){
|
||||||
|
System.out.println("a");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param line
|
|
||||||
* ...
|
|
||||||
* @param style
|
|
||||||
* ...
|
|
||||||
* @param src
|
|
||||||
* ...
|
|
||||||
* @param stroke
|
|
||||||
* ...
|
|
||||||
* @param strokeWidth
|
|
||||||
* ...
|
|
||||||
* @param stipple
|
|
||||||
* ...
|
|
||||||
* @param strokeLinecap
|
|
||||||
* ...
|
|
||||||
* @param level
|
|
||||||
* ...
|
|
||||||
* @param fixed
|
|
||||||
* ...
|
|
||||||
* @param fade
|
|
||||||
* ...
|
|
||||||
* @param blur
|
|
||||||
* ...
|
|
||||||
* @param isOutline
|
|
||||||
* ...
|
|
||||||
* @param min ...
|
|
||||||
*/
|
|
||||||
private Line(Line line, String style, String src, int stroke, float strokeWidth,
|
private Line(Line line, String style, String src, int stroke, float strokeWidth,
|
||||||
int stipple, Cap strokeLinecap, int level, boolean fixed,
|
int stipple, Cap strokeLinecap, int level, boolean fixed,
|
||||||
int fade, float blur, boolean isOutline, float min) {
|
int fade, float blur, boolean isOutline, float min) {
|
||||||
|
|||||||
@ -54,6 +54,13 @@ public class FastMath {
|
|||||||
|
|
||||||
return (pow > 0 ? (1 << pow) : (1.0f / (1 << -pow)));
|
return (pow > 0 ? (1 << pow) : (1.0f / (1 << -pow)));
|
||||||
}
|
}
|
||||||
|
public static int clamp(int value, int max, int min){
|
||||||
|
return (value < min ? min : (value > max ? max : value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte clampToByte(int value){
|
||||||
|
return (byte)(value < 0 ? 0 : (value > 255 ? 255 : value));
|
||||||
|
}
|
||||||
|
|
||||||
public static float abs(float value){
|
public static float abs(float value){
|
||||||
return value < 0 ? -value : value;
|
return value < 0 ? -value : value;
|
||||||
|
|||||||
@ -30,10 +30,25 @@ import android.util.Log;
|
|||||||
public class GlUtils {
|
public class GlUtils {
|
||||||
private static String TAG = "GlUtils";
|
private static String TAG = "GlUtils";
|
||||||
|
|
||||||
|
public static void setTextureParameter(int min_filter, int mag_filter, int wrap_s, int wrap_t) {
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MIN_FILTER,
|
||||||
|
min_filter);
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MAG_FILTER,
|
||||||
|
mag_filter);
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_S,
|
||||||
|
wrap_s); // Set U Wrapping
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_T,
|
||||||
|
wrap_t); // Set V Wrapping
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bitmap
|
* @param bitmap
|
||||||
* ...
|
* ...
|
||||||
* @return gl identifier
|
* @return textureId
|
||||||
*/
|
*/
|
||||||
public static int loadTextures(Bitmap bitmap) {
|
public static int loadTextures(Bitmap bitmap) {
|
||||||
|
|
||||||
@ -44,21 +59,8 @@ public class GlUtils {
|
|||||||
|
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
|
||||||
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
setTextureParameter(GLES20.GL_LINEAR, GLES20.GL_LINEAR,
|
||||||
GLES20.GL_TEXTURE_MIN_FILTER,
|
GLES20.GL_CLAMP_TO_EDGE, GLES20.GL_CLAMP_TO_EDGE);
|
||||||
GLES20.GL_LINEAR);
|
|
||||||
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_MAG_FILTER,
|
|
||||||
GLES20.GL_LINEAR);
|
|
||||||
|
|
||||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_WRAP_S,
|
|
||||||
GLES20.GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_WRAP_T,
|
|
||||||
GLES20.GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
|
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
|
||||||
|
|
||||||
@ -66,24 +68,13 @@ public class GlUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int loadTexture(byte[] pixel, int width, int height, int format,
|
public static int loadTexture(byte[] pixel, int width, int height, int format,
|
||||||
int wrap_s, int wrap_t) {
|
int min_filter, int mag_filter, int wrap_s, int wrap_t) {
|
||||||
int[] textureIds = new int[1];
|
int[] textureIds = new int[1];
|
||||||
GLES20.glGenTextures(1, textureIds, 0);
|
GLES20.glGenTextures(1, textureIds, 0);
|
||||||
|
|
||||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
|
||||||
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
setTextureParameter(min_filter, mag_filter, wrap_s, wrap_t);
|
||||||
GLES20.GL_TEXTURE_MIN_FILTER,
|
|
||||||
GLES20.GL_NEAREST);
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_MAG_FILTER,
|
|
||||||
GLES20.GL_NEAREST);
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_WRAP_S,
|
|
||||||
wrap_s); // Set U Wrapping
|
|
||||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
|
||||||
GLES20.GL_TEXTURE_WRAP_T,
|
|
||||||
wrap_t); // Set V Wrapping
|
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.allocateDirect(width * height).order(ByteOrder.nativeOrder());
|
ByteBuffer buf = ByteBuffer.allocateDirect(width * height).order(ByteOrder.nativeOrder());
|
||||||
buf.put(pixel);
|
buf.put(pixel);
|
||||||
@ -96,6 +87,37 @@ public class GlUtils {
|
|||||||
return textureIds[0];
|
return textureIds[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int loadStippleTexture(byte[] stipple) {
|
||||||
|
int sum = 0;
|
||||||
|
for (byte flip : stipple)
|
||||||
|
sum += flip;
|
||||||
|
|
||||||
|
byte[] pixel = new byte[sum];
|
||||||
|
|
||||||
|
boolean on = true;
|
||||||
|
int pos = 0;
|
||||||
|
for (byte flip : stipple) {
|
||||||
|
float max = flip;
|
||||||
|
|
||||||
|
for (int s = 0; s < flip; s++) {
|
||||||
|
float color = Math.abs(s / (max - 1) - 0.5f);
|
||||||
|
if (on)
|
||||||
|
color = 255 * (1 - color);
|
||||||
|
else
|
||||||
|
color = 255 * color;
|
||||||
|
|
||||||
|
pixel[pos + s] = FastMath.clampToByte((int) color);
|
||||||
|
}
|
||||||
|
on = !on;
|
||||||
|
pos += flip;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadTexture(pixel, sum, 1, GLES20.GL_ALPHA,
|
||||||
|
GLES20.GL_LINEAR, GLES20.GL_LINEAR,
|
||||||
|
//GLES20.GL_NEAREST, GLES20.GL_NEAREST,
|
||||||
|
GLES20.GL_REPEAT, GLES20.GL_REPEAT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param shaderType
|
* @param shaderType
|
||||||
* shader type
|
* shader type
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user