From f32aa5d431a0d16de12cc445dbaf4f6d8a11ab51 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Mon, 23 Jul 2012 17:07:32 +0200 Subject: [PATCH] add client-side triangulator, not enabled yet --- .../android/glrenderer/DatabaseRenderer.java | 7 + .../android/glrenderer/GLMapTile.java | 1 + .../mapsforge/android/glrenderer/Layer.java | 2 +- .../android/glrenderer/LineLayer.java | 37 +- .../android/glrenderer/MapRenderer.java | 322 ++++++++++++------ .../android/glrenderer/MeshLayer.java | 75 ++++ .../android/glrenderer/MeshLayers.java | 150 ++++++++ .../android/glrenderer/PolygonLayer.java | 30 +- .../android/glrenderer/SymbolLayer.java | 19 ++ 9 files changed, 509 insertions(+), 134 deletions(-) create mode 100644 src/org/mapsforge/android/glrenderer/MeshLayer.java create mode 100644 src/org/mapsforge/android/glrenderer/MeshLayers.java create mode 100644 src/org/mapsforge/android/glrenderer/SymbolLayer.java diff --git a/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java b/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java index c3bcf921..459dd41a 100644 --- a/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java +++ b/src/org/mapsforge/android/glrenderer/DatabaseRenderer.java @@ -75,6 +75,7 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback, private LineLayers mLineLayers; private PolygonLayers mPolyLayers; + private MeshLayers mMeshLayers; private int mDrawingLayer; private int mLevels; @@ -316,6 +317,9 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback, PolygonLayer l = mPolyLayers.getLayer(mDrawingLayer + area.level, area.color, area.fade); + // MeshLayer l = mMeshLayers.getLayer(mDrawingLayer + area.level, area.color, + // area.fade); + for (int i = 0, pos = 0, n = mWays.length; i < n; i++) { int length = mWays[i]; // need at least three points @@ -324,6 +328,7 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback, pos += length; } + } @Override @@ -386,8 +391,10 @@ public class DatabaseRenderer implements MapGenerator, RenderCallback, mLineLayers = new LineLayers(); mPolyLayers = new PolygonLayers(); + mMeshLayers = new MeshLayers(); mCurrentTile.lineLayers = mLineLayers; mCurrentTile.polygonLayers = mPolyLayers; + mCurrentTile.meshLayers = mMeshLayers; firstMatch = true; mMapDatabase.executeQuery(mCurrentTile, this); diff --git a/src/org/mapsforge/android/glrenderer/GLMapTile.java b/src/org/mapsforge/android/glrenderer/GLMapTile.java index 223e912f..317a8795 100644 --- a/src/org/mapsforge/android/glrenderer/GLMapTile.java +++ b/src/org/mapsforge/android/glrenderer/GLMapTile.java @@ -24,6 +24,7 @@ class GLMapTile extends MapTile { LineLayers lineLayers; PolygonLayers polygonLayers; + MeshLayers meshLayers; boolean newData; boolean loading; diff --git a/src/org/mapsforge/android/glrenderer/Layer.java b/src/org/mapsforge/android/glrenderer/Layer.java index af2f1709..e7d3de3b 100644 --- a/src/org/mapsforge/android/glrenderer/Layer.java +++ b/src/org/mapsforge/android/glrenderer/Layer.java @@ -39,7 +39,7 @@ class Layer { colors[3] = (color >> 24 & 0xff) / 255.0f; } - float[] getNextItem() { + float[] getNextPoolItem() { curItem.used = PoolItem.SIZE; curItem = LayerPool.get(); pool.add(curItem); diff --git a/src/org/mapsforge/android/glrenderer/LineLayer.java b/src/org/mapsforge/android/glrenderer/LineLayer.java index 933e0b0c..085a3e95 100644 --- a/src/org/mapsforge/android/glrenderer/LineLayer.java +++ b/src/org/mapsforge/android/glrenderer/LineLayer.java @@ -44,10 +44,9 @@ class LineLayer extends Layer { outlines.add(link); } - // private void addVertex(float x, float y, byte tex, byte[] c){ - // // - // } - + /* + * line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj + */ void addLine(float[] pointArray, int pos, int length, float w, boolean capRound) { float x, y, nextX, nextY, prevX, prevY, ux, uy, vx, vy, wx, wy; double a; @@ -64,7 +63,7 @@ class LineLayer extends Layer { int vertexPos = curItem.used; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -105,7 +104,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 1.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -115,7 +114,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 1.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -125,7 +124,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 1.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -136,7 +135,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -163,7 +162,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -173,7 +172,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -244,7 +243,7 @@ class LineLayer extends Layer { uyw = uy * w; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -254,7 +253,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -304,7 +303,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -314,7 +313,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -325,7 +324,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = -1.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -336,7 +335,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = -1.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -360,7 +359,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } @@ -371,7 +370,7 @@ class LineLayer extends Layer { curVertices[vertexPos++] = 0.0f; if (vertexPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); vertexPos = 0; } diff --git a/src/org/mapsforge/android/glrenderer/MapRenderer.java b/src/org/mapsforge/android/glrenderer/MapRenderer.java index 57800a04..d15bdeaa 100644 --- a/src/org/mapsforge/android/glrenderer/MapRenderer.java +++ b/src/org/mapsforge/android/glrenderer/MapRenderer.java @@ -164,9 +164,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } private void updateTileDistances() { + int h = (Tile.TILE_SIZE >> 1); byte zoom = mMapPosition.zoomLevel; - long x = mTileX * (Tile.TILE_SIZE); // - (Tile.TILE_SIZE >> 1); - long y = mTileY * (Tile.TILE_SIZE); // - (Tile.TILE_SIZE >> 1); + long x = mTileX * (Tile.TILE_SIZE) + h; + long y = mTileY * (Tile.TILE_SIZE) + h; int diff; long dx, dy; @@ -178,26 +179,26 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { if (diff != 0) { if (diff > 0) { // tile zoom level is child of current - dx = (t.pixelX >> diff) - x; - dy = (t.pixelY >> diff) - y; + dx = ((t.pixelX + h) >> diff) - x; + dy = ((t.pixelY + h) >> diff) - y; } else { // tile zoom level is parent of current - dx = (t.pixelX << -diff) - x; - dy = (t.pixelY << -diff) - y; + dx = ((t.pixelX + h) << -diff) - x; + dy = ((t.pixelY + h) << -diff) - y; } if (diff == -1) { - // load parent before current layer (kind of progressive transmission :) dy *= mAspect; t.distance = 2 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)); } else { + // load parent before current layer (kind of progressive transmission :) t.distance = ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)); // prefer lower zoom level, i.e. it covers a larger area t.distance *= (1 + (diff > 0 ? diff * 4 : -diff * 2)); } } else { - dx = t.pixelX - x; - dy = t.pixelY - y; + dx = (t.pixelX + h) - x; + dy = (t.pixelY + h) - y; dy *= mAspect; t.distance = (1 + ((dx > 0 ? dx : -dx) + (dy > 0 ? dy : -dy)));// * 2; } @@ -307,10 +308,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { long pixelLeft = (long) x - offsetX; long pixelTop = (long) y - offsetY; - long tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel); - long tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel); - long tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel); - long tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel); + long tileLeft = MercatorProjection.pixelXToTileX(pixelLeft, zoomLevel) - 1; + long tileTop = MercatorProjection.pixelYToTileY(pixelTop, zoomLevel) - 1; + long tileRight = MercatorProjection.pixelXToTileX(pixelRight, zoomLevel) + 1; + long tileBottom = MercatorProjection.pixelYToTileY(pixelBottom, zoomLevel) + 1; mJobList.clear(); mJobParameter = mMapView.getJobParameters(); @@ -321,9 +322,19 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { return false; int max = newTiles.tiles.length - 1; + long limit = (long) Math.pow(2, zoomLevel) - 1; - for (long tileY = tileTop - 1; tileY <= tileBottom + 1; tileY++) { - for (long tileX = tileLeft - 1; tileX <= tileRight + 1; tileX++) { + if (tileTop < 0) + tileTop = 0; + if (tileLeft < 0) + tileLeft = 0; + if (tileBottom >= limit) + tileBottom = limit; + if (tileRight >= limit) + tileRight = limit; + + for (long tileY = tileTop; tileY <= tileBottom; tileY++) { + for (long tileX = tileLeft; tileX <= tileRight; tileX++) { // FIXME if (tiles == max) break; @@ -553,7 +564,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } private boolean drawPolygons(GLMapTile tile, int diff) { - float scale, x, y, z = 1; + int cnt = 0; if (tile.polygonLayers == null || tile.polygonLayers.array == null) return true; @@ -574,24 +585,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - if (diff == 0) { - scale = (float) (mDrawScale * 2.0 / mHeight); - x = (float) (mDrawX - tile.x); - y = (float) (tile.y - mDrawY); - } else { - z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); - scale = (float) (mDrawScale * 2.0 / mHeight / z); - x = (float) (mDrawX * z - tile.x); - y = (float) (tile.y - mDrawY * z); - } - - int cnt = 0; - - mMVPMatrix[12] = -x * (scale * mAspect); - mMVPMatrix[13] = -y * (scale); - mMVPMatrix[0] = (scale * mAspect); - mMVPMatrix[5] = (scale); - + setMatrix(tile, diff); GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); boolean firstPass = true; @@ -611,11 +605,11 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { else { // clear stencilbuffer GLES20.glStencilMask(0xFF); - // GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); + GLES20.glClear(GLES20.GL_STENCIL_BUFFER_BIT); // clear stencilbuffer (tile region) - GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + // GLES20.glStencilOp(GLES20.GL_ZERO, GLES20.GL_ZERO, GLES20.GL_ZERO); + // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); } // stencil op for stencil method polygon drawing @@ -646,8 +640,45 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { return true; } + private boolean drawTriangles(GLMapTile tile, int diff) { + + if (tile.meshLayers == null || tile.meshLayers.array == null) + return true; + + GLES20.glScissor(tile.sx, tile.sy, tile.sw, tile.sh); + + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); + + if (useHalfFloat) { + GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + OES_HALF_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } else { + GLES20.glVertexAttribPointer(gPolygonVertexPositionHandle, 2, + GLES20.GL_FLOAT, false, 0, + POLYGON_VERTICES_DATA_POS_OFFSET); + } + + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); + + setMatrix(tile, diff); + GLES20.glUniformMatrix4fv(gPolygonMatrixHandle, 1, false, mMVPMatrix, 0); + + MeshLayer[] layers = tile.meshLayers.array; + + for (int i = 0, n = layers.length; i < n; i++) { + MeshLayer l = layers[i]; + GLES20.glUniform4fv(gPolygonColorHandle, 1, l.colors, 0); + + // GLES20.glUniform4f(gPolygonColorHandle, 1, 0, 0, 1); + + // System.out.println("draw: " + l.offset + " " + l.verticesCnt); + GLES20.glDrawArrays(GLES20.GL_TRIANGLES, l.offset, l.verticesCnt); + } + return true; + } + private boolean drawLines(GLMapTile tile, int diff) { - float x, y, scale; float z = 1; if (tile.lineLayers == null || tile.lineLayers.array == null) @@ -672,22 +703,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - if (diff == 0) { - scale = (float) (mDrawScale * 2.0 / mHeight); - x = (float) (mDrawX - tile.x); - y = (float) (tile.y - mDrawY); - } else { + if (diff != 0) z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); - scale = (float) (mDrawScale * 2.0 / mHeight / z); - x = (float) (mDrawX * z - tile.x); - y = (float) (tile.y - mDrawY * z); - } - - mMVPMatrix[12] = -x * (scale * mAspect); - mMVPMatrix[13] = -y * (scale); - mMVPMatrix[0] = (scale * mAspect); - mMVPMatrix[5] = (scale); + setMatrix(tile, diff); GLES20.glUniformMatrix4fv(gLineMatrixHandle, 1, false, mMVPMatrix, 0); LineLayer[] layers = tile.lineLayers.array; @@ -750,6 +769,27 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { return true; } + private void setMatrix(GLMapTile tile, int diff) { + float x, y, scale; + float z = 1; + + if (diff == 0) { + scale = (float) (mDrawScale * 2.0 / mHeight); + x = (float) (mDrawX - tile.x); + y = (float) (tile.y - mDrawY); + } else { + z = (diff > 0) ? (1 << diff) : 1.0f / (1 << -diff); + scale = (float) (mDrawScale * 2.0 / mHeight / z); + x = (float) (mDrawX * z - tile.x); + y = (float) (tile.y - mDrawY * z); + } + + mMVPMatrix[12] = -x * (scale * mAspect); + mMVPMatrix[13] = -y * (scale); + mMVPMatrix[0] = (scale * mAspect); + mMVPMatrix[5] = (scale); + } + private boolean setTileScissor(GLMapTile tile, float div) { double dx, dy, scale; @@ -868,15 +908,49 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } - // private int uploadCnt; + private void drawProxyTriangles(GLMapTile tile) { + if (tile.parent != null && tile.parent.isDrawn) { + tile.parent.sx = tile.sx; + tile.parent.sy = tile.sy; + tile.parent.sw = tile.sw; + tile.parent.sh = tile.sh; + drawTriangles(tile.parent, -1); + } else { + int drawn = 0; + + for (int i = 0; i < 4; i++) { + GLMapTile c = tile.child[i]; + + if (c != null && c.isDrawn && setTileScissor(c, 2)) { + drawTriangles(c, 1); + drawn++; + } + } + + if (drawn < 4 && tile.parent != null) { + GLMapTile p = tile.parent.parent; + if (p != null && p.isDrawn) { + p.sx = tile.sx; + p.sy = tile.sy; + p.sw = tile.sw; + p.sh = tile.sh; + drawTriangles(p, -2); + } + } + } + } + + private boolean mTriangulate = false; + + private int uploadCnt = 0; private boolean uploadTileData(GLMapTile tile) { // not sure about this, but seems it fixes some flickering when // multiple tiles are uploaded in one go. but if this is really // the issue tiles should stay corrupted.. - // if (uploadCnt++ > 0) - // GLES20.glFinish(); + if (uploadCnt++ > 0) + GLES20.glFinish(); if (tile.lineVBO == null) { // Upload line data to vertex buffer object @@ -915,33 +989,64 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { tile.lineLayers = null; } - if (useHalfFloat) - shortBuffer = tile.polygonLayers.compileLayerData(shortBuffer); - else - floatBuffer = tile.polygonLayers.compileLayerData(floatBuffer); + if (!mTriangulate) { + if (useHalfFloat) + shortBuffer = tile.polygonLayers.compileLayerData(shortBuffer); + else + floatBuffer = tile.polygonLayers.compileLayerData(floatBuffer); - // Upload polygon data to vertex buffer object - if (tile.polygonLayers.size > 0) { - mBufferMemoryUsage -= tile.polygonVBO.size; + // Upload polygon data to vertex buffer object + if (tile.polygonLayers.size > 0) { + mBufferMemoryUsage -= tile.polygonVBO.size; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, GLES20.GL_STATIC_DRAW); + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, + GLES20.GL_STATIC_DRAW); + + if (useHalfFloat) { + tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES; + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, + shortBuffer, GLES20.GL_STATIC_DRAW); + } else { + tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES; + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, + floatBuffer, GLES20.GL_STATIC_DRAW); + } + mBufferMemoryUsage += tile.polygonVBO.size; - if (useHalfFloat) { - tile.polygonVBO.size = tile.polygonLayers.size * SHORT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - shortBuffer, GLES20.GL_STATIC_DRAW); } else { - tile.polygonVBO.size = tile.polygonLayers.size * FLOAT_BYTES; - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, - floatBuffer, GLES20.GL_STATIC_DRAW); + tile.polygonLayers = null; } - mBufferMemoryUsage += tile.polygonVBO.size; - - } else { - tile.polygonLayers = null; } + else { + if (useHalfFloat) + shortBuffer = tile.meshLayers.compileLayerData(shortBuffer); + else + floatBuffer = tile.meshLayers.compileLayerData(floatBuffer); + // Upload triangle data to vertex buffer object + if (tile.meshLayers.size > 0) { + mBufferMemoryUsage -= tile.polygonVBO.size; + + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.id); + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 0, null, + GLES20.GL_STATIC_DRAW); + + if (useHalfFloat) { + tile.polygonVBO.size = tile.meshLayers.size * SHORT_BYTES; + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, + shortBuffer, GLES20.GL_STATIC_DRAW); + } else { + tile.polygonVBO.size = tile.meshLayers.size * FLOAT_BYTES; + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, tile.polygonVBO.size, + floatBuffer, GLES20.GL_STATIC_DRAW); + } + mBufferMemoryUsage += tile.polygonVBO.size; + + } else { + tile.meshLayers = null; + } + } tile.newData = false; tile.isDrawn = true; tile.isLoading = false; @@ -964,7 +1069,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { GLES20.glStencilMask(0xFF); GLES20.glDisable(GLES20.GL_SCISSOR_TEST); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT); - GLES20.glFlush(); + // GLES20.glFlush(); // long endTime = SystemClock.uptimeMillis(); // long dt = endTime - startTime; @@ -1018,7 +1123,7 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { CACHE_TILES += 50; } - // uploadCnt = 0; + uploadCnt = 0; // check visible tiles, set tile clip scissors, upload new vertex data for (int i = 0; i < tileCnt; i++) { @@ -1054,46 +1159,64 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { } } // GLES20.glFinish(); + GlUtils.checkGlError("upload"); if (timing) clear_time = (SystemClock.uptimeMillis() - start); GLES20.glEnable(GLES20.GL_SCISSOR_TEST); - GLES20.glDisable(GLES20.GL_BLEND); - - // Draw Polygons - GLES20.glEnable(GLES20.GL_STENCIL_TEST); GLES20.glUseProgram(gPolygonProgram); - GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); + // GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); - for (int i = 0; i < tileCnt; i++) { - if (tiles[i].isVisible) { - GLMapTile tile = tiles[i]; + if (!mTriangulate) { + GLES20.glDisable(GLES20.GL_BLEND); + // Draw Polygons + GLES20.glEnable(GLES20.GL_STENCIL_TEST); - if (tile.isDrawn) - drawPolygons(tile, 0); - else - drawProxyPolygons(tile); + // GLES20.glEnableVertexAttribArray(gPolygonVertexPositionHandle); + + for (int i = 0; i < tileCnt; i++) { + if (tiles[i].isVisible) { + GLMapTile tile = tiles[i]; + + if (tile.isDrawn) + drawPolygons(tile, 0); + else + drawProxyPolygons(tile); + } } - } + GlUtils.checkGlError("polygons"); + GLES20.glDisable(GLES20.GL_STENCIL_TEST); + } else { + // Draw Triangles + for (int i = 0; i < tileCnt; i++) { + if (tiles[i].isVisible) { + GLMapTile tile = tiles[i]; - GLES20.glDisable(GLES20.GL_STENCIL_TEST); + if (tile.isDrawn) + drawTriangles(tile, 0); + else + drawProxyTriangles(tile); + } + } + GlUtils.checkGlError("triangles"); + } // required on GalaxyII, Android 2.3.3 - GLES20.glDisableVertexAttribArray(gPolygonVertexPositionHandle); + // GLES20.glDisableVertexAttribArray(gPolygonVertexPositionHandle); if (timing) { GLES20.glFinish(); poly_time = (SystemClock.uptimeMillis() - start); } - // GLES20.glFlush(); + GLES20.glFlush(); // Draw lines GLES20.glEnable(GLES20.GL_BLEND); GLES20.glUseProgram(gLineProgram); - GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle); - GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle); + // GLES20.glEnableVertexAttribArray(gLineVertexPositionHandle); + // GLES20.glEnableVertexAttribArray(gLineTexturePositionHandle); for (int i = 0; i < tileCnt; i++) { if (tiles[i].isVisible) { @@ -1111,9 +1234,10 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start) + " " + clear_time + " " + poly_time); } - GLES20.glDisableVertexAttribArray(gLineVertexPositionHandle); - GLES20.glDisableVertexAttribArray(gLineTexturePositionHandle); - + // GLES20.glDisableVertexAttribArray(gLineVertexPositionHandle); + // GLES20.glDisableVertexAttribArray(gLineTexturePositionHandle); + GlUtils.checkGlError("lines"); + GLES20.glFinish(); } private int[] mVboIds; @@ -1220,6 +1344,8 @@ public class MapRenderer implements org.mapsforge.android.MapRenderer { GLES20.glDisable(GLES20.GL_DITHER); GLES20.glClearColor(0.98f, 0.98f, 0.97f, 1.0f); GLES20.glClearStencil(0); + + // GLES20.glFrontFace(GLES20.GL_CCW); } @Override diff --git a/src/org/mapsforge/android/glrenderer/MeshLayer.java b/src/org/mapsforge/android/glrenderer/MeshLayer.java new file mode 100644 index 00000000..614e832c --- /dev/null +++ b/src/org/mapsforge/android/glrenderer/MeshLayer.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010, 2011, 2012 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.mapsforge.android.glrenderer; + +import java.util.LinkedList; + +import org.poly2tri.Poly2Tri; +import org.poly2tri.geometry.polygon.Polygon; +import org.poly2tri.geometry.polygon.PolygonPoint; +import org.poly2tri.triangulation.delaunay.DelaunayTriangle; + +public class MeshLayer extends Layer { + + MeshLayer(int l, int color) { + super(l, color); + + curItem = LayerPool.get(); + pool = new LinkedList(); + pool.add(curItem); + } + + void addPolygon(float[] points, int position, int length) { + float[] curVertices = curItem.vertices; + int outPos = curItem.used; + + int len = length / 2 - 1; + int pos = position; + + PolygonPoint[] pp = new PolygonPoint[len]; + + for (int i = 0; i < len; i++) { + pp[i] = new PolygonPoint(points[pos++], points[pos++]); + } + + Polygon poly = new Polygon(pp); + + Poly2Tri.triangulate(poly); + + for (DelaunayTriangle tri : poly.getTriangles()) { + + for (int i = 0; i < 3; i++) { + + if (outPos == PoolItem.SIZE) { + curVertices = getNextPoolItem(); + outPos = 0; + } + + curVertices[outPos++] = (float) tri.points[i].getX(); + curVertices[outPos++] = (float) tri.points[i].getY(); + + } + // System.out.println("" + + // (float) tri.points[0].getX() + "/" + (float) tri.points[0].getY() + // + ", " + + // (float) tri.points[1].getX() + "/" + (float) tri.points[1].getY() + // + ", " + + // (float) tri.points[2].getX() + "/" + (float) tri.points[2].getY()); + } + // System.out.println("---"); + curItem.used = outPos; + verticesCnt += poly.getTriangles().size() * 3; + } +} diff --git a/src/org/mapsforge/android/glrenderer/MeshLayers.java b/src/org/mapsforge/android/glrenderer/MeshLayers.java new file mode 100644 index 00000000..b97f6556 --- /dev/null +++ b/src/org/mapsforge/android/glrenderer/MeshLayers.java @@ -0,0 +1,150 @@ +/* + * Copyright 2010, 2011, 2012 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.mapsforge.android.glrenderer; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.ShortBuffer; + +import android.util.SparseArray; + +public class MeshLayers { + private static final int NUM_VERTEX_FLOATS = 2; + + private SparseArray layers; + + MeshLayer[] array = null; + int size; + + MeshLayers() { + layers = new SparseArray(10); + size = 0; + } + + MeshLayer getLayer(int layer, int color, int fade) { + MeshLayer l = layers.get(layer); + if (l != null) { + return l; + } + + l = new MeshLayer(layer, color); + layers.put(layer, l); + return l; + } + + FloatBuffer compileLayerData(FloatBuffer buf) { + FloatBuffer fbuf = buf; + + array = new MeshLayer[layers.size()]; + + for (int i = 0, n = layers.size(); i < n; i++) { + MeshLayer l = layers.valueAt(i); + array[i] = l; + size += l.verticesCnt; + } + + size *= NUM_VERTEX_FLOATS; + + if (buf == null || buf.capacity() < size) { + ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 4).order( + ByteOrder.nativeOrder()); + // Log.d("GLMap", "allocate buffer " + size); + fbuf = bbuf.asFloatBuffer(); + } else { + fbuf.position(0); + } + + int pos = 0; + + for (int i = 0, n = array.length; i < n; i++) { + MeshLayer l = array[i]; + + for (PoolItem item : l.pool) { + fbuf.put(item.vertices, 0, item.used); + + // for (int j = 0; j < item.used; j++) + // System.out.println(">" + item.vertices[j]); + } + + l.offset = pos; + pos += l.verticesCnt; + + LayerPool.add(l.pool); + l.pool = null; + } + + fbuf.position(0); + // for (int i = 0; i < size; i++) + // System.out.println("<" + fbuf.get()); + // fbuf.position(0); + // System.out.println("....... mesh layer size: " + size + " " + array.length); + + // not needed for drawing + layers = null; + + return fbuf; + } + + ShortBuffer compileLayerData(ShortBuffer buf) { + ShortBuffer sbuf = buf; + + array = new MeshLayer[layers.size()]; + + for (int i = 0, n = layers.size(); i < n; i++) { + MeshLayer l = layers.valueAt(i); + array[i] = l; + size += l.verticesCnt; + } + + size *= NUM_VERTEX_FLOATS; + + if (buf == null || buf.capacity() < size) { + ByteBuffer bbuf = ByteBuffer.allocateDirect(size * 2).order( + ByteOrder.nativeOrder()); + sbuf = bbuf.asShortBuffer(); + } else { + sbuf.position(0); + } + + short[] data = new short[PoolItem.SIZE]; + + int pos = 0; + + for (int i = 0, n = array.length; i < n; i++) { + MeshLayer l = array[i]; + + for (int k = 0, m = l.pool.size(); k < m; k++) { + PoolItem item = l.pool.get(k); + PoolItem.toHalfFloat(item, data); + sbuf.put(data, 0, item.used); + } + + l.offset = pos; + pos += l.verticesCnt; + + LayerPool.add(l.pool); + l.pool = null; + } + + // System.out.println("....... mesh layer size: " + size + " " + array.length); + sbuf.position(0); + + // not needed for drawing + layers = null; + + return sbuf; + } +} diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayer.java b/src/org/mapsforge/android/glrenderer/PolygonLayer.java index 10631ba1..d8890fb3 100644 --- a/src/org/mapsforge/android/glrenderer/PolygonLayer.java +++ b/src/org/mapsforge/android/glrenderer/PolygonLayer.java @@ -16,14 +16,12 @@ package org.mapsforge.android.glrenderer; import java.util.LinkedList; -import org.mapsforge.core.Tile; - class PolygonLayer extends Layer { int fadeLevel; - // private boolean first = true; - // private float originX; - // private float originY; + private boolean first = true; + private float originX; + private float originY; PolygonLayer(int layer, int color, int fade) { super(layer, color); @@ -37,29 +35,29 @@ class PolygonLayer extends Layer { verticesCnt += length / 2 + 2; - // if (first) { - // first = false; - // originX = points[pos]; - // originY = points[pos + 1]; - // } + if (first) { + first = false; + originX = points[pos]; + originY = points[pos + 1]; + } float[] curVertices = curItem.vertices; int outPos = curItem.used; if (outPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); outPos = 0; } - curVertices[outPos++] = Tile.TILE_SIZE >> 1; - curVertices[outPos++] = Tile.TILE_SIZE >> 1; + curVertices[outPos++] = originX; // Tile.TILE_SIZE >> 1; + curVertices[outPos++] = originY; // Tile.TILE_SIZE >> 1; int remaining = length; int inPos = pos; while (remaining > 0) { if (outPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); outPos = 0; } @@ -74,10 +72,10 @@ class PolygonLayer extends Layer { } if (outPos == PoolItem.SIZE) { - curVertices = getNextItem(); + curVertices = getNextPoolItem(); outPos = 0; } - // Float.intBitsToFloat(bits) + curVertices[outPos++] = points[pos + 0]; curVertices[outPos++] = points[pos + 1]; diff --git a/src/org/mapsforge/android/glrenderer/SymbolLayer.java b/src/org/mapsforge/android/glrenderer/SymbolLayer.java new file mode 100644 index 00000000..42b6e13c --- /dev/null +++ b/src/org/mapsforge/android/glrenderer/SymbolLayer.java @@ -0,0 +1,19 @@ +/* + * Copyright 2010, 2011, 2012 mapsforge.org + * + * 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 . + */ +package org.mapsforge.android.glrenderer; + +public class SymbolLayer { + +}