- 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 java.util.Arrays;
|
||||
|
||||
import org.oscim.core.MercatorProjection;
|
||||
import org.oscim.core.Tag;
|
||||
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.Layers;
|
||||
import org.oscim.renderer.layer.LineLayer;
|
||||
import org.oscim.renderer.layer.LineTexLayer;
|
||||
import org.oscim.renderer.layer.PolygonLayer;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.theme.IRenderCallback;
|
||||
@ -132,7 +135,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
*/
|
||||
public TileGenerator(MapView 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() {
|
||||
@ -254,6 +257,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
mTagHouseNr = tags[i];
|
||||
tags[i] = mTagEmptyHouseNr;
|
||||
} else if (mTile.zoomLevel >= 17 &&
|
||||
// FIXME, allow overlays to intercept
|
||||
// this, or use a theme option for this
|
||||
key == Tag.TAG_KEY_BUILDING) {
|
||||
mRenderBuildingModel = true;
|
||||
}
|
||||
@ -270,38 +275,12 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
mTagName = 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;
|
||||
mPoiY = latitude;
|
||||
//}
|
||||
|
||||
// remove tags that should not be cached in Rendertheme
|
||||
filterTags(tags);
|
||||
// Log.d(TAG, "renderPointOfInterest: " + mTagName);
|
||||
|
||||
// mNodeRenderInstructions =
|
||||
TileGenerator.renderTheme.matchNode(this, tags, mTile.zoomLevel);
|
||||
}
|
||||
|
||||
@ -338,8 +317,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
private void debugUnmatched(boolean closed, Tag[] tags) {
|
||||
|
||||
Log.d(TAG, "way not matched: " + tags[0] + " "
|
||||
+ (tags.length > 1 ? tags[1] : "") + " " + closed);
|
||||
Log.d(TAG, "DBG way not matched: " + closed + " " + Arrays.deepToString(tags));
|
||||
|
||||
mTagName = new Tag("name", tags[0].key + ":" + tags[0].value, false);
|
||||
|
||||
@ -366,37 +344,62 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
// ----------------- RenderThemeCallback -----------------
|
||||
@Override
|
||||
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;
|
||||
|
||||
LineLayer lineLayer = (LineLayer) mLayers.getLayer(numLayer, Layer.LINE);
|
||||
if (lineLayer == null)
|
||||
return;
|
||||
|
||||
if (lineLayer.line == null) {
|
||||
lineLayer.line = line;
|
||||
|
||||
float w = line.width;
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mProjectionScaleFactor;
|
||||
if (line.stipple == 0) {
|
||||
if (line.outline && mCurLineLayer == null) {
|
||||
// FIXME in RenderTheme
|
||||
Log.e(TAG, "BUG in theme: line must come before outline!");
|
||||
return;
|
||||
}
|
||||
lineLayer.width = w;
|
||||
}
|
||||
|
||||
if (line.outline) {
|
||||
lineLayer.addOutline(mCurLineLayer);
|
||||
return;
|
||||
}
|
||||
LineLayer lineLayer = (LineLayer)
|
||||
mLayers.getLayer(numLayer, Layer.LINE);
|
||||
|
||||
lineLayer.addLine(mCoords, mIndices, mClosed);
|
||||
mCurLineLayer = lineLayer;
|
||||
if (lineLayer == null)
|
||||
return;
|
||||
|
||||
if (lineLayer.line == null) {
|
||||
lineLayer.line = line;
|
||||
|
||||
float w = line.width;
|
||||
if (!line.fixed) {
|
||||
w *= mStrokeScale;
|
||||
w *= mProjectionScaleFactor;
|
||||
}
|
||||
lineLayer.width = w;
|
||||
}
|
||||
|
||||
if (line.outline) {
|
||||
lineLayer.addOutline(mCurLineLayer);
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
@ -480,8 +483,8 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
int length = mIndices[i];
|
||||
if (length < 4)
|
||||
break;
|
||||
mLabels = WayDecorator.renderText(mClipper,mCoords, mTagName.value, text,
|
||||
offset, length, mLabels);
|
||||
mLabels = WayDecorator.renderText(mClipper, mCoords, mTagName.value, text,
|
||||
offset, length, mLabels);
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
@ -520,6 +523,31 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
// // 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 static final double PI180 = (Math.PI / 180) / 1000000.0;
|
||||
// private static final double PIx4 = Math.PI * 4;
|
||||
|
||||
@ -28,7 +28,8 @@ import android.opengl.GLES20;
|
||||
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
|
||||
* tiles are rendered when available.
|
||||
*
|
||||
@ -107,12 +108,12 @@ public class BaseMap {
|
||||
if (t.holder != null)
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.vbo.id);
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, t.layers.vbo.id);
|
||||
|
||||
// place tile relative to map position
|
||||
float div = FastMath.pow(tile.zoomLevel - pos.zoomLevel);
|
||||
@ -135,8 +136,9 @@ public class BaseMap {
|
||||
int simpleShader = (pos.tilt < 1 ? 1 : 0);
|
||||
|
||||
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) {
|
||||
case Layer.POLYGON:
|
||||
l = PolygonRenderer.draw(pos, l, mvp, !clipped, true);
|
||||
@ -144,16 +146,38 @@ public class BaseMap {
|
||||
break;
|
||||
|
||||
case Layer.LINE:
|
||||
//if (!lineTexture) {
|
||||
LineRenderer.beginLines();
|
||||
// lineTexture = true;
|
||||
//}
|
||||
if (!clipped) {
|
||||
// draw stencil buffer clip region
|
||||
PolygonRenderer.draw(pos, null, mvp, true, true);
|
||||
clipped = true;
|
||||
}
|
||||
l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
|
||||
t.layers.lineOffset);
|
||||
l = LineRenderer.draw(t.layers, l, pos, mvp, div, simpleShader);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -74,7 +74,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// bytes currently loaded in VBOs
|
||||
private static int mBufferMemoryUsage;
|
||||
|
||||
|
||||
private static float[] mTileCoords = 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;
|
||||
|
||||
public static boolean uploadLayers(Layers layers, BufferObject vbo, int newSize,
|
||||
public static boolean uploadLayers(Layers layers, int newSize,
|
||||
boolean addFill) {
|
||||
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, layers.vbo.id);
|
||||
|
||||
// add fill coordinates
|
||||
if (addFill)
|
||||
@ -241,23 +240,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
if (newSize != sbuf.remaining()) {
|
||||
Log.d(TAG, "wrong size: "
|
||||
+ newSize + " "
|
||||
+ sbuf.position() + " "
|
||||
+ sbuf.limit() + " "
|
||||
+ sbuf.remaining());
|
||||
+ " new size: " + newSize
|
||||
+ " buffer pos: " + sbuf.position()
|
||||
+ " buffer limit: " + sbuf.limit()
|
||||
+ " buffer fill: " + sbuf.remaining());
|
||||
return false;
|
||||
}
|
||||
newSize *= SHORT_BYTES;
|
||||
|
||||
// reuse memory allocated for vbo when possible and allocated
|
||||
// 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) {
|
||||
GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
|
||||
} else {
|
||||
mBufferMemoryUsage += newSize - vbo.size;
|
||||
vbo.size = newSize;
|
||||
GLES20.glBufferData(GL_ARRAY_BUFFER, vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||
mBufferMemoryUsage += newSize - layers.vbo.size;
|
||||
layers.vbo.size = newSize;
|
||||
GLES20.glBufferData(GL_ARRAY_BUFFER, layers.vbo.size, sbuf, GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -272,15 +271,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
int newSize = tile.layers.getSize();
|
||||
if (newSize > 0) {
|
||||
|
||||
if (tile.vbo == null)
|
||||
tile.vbo = BufferObject.get(newSize);
|
||||
if (tile.layers.vbo == null)
|
||||
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!");
|
||||
|
||||
BufferObject.release(tile.layers.vbo);
|
||||
tile.layers.vbo = null;
|
||||
tile.layers.clear();
|
||||
tile.layers = null;
|
||||
BufferObject.release(tile.vbo);
|
||||
tile.vbo = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -376,7 +376,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
MapPosition pos = mMapPosition;
|
||||
float[] coords = mTileCoords;
|
||||
boolean changed;
|
||||
synchronized(mMapViewPosition){
|
||||
synchronized (mMapViewPosition) {
|
||||
changed = mMapViewPosition.getMapPosition(pos);
|
||||
mMapViewPosition.getMapViewProjection(coords);
|
||||
mMapViewPosition.getMatrix(mMatrices.view, null, mMatrices.viewproj);
|
||||
@ -621,7 +621,9 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
||||
// String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||
// Log.d(TAG, "Extensions: " + ext);
|
||||
|
||||
// classes that require GL context for initialization
|
||||
LineRenderer.init();
|
||||
LineTexRenderer.init();
|
||||
PolygonRenderer.init();
|
||||
TextureRenderer.init();
|
||||
TextureObject.init(10);
|
||||
|
||||
@ -27,6 +27,7 @@ import static android.opengl.GLES20.glVertexAttribPointer;
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.generator.TileGenerator;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.Layers;
|
||||
import org.oscim.renderer.layer.LineLayer;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
import org.oscim.utils.GlUtils;
|
||||
@ -34,10 +35,6 @@ import org.oscim.utils.GlUtils;
|
||||
import android.opengl.GLES20;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
|
||||
public final class LineRenderer {
|
||||
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,
|
||||
GLES20.GL_NEAREST, GLES20.GL_NEAREST,
|
||||
GLES20.GL_MIRRORED_REPEAT, GLES20.GL_MIRRORED_REPEAT);
|
||||
|
||||
return true;
|
||||
@ -110,13 +108,13 @@ public final class LineRenderer {
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
public static Layer draw(MapPosition pos, Layer layer, float[] matrix, float div,
|
||||
int mode, int bufferOffset) {
|
||||
public static Layer draw(Layers layers, Layer curLayer, MapPosition pos,
|
||||
float[] matrix, float div, int mode) {
|
||||
|
||||
int zoom = pos.zoomLevel;
|
||||
float scale = pos.scale;
|
||||
|
||||
if (layer == null)
|
||||
if (curLayer == null)
|
||||
return null;
|
||||
|
||||
GLState.blend(true);
|
||||
@ -131,13 +129,13 @@ public final class LineRenderer {
|
||||
GLState.enableVertexArrays(hLineVertexPosition[mode], -1);
|
||||
|
||||
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);
|
||||
|
||||
// line scale factor for non fixed lines: within a zoom-
|
||||
// level lines would be scaled by the factor 2 via projection.
|
||||
// though lines should only scale by sqrt(2). this is achieved
|
||||
// Line scale factor for non fixed lines: Within a zoom-
|
||||
// level lines would be scaled by the factor 2 by view-matrix.
|
||||
// Though lines should only scale by sqrt(2). This is achieved
|
||||
// by inverting scaling of extrusion vector with: width/sqrt(s).
|
||||
// within one zoom-level: 1 <= s <= 2
|
||||
float s = scale / div;
|
||||
@ -158,7 +156,7 @@ public final class LineRenderer {
|
||||
// dont increase scale when max is reached
|
||||
boolean strokeMaxZoom = zoom > TileGenerator.STROKE_MAX_ZOOM_LEVEL;
|
||||
|
||||
Layer l = layer;
|
||||
Layer l = curLayer;
|
||||
for (; l != null && l.type == Layer.LINE; l = l.next) {
|
||||
LineLayer ll = (LineLayer) l;
|
||||
Line line = ll.line;
|
||||
@ -187,7 +185,7 @@ public final class LineRenderer {
|
||||
} else {
|
||||
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)
|
||||
continue;
|
||||
}
|
||||
@ -223,7 +221,9 @@ public final class LineRenderer {
|
||||
// line width increases by sqrt(2.2).
|
||||
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;
|
||||
}
|
||||
|
||||
@ -262,7 +262,6 @@ public final class LineRenderer {
|
||||
+ "attribute vec4 a_pos;"
|
||||
+ "uniform float u_mode;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "varying vec2 v_mode;"
|
||||
+ "void main() {"
|
||||
// scale extrusion to u_width pixel
|
||||
// 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
|
||||
// ..maybe one could wrap texture so that `abs` is not required
|
||||
+ " v_st = abs(mod(dir, 4.0)) - 1.0;"
|
||||
+ " v_mode = vec2(1.0 - u_mode, u_mode);"
|
||||
+ "}";
|
||||
|
||||
private final static String lineSimpleFragmentShader = ""
|
||||
+ "precision mediump float;"
|
||||
+ "uniform sampler2D tex;"
|
||||
+ "uniform float u_wscale;"
|
||||
+ "uniform float u_mode;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "varying vec2 v_mode;"
|
||||
+ "void main() {"
|
||||
//+ " float len;"
|
||||
// some say one should not use conditionals
|
||||
// (FIXME currently required as overlay line renderers dont load the texture)
|
||||
// (currently required as overlay line renderers dont load the texture)
|
||||
//+ " if (u_mode == 0)"
|
||||
//+ " len = abs(v_st.s);"
|
||||
//+ " else"
|
||||
//+ " len = texture2D(tex, v_st).a;"
|
||||
// one trick to avoid branching, need to check performance
|
||||
+ " float len = max(v_mode[0] * abs(v_st.s), v_mode[1] * texture2D(tex, v_st).a);"
|
||||
// this avoids branching, need to check performance
|
||||
+ " 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
|
||||
// where wscale is 'filter width' / 'line width' and 0 <= len <= sqrt(2)
|
||||
+ " 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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
@ -162,7 +162,7 @@ public class TileManager {
|
||||
MapPosition mapPosition = mMapPosition;
|
||||
float[] coords = mTileCoords;
|
||||
|
||||
synchronized(mMapViewPosition){
|
||||
synchronized (mMapViewPosition) {
|
||||
changedPos = mMapViewPosition.getMapPosition(mapPosition);
|
||||
mMapViewPosition.getMapViewProjection(coords);
|
||||
}
|
||||
@ -390,17 +390,18 @@ public class TileManager {
|
||||
return;
|
||||
|
||||
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 = null;
|
||||
}
|
||||
|
||||
TextItem.release(t.labels);
|
||||
|
||||
if (t.vbo != null) {
|
||||
BufferObject.release(t.vbo);
|
||||
t.vbo = null;
|
||||
}
|
||||
|
||||
QuadTree.remove(t);
|
||||
t.state = STATE_NONE;
|
||||
|
||||
@ -522,19 +523,19 @@ public class TileManager {
|
||||
tiles[i] = null;
|
||||
}
|
||||
}
|
||||
// if (locked) {
|
||||
// Log.d(TAG, "------------ "
|
||||
// + remove + " / " + r + " "
|
||||
// + mMapPosition.zoomLevel
|
||||
// + " ----------");
|
||||
// for (int i = 0; i < size; i++) {
|
||||
// MapTile t = tiles[i];
|
||||
// if (t == null)
|
||||
// continue;
|
||||
// Log.d(TAG, "limitCache: " + t + " " + t.distance);
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//if (locked) {
|
||||
// Log.d(TAG, "------------ "
|
||||
// + remove + " / " + r + " "
|
||||
// + mMapPosition.zoomLevel
|
||||
// + " ----------");
|
||||
// for (int i = 0; i < size; i++) {
|
||||
// MapTile t = tiles[i];
|
||||
// if (t == null)
|
||||
// continue;
|
||||
// Log.d(TAG, "limitCache: " + t + " " + t.distance);
|
||||
//
|
||||
// }
|
||||
//}
|
||||
remove = (newTileCnt - MAX_TILES_IN_QUEUE) + 10;
|
||||
//int r = remove;
|
||||
for (int i = size - 1; i >= 0 && remove > 0; i--) {
|
||||
@ -572,11 +573,11 @@ public class TileManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tile.vbo != null) {
|
||||
// BAD Things(tm) happend: tile is already loaded
|
||||
Log.d(TAG, "BUG: tile loaded before " + tile);
|
||||
return true;
|
||||
}
|
||||
//if (tile.vbo != null) {
|
||||
// // BAD Things(tm) happend: tile is already loaded
|
||||
// Log.d(TAG, "BUG: tile loaded before " + tile);
|
||||
// return true;
|
||||
//}
|
||||
|
||||
tile.state = STATE_NEW_DATA;
|
||||
mTilesForUpload++;
|
||||
|
||||
@ -64,7 +64,7 @@ public class ExtrusionLayer extends Layer {
|
||||
|
||||
public ExtrusionLayer(int level) {
|
||||
this.type = Layer.EXTRUSION;
|
||||
this.layer = level;
|
||||
this.level = level;
|
||||
|
||||
mVertices = mCurVertices = VertexPool.get();
|
||||
|
||||
@ -346,6 +346,7 @@ public class ExtrusionLayer extends Layer {
|
||||
return convex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compile(ShortBuffer sbuf) {
|
||||
|
||||
if (mNumVertices == 0 || compiled)
|
||||
|
||||
@ -14,24 +14,28 @@
|
||||
*/
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
/**
|
||||
* @authorHannes Janetzek
|
||||
*/
|
||||
public abstract class Layer {
|
||||
public final static byte LINE = 0;
|
||||
public final static byte POLYGON = 1;
|
||||
public final static byte WAYTEXT = 2;
|
||||
public final static byte POITEXT = 3;
|
||||
public final static byte SYMBOL = 4;
|
||||
public final static byte BITMAP = 5;
|
||||
public final static byte TEXLINE = 6;
|
||||
public final static byte TEXLINE = 2;
|
||||
public final static byte WAYTEXT = 3;
|
||||
public final static byte POITEXT = 4;
|
||||
public final static byte SYMBOL = 5;
|
||||
public final static byte BITMAP = 6;
|
||||
public final static byte EXTRUSION = 7;
|
||||
|
||||
public byte type = -1;
|
||||
|
||||
public Layer next;
|
||||
|
||||
int layer;
|
||||
// drawing order from bottom to top
|
||||
int level;
|
||||
|
||||
// number of vertices for this layer
|
||||
public int verticesCnt;
|
||||
|
||||
@ -44,5 +48,6 @@ public abstract class Layer {
|
||||
VertexPoolItem pool;
|
||||
protected VertexPoolItem curItem;
|
||||
|
||||
abstract protected void compile(ShortBuffer sbuf);
|
||||
abstract protected void clear();
|
||||
}
|
||||
|
||||
@ -16,22 +16,33 @@ package org.oscim.renderer.layer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.BufferObject;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public class Layers {
|
||||
// mixed Polygon and Line layers
|
||||
public Layer layers;
|
||||
private final static String TAG = Layers.class.getName();
|
||||
|
||||
// mixed Polygon- and LineLayer
|
||||
public Layer baseLayers;
|
||||
public Layer textureLayers;
|
||||
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:
|
||||
// 1. polygons are packed in VBO at offset 0
|
||||
// 2. lines afterwards at lineOffset
|
||||
// 3. other layers keep their byte offset in Layer.offset
|
||||
public int lineOffset;
|
||||
public int texLineOffset;
|
||||
|
||||
// time when layers became first rendered (in uptime)
|
||||
// used for animations
|
||||
@ -39,93 +50,109 @@ public class Layers {
|
||||
|
||||
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) {
|
||||
Layer l = layers;
|
||||
Layer ret = null;
|
||||
Layer l = baseLayers;
|
||||
Layer layer = null;
|
||||
|
||||
if (mCurLayer != null && mCurLayer.layer == level) {
|
||||
ret = mCurLayer;
|
||||
} else if (l == null || l.layer > level) {
|
||||
// insert new layer at start
|
||||
l = null;
|
||||
if (mCurLayer != null && mCurLayer.level == level) {
|
||||
layer = mCurLayer;
|
||||
} 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
|
||||
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) {
|
||||
// insert at start
|
||||
ret.next = layers;
|
||||
layers = ret;
|
||||
} else {
|
||||
ret.next = l.next;
|
||||
l.next = ret;
|
||||
}
|
||||
} else if (ret.type != type) {
|
||||
Log.d("...", "wrong layer type " + ret.type + " " + type);
|
||||
// FIXME thorw exception
|
||||
if (layer.type != type) {
|
||||
// check if found layer matches requested type
|
||||
Log.d(TAG, "BUG wrong layer " + layer.type + " " + type);
|
||||
// TODO throw exception
|
||||
return null;
|
||||
}
|
||||
|
||||
return ret;
|
||||
mCurLayer = layer;
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
private static int LINE_VERTEX_SHORTS = 4;
|
||||
private static int POLY_VERTEX_SHORTS = 2;
|
||||
private static int TEXTURE_VERTEX_SHORTS = 6;
|
||||
private final static int[] VERTEX_SHORT_CNT = {
|
||||
4, // LINE_VERTEX_SHORTS
|
||||
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() {
|
||||
|
||||
int size = 0;
|
||||
|
||||
for (Layer l = layers; l != null; l = l.next) {
|
||||
if (l.type == Layer.LINE)
|
||||
size += l.verticesCnt * LINE_VERTEX_SHORTS;
|
||||
else
|
||||
size += l.verticesCnt * POLY_VERTEX_SHORTS;
|
||||
}
|
||||
for (Layer l = baseLayers; l != null; l = l.next)
|
||||
size += l.verticesCnt * VERTEX_SHORT_CNT[l.type];
|
||||
|
||||
for (Layer l = textureLayers; l != null; l = l.next)
|
||||
size += l.verticesCnt * TEXTURE_VERTEX_SHORTS;
|
||||
|
||||
//for (Layer l = extrusionLayers; l != null; l = l.next)
|
||||
// size += l.verticesCnt * EXTRUSION_VERTEX_SHORTS;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public void compile(ShortBuffer sbuf, boolean addFill) {
|
||||
// offset from fill coordinates
|
||||
int pos = 0;
|
||||
if (addFill)
|
||||
int size = 0;
|
||||
|
||||
if (addFill){
|
||||
pos = 4;
|
||||
size = 8;
|
||||
}
|
||||
|
||||
// add polygons first, needed to get the offsets right...
|
||||
addLayerItems(sbuf, layers, Layer.POLYGON, pos);
|
||||
size += addLayerItems(sbuf, baseLayers, Layer.POLYGON, pos);
|
||||
|
||||
lineOffset = sbuf.position() * 2; // * short-bytes
|
||||
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
||||
lineOffset = size * SHORT_BYTES;
|
||||
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) {
|
||||
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
|
||||
private static void addLayerItems(ShortBuffer sbuf, Layer l, byte type, int pos) {
|
||||
// optimization for Line- and PolygonLayer:
|
||||
// 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;
|
||||
int size = 0;
|
||||
|
||||
// HACK, see LineTexLayer
|
||||
boolean addOffset = (type == Layer.TEXLINE);
|
||||
|
||||
for (; l != null; l = l.next) {
|
||||
if (l.type != type)
|
||||
continue;
|
||||
|
||||
for (VertexPoolItem it = l.pool; it != null; it = it.next) {
|
||||
if (it.next == null)
|
||||
sbuf.put(it.vertices, 0, it.used);
|
||||
else
|
||||
sbuf.put(it.vertices, 0, VertexPoolItem.SIZE);
|
||||
if (addOffset){
|
||||
sbuf.position(sbuf.position() + 6);
|
||||
addOffset = false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (last == null)
|
||||
@ -169,11 +209,13 @@ public class Layers {
|
||||
l.curItem = null;
|
||||
}
|
||||
VertexPool.release(items);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void addPoolItems(Layer l, ShortBuffer sbuf) {
|
||||
// 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) {
|
||||
if (it.next == null)
|
||||
@ -190,7 +232,7 @@ public class Layers {
|
||||
public void clear() {
|
||||
|
||||
// clear line and polygon layers directly
|
||||
Layer l = layers;
|
||||
Layer l = baseLayers;
|
||||
while (l != null) {
|
||||
if (l.pool != null) {
|
||||
VertexPool.release(l.pool);
|
||||
@ -207,8 +249,13 @@ public class Layers {
|
||||
for (l = extrusionLayers; l != null; l = l.next) {
|
||||
l.clear();
|
||||
}
|
||||
layers = null;
|
||||
baseLayers = null;
|
||||
textureLayers = null;
|
||||
extrusionLayers = null;
|
||||
|
||||
// if (vbo != null){
|
||||
// BufferObject.release(vbo);
|
||||
// vbo = null;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
*/
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.theme.renderinstruction.Line;
|
||||
@ -26,7 +28,6 @@ import android.graphics.Paint.Cap;
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public final class LineLayer extends Layer {
|
||||
|
||||
private static final float COORD_SCALE = GLRenderer.COORD_MULTIPLIER;
|
||||
// scale factor mapping extrusion vector to short values
|
||||
public static final float DIR_SCALE = 2048;
|
||||
@ -42,7 +43,7 @@ public final class LineLayer extends Layer {
|
||||
public boolean roundCap;
|
||||
|
||||
LineLayer(int layer) {
|
||||
this.layer = layer;
|
||||
this.level = layer;
|
||||
this.type = Layer.LINE;
|
||||
}
|
||||
|
||||
@ -312,11 +313,13 @@ public final class LineLayer extends Layer {
|
||||
vx *= -1;
|
||||
vy *= -1;
|
||||
|
||||
int end = pos + length;
|
||||
|
||||
for (;;) {
|
||||
if (ipos < pos + length) {
|
||||
if (ipos < end) {
|
||||
nextX = points[ipos++];
|
||||
nextY = points[ipos++];
|
||||
} else if (closed && ipos < pos + length + 2) {
|
||||
} else if (closed && ipos < end + 2) {
|
||||
// add startpoint == endpoint
|
||||
nextX = points[pos];
|
||||
nextY = points[pos + 1];
|
||||
@ -543,4 +546,8 @@ public final class LineLayer extends Layer {
|
||||
@Override
|
||||
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;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.core.Tile;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.theme.renderinstruction.Area;
|
||||
@ -24,7 +26,7 @@ public final class PolygonLayer extends Layer {
|
||||
public Area area;
|
||||
|
||||
PolygonLayer(int layer) {
|
||||
this.layer = layer;
|
||||
this.level = layer;
|
||||
this.type = Layer.POLYGON;
|
||||
curItem = VertexPool.get();
|
||||
pool = curItem;
|
||||
@ -87,6 +89,10 @@ public final class PolygonLayer extends Layer {
|
||||
curItem = si;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compile(ShortBuffer sbuf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
}
|
||||
|
||||
@ -32,7 +32,8 @@ public abstract class TextureLayer extends Layer {
|
||||
* @param sbuf
|
||||
* buffer to add vertices
|
||||
*/
|
||||
void compile(ShortBuffer sbuf) {
|
||||
@Override
|
||||
protected void compile(ShortBuffer sbuf) {
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
|
||||
@ -22,7 +22,7 @@ public class VertexPoolItem {
|
||||
|
||||
// must be multiple of
|
||||
// 4 (LineLayer/PolygonLayer),
|
||||
// 6 (TexLineLayer)
|
||||
// 24 (TexLineLayer - one block, i.e. two segments)
|
||||
// 24 (TextureLayer)
|
||||
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.GLState;
|
||||
import org.oscim.renderer.LineRenderer;
|
||||
import org.oscim.renderer.LineTexRenderer;
|
||||
import org.oscim.renderer.PolygonRenderer;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
@ -34,8 +35,6 @@ public abstract class BasicOverlay extends RenderOverlay {
|
||||
|
||||
public final Layers layers;
|
||||
|
||||
public BufferObject vbo;
|
||||
|
||||
protected float[] mvp = new float[16];
|
||||
|
||||
public BasicOverlay(MapView mapView) {
|
||||
@ -51,17 +50,23 @@ public abstract class BasicOverlay extends RenderOverlay {
|
||||
|
||||
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);
|
||||
|
||||
if (layers.layers != null) {
|
||||
if (layers.baseLayers != null) {
|
||||
setMatrix(pos, m, true);
|
||||
|
||||
for (Layer l = layers.layers; l != null;) {
|
||||
if (l.type == Layer.POLYGON) {
|
||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||
} else {
|
||||
l = LineRenderer.draw(pos, l, m.mvp, div, 0, layers.lineOffset);
|
||||
for (Layer l = layers.baseLayers; l != null;) {
|
||||
switch (l.type) {
|
||||
case Layer.POLYGON:
|
||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||
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() {
|
||||
int newSize = layers.getSize();
|
||||
if (newSize == 0) {
|
||||
BufferObject.release(vbo);
|
||||
vbo = null;
|
||||
BufferObject.release(layers.vbo);
|
||||
layers.vbo = null;
|
||||
isReady = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vbo == null) {
|
||||
vbo = BufferObject.get(0);
|
||||
if (layers.vbo == null) {
|
||||
layers.vbo = BufferObject.get(0);
|
||||
|
||||
if (vbo == null)
|
||||
if (layers.vbo == null)
|
||||
return;
|
||||
}
|
||||
|
||||
if (newSize > 0) {
|
||||
if (GLRenderer.uploadLayers(layers, vbo, newSize, true))
|
||||
if (GLRenderer.uploadLayers(layers, newSize, true))
|
||||
isReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,85 +40,51 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
super(mapView);
|
||||
}
|
||||
|
||||
// Interleave two quads to be able to use vertices
|
||||
// twice. pos0 and pos1 use the same vertex array
|
||||
// where pos1 is off-setted by one vertex. The
|
||||
// vertex shader will use pos0 when the vertexId
|
||||
// is even, pos1 when the Id is odd.
|
||||
// Interleave two segment quads in one block to be able to use
|
||||
// vertices twice. pos0 and pos1 use the same vertex array where
|
||||
// pos1 is off-setted by 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.
|
||||
// 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
|
||||
// pos0 - (0) 1 (2) 3 -
|
||||
// pos1 - (0) 1 (2) 3 -
|
||||
// flip 0 1 0 1
|
||||
// vertex id 0 1 2 3 4 5 6 7
|
||||
// pos0 - (0) 1 (2) 3 (4) 5 (6) 7 -
|
||||
// pos1 - (0) 1 (2) 3 (4) 5 (6) 7 -
|
||||
// flip 0 1 0 1 0 1 0 1
|
||||
//
|
||||
// Second pass: using odd vertex array positions
|
||||
// vertex id 0, 1, 2, 3
|
||||
// pos0 - 0 (1) 2 (3) -
|
||||
// pos1 - 0 (1) 2 (3) -
|
||||
// flip 0 1 0 1
|
||||
// vertex id 0 1 2 3 4 5 6 7
|
||||
// pos0 - 0 (1) 2 (3) 4 (5) 6 (7) -
|
||||
// pos1 - 0 (1) 2 (3) 4 (5) 6 (7) -
|
||||
// flip 0 1 0 1 0 1 0 1
|
||||
//
|
||||
// Vertex layout:
|
||||
// x/y pos[16][16], dir_x[8]|dir_y[8], start[4]|length[12]
|
||||
// - 'direction' precision 1/16, maximum line width is 2*16
|
||||
// - texture 'start' prescision 1
|
||||
// -> max tex width is 32
|
||||
// - 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,
|
||||
// [2 short] position,
|
||||
// [2 short] extrusion,
|
||||
// [1 short] line length
|
||||
// [1 short] unused
|
||||
//
|
||||
// -800, 200, 127, 0,
|
||||
// 0, 200, 127, 0,
|
||||
// 0, 200, 127, 1,
|
||||
// 800, 200, 127, 1,
|
||||
//
|
||||
// -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;
|
||||
// indices: (two indice blocks)
|
||||
// 0, 1, 2,
|
||||
// 2, 1, 3,
|
||||
// 4, 5, 6,
|
||||
// 6, 5, 7,
|
||||
|
||||
private static int testProgram;
|
||||
private static int htestVertexPosition0;
|
||||
private static int htestVertexPosition1;
|
||||
private static int htestVertexLength0;
|
||||
private static int htestVertexLength1;
|
||||
private static int htestVertexFlip;
|
||||
private static int htestMatrix;
|
||||
private static int htestColor;
|
||||
private static int htestTexColor;
|
||||
private static int htestBgColor;
|
||||
private static int htestScale;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@ -126,38 +92,52 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
+ "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 vec4 color;"
|
||||
+ "const float ff = 256.0;"
|
||||
+ "const float ffff = 65536.0;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "void main() {"
|
||||
+ " float div = (8.0 * 16.0) / max(ceil(log(u_scale)),1.0);"
|
||||
+ " if (a_flip == 0.0){"
|
||||
// extract 8 bit direction vector
|
||||
+ " vec2 dir = a_pos0.zw/16.0;"
|
||||
+ " gl_Position = u_mvp * vec4(a_pos0.xy + dir, 0.0, 1.0);"
|
||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.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, 0.0, 1.0);"
|
||||
+ " color = vec4(dir/255.0 + 0.5, 1.0,1.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 testFragmentShader = ""
|
||||
+ "precision mediump float;"
|
||||
+ "varying vec4 color;"
|
||||
+ "uniform sampler2D tex;"
|
||||
+ " uniform vec4 u_color;"
|
||||
+ " uniform vec4 u_bgcolor;"
|
||||
+ "varying vec2 v_st;"
|
||||
+ "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 mVertexBufferID;
|
||||
private int mVertexFlipID;
|
||||
|
||||
private int mNumVertices;
|
||||
//private int mNumVertices;
|
||||
private int mNumIndices;
|
||||
|
||||
private int mTexID;
|
||||
|
||||
@Override
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
||||
boolean tilesChanged) {
|
||||
@ -174,9 +154,14 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
return;
|
||||
}
|
||||
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");
|
||||
htestVertexPosition1 = GLES20.glGetAttribLocation(testProgram, "a_pos1");
|
||||
htestVertexLength0 = GLES20.glGetAttribLocation(testProgram, "a_len0");
|
||||
htestVertexLength1 = GLES20.glGetAttribLocation(testProgram, "a_len1");
|
||||
htestVertexFlip = GLES20.glGetAttribLocation(testProgram, "a_flip");
|
||||
|
||||
int[] mVboIds = new int[3];
|
||||
@ -186,34 +171,37 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
mVertexFlipID = mVboIds[2];
|
||||
|
||||
float points[] = {
|
||||
800, 0,
|
||||
0, 0,
|
||||
//-400, 100,
|
||||
//-600, 200,
|
||||
//-800, 100,
|
||||
-800, -800,
|
||||
800, -800,
|
||||
800, 800,
|
||||
-800, 800,
|
||||
-800, -800,
|
||||
};
|
||||
|
||||
// float[] points = new float[12 * 2];
|
||||
// for (int i = 0; i < 24; i += 2) {
|
||||
// points[i + 0] = (float) Math.sin(-i / 11f * Math.PI) * 400;
|
||||
// points[i + 1] = (float) Math.cos(-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) * 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 y = points[1];
|
||||
|
||||
float scale = 127;
|
||||
float scale = 255;
|
||||
boolean even = true;
|
||||
float len = 0;
|
||||
|
||||
for (int i = 2; i < points.length;) {
|
||||
float nx = points[i++];
|
||||
float ny = points[i++];
|
||||
for (int i = 2; i < points.length; i += 2) {
|
||||
float nx = points[i + 0];
|
||||
float ny = points[i + 1];
|
||||
|
||||
// Calculate triangle corners for the given width
|
||||
float vx = nx - x;
|
||||
@ -225,7 +213,7 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
vx /= a;
|
||||
vy /= a;
|
||||
|
||||
// perpendicular
|
||||
// perpendicular to line segment
|
||||
float ux = -vy;
|
||||
float uy = vx;
|
||||
|
||||
@ -236,33 +224,41 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
vertices[opos + 1] = (short) y;
|
||||
vertices[opos + 2] = dx;
|
||||
vertices[opos + 3] = dy;
|
||||
vertices[opos + 4] = (short) len;
|
||||
vertices[opos + 5] = 0;
|
||||
|
||||
vertices[opos + 8] = (short) nx;
|
||||
vertices[opos + 9] = (short) ny;
|
||||
vertices[opos + 10] = dx;
|
||||
vertices[opos + 11] = dy;
|
||||
len += a;
|
||||
vertices[opos + 12] = (short) nx;
|
||||
vertices[opos + 13] = (short) ny;
|
||||
vertices[opos + 14] = dx;
|
||||
vertices[opos + 15] = dy;
|
||||
vertices[opos + 16] = (short) len;
|
||||
vertices[opos + 17] = 0;
|
||||
|
||||
x = nx;
|
||||
y = ny;
|
||||
|
||||
if (even) {
|
||||
opos += 4;
|
||||
// go to second segment
|
||||
opos += 6;
|
||||
even = false;
|
||||
} else {
|
||||
// go to next block
|
||||
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++)
|
||||
flip[i] = (byte) (i % 2);
|
||||
|
||||
short j = 0;
|
||||
mNumIndices = ((points.length) >> 2) * 6;
|
||||
|
||||
indices = new short[mNumIndices];
|
||||
short[] indices = new short[mNumIndices];
|
||||
for (int i = 0; i < mNumIndices; i += 6, j += 4) {
|
||||
indices[i + 0] = (short) (j + 0);
|
||||
indices[i + 1] = (short) (j + 1);
|
||||
@ -273,7 +269,7 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
indices[i + 5] = (short) (j + 3);
|
||||
}
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(128 * 4)
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(numVertices * 6 * 2)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
|
||||
ShortBuffer sbuf = buf.asShortBuffer();
|
||||
@ -285,7 +281,6 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
sbuf.clear();
|
||||
//sbuf.put(box);
|
||||
sbuf.put(vertices);
|
||||
sbuf.flip();
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||
@ -300,12 +295,23 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
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);
|
||||
|
||||
mMapView.getMapViewPosition().getMapPosition(mMapPosition);
|
||||
|
||||
// tell GLRenderer to call 'render'
|
||||
isReady = true;
|
||||
}
|
||||
|
||||
private final static int STRIDE = 12;
|
||||
private final static int LEN_OFFSET = 8;
|
||||
|
||||
@Override
|
||||
public synchronized void render(MapPosition pos, Matrices m) {
|
||||
|
||||
@ -318,42 +324,79 @@ public class TestLineOverlay extends RenderOverlay {
|
||||
GLState.enableVertexArrays(-1, -1);
|
||||
GLES20.glEnableVertexAttribArray(htestVertexPosition0);
|
||||
GLES20.glEnableVertexAttribArray(htestVertexPosition1);
|
||||
|
||||
GlUtils.checkGlError("-4");
|
||||
GLES20.glEnableVertexAttribArray(htestVertexLength0);
|
||||
GlUtils.checkGlError("-3");
|
||||
GLES20.glEnableVertexAttribArray(htestVertexLength1);
|
||||
GlUtils.checkGlError("-2");
|
||||
GLES20.glEnableVertexAttribArray(htestVertexFlip);
|
||||
|
||||
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.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);
|
||||
GlUtils.checkGlError("1");
|
||||
|
||||
// first pass
|
||||
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,
|
||||
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.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
GLES20.glVertexAttribPointer(htestVertexLength1,
|
||||
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,
|
||||
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,
|
||||
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.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
GLES20.glVertexAttribPointer(htestVertexLength1,
|
||||
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.glDisableVertexAttribArray(htestVertexPosition0);
|
||||
GLES20.glDisableVertexAttribArray(htestVertexPosition1);
|
||||
GLES20.glDisableVertexAttribArray(htestVertexLength0);
|
||||
GLES20.glDisableVertexAttribArray(htestVertexLength1);
|
||||
GLES20.glDisableVertexAttribArray(htestVertexFlip);
|
||||
GlUtils.checkGlError("...");
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -14,13 +14,10 @@
|
||||
*/
|
||||
package org.oscim.renderer.overlays;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.renderer.layer.SymbolItem;
|
||||
import org.oscim.renderer.layer.SymbolLayer;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.LineTexLayer;
|
||||
import org.oscim.renderer.layer.TextItem;
|
||||
import org.oscim.theme.renderinstruction.BitmapUtils;
|
||||
import org.oscim.view.MapView;
|
||||
|
||||
public class TestOverlay extends BasicOverlay {
|
||||
@ -34,12 +31,33 @@ public class TestOverlay extends BasicOverlay {
|
||||
public TestOverlay(MapView mapView) {
|
||||
super(mapView);
|
||||
|
||||
// LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||
// ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||
// ll.width = 2;
|
||||
// float[] points = { -100, -100, 100, -100, 100, 100, -100, 100, -100, -100 };
|
||||
// short[] index = { (short) points.length };
|
||||
// ll.addLine(points, index, false);
|
||||
// draw a rectangle
|
||||
//LineLayer ll = (LineLayer) layers.getLayer(1, Layer.LINE);
|
||||
//ll.line = new Line(Color.BLUE, 1.0f, Cap.BUTT);
|
||||
//ll.width = 2;
|
||||
float[] points = {
|
||||
-100, -100,
|
||||
100, -100,
|
||||
100, 100,
|
||||
-100, 100,
|
||||
-100, -100
|
||||
};
|
||||
//short[] index = { (short) points.length };
|
||||
//ll.addLine(points, index, 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);
|
||||
@ -54,33 +72,33 @@ public class TestOverlay extends BasicOverlay {
|
||||
// short[] pindex = { (short) ppoints.length };
|
||||
// pl.addPolygon(ppoints, pindex);
|
||||
|
||||
SymbolLayer sl = new SymbolLayer();
|
||||
SymbolItem it = new SymbolItem();
|
||||
|
||||
it.x = 0;
|
||||
it.y = 0;
|
||||
// billboard always faces camera
|
||||
it.billboard = true;
|
||||
|
||||
try {
|
||||
it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
sl.addSymbol(it);
|
||||
|
||||
SymbolItem it2 = new SymbolItem();
|
||||
it2.bitmap = it.bitmap;
|
||||
it2.x = 0;
|
||||
it2.y = 0;
|
||||
// billboard always faces camera
|
||||
it2.billboard = false;
|
||||
|
||||
sl.addSymbol(it2);
|
||||
sl.fixed = false;
|
||||
|
||||
layers.textureLayers = sl;
|
||||
//SymbolLayer sl = new SymbolLayer();
|
||||
//SymbolItem it = new SymbolItem();
|
||||
//
|
||||
//it.x = 0;
|
||||
//it.y = 0;
|
||||
//// billboard always faces camera
|
||||
//it.billboard = true;
|
||||
//
|
||||
//try {
|
||||
// it.bitmap = BitmapUtils.createBitmap("file:/sdcard/cheshire.png");
|
||||
//} catch (IOException e) {
|
||||
// // TODO Auto-generated catch block
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
//sl.addSymbol(it);
|
||||
//
|
||||
//SymbolItem it2 = new SymbolItem();
|
||||
//it2.bitmap = it.bitmap;
|
||||
//it2.x = 0;
|
||||
//it2.y = 0;
|
||||
//// billboard always faces camera
|
||||
//it2.billboard = false;
|
||||
//
|
||||
//sl.addSymbol(it2);
|
||||
//sl.fixed = false;
|
||||
//
|
||||
//layers.textureLayers = sl;
|
||||
|
||||
// TextLayer tl = new TextLayer();
|
||||
// Text t = Text.createText(20, 2, Color.WHITE, Color.BLACK, false);
|
||||
@ -106,7 +124,7 @@ public class TestOverlay extends BasicOverlay {
|
||||
updateMapPosition();
|
||||
|
||||
first = false;
|
||||
((SymbolLayer) (layers.textureLayers)).prepare();
|
||||
//((SymbolLayer) (layers.textureLayers)).prepare();
|
||||
|
||||
// pass layers to be uploaded and drawn to GL Thread
|
||||
// afterwards never modify 'layers' outside of this function!
|
||||
|
||||
@ -386,8 +386,8 @@ public class TextOverlay extends BasicOverlay {
|
||||
layers.clear();
|
||||
|
||||
if (mDebugLayer != null) {
|
||||
layers.layers = mDebugLayer.layers;
|
||||
mDebugLayer.layers = null;
|
||||
layers.baseLayers = mDebugLayer.baseLayers;
|
||||
mDebugLayer.baseLayers = null;
|
||||
}
|
||||
|
||||
// set new TextLayer to be uploaded and used
|
||||
|
||||
@ -627,7 +627,7 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
layers.clear();
|
||||
|
||||
if (mDebugLayer != null) {
|
||||
layers.layers = mDebugLayer.layers;
|
||||
layers.baseLayers = mDebugLayer.baseLayers;
|
||||
mDebugLayer = null;
|
||||
}
|
||||
|
||||
@ -665,12 +665,12 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vbo == null) {
|
||||
vbo = BufferObject.get(0);
|
||||
if (layers.vbo == null) {
|
||||
layers.vbo = BufferObject.get(0);
|
||||
}
|
||||
|
||||
if (newSize > 0) {
|
||||
if (GLRenderer.uploadLayers(layers, vbo, newSize, true))
|
||||
if (GLRenderer.uploadLayers(layers, newSize, true))
|
||||
isReady = true;
|
||||
}
|
||||
}
|
||||
@ -679,19 +679,19 @@ public class TextOverlayExp extends BasicOverlay {
|
||||
public synchronized void render(MapPosition pos, Matrices m) {
|
||||
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);
|
||||
|
||||
if (layers.layers != null) {
|
||||
if (layers.baseLayers != null) {
|
||||
setMatrix(pos, m, true);
|
||||
|
||||
//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) {
|
||||
l = PolygonRenderer.draw(pos, l, m.mvp, true, false);
|
||||
} else {
|
||||
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.stipple = stipple;
|
||||
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,
|
||||
int stipple, Cap strokeLinecap, int level, boolean fixed,
|
||||
int fade, float blur, boolean isOutline, float min) {
|
||||
|
||||
@ -54,6 +54,13 @@ public class FastMath {
|
||||
|
||||
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){
|
||||
return value < 0 ? -value : value;
|
||||
|
||||
@ -30,10 +30,25 @@ import android.util.Log;
|
||||
public class 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
|
||||
* ...
|
||||
* @return gl identifier
|
||||
* @return textureId
|
||||
*/
|
||||
public static int loadTextures(Bitmap bitmap) {
|
||||
|
||||
@ -44,21 +59,8 @@ public class GlUtils {
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||
GLES20.GL_TEXTURE_MIN_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||
GLES20.GL_TEXTURE_MAG_FILTER,
|
||||
GLES20.GL_LINEAR);
|
||||
|
||||
GLES20.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);
|
||||
setTextureParameter(GLES20.GL_LINEAR, GLES20.GL_LINEAR,
|
||||
GLES20.GL_CLAMP_TO_EDGE, GLES20.GL_CLAMP_TO_EDGE);
|
||||
|
||||
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,
|
||||
int wrap_s, int wrap_t) {
|
||||
int min_filter, int mag_filter, int wrap_s, int wrap_t) {
|
||||
int[] textureIds = new int[1];
|
||||
GLES20.glGenTextures(1, textureIds, 0);
|
||||
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureIds[0]);
|
||||
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||
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
|
||||
setTextureParameter(min_filter, mag_filter, wrap_s, wrap_t);
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(width * height).order(ByteOrder.nativeOrder());
|
||||
buf.put(pixel);
|
||||
@ -96,6 +87,37 @@ public class GlUtils {
|
||||
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
|
||||
* shader type
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user