more work on building layer
This commit is contained in:
parent
74ca621de0
commit
eb278585fa
@ -53,9 +53,10 @@ public interface IMapDatabaseCallback {
|
||||
* length of way data in wayNodes
|
||||
* @param closed
|
||||
* way is closed (means need to add endpoint == startpoint)
|
||||
* @param prio TODO
|
||||
*/
|
||||
void renderWay(byte layer, Tag[] tags, float[] wayNodes, short[] wayLength,
|
||||
boolean closed);
|
||||
boolean closed, int prio);
|
||||
|
||||
/**
|
||||
* TBD: check if way will be rendered before decoding
|
||||
|
@ -961,7 +961,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
&& mWayNodes[1] == mWayNodes[l - 1];
|
||||
|
||||
mapDatabaseCallback
|
||||
.renderWay(layer, tags, mWayNodes, wayLengths, closed);
|
||||
.renderWay(layer, tags, mWayNodes, wayLengths, closed, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
private static final int TAG_ELEM_INDEX = 12;
|
||||
private static final int TAG_ELEM_COORDS = 13;
|
||||
private static final int TAG_ELEM_LAYER = 21;
|
||||
// private static final int TAG_ELEM_PRIORITY = 31;
|
||||
private static final int TAG_ELEM_PRIORITY = 31;
|
||||
|
||||
private short[] mTmpKeys = new short[100];
|
||||
private short[] mIndices = new short[10];
|
||||
@ -376,6 +376,8 @@ public class MapDatabase implements IMapDatabase {
|
||||
int indexCnt = 1;
|
||||
int coordCnt = 0;
|
||||
int layer = 5;
|
||||
int prio = 0;
|
||||
|
||||
Tag[] tags = null;
|
||||
short[] index = null;
|
||||
|
||||
@ -441,6 +443,10 @@ public class MapDatabase implements IMapDatabase {
|
||||
layer = decodeVarint32();
|
||||
break;
|
||||
|
||||
case TAG_ELEM_PRIORITY:
|
||||
prio = decodeVarint32();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.d(TAG, "X invalid type for way: " + tag);
|
||||
}
|
||||
@ -457,9 +463,9 @@ public class MapDatabase implements IMapDatabase {
|
||||
float[] coords = mTmpCoords;
|
||||
|
||||
if (type == TAG_TILE_LINE)
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, false);
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, false, prio);
|
||||
else if (type == TAG_TILE_POLY)
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, true);
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, true, prio);
|
||||
else {
|
||||
if (debug)
|
||||
Log.d(TAG, "add poi " + coords[1] + " " + coords[0] + " " + tags[0]);
|
||||
|
@ -556,7 +556,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
if (layer == 0)
|
||||
layer = 5;
|
||||
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, polygon);
|
||||
mMapGenerator.renderWay((byte) layer, tags, coords, index, polygon, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
|
||||
short[] idx = new short[mIndexPos];
|
||||
System.arraycopy(mIndex, 0, idx, 0, mIndexPos);
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon);
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, idx, polygon, 0);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
|
@ -100,7 +100,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
mIndex[2] = 10;
|
||||
mIndex[3] = 0;
|
||||
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true);
|
||||
mapDatabaseCallback.renderWay((byte) 0, mTags, mCoords, mIndex, true, 0);
|
||||
|
||||
mIndex[0] = 4;
|
||||
mIndex[1] = -1;
|
||||
@ -113,7 +113,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
Tag[] tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false);
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0);
|
||||
|
||||
// center up
|
||||
mCoords[0] = size / 2;
|
||||
@ -124,7 +124,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex,
|
||||
false);
|
||||
false, 0);
|
||||
|
||||
// center down
|
||||
mCoords[0] = size / 2;
|
||||
@ -134,7 +134,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false);
|
||||
mapDatabaseCallback.renderWay((byte) 0, tags, mCoords, mIndex, false, 0);
|
||||
|
||||
// left-top to center
|
||||
mCoords[0] = size / 2;
|
||||
@ -144,7 +144,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
|
||||
|
||||
// middle horizontal
|
||||
mCoords[0] = 0;
|
||||
@ -154,7 +154,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
|
||||
|
||||
// middle horizontal
|
||||
mCoords[0] = 10;
|
||||
@ -164,7 +164,7 @@ public class MapDatabase implements IMapDatabase {
|
||||
tags = new Tag[2];
|
||||
tags[0] = mTagsWay[0];
|
||||
tags[1] = mTagsWay[1];
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false);
|
||||
mapDatabaseCallback.renderWay((byte) 1, tags, mCoords, mIndex, false, 0);
|
||||
|
||||
// lon1 = size / 2;
|
||||
// lat1 = size / 2;
|
||||
|
@ -24,6 +24,7 @@ import org.oscim.database.IMapDatabaseCallback;
|
||||
import org.oscim.database.QueryResult;
|
||||
import org.oscim.renderer.MapTile;
|
||||
import org.oscim.renderer.WayDecorator;
|
||||
import org.oscim.renderer.layer.ExtrusionLayer;
|
||||
import org.oscim.renderer.layer.Layer;
|
||||
import org.oscim.renderer.layer.Layers;
|
||||
import org.oscim.renderer.layer.LineLayer;
|
||||
@ -103,6 +104,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
private float mProjectionScaleFactor;
|
||||
|
||||
private float mPoiX, mPoiY;
|
||||
private int mPriority;
|
||||
|
||||
private Tag mTagEmptyName = new Tag(Tag.TAG_KEY_NAME, null, false);
|
||||
private Tag mTagName;
|
||||
@ -159,6 +161,14 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
mLayers = new Layers();
|
||||
|
||||
//Log.d(TAG, "loading: " + tile);
|
||||
//if ((tile.zoomLevel != 17) || (tile.tileX == 68752 && tile.tileY == 42640))
|
||||
//if ((tile.zoomLevel != 17) || (tile.tileX == 68743 && tile.tileY == 42681))
|
||||
//if ((tile.zoomLevel != 17) || (tile.tileX == 68736 && tile.tileY == 42653))
|
||||
// TODO: building with non simple holes (Berlin):
|
||||
//if ((tile.zoomLevel != 17) || (tile.tileX == 70428 && tile.tileY == 43009)),
|
||||
//if ((tile.zoomLevel != 17) || (tile.tileX == 70463 && tile.tileY == 42990))
|
||||
|
||||
if (mMapDatabase.executeQuery(tile, this) != QueryResult.SUCCESS) {
|
||||
//Log.d(TAG, "Failed loading: " + tile);
|
||||
mLayers.clear();
|
||||
@ -188,6 +198,9 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
mLayers = null;
|
||||
mLabels = null;
|
||||
|
||||
if (tile.layers.extrusionLayers != null)
|
||||
((ExtrusionLayer) tile.layers.extrusionLayers).ready = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -226,16 +239,19 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
return mMapDatabase;
|
||||
}
|
||||
|
||||
private boolean mRenderBuildingModel;
|
||||
|
||||
private boolean filterTags(Tag[] tags) {
|
||||
mRenderBuildingModel = false;
|
||||
|
||||
for (int i = 0; i < tags.length; i++) {
|
||||
String key = tags[i].key;
|
||||
if (key == Tag.TAG_KEY_NAME) {
|
||||
if (tags[i].key == Tag.TAG_KEY_NAME) {
|
||||
mTagName = tags[i];
|
||||
tags[i] = mTagEmptyName;
|
||||
} else if (mCurrentTile.zoomLevel >= 17 &&
|
||||
key == TAG_BUILDING) {
|
||||
|
||||
return false;
|
||||
mRenderBuildingModel = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -292,20 +308,19 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
@Override
|
||||
public void renderWay(byte layer, Tag[] tags, float[] coords, short[] indices,
|
||||
boolean closed) {
|
||||
boolean closed, int prio) {
|
||||
|
||||
// reset state
|
||||
mTagName = null;
|
||||
mCurLineLayer = null;
|
||||
|
||||
mPriority = prio;
|
||||
mClosed = closed;
|
||||
|
||||
// replace tags that should not be cached in Rendertheme (e.g. name)
|
||||
if (!filterTags(tags))
|
||||
return;
|
||||
|
||||
mDrawingLayer = getValidLayer(layer) * mLevels;
|
||||
|
||||
// mProjected = false;
|
||||
// mSimplify = 0.5f;
|
||||
// if (closed) {
|
||||
@ -317,6 +332,7 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
// mSimplify = 0;
|
||||
// }
|
||||
|
||||
mDrawingLayer = getValidLayer(layer) * mLevels;
|
||||
mCoords = coords;
|
||||
mIndices = indices;
|
||||
|
||||
@ -394,14 +410,24 @@ public class TileGenerator implements IRenderCallback, IMapDatabaseCallback {
|
||||
|
||||
@Override
|
||||
public void renderArea(Area area, int level) {
|
||||
int numLayer = mDrawingLayer + level;
|
||||
|
||||
if (mRenderBuildingModel) {
|
||||
//Log.d(TAG, "add buildings: " + mCurrentTile + " " + mPriority);
|
||||
if (mLayers.extrusionLayers == null)
|
||||
mLayers.extrusionLayers = new ExtrusionLayer(0);
|
||||
|
||||
((ExtrusionLayer) mLayers.extrusionLayers).addBuildings(mCoords, mIndices, mPriority);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mDebugDrawPolygons)
|
||||
return;
|
||||
|
||||
// if (!mProjected && !projectToTile())
|
||||
// return;
|
||||
|
||||
int numLayer = mDrawingLayer + level;
|
||||
|
||||
PolygonLayer layer = (PolygonLayer) mLayers.getLayer(numLayer, Layer.POLYGON);
|
||||
if (layer == null)
|
||||
return;
|
||||
|
@ -89,8 +89,7 @@ public final class TextureRenderer {
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
public static Layer draw(Layer layer, float scale, float[] projection,
|
||||
float matrix[], int offset) {
|
||||
public static Layer draw(Layer layer, float scale, float[] projection, float matrix[]) {
|
||||
|
||||
// GlUtils.checkGlError("draw texture >");
|
||||
GLES20.glUseProgram(mTextureProgram);
|
||||
@ -121,7 +120,7 @@ public final class TextureRenderer {
|
||||
// can only draw MAX_ITEMS in each iteration
|
||||
for (int i = 0; i < to.vertices; i += maxVertices) {
|
||||
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
|
||||
int off = (to.offset + i) * 8 + offset;
|
||||
int off = (to.offset + i) * 8 + tl.offset;
|
||||
|
||||
GLES20.glVertexAttribPointer(hTextureVertex, 4,
|
||||
GLES20.GL_SHORT, false, 12, off);
|
||||
|
@ -35,6 +35,9 @@ import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
* @TODO
|
||||
* - this class should probably not be in 'renderer' -> tilemap?
|
||||
* - make it general for reuse in tile-overlays
|
||||
*/
|
||||
public class TileManager {
|
||||
static final String TAG = TileManager.class.getSimpleName();
|
||||
|
475
src/org/oscim/renderer/layer/ExtrusionLayer.java
Normal file
475
src/org/oscim/renderer/layer/ExtrusionLayer.java
Normal file
@ -0,0 +1,475 @@
|
||||
/*
|
||||
* Copyright 2012, 2013 OpenScienceMap
|
||||
*
|
||||
* 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.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.view.MapView;
|
||||
import org.quake.triangle.TriangleJNI;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public class ExtrusionLayer extends Layer {
|
||||
private final static String TAG = ExtrusionLayer.class.getName();
|
||||
private static final float S = GLRenderer.COORD_MULTIPLIER;
|
||||
public int mIndicesBufferID;
|
||||
public int mVertexBufferID;
|
||||
public int mNumIndices = 0;
|
||||
private int mNumVertices = 0;
|
||||
private VertexPoolItem mVertices, mCurVertices;
|
||||
private VertexPoolItem mIndices[], mCurIndices[];
|
||||
|
||||
public int mIndiceCnt[] = { 0, 0, 0 };
|
||||
|
||||
public ExtrusionLayer(int level) {
|
||||
this.type = Layer.EXTRUSION;
|
||||
this.layer = level;
|
||||
|
||||
mVertices = mCurVertices = VertexPool.get();
|
||||
mIndices = new VertexPoolItem[3];
|
||||
mCurIndices = new VertexPoolItem[3];
|
||||
mIndices[0] = mCurIndices[0] = VertexPool.get();
|
||||
mIndices[1] = mCurIndices[1] = VertexPool.get();
|
||||
mIndices[2] = mCurIndices[2] = VertexPool.get();
|
||||
}
|
||||
|
||||
public void addBuildings(float[] points, short[] index, int height) {
|
||||
int complex = 0;
|
||||
boolean simple = true;
|
||||
|
||||
if (height == 0)
|
||||
height = 400;
|
||||
else
|
||||
height *= 40;
|
||||
|
||||
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
|
||||
int length = index[i];
|
||||
|
||||
// end marker
|
||||
if (length < 0)
|
||||
break;
|
||||
|
||||
// start next polygon
|
||||
if (length == 0) {
|
||||
complex = i + 1;
|
||||
simple = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// need at least three points
|
||||
if (length < 6) {
|
||||
pos += length;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if polygon contains inner rings
|
||||
//if (simple && ((i < n - 1) && (index[i + 1] > 0)))
|
||||
// simple = false;
|
||||
|
||||
addOutline(points, pos, length, height, simple);
|
||||
pos += length;
|
||||
}
|
||||
}
|
||||
|
||||
private void addOutline(float[] points, int pos, int len, float height, boolean simple) {
|
||||
if (!MapView.enableClosePolygons)
|
||||
len -= 2;
|
||||
|
||||
// add two vertices for last face to make zigzag indices work
|
||||
boolean addFace = (len % 4 != 0);
|
||||
|
||||
// Log.d(TAG, "add: " + addFace + " " + len + " (" + pos + ")");
|
||||
|
||||
int vertexCnt = len + (addFace ? 2 : 0);
|
||||
int indicesCnt = (len >> 1) * 6;
|
||||
|
||||
short h = (short) height;
|
||||
|
||||
float cx = points[pos + len - 2];
|
||||
float cy = points[pos + len - 1];
|
||||
float nx = points[pos + 0];
|
||||
float ny = points[pos + 1];
|
||||
|
||||
float vx = nx - cx;
|
||||
float vy = ny - cy;
|
||||
float ca = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
float pa = ca;
|
||||
float ux = vx;
|
||||
float uy = vy;
|
||||
|
||||
float vlight = vx > 0 ? (vx / ca) : -(vx / ca) - 0.1f;
|
||||
|
||||
short color1 = (short) (200 + (50 * vlight));
|
||||
short fcolor = color1;
|
||||
short color2 = 0;
|
||||
|
||||
boolean even = true;
|
||||
|
||||
short[] vertices = mCurVertices.vertices;
|
||||
int v = mCurVertices.used;
|
||||
|
||||
int convex = 0;
|
||||
|
||||
for (int i = 0; i < len; i += 2, v += 8) {
|
||||
cx = nx;
|
||||
cy = ny;
|
||||
|
||||
if (v == VertexPoolItem.SIZE) {
|
||||
mCurVertices.used = VertexPoolItem.SIZE;
|
||||
mCurVertices.next = VertexPool.get();
|
||||
mCurVertices = mCurVertices.next;
|
||||
vertices = mCurVertices.vertices;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
vertices[v + 0] = vertices[v + 4] = (short) (cx * S);
|
||||
vertices[v + 1] = vertices[v + 5] = (short) (cy * S);
|
||||
|
||||
vertices[v + 2] = 0;
|
||||
vertices[v + 6] = h;
|
||||
|
||||
if (i < len - 2) {
|
||||
nx = points[pos + i + 2];
|
||||
ny = points[pos + i + 3];
|
||||
|
||||
vx = nx - cx;
|
||||
vy = ny - cy;
|
||||
ca = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
|
||||
if (convex > -1) {
|
||||
// TODO fix for straight line...
|
||||
double dir = (vx * ux + vy * uy) / (ca * pa);
|
||||
|
||||
if (convex == 0)
|
||||
convex = dir > 0 ? 1 : 2;
|
||||
else if (convex == 1)
|
||||
convex = dir > 0 ? 1 : -1;
|
||||
else
|
||||
convex = dir > 0 ? -1 : 2;
|
||||
}
|
||||
vlight = vx > 0 ? (vx / ca) : -(vx / ca) - 0.1f;
|
||||
color2 = (short) (200 + (50 * vlight));
|
||||
} else {
|
||||
color2 = fcolor;
|
||||
}
|
||||
|
||||
short c;
|
||||
if (even)
|
||||
c = (short) (color1 | color2 << 8);
|
||||
else
|
||||
c = (short) (color2 | color1 << 8);
|
||||
|
||||
vertices[v + 3] = vertices[v + 7] = c;
|
||||
|
||||
pa = ca;
|
||||
ux = vx;
|
||||
uy = vy;
|
||||
color1 = color2;
|
||||
even = !even;
|
||||
}
|
||||
|
||||
if (addFace) {
|
||||
if (v == VertexPoolItem.SIZE) {
|
||||
mCurVertices.used = VertexPoolItem.SIZE;
|
||||
mCurVertices.next = VertexPool.get();
|
||||
mCurVertices = mCurVertices.next;
|
||||
vertices = mCurVertices.vertices;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
cx = points[pos + 0];
|
||||
cy = points[pos + 1];
|
||||
|
||||
vertices[v + 0] = vertices[v + 4] = (short) (cx * S);
|
||||
vertices[v + 1] = vertices[v + 5] = (short) (cy * S);
|
||||
|
||||
vertices[v + 2] = 0;
|
||||
vertices[v + 6] = h;
|
||||
|
||||
short c = (short) (color1 | fcolor << 8);
|
||||
vertices[v + 3] = vertices[v + 7] = c;
|
||||
|
||||
v += 8;
|
||||
}
|
||||
|
||||
mCurVertices.used = v;
|
||||
|
||||
// fill ZigZagQuadIndices(tm)
|
||||
for (int j = 0; j < 2; j++) {
|
||||
short[] indices = mCurIndices[j].vertices;
|
||||
|
||||
// index id relative to mCurIndices
|
||||
int i = mCurIndices[j].used;
|
||||
|
||||
// vertex id
|
||||
v = mNumVertices + (j * 2);
|
||||
|
||||
for (int k = j * 2; k < len; k += 4) {
|
||||
short s0 = (short) (v++);
|
||||
short s1 = (short) (v++);
|
||||
short s2 = (short) (v++);
|
||||
short s3 = (short) (v++);
|
||||
|
||||
if (i == VertexPoolItem.SIZE) {
|
||||
mCurIndices[j].used = VertexPoolItem.SIZE;
|
||||
mCurIndices[j].next = VertexPool.get();
|
||||
mCurIndices[j] = mCurIndices[j].next;
|
||||
indices = mCurIndices[j].vertices;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (k + 2 == len) {
|
||||
// connect last to first (when number of faces is even)
|
||||
if (!addFace) {
|
||||
//Log.d(TAG, "connect last " + vertexCnt + " " + len);
|
||||
s2 -= len;
|
||||
s3 -= len;
|
||||
}
|
||||
}
|
||||
indices[i++] = s0;
|
||||
indices[i++] = s1;
|
||||
indices[i++] = s2;
|
||||
|
||||
indices[i++] = s1;
|
||||
indices[i++] = s3;
|
||||
indices[i++] = s2;
|
||||
//System.out.println(" i:" + (mNumIndices + (k * 6))
|
||||
// + "\t(" + s0 + "," + s1 + "," + s2
|
||||
// + ")\t(" + s1 + "," + s3 + "," + s2 + ")");
|
||||
}
|
||||
mCurIndices[j].used = i;
|
||||
}
|
||||
|
||||
if (simple && (len <= 8 || convex > 0)) {
|
||||
//Log.d(TAG, len + " is simple " + convex);
|
||||
|
||||
// roof indices for convex shapes
|
||||
int i = mCurIndices[2].used;
|
||||
short[] indices = mCurIndices[2].vertices;
|
||||
short first = (short) (mNumVertices + 1);
|
||||
|
||||
for (int k = 0; k < len - 4; k += 2) {
|
||||
if (i == VertexPoolItem.SIZE) {
|
||||
mCurIndices[2].used = VertexPoolItem.SIZE;
|
||||
mCurIndices[2].next = VertexPool.get();
|
||||
mCurIndices[2] = mCurIndices[2].next;
|
||||
indices = mCurIndices[2].vertices;
|
||||
i = 0;
|
||||
}
|
||||
indices[i++] = first;
|
||||
//if (convex != 2) {
|
||||
// cw ?
|
||||
indices[i++] = (short) (first + k + 4);
|
||||
indices[i++] = (short) (first + k + 2);
|
||||
// } else {
|
||||
// indices[i++] = (short) (first + k + 2);
|
||||
// indices[i++] = (short) (first + k + 4);
|
||||
// }
|
||||
|
||||
// System.out.println("indice:" + k + "\t" + indices[cnt - 3] + ","
|
||||
// + indices[cnt - 2]+ "," + indices[cnt - 1]);
|
||||
|
||||
indicesCnt += 3;
|
||||
}
|
||||
mCurIndices[2].used = i;
|
||||
} else if (len < 400) {
|
||||
// triangulate up to 200 points
|
||||
short first = (short) (mNumVertices + 1);
|
||||
int used = triangulate(points, pos, len, mCurIndices[2], first);
|
||||
if (used > 0) {
|
||||
indicesCnt += used;
|
||||
// find the last item added..
|
||||
VertexPoolItem it = mIndices[2];
|
||||
while (it.next != null)
|
||||
it = it.next;
|
||||
mCurIndices[2] = it;
|
||||
}
|
||||
|
||||
// mCurIndices[2].next = VertexPool.get();
|
||||
// mCurIndices[2] = mCurIndices[2].next;
|
||||
// short[] indices = mCurIndices[2].vertices;
|
||||
// int used = triangulate(points, pos, len, indices);
|
||||
// if (used > 0) {
|
||||
// short first = (short) (mNumVertices + 1);
|
||||
// for (int i = 0; i < used; i += 3) {
|
||||
// indices[i] = (short) (indices[i] * 2 + first);
|
||||
// short tmp = indices[i + 1];
|
||||
// indices[i + 1] = (short) (indices[i + 2] * 2 + first);
|
||||
// indices[i + 2] = (short) (tmp * 2 + first);
|
||||
// }
|
||||
// mCurIndices[2].used = used;
|
||||
// indicesCnt += used;
|
||||
// }
|
||||
} else
|
||||
Log.d(TAG, "skip >>>>>>>>>> : " + len + " <<<<<<<<<<<<<");
|
||||
|
||||
//Log.d(TAG, "add building: " + vertexCnt);
|
||||
mNumVertices += vertexCnt;
|
||||
mNumIndices += indicesCnt;
|
||||
}
|
||||
|
||||
public void compile(ShortBuffer sbuf) {
|
||||
|
||||
if (mNumVertices == 0 || compiled)
|
||||
return;
|
||||
|
||||
mVboIds = new int[2];
|
||||
GLES20.glGenBuffers(2, mVboIds, 0);
|
||||
mIndicesBufferID = mVboIds[0];
|
||||
mVertexBufferID = mVboIds[1];
|
||||
|
||||
// upload indices
|
||||
|
||||
sbuf.clear();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (VertexPoolItem vi = mIndices[i]; vi != null; vi = vi.next) {
|
||||
//System.out.println("put indices: " + vi.used + " " + mNumIndices);
|
||||
sbuf.put(vi.vertices, 0, vi.used);
|
||||
mIndiceCnt[i] += vi.used;
|
||||
}
|
||||
}
|
||||
|
||||
// Log.d(TAG,"put indices: " + mNumIndices + "=="
|
||||
// + (mIndiceCnt[0] + mIndiceCnt[1] + mIndiceCnt[2])
|
||||
// + " " + mIndiceCnt[0] + " " + mIndiceCnt[1] + " " + mIndiceCnt[2]);
|
||||
|
||||
mNumIndices = mIndiceCnt[0] + mIndiceCnt[1] + mIndiceCnt[2];
|
||||
|
||||
sbuf.flip();
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
|
||||
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
|
||||
mNumIndices * 2, sbuf, GLES20.GL_DYNAMIC_DRAW);
|
||||
|
||||
sbuf.clear();
|
||||
|
||||
// upload vertices
|
||||
for (VertexPoolItem vi = mVertices; vi != null; vi = vi.next) {
|
||||
//System.out.println("put vertices: " + vi.used + " " + mNumVertices);
|
||||
sbuf.put(vi.vertices, 0, vi.used);
|
||||
}
|
||||
|
||||
sbuf.flip();
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
|
||||
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
|
||||
mNumVertices * 4 * 2, sbuf, GLES20.GL_DYNAMIC_DRAW);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
|
||||
|
||||
for (VertexPoolItem i : mIndices)
|
||||
VertexPool.release(i);
|
||||
|
||||
VertexPool.release(mVertices);
|
||||
|
||||
compiled = true;
|
||||
}
|
||||
|
||||
public boolean compiled = false;
|
||||
|
||||
int[] mVboIds;
|
||||
|
||||
public boolean ready;
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
if (compiled) {
|
||||
GLES20.glDeleteBuffers(2, mVboIds, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void render() {
|
||||
|
||||
}
|
||||
|
||||
private static boolean initialized = false;
|
||||
private static ShortBuffer sBuf;
|
||||
private static FloatBuffer fBuf;
|
||||
|
||||
public static synchronized int triangulate(float[] points, int pos, int len,
|
||||
VertexPoolItem item, int first) {
|
||||
|
||||
int numRings = 1;
|
||||
|
||||
if (!initialized) {
|
||||
// FIXME also cleanup on shutdown!
|
||||
fBuf = ByteBuffer.allocateDirect(360 * 4).order(ByteOrder.nativeOrder())
|
||||
.asFloatBuffer();
|
||||
|
||||
sBuf = ByteBuffer.allocateDirect(720 * 2).order(ByteOrder.nativeOrder())
|
||||
.asShortBuffer();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
fBuf.clear();
|
||||
fBuf.put(points, pos, len);
|
||||
|
||||
sBuf.clear();
|
||||
sBuf.put((short) (len >> 1)); // all points
|
||||
sBuf.put((short) (len >> 1)); // outer ring
|
||||
//sBuf.put((short)4); // inner ring
|
||||
|
||||
int numTris = TriangleJNI.triangulate(fBuf, numRings, sBuf, first);
|
||||
|
||||
int numIndices = numTris * 3;
|
||||
sBuf.limit(numIndices);
|
||||
sBuf.position(0);
|
||||
|
||||
for (int k = 0, cnt = 0; k < numIndices; k += cnt) {
|
||||
cnt = VertexPoolItem.SIZE - item.used;
|
||||
|
||||
if (item.used == VertexPoolItem.SIZE) {
|
||||
item.next = VertexPool.get();
|
||||
item = item.next;
|
||||
}
|
||||
|
||||
if (k + cnt > numIndices)
|
||||
cnt = numIndices - k;
|
||||
|
||||
sBuf.get(item.vertices, item.used, cnt);
|
||||
item.used += cnt;
|
||||
}
|
||||
|
||||
// sBuf.get(sIndices, 0, numIndices);
|
||||
//
|
||||
// short[] indices = item.vertices;
|
||||
// int i = item.used;
|
||||
//
|
||||
// for (int k = 0; k < numIndices; k += 3) {
|
||||
// if (i == VertexPoolItem.SIZE) {
|
||||
// item.used = VertexPoolItem.SIZE;
|
||||
// item.next = VertexPool.get();
|
||||
// item = item.next;
|
||||
// indices = item.vertices;
|
||||
// i = 0;
|
||||
// }
|
||||
// indices[i++] = sIndices[k + 0];
|
||||
// indices[i++] = sIndices[k + 1];
|
||||
// indices[i++] = sIndices[k + 2];
|
||||
// }
|
||||
// item.used = i;
|
||||
|
||||
return numIndices;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Hannes Janetzek
|
||||
* Copyright 2012, 2013 OpenScienceMap
|
||||
*
|
||||
* 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
|
||||
@ -14,6 +14,9 @@
|
||||
*/
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
/**
|
||||
* @authorHannes Janetzek
|
||||
*/
|
||||
public abstract class Layer {
|
||||
public final static byte LINE = 0;
|
||||
public final static byte POLYGON = 1;
|
||||
@ -21,15 +24,21 @@ public abstract class Layer {
|
||||
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 EXTRUSION = 7;
|
||||
|
||||
public byte type;
|
||||
public byte type = -1;
|
||||
|
||||
public Layer next;
|
||||
|
||||
int layer;
|
||||
// number of vertices this layer holds
|
||||
// number of vertices for this layer
|
||||
public int verticesCnt;
|
||||
// vertices offset of this layer in VBO
|
||||
|
||||
// in case of line and polygon layer:
|
||||
// - number of VERTICES offset for this layertype in VBO
|
||||
// otherwise:
|
||||
// - offset in byte in VBO
|
||||
public int offset;
|
||||
|
||||
VertexPoolItem pool;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Hannes Janetzek
|
||||
* Copyright 2012, 2013 OpenScienceMap
|
||||
*
|
||||
* 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
|
||||
@ -18,13 +18,22 @@ import java.nio.ShortBuffer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public class Layers {
|
||||
|
||||
// mixed Polygon and Line layers
|
||||
public Layer layers;
|
||||
public int lineOffset;
|
||||
|
||||
public Layer textureLayers;
|
||||
public int texOffset;
|
||||
public Layer extrusionLayers;
|
||||
|
||||
// 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;
|
||||
|
||||
private Layer mCurLayer;
|
||||
|
||||
@ -78,10 +87,78 @@ public class Layers {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// public boolean uploadLayers(BufferObject vbo, boolean addFill, boolean limit) {
|
||||
//
|
||||
// int newSize = getSize();
|
||||
// if (newSize == 0) {
|
||||
// // Log.d(TAG, "empty");
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
|
||||
//
|
||||
// // use multiple buffers to avoid overwriting buffer while current
|
||||
// // data is uploaded (or rather the blocking which is probably done to
|
||||
// // avoid overwriting)
|
||||
// int curBuffer = uploadCnt++ % rotateBuffers;
|
||||
//
|
||||
// ShortBuffer sbuf = shortBuffer[curBuffer];
|
||||
//
|
||||
// // add fill coordinates
|
||||
// if (addFill)
|
||||
// newSize += 8;
|
||||
//
|
||||
// if (sbuf.capacity() < newSize) {
|
||||
// sbuf = ByteBuffer
|
||||
// .allocateDirect(newSize * SHORT_BYTES)
|
||||
// .order(ByteOrder.nativeOrder())
|
||||
// .asShortBuffer();
|
||||
//
|
||||
// shortBuffer[curBuffer] = sbuf;
|
||||
// } else {
|
||||
// sbuf.clear();
|
||||
// // if (addFill)
|
||||
// // sbuf.position(8);
|
||||
// }
|
||||
//
|
||||
// if (addFill)
|
||||
// sbuf.put(mFillCoords, 0, 8);
|
||||
//
|
||||
// compile(sbuf, addFill);
|
||||
//
|
||||
// sbuf.flip();
|
||||
//
|
||||
// if (newSize != sbuf.remaining()) {
|
||||
// Log.d(TAG, "wrong size: "
|
||||
// + newSize + " "
|
||||
// + sbuf.position() + " "
|
||||
// + sbuf.limit() + " "
|
||||
// + 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
|
||||
// && !limit) {
|
||||
// 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 += vbo.size;
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
private static int LINE_VERTEX_SHORTS = 4;
|
||||
private static int POLY_VERTEX_SHORTS = 2;
|
||||
private static int TEXTURE_VERTEX_SHORTS = 6;
|
||||
|
||||
//private static int EXTRUSION_VERTEX_SHORTS = 4;
|
||||
|
||||
public int getSize() {
|
||||
|
||||
int size = 0;
|
||||
@ -91,12 +168,13 @@ public class Layers {
|
||||
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;
|
||||
}
|
||||
|
||||
//for (Layer l = extrusionLayers; l != null; l = l.next)
|
||||
// size += l.verticesCnt * EXTRUSION_VERTEX_SHORTS;
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -113,18 +191,18 @@ public class Layers {
|
||||
lineOffset = sbuf.position() * 2; // * short-bytes
|
||||
addLayerItems(sbuf, layers, Layer.LINE, 0);
|
||||
|
||||
texOffset = sbuf.position() * 2; // * short-bytes
|
||||
|
||||
for (Layer l = textureLayers; l != null; l = l.next) {
|
||||
TextureLayer sl = (TextureLayer) l;
|
||||
sl.compile(sbuf);
|
||||
TextureLayer tl = (TextureLayer) l;
|
||||
tl.compile(sbuf);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
addLayerItems(sbuf, textureLayers, Layer.SYMBOL, 0);
|
||||
|
||||
// for (Layer l = extrusionLayers; l != null; l = l.next) {
|
||||
// ExtrusionLayer tl = (ExtrusionLayer) l;
|
||||
// tl.compile(sbuf);
|
||||
// }
|
||||
}
|
||||
|
||||
// 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) {
|
||||
VertexPoolItem last = null, items = null;
|
||||
|
||||
@ -136,7 +214,8 @@ public class Layers {
|
||||
if (it.next == null)
|
||||
sbuf.put(it.vertices, 0, it.used);
|
||||
else
|
||||
sbuf.put(it.vertices);
|
||||
sbuf.put(it.vertices, 0, VertexPoolItem.SIZE);
|
||||
|
||||
last = it;
|
||||
}
|
||||
if (last == null)
|
||||
@ -155,8 +234,22 @@ public class Layers {
|
||||
VertexPool.release(items);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
static void addPoolItems(Layer l, ShortBuffer sbuf) {
|
||||
l.offset = sbuf.position() * 2; // (* short-bytes)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
VertexPool.release(l.pool);
|
||||
l.pool = null;
|
||||
}
|
||||
|
||||
// cleanup only when layers are not used by tile or overlay anymore!
|
||||
public void clear() {
|
||||
while (layers != null) {
|
||||
Layer l = layers;
|
||||
if (l.pool != null) {
|
||||
@ -181,5 +274,20 @@ public class Layers {
|
||||
l = l.next;
|
||||
}
|
||||
textureLayers = null;
|
||||
|
||||
l = extrusionLayers;
|
||||
while (l != null) {
|
||||
|
||||
l.clear();
|
||||
|
||||
if (l.pool != null) {
|
||||
VertexPool.release(l.pool);
|
||||
l.pool = null;
|
||||
l.curItem = null;
|
||||
}
|
||||
|
||||
l = l.next;
|
||||
}
|
||||
extrusionLayers = null;
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
*/
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.TextureObject;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
|
||||
@ -85,14 +83,16 @@ public final class SymbolLayer extends TextureLayer {
|
||||
symbols = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
}
|
||||
// @Override
|
||||
// void compile(ShortBuffer sbuf) {
|
||||
// if (TextureRenderer.debug)
|
||||
// Log.d("...", "compile");
|
||||
//
|
||||
// for (TextureObject to = textures; to != null; to = to.next)
|
||||
// TextureObject.uploadTexture(to);
|
||||
//
|
||||
// Layers.addPoolItems(this, sbuf);
|
||||
// }
|
||||
|
||||
private final static int LBIT_MASK = 0xfffffffe;
|
||||
|
||||
|
@ -14,13 +14,10 @@
|
||||
*/
|
||||
package org.oscim.renderer.layer;
|
||||
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.TextureObject;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.util.FloatMath;
|
||||
import android.util.Log;
|
||||
|
||||
public final class TextLayer extends TextureLayer {
|
||||
@ -92,15 +89,6 @@ public final class TextLayer extends TextureLayer {
|
||||
labels = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare() {
|
||||
if (TextureRenderer.debug)
|
||||
@ -189,7 +177,7 @@ public final class TextLayer extends TextureLayer {
|
||||
} else {
|
||||
float vx = it.x1 - it.x2;
|
||||
float vy = it.y1 - it.y2;
|
||||
float a = FloatMath.sqrt(vx * vx + vy * vy);
|
||||
float a = (float) Math.sqrt(vx * vx + vy * vy);
|
||||
vx = vx / a;
|
||||
vy = vy / a;
|
||||
|
||||
|
@ -17,6 +17,9 @@ package org.oscim.renderer.layer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.renderer.TextureObject;
|
||||
import org.oscim.renderer.TextureRenderer;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public abstract class TextureLayer extends Layer {
|
||||
public TextureObject textures;
|
||||
@ -26,7 +29,15 @@ public abstract class TextureLayer extends Layer {
|
||||
* @param sbuf
|
||||
* buffer to add vertices
|
||||
*/
|
||||
abstract void compile(ShortBuffer sbuf);
|
||||
void compile(ShortBuffer sbuf) {
|
||||
if (TextureRenderer.debug)
|
||||
Log.d("...", "compile");
|
||||
|
||||
for (TextureObject to = textures; to != null; to = to.next)
|
||||
TextureObject.uploadTexture(to);
|
||||
|
||||
Layers.addPoolItems(this, sbuf);
|
||||
}
|
||||
|
||||
abstract public boolean prepare();
|
||||
}
|
||||
|
@ -29,6 +29,15 @@ public class VertexPool {
|
||||
pool = null;
|
||||
}
|
||||
|
||||
// public static VertexPoolItem get(VertexPoolItem prev) {
|
||||
// VertexPoolItem it = get();
|
||||
// if (prev != null) {
|
||||
// prev.next = it;
|
||||
// prev.used = VertexPoolItem.SIZE;
|
||||
// }
|
||||
// return it;
|
||||
// }
|
||||
|
||||
public static synchronized VertexPoolItem get() {
|
||||
|
||||
if (pool == null && count > 0) {
|
||||
|
@ -40,9 +40,6 @@ public class BuildingOverlay extends RenderOverlay {
|
||||
super(mapView);
|
||||
}
|
||||
|
||||
private int mNumIndices = 0;
|
||||
private int mNumVertices = 0;
|
||||
|
||||
private static int buildingProgram;
|
||||
private static int hBuildingVertexPosition;
|
||||
private static int hBuildingLightPosition;
|
||||
@ -55,8 +52,9 @@ public class BuildingOverlay extends RenderOverlay {
|
||||
private int mIndicesBufferID;
|
||||
private int mVertexBufferID;
|
||||
|
||||
private int mNumIndices = 0;
|
||||
private int mNumVertices = 0;
|
||||
private VertexPoolItem mVertices, mCurVertices;
|
||||
|
||||
private VertexPoolItem mIndices[], mCurIndices[];
|
||||
|
||||
private int mIndiceCnt[] = { 0, 0, 0 };
|
||||
|
328
src/org/oscim/renderer/overlays/BuildingOverlay2.java
Normal file
328
src/org/oscim/renderer/overlays/BuildingOverlay2.java
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2012 OpenScienceMap
|
||||
*
|
||||
* 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.overlays;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import org.oscim.core.MapPosition;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.renderer.MapTile;
|
||||
import org.oscim.renderer.TileManager;
|
||||
import org.oscim.renderer.TileSet;
|
||||
import org.oscim.renderer.layer.ExtrusionLayer;
|
||||
import org.oscim.utils.GlUtils;
|
||||
import org.oscim.view.MapView;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.Matrix;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* @author Hannes Janetzek
|
||||
*/
|
||||
public class BuildingOverlay2 extends RenderOverlay {
|
||||
private final static String TAG = BuildingOverlay2.class.getName();
|
||||
|
||||
public BuildingOverlay2(MapView mapView) {
|
||||
super(mapView);
|
||||
}
|
||||
|
||||
private static int buildingProgram;
|
||||
private static int hBuildingVertexPosition;
|
||||
private static int hBuildingLightPosition;
|
||||
private static int hBuildingMatrix;
|
||||
private static int hBuildingColor;
|
||||
private static int hBuildingMode;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private int BUFFERSIZE = 65536 * 2;
|
||||
private TileSet mTileSet;
|
||||
private ShortBuffer mShortBuffer;
|
||||
|
||||
@Override
|
||||
public synchronized void update(MapPosition curPos, boolean positionChanged,
|
||||
boolean tilesChanged) {
|
||||
|
||||
mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
|
||||
|
||||
if (!initialized) {
|
||||
initialized = true;
|
||||
|
||||
// Set up the program for rendering buildings
|
||||
buildingProgram = GlUtils.createProgram(buildingVertexShader,
|
||||
buildingFragmentShader);
|
||||
if (buildingProgram == 0) {
|
||||
Log.e("blah", "Could not create building program.");
|
||||
return;
|
||||
}
|
||||
hBuildingMatrix = GLES20.glGetUniformLocation(buildingProgram, "u_mvp");
|
||||
hBuildingColor = GLES20.glGetUniformLocation(buildingProgram, "u_color");
|
||||
hBuildingMode = GLES20.glGetUniformLocation(buildingProgram, "u_mode");
|
||||
hBuildingVertexPosition = GLES20.glGetAttribLocation(buildingProgram, "a_position");
|
||||
hBuildingLightPosition = GLES20.glGetAttribLocation(buildingProgram, "a_light");
|
||||
|
||||
ByteBuffer buf = ByteBuffer.allocateDirect(BUFFERSIZE)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
|
||||
mShortBuffer = buf.asShortBuffer();
|
||||
}
|
||||
|
||||
int ready = 0;
|
||||
//if (curPos.zoomLevel < 17)
|
||||
mTileSet = TileManager.getActiveTiles(mTileSet);
|
||||
MapTile[] tiles = mTileSet.tiles;
|
||||
for (int i = 0; i < mTileSet.cnt; i++) {
|
||||
if (!tiles[i].isVisible || tiles[i].layers == null
|
||||
|| tiles[i].layers.extrusionLayers == null)
|
||||
continue;
|
||||
|
||||
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
||||
|
||||
if (el.ready && !el.compiled) {
|
||||
el.compile(mShortBuffer);
|
||||
GlUtils.checkGlError("...");
|
||||
}
|
||||
|
||||
if (el.compiled)
|
||||
ready++;
|
||||
}
|
||||
|
||||
isReady = ready > 0;
|
||||
}
|
||||
|
||||
// r: 0.815686275, 0.91372549
|
||||
// g: 0.901960784
|
||||
// b: 0.890196078
|
||||
// sligthly differ adjacent faces to imrpove contrast
|
||||
float mColor[] = { 0.71872549f, 0.701960784f, 0.690196078f, 0.7f };
|
||||
float mColor2[] = { 0.71372549f, 0.701960784f, 0.695196078f, 0.7f };
|
||||
float mRoofColor[] = { 0.81f, 0.80f, 0.79f, 0.7f };
|
||||
boolean debug = false;
|
||||
|
||||
@Override
|
||||
public synchronized void render(MapPosition pos, float[] mv, float[] proj) {
|
||||
|
||||
boolean first = true;
|
||||
|
||||
if (debug) {
|
||||
MapTile[] tiles = mTileSet.tiles;
|
||||
for (int i = 0; i < mTileSet.cnt; i++) {
|
||||
if (!tiles[i].isVisible || tiles[i].layers == null
|
||||
|| tiles[i].layers.extrusionLayers == null)
|
||||
continue;
|
||||
|
||||
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
||||
if (!el.compiled)
|
||||
continue;
|
||||
|
||||
if (first) {
|
||||
GLES20.glUseProgram(buildingProgram);
|
||||
GLRenderer.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition);
|
||||
GLES20.glUniform1i(hBuildingMode, 0);
|
||||
GLES20.glUniform4f(hBuildingColor, 0.6f, 0.6f, 0.6f, 0.8f);
|
||||
first = false;
|
||||
}
|
||||
|
||||
setMatrix(pos, mv, proj, tiles[i], 1);
|
||||
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
|
||||
|
||||
GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3,
|
||||
GLES20.GL_SHORT, false, 8, 0);
|
||||
|
||||
GLES20.glVertexAttribPointer(hBuildingLightPosition, 2,
|
||||
GLES20.GL_UNSIGNED_BYTE, false, 8, 6);
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mNumIndices,
|
||||
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int drawCount = 20;
|
||||
// draw to depth buffer
|
||||
MapTile[] tiles = mTileSet.tiles;
|
||||
for (int i = 0; i < mTileSet.cnt; i++) {
|
||||
if (!tiles[i].isVisible || tiles[i].layers == null
|
||||
|| tiles[i].layers.extrusionLayers == null)
|
||||
continue;
|
||||
|
||||
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
||||
if (!el.compiled)
|
||||
continue;
|
||||
|
||||
if (first) {
|
||||
GLES20.glUseProgram(buildingProgram);
|
||||
GLRenderer.enableVertexArrays(hBuildingVertexPosition, -1);
|
||||
|
||||
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);
|
||||
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
|
||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
||||
GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
|
||||
//GLES20.glCullFace(GLES20.GL_CW);
|
||||
GLES20.glDepthMask(true);
|
||||
GLES20.glDepthFunc(GLES20.GL_LESS);
|
||||
GLES20.glUniform1i(hBuildingMode, 0);
|
||||
GLES20.glColorMask(false, false, false, false);
|
||||
first = false;
|
||||
}
|
||||
|
||||
GLES20.glPolygonOffset(0, drawCount--);
|
||||
// seems there are not infinite offset units possible
|
||||
// this should suffice for at least two rows, i.e.
|
||||
// having not two neighbours with the same depth
|
||||
if (drawCount == 0)
|
||||
drawCount = 20;
|
||||
|
||||
setMatrix(pos, mv, proj, tiles[i], 1);
|
||||
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
|
||||
|
||||
GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3,
|
||||
GLES20.GL_SHORT, false, 8, 0);
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mNumIndices,
|
||||
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
}
|
||||
|
||||
if (first)
|
||||
return;
|
||||
// enable color buffer, use depth mask
|
||||
GLRenderer.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition);
|
||||
GLES20.glColorMask(true, true, true, true);
|
||||
GLES20.glDepthMask(false);
|
||||
GLES20.glDepthFunc(GLES20.GL_EQUAL);
|
||||
|
||||
drawCount = 20;
|
||||
|
||||
for (int i = 0; i < mTileSet.cnt; i++) {
|
||||
if (!tiles[i].isVisible || tiles[i].layers == null
|
||||
|| tiles[i].layers.extrusionLayers == null)
|
||||
continue;
|
||||
|
||||
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers;
|
||||
if (!el.compiled)
|
||||
continue;
|
||||
|
||||
GLES20.glPolygonOffset(0, drawCount--);
|
||||
if (drawCount == 0)
|
||||
drawCount = 20;
|
||||
|
||||
setMatrix(pos, mv, proj, tiles[i], 1);
|
||||
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
|
||||
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID);
|
||||
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID);
|
||||
|
||||
GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3,
|
||||
GLES20.GL_SHORT, false, 8, 0);
|
||||
|
||||
GLES20.glVertexAttribPointer(hBuildingLightPosition, 2,
|
||||
GLES20.GL_UNSIGNED_BYTE, false, 8, 6);
|
||||
|
||||
// draw roof
|
||||
GLES20.glUniform1i(hBuildingMode, 0);
|
||||
//GLES20.glUniform4f(hBuildingColor, 0.81f, 0.8f, 0.8f, 0.9f);
|
||||
GLES20.glUniform4fv(hBuildingColor, 1, mRoofColor, 0);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[2],
|
||||
GLES20.GL_UNSIGNED_SHORT, (el.mIndiceCnt[0] + el.mIndiceCnt[1]) * 2);
|
||||
|
||||
// draw sides 1
|
||||
//GLES20.glUniform4f(hBuildingColor, 0.8f, 0.8f, 0.8f, 1.0f);
|
||||
//GLES20.glUniform4f(hBuildingColor, 0.9f, 0.905f, 0.9f, 1.0f);
|
||||
GLES20.glUniform4fv(hBuildingColor, 1, mColor, 0);
|
||||
GLES20.glUniform1i(hBuildingMode, 1);
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[0],
|
||||
GLES20.GL_UNSIGNED_SHORT, 0);
|
||||
|
||||
// draw sides 2
|
||||
//GLES20.glUniform4f(hBuildingColor, 0.9f, 0.9f, 0.905f, 1.0f);
|
||||
GLES20.glUniform4fv(hBuildingColor, 1, mColor2, 0);
|
||||
GLES20.glUniform1i(hBuildingMode, 2);
|
||||
|
||||
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[1],
|
||||
GLES20.GL_UNSIGNED_SHORT, el.mIndiceCnt[0] * 2);
|
||||
|
||||
GlUtils.checkGlError("...");
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
GLES20.glDisable(GLES20.GL_CULL_FACE);
|
||||
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
|
||||
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
|
||||
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setMatrix(MapPosition mapPosition, float[] matrix, float[] proj,
|
||||
MapTile tile, float div) {
|
||||
|
||||
float x = (float) (tile.pixelX - mapPosition.x * div);
|
||||
float y = (float) (tile.pixelY - mapPosition.y * div);
|
||||
float scale = mapPosition.scale / div;
|
||||
|
||||
Matrix.setIdentityM(matrix, 0);
|
||||
|
||||
// translate relative to map center
|
||||
matrix[12] = x * scale;
|
||||
matrix[13] = y * scale;
|
||||
|
||||
// scale to tile to world coordinates
|
||||
scale /= GLRenderer.COORD_MULTIPLIER;
|
||||
matrix[0] = scale;
|
||||
matrix[5] = scale;
|
||||
matrix[10] = scale / 1000f;
|
||||
|
||||
Matrix.multiplyMM(matrix, 0, mapPosition.viewMatrix, 0, matrix, 0);
|
||||
Matrix.multiplyMM(matrix, 0, proj, 0, matrix, 0);
|
||||
}
|
||||
|
||||
final static String buildingVertexShader = ""
|
||||
+ "precision mediump float;"
|
||||
+ "uniform mat4 u_mvp;"
|
||||
+ "uniform vec4 u_color;"
|
||||
+ "uniform int u_mode;"
|
||||
+ "uniform float u_scale;"
|
||||
+ "attribute vec4 a_position;"
|
||||
+ "attribute vec2 a_light;"
|
||||
+ "varying vec4 color;"
|
||||
+ "const float ff = 255.0;"
|
||||
+ "void main() {"
|
||||
+ " gl_Position = u_mvp * a_position;"
|
||||
+ " if (u_mode == 0)"
|
||||
// roof / depth pass
|
||||
+ " color = u_color;"
|
||||
+ " else if (u_mode == 1)"
|
||||
// sides 1 - use 0xff00
|
||||
+ " color = vec4(u_color.rgb * (a_light.y / ff), 0.8);"
|
||||
+ " else"
|
||||
// sides 2 - use 0x00ff
|
||||
+ " color = vec4(u_color.rgb * (a_light.x / ff), 0.8);"
|
||||
+ "}";
|
||||
|
||||
final static String buildingFragmentShader = ""
|
||||
+ "precision lowp float;"
|
||||
+ "varying vec4 color;"
|
||||
+ "void main() {"
|
||||
+ " gl_FragColor = color;"
|
||||
+ "}";
|
||||
}
|
@ -116,9 +116,7 @@ public abstract class RenderOverlay {
|
||||
}
|
||||
|
||||
for (Layer l = layers.textureLayers; l != null;) {
|
||||
|
||||
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv,
|
||||
layers.texOffset);
|
||||
l = TextureRenderer.draw(l, (mMapPosition.scale / pos.scale) * div, proj, mv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,6 +179,10 @@
|
||||
<line stroke="#9aabae" width="1.0" fixed="true" cap="butt"/>
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="hospital" zoom-min="14">
|
||||
<area fill="#f0f0d8" />
|
||||
</rule>
|
||||
|
||||
<rule e="way" k="*" v="parking" zoom-min="14">
|
||||
<area fill="#f4f4f4" stroke="#d4d4d4" stroke-width="0.2" />
|
||||
</rule>
|
||||
@ -472,7 +476,7 @@
|
||||
<!-- building -->
|
||||
<rule e="way" k="building" v="*">
|
||||
|
||||
<rule e="way" k="*" v="*" zoom-min="15">
|
||||
<rule e="way" k="*" v="*" zoom-min="15" zoom-max="16">
|
||||
<use-area name="building" fade="15"/>
|
||||
<use-line name="building" fade="15"/>
|
||||
<!-- <line stroke="#c9c3c1" width="1.0" fixed="true" cap="butt" fade="15"/>
|
||||
@ -926,6 +930,11 @@
|
||||
<rule e="way" k="debug" v="box">
|
||||
<line stroke="#000000" width="1.5" fixed="true" cap="butt" />
|
||||
</rule>
|
||||
|
||||
<!-- HACK!!! render building models last -->
|
||||
<rule e="way" k="building" v="*" zoom-min="17">
|
||||
<use-area name="building" fade="15"/>
|
||||
</rule>
|
||||
</rule>
|
||||
|
||||
<rule e="node" k="*" v="*">
|
||||
|
@ -45,7 +45,7 @@ import org.oscim.overlay.OverlayManager;
|
||||
import org.oscim.renderer.GLRenderer;
|
||||
import org.oscim.renderer.GLView;
|
||||
import org.oscim.renderer.TileManager;
|
||||
import org.oscim.renderer.overlays.BuildingOverlay;
|
||||
import org.oscim.renderer.overlays.BuildingOverlay2;
|
||||
import org.oscim.theme.ExternalRenderTheme;
|
||||
import org.oscim.theme.InternalRenderTheme;
|
||||
import org.oscim.theme.RenderTheme;
|
||||
@ -184,9 +184,9 @@ public class MapView extends RelativeLayout {
|
||||
mMapZoomControls.setShowMapZoomControls(true);
|
||||
enableRotation = true;
|
||||
|
||||
mOverlayManager.add(new LabelingOverlay(this));
|
||||
//mOverlayManager.add(new GenericOverlay(this, new GridOverlay(this)));
|
||||
mOverlayManager.add(new GenericOverlay(this, new BuildingOverlay(this)));
|
||||
mOverlayManager.add(new GenericOverlay(this, new BuildingOverlay2(this)));
|
||||
mOverlayManager.add(new LabelingOverlay(this));
|
||||
|
||||
// mOverlayManager.add(new GenericOverlay(this, new TestOverlay(this)));
|
||||
|
||||
|
58
src/org/quake/triangle/TriangleJNI.java
Normal file
58
src/org/quake/triangle/TriangleJNI.java
Normal file
@ -0,0 +1,58 @@
|
||||
package org.quake.triangle;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
public class TriangleJNI {
|
||||
public TriangleJNI() {
|
||||
|
||||
}
|
||||
|
||||
// private static boolean initialized = false;
|
||||
//
|
||||
// private static ShortBuffer sBuf;
|
||||
// private static FloatBuffer fBuf;
|
||||
//
|
||||
// public static synchronized int triangulate(float[] points, int pos, int len, short[] indices) {
|
||||
//
|
||||
// int numRings = 1;
|
||||
//
|
||||
// if (!initialized) {
|
||||
// fBuf = ByteBuffer.allocateDirect(360 * 4).order(ByteOrder.nativeOrder())
|
||||
// .asFloatBuffer();
|
||||
// sBuf = ByteBuffer.allocateDirect(360 * 2).order(ByteOrder.nativeOrder())
|
||||
// .asShortBuffer();
|
||||
// initialized = true;
|
||||
// }
|
||||
//
|
||||
// fBuf.clear();
|
||||
// fBuf.put(points, pos, len);
|
||||
//
|
||||
// sBuf.clear();
|
||||
// sBuf.put((short) (len >> 1)); // all points
|
||||
// sBuf.put((short) (len >> 1)); // outer ring
|
||||
// //sBuf.put((short)4); // inner ring
|
||||
//
|
||||
// int numTris = TriangleJNI.triangulate(fBuf, numRings, sBuf);
|
||||
// if (numTris > 100)
|
||||
// Log.d("triangle", "Triangles: " + numTris);
|
||||
//
|
||||
// sBuf.limit(numTris * 3);
|
||||
// sBuf.position(0);
|
||||
//
|
||||
// // for(int i = 0; i < numTris * 3; i+=3){
|
||||
// // Log.d("triangle", ">>" + sBuf.get()+ " "+ sBuf.get() + " "+ sBuf.get());
|
||||
// // }
|
||||
//
|
||||
// sBuf.get(indices, 0, numTris * 3);
|
||||
//
|
||||
// return numTris * 3;
|
||||
// }
|
||||
|
||||
public static native int triangulate(FloatBuffer points, int length, ShortBuffer result,
|
||||
int ioffset);
|
||||
|
||||
static {
|
||||
System.loadLibrary("triangle-jni");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user