From 18d10e744cd91a175b271bbf371ab3c99d77644e Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Fri, 7 Sep 2012 21:10:09 +0200 Subject: [PATCH] - add multi-linestrings / -polygons in one go --- .../android/glrenderer/GLMapTile.java | 2 +- .../android/glrenderer/LineLayer.java | 748 +++++++++--------- .../android/glrenderer/LineLayers.java | 9 +- .../android/glrenderer/MapGenerator.java | 35 +- .../android/glrenderer/PolygonLayer.java | 152 ++-- .../android/glrenderer/PolygonLayers.java | 9 +- 6 files changed, 491 insertions(+), 464 deletions(-) diff --git a/src/org/mapsforge/android/glrenderer/GLMapTile.java b/src/org/mapsforge/android/glrenderer/GLMapTile.java index a4e63217..4550e985 100644 --- a/src/org/mapsforge/android/glrenderer/GLMapTile.java +++ b/src/org/mapsforge/android/glrenderer/GLMapTile.java @@ -37,7 +37,7 @@ class GLMapTile extends MapTile { boolean newData; - // pointer in TileTree + // pointer to access relatives in TileTree TreeTile rel; GLMapTile(int tileX, int tileY, byte zoomLevel) { diff --git a/src/org/mapsforge/android/glrenderer/LineLayer.java b/src/org/mapsforge/android/glrenderer/LineLayer.java index a8e95633..6cfa9d8d 100644 --- a/src/org/mapsforge/android/glrenderer/LineLayer.java +++ b/src/org/mapsforge/android/glrenderer/LineLayer.java @@ -23,9 +23,9 @@ import android.util.FloatMath; class LineLayer { private static final float COORD_SCALE = MapRenderer.COORD_MULTIPLIER; - // scale factor mapping direction vector to short values + // scale factor mapping extrusion vector to short values private static final float DIR_SCALE = 2048; - // mask for packing last two bits of direction vector with texture coordinates + // mask for packing last two bits of extrusion vector with texture coordinates private static final int DIR_MASK = 0xFFFFFFFC; // next layer @@ -66,11 +66,14 @@ class LineLayer { /* * line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj */ - void addLine(float[] points, int pos, int length) { + + void addLine(float[] points, short[] index) { float x, y, nextX, nextY, prevX, prevY; float a, ux, uy, vx, vy, wx, wy; - int ipos = pos; + int tmax = Tile.TILE_SIZE + 10; + int tmin = -10; + boolean rounded = false; boolean squared = false; @@ -79,30 +82,6 @@ class LineLayer { else if (line.cap == Cap.SQUARE) squared = true; - // amount of vertices used - verticesCnt += length + (rounded ? 6 : 2); - - x = points[ipos++]; - y = points[ipos++]; - - nextX = points[ipos++]; - nextY = points[ipos++]; - - // Calculate triangle corners for the given width - vx = nextX - x; - vy = nextY - y; - - a = FloatMath.sqrt(vx * vx + vy * vy); - - vx = (vx / a); - vy = (vy / a); - - ux = -vy; - uy = vx; - - int tmax = Tile.TILE_SIZE + 10; - int tmin = -10; - if (pool == null) { pool = curItem = ShortPool.get(); } @@ -111,199 +90,273 @@ class LineLayer { short v[] = si.vertices; int opos = si.used; - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } + for (int i = 0, pos = 0, n = index.length; i < n; i++) { + int length = index[i]; + if (length < 0) + break; - short ox, oy, dx, dy; - int ddx, ddy; + // save some vertices + if (rounded && i > 200) + rounded = false; - ox = (short) (x * COORD_SCALE); - oy = (short) (y * COORD_SCALE); + int ipos = pos; - boolean outside = (x < tmin || x > tmax || y < tmin || y > tmax); - - if (rounded && !outside) { - // add first vertex twice - ddx = (int) ((ux - vx) * DIR_SCALE); - ddy = (int) ((uy - vy) * DIR_SCALE); - dx = (short) (0 | ddx & DIR_MASK); - dy = (short) (2 | ddy & DIR_MASK); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; + // need at least two points + if (length < 4) { + pos += length; + continue; } + // amount of vertices used + verticesCnt += length + (rounded ? 6 : 2); - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; + x = points[ipos++]; + y = points[ipos++]; - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - ddx = (int) (-(ux + vx) * DIR_SCALE); - ddy = (int) (-(uy + vy) * DIR_SCALE); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (2 | ddx & DIR_MASK); - v[opos++] = (short) (2 | ddy & DIR_MASK); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - // Start of line - ddx = (int) (ux * DIR_SCALE); - ddy = (int) (uy * DIR_SCALE); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (0 | ddx & DIR_MASK); - v[opos++] = (short) (1 | ddy & DIR_MASK); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (2 | -ddx & DIR_MASK); - v[opos++] = (short) (1 | -ddy & DIR_MASK); - - } else { - // outside means line is probably clipped - // TODO should align ending with tile boundary - // for now, just extend the line a little - - if (squared) { - vx = 0; - vy = 0; - } else if (!outside) { - vx *= 0.5; - vy *= 0.5; - } - - if (rounded) - verticesCnt -= 2; - - // add first vertex twice - ddx = (int) ((ux - vx) * DIR_SCALE); - ddy = (int) ((uy - vy) * DIR_SCALE); - dx = (short) (0 | ddx & DIR_MASK); - dy = (short) (1 | ddy & DIR_MASK); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - ddx = (int) (-(ux + vx) * DIR_SCALE); - ddy = (int) (-(uy + vy) * DIR_SCALE); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (2 | ddx & DIR_MASK); - v[opos++] = (short) (1 | ddy & DIR_MASK); - - } - - prevX = x; - prevY = y; - x = nextX; - y = nextY; - - for (; ipos < pos + length;) { nextX = points[ipos++]; nextY = points[ipos++]; - // Unit vector pointing back to previous node - vx = prevX - x; - vy = prevY - y; + // Calculate triangle corners for the given width + vx = nextX - x; + vy = nextY - y; + a = FloatMath.sqrt(vx * vx + vy * vy); + vx = (vx / a); vy = (vy / a); - // Unit vector pointing forward to next node - wx = nextX - x; - wy = nextY - y; - a = FloatMath.sqrt(wx * wx + wy * wy); - wx = (wx / a); - wy = (wy / a); - - // Sum of these two vectors points - ux = vx + wx; - uy = vy + wy; - - a = -wy * ux + wx * uy; - - // boolean split = false; - if (a < 0.01f && a > -0.01f) { - // Almost straight - ux = -wy; - uy = wx; - } else { - ux = (ux / a); - uy = (uy / a); - - // hack to avoid miter going to infinity - // note to myself: find my mathbook and do this properly! - if (ux > 2.0f || ux < -2.0f || uy > 2.0f || uy < -2.0f) { - ux = -wy; - uy = wx; - } - } + ux = -vy; + uy = vx; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + short ox, oy, dx, dy; + int ddx, ddy; + + ox = (short) (x * COORD_SCALE); + oy = (short) (y * COORD_SCALE); + + boolean outside = (x < tmin || x > tmax || y < tmin || y > tmax); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + if (rounded && !outside) { + // add first vertex twice + ddx = (int) ((ux - vx) * DIR_SCALE); + ddy = (int) ((uy - vy) * DIR_SCALE); + dx = (short) (0 | ddx & DIR_MASK); + dy = (short) (2 | ddy & DIR_MASK); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + ddx = (int) (-(ux + vx) * DIR_SCALE); + ddy = (int) (-(uy + vy) * DIR_SCALE); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (2 | ddx & DIR_MASK); + v[opos++] = (short) (2 | ddy & DIR_MASK); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + // Start of line + ddx = (int) (ux * DIR_SCALE); + ddy = (int) (uy * DIR_SCALE); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (0 | ddx & DIR_MASK); + v[opos++] = (short) (1 | ddy & DIR_MASK); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (2 | -ddx & DIR_MASK); + v[opos++] = (short) (1 | -ddy & DIR_MASK); + + } else { + // outside means line is probably clipped + // TODO should align ending with tile boundary + // for now, just extend the line a little + + if (squared) { + vx = 0; + vy = 0; + } else if (!outside) { + vx *= 0.5; + vy *= 0.5; + } + + if (rounded) + verticesCnt -= 2; + + // add first vertex twice + ddx = (int) ((ux - vx) * DIR_SCALE); + ddy = (int) ((uy - vy) * DIR_SCALE); + dx = (short) (0 | ddx & DIR_MASK); + dy = (short) (1 | ddy & DIR_MASK); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + ddx = (int) (-(ux + vx) * DIR_SCALE); + ddy = (int) (-(uy + vy) * DIR_SCALE); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (2 | ddx & DIR_MASK); + v[opos++] = (short) (1 | ddy & DIR_MASK); + + } + + prevX = x; + prevY = y; + x = nextX; + y = nextY; + + for (; ipos < pos + length;) { + nextX = points[ipos++]; + nextY = points[ipos++]; + + // Unit vector pointing back to previous node + vx = prevX - x; + vy = prevY - y; + a = FloatMath.sqrt(vx * vx + vy * vy); + vx = (vx / a); + vy = (vy / a); + + // Unit vector pointing forward to next node + wx = nextX - x; + wy = nextY - y; + a = FloatMath.sqrt(wx * wx + wy * wy); + wx = (wx / a); + wy = (wy / a); + + // Sum of these two vectors points + ux = vx + wx; + uy = vy + wy; + + a = -wy * ux + wx * uy; + + // boolean split = false; + if (a < 0.01f && a > -0.01f) { + // Almost straight + ux = -wy; + uy = wx; + } else { + ux = (ux / a); + uy = (uy / a); + + // hack to avoid miter going to infinity + if (ux > 2.0f || ux < -2.0f || uy > 2.0f || uy < -2.0f) { + ux = -wy; + uy = wx; + } + } + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + ox = (short) (x * COORD_SCALE); + oy = (short) (y * COORD_SCALE); + + ddx = (int) (ux * DIR_SCALE); + ddy = (int) (uy * DIR_SCALE); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (0 | ddx & DIR_MASK); + v[opos++] = (short) (1 | ddy & DIR_MASK); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (2 | -ddx & DIR_MASK); + v[opos++] = (short) (1 | -ddy & DIR_MASK); + + prevX = x; + prevY = y; + x = nextX; + y = nextY; + } + + vx = prevX - x; + vy = prevY - y; + + a = FloatMath.sqrt(vx * vx + vy * vy); + + vx = (vx / a); + vy = (vy / a); + + ux = vy; + uy = -vx; + + outside = (x < tmin || x > tmax || y < tmin || y > tmax); if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; si.next = ShortPool.get(); si = si.next; opos = 0; @@ -313,181 +366,120 @@ class LineLayer { ox = (short) (x * COORD_SCALE); oy = (short) (y * COORD_SCALE); - ddx = (int) (ux * DIR_SCALE); - ddy = (int) (uy * DIR_SCALE); + if (rounded && !outside) { + ddx = (int) (ux * DIR_SCALE); + ddy = (int) (uy * DIR_SCALE); - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (0 | ddx & DIR_MASK); - v[opos++] = (short) (1 | ddy & DIR_MASK); + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (0 | ddx & DIR_MASK); + v[opos++] = (short) (1 | ddy & DIR_MASK); - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (2 | -ddx & DIR_MASK); + v[opos++] = (short) (1 | -ddy & DIR_MASK); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + // For rounded line edges + ddx = (int) ((ux - vx) * DIR_SCALE); + ddy = (int) ((uy - vy) * DIR_SCALE); + dx = (short) (0 | ddx & DIR_MASK); + dy = (short) (0 | ddy & DIR_MASK); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + // add last vertex twice + ddx = (int) (-(ux + vx) * DIR_SCALE); + ddy = (int) (-(uy + vy) * DIR_SCALE); + dx = (short) (2 | ddx & DIR_MASK); + dy = (short) (0 | ddy & DIR_MASK); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + } else { + if (squared) { + vx = 0; + vy = 0; + } else if (!outside) { + vx *= 0.5; + vy *= 0.5; + } + + if (rounded) + verticesCnt -= 2; + + ddx = (int) ((ux - vx) * DIR_SCALE); + ddy = (int) ((uy - vy) * DIR_SCALE); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = (short) (0 | ddx & DIR_MASK); + v[opos++] = (short) (1 | ddy & DIR_MASK); + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + // add last vertex twice + ddx = (int) (-(ux + vx) * DIR_SCALE); + ddy = (int) (-(uy + vy) * DIR_SCALE); + dx = (short) (2 | ddx & DIR_MASK); + dy = (short) (1 | ddy & DIR_MASK); + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; + + if (opos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + opos = 0; + } + + v[opos++] = ox; + v[opos++] = oy; + v[opos++] = dx; + v[opos++] = dy; } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (2 | -ddx & DIR_MASK); - v[opos++] = (short) (1 | -ddy & DIR_MASK); - - prevX = x; - prevY = y; - x = nextX; - y = nextY; - } - - vx = prevX - x; - vy = prevY - y; - - a = FloatMath.sqrt(vx * vx + vy * vy); - - vx = (vx / a); - vy = (vy / a); - - ux = vy; - uy = -vx; - - outside = (x < tmin || x > tmax || y < tmin || y > tmax); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - ox = (short) (x * COORD_SCALE); - oy = (short) (y * COORD_SCALE); - - if (rounded && !outside) { - ddx = (int) (ux * DIR_SCALE); - ddy = (int) (uy * DIR_SCALE); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (0 | ddx & DIR_MASK); - v[opos++] = (short) (1 | ddy & DIR_MASK); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (2 | -ddx & DIR_MASK); - v[opos++] = (short) (1 | -ddy & DIR_MASK); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - // For rounded line edges - ddx = (int) ((ux - vx) * DIR_SCALE); - ddy = (int) ((uy - vy) * DIR_SCALE); - dx = (short) (0 | ddx & DIR_MASK); - dy = (short) (0 | ddy & DIR_MASK); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - // add last vertex twice - ddx = (int) (-(ux + vx) * DIR_SCALE); - ddy = (int) (-(uy + vy) * DIR_SCALE); - dx = (short) (2 | ddx & DIR_MASK); - dy = (short) (0 | ddy & DIR_MASK); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - } else { - if (squared) { - vx = 0; - vy = 0; - } else if (!outside) { - vx *= 0.5; - vy *= 0.5; - } - - if (rounded) - verticesCnt -= 2; - - ddx = (int) ((ux - vx) * DIR_SCALE); - ddy = (int) ((uy - vy) * DIR_SCALE); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = (short) (0 | ddx & DIR_MASK); - v[opos++] = (short) (1 | ddy & DIR_MASK); - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - // add last vertex twice - ddx = (int) (-(ux + vx) * DIR_SCALE); - ddy = (int) (-(uy + vy) * DIR_SCALE); - dx = (short) (2 | ddx & DIR_MASK); - dy = (short) (1 | ddy & DIR_MASK); - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; - - if (opos == ShortItem.SIZE) { - si.used = ShortItem.SIZE; - si.next = ShortPool.get(); - si = si.next; - opos = 0; - v = si.vertices; - } - - v[opos++] = ox; - v[opos++] = oy; - v[opos++] = dx; - v[opos++] = dy; + pos += length; } si.used = opos; diff --git a/src/org/mapsforge/android/glrenderer/LineLayers.java b/src/org/mapsforge/android/glrenderer/LineLayers.java index 9241dea0..f2241dce 100644 --- a/src/org/mapsforge/android/glrenderer/LineLayers.java +++ b/src/org/mapsforge/android/glrenderer/LineLayers.java @@ -191,7 +191,14 @@ class LineLayers { continue; for (ShortItem item = l.pool; item != null; item = item.next) { - sbuf.put(item.vertices, 0, item.used); + + if (item.next == null) { + sbuf.put(item.vertices, 0, item.used); + } else { + // item.used = ShortItem.SIZE; + sbuf.put(item.vertices); + } + last = item; } diff --git a/src/org/mapsforge/android/glrenderer/MapGenerator.java b/src/org/mapsforge/android/glrenderer/MapGenerator.java index 7541c70d..b3578cf2 100644 --- a/src/org/mapsforge/android/glrenderer/MapGenerator.java +++ b/src/org/mapsforge/android/glrenderer/MapGenerator.java @@ -351,26 +351,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas mCurLineLayer = lineLayer; - boolean round = line.round; - - for (int i = 0, pos = 0, n = mWays.length; i < n; i++) { - int length = mWays[i]; - if (length < 0) - break; - - // save some vertices - if (round && i > 200) { - // Log.d(TAG, "WAY TOO MANY LINES!!!"); - round = false; - } - // need at least two points - if (length >= 4) { - lineLayer.addLine(mWayNodes, pos, length); - countLines++; - countNodes += length; - } - pos += length; - } + lineLayer.addLine(mWayNodes, mWays); } @Override @@ -415,19 +396,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas mCurPolyLayer = layer; - for (int i = 0, pos = 0, n = mWays.length; i < n; i++) { - int length = mWays[i]; - if (length < 0) - break; - - // need at least three points - if (length >= 6) - layer.addPolygon(mWayNodes, pos, length); - - pos += length; - } - - // if (area.line != null) + layer.addPolygon(mWayNodes, mWays); } @Override diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayer.java b/src/org/mapsforge/android/glrenderer/PolygonLayer.java index abe5636c..64e28f83 100644 --- a/src/org/mapsforge/android/glrenderer/PolygonLayer.java +++ b/src/org/mapsforge/android/glrenderer/PolygonLayer.java @@ -24,8 +24,8 @@ class PolygonLayer { Area area; // private static final float MapRenderer.COORD_MULTIPLIER = 8.0f; private boolean first = true; - private float originX; - private float originY; + private short originX; + private short originY; ShortItem pool; protected ShortItem curItem; @@ -41,69 +41,121 @@ class PolygonLayer { pool = curItem; } - short[] getNextItem() { - curItem.used = ShortItem.SIZE; + // short[] getNextItem() { + // curItem.used = ShortItem.SIZE; + // curItem.next = ShortPool.get(); + // curItem = curItem.next; + // + // return curItem.vertices; + // } + // + // void addPolygon(float[] points, int pos, int length) { + // + // verticesCnt += length / 2 + 2; + // + // if (first) { + // first = false; + // originX = (short) ((Tile.TILE_SIZE >> 1) * S); + // originY = (short) ((Tile.TILE_SIZE >> 1) * S); + // } + // + // short[] curVertices = curItem.vertices; + // int outPos = curItem.used; + // + // if (outPos == ShortItem.SIZE) { + // curVertices = getNextItem(); + // outPos = 0; + // } + // + // curVertices[outPos++] = originX; + // curVertices[outPos++] = originY; + // + // int MAX = ShortItem.SIZE; + // int remaining = length; + // int inPos = pos; + // while (remaining > 0) { + // + // if (outPos == MAX) { + // curVertices = getNextItem(); + // outPos = 0; + // } + // + // int len = remaining; + // if (len > MAX - outPos) + // len = MAX - outPos; + // + // for (int i = 0; i < len; i++) + // curVertices[outPos++] = (short) (points[inPos++] * S); + // + // remaining -= len; + // } + // + // if (outPos == MAX) { + // curVertices = getNextItem(); + // outPos = 0; + // } + // + // curVertices[outPos++] = (short) (points[pos + 0] * S); + // curVertices[outPos++] = (short) (points[pos + 1] * S); + // + // curItem.used = outPos; + // } - curItem.next = ShortPool.get(); - curItem = curItem.next; + void addPolygon(float[] points, short[] index) { + short center = (short) ((Tile.TILE_SIZE >> 1) * S); - return curItem.vertices; - } + ShortItem si = curItem; + short[] v = si.vertices; + int outPos = si.used; - void addPolygon(float[] points, int pos, int length) { + for (int i = 0, pos = 0, n = index.length; i < n; i++) { + int length = index[i]; + if (length < 0) + break; - verticesCnt += length / 2 + 2; + // need at least three points + if (length < 6) { + pos += length; + continue; + } - if (first) { - first = false; - originX = Tile.TILE_SIZE >> 1; // points[pos]; - originY = Tile.TILE_SIZE >> 1; // points[pos + 1]; - } + verticesCnt += length / 2 + 2; - short[] curVertices = curItem.vertices; - int outPos = curItem.used; + int inPos = pos; - if (outPos == ShortItem.SIZE) { - curVertices = getNextItem(); - outPos = 0; - } - - curVertices[outPos++] = (short) (originX * S); - curVertices[outPos++] = (short) (originY * S); - - int MAX = ShortItem.SIZE; - int remaining = length; - int inPos = pos; - while (remaining > 0) { - - if (outPos == MAX) { - curVertices = getNextItem(); + if (outPos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; outPos = 0; } - int len = remaining; - if (len > MAX - outPos) - len = MAX - outPos; + v[outPos++] = center; + v[outPos++] = center; - for (int i = 0; i < len; i++) - curVertices[outPos++] = (short) (points[inPos++] * S); + for (int j = 0; j < length; j += 2) { + if (outPos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + outPos = 0; + } + v[outPos++] = (short) (points[inPos++] * S); + v[outPos++] = (short) (points[inPos++] * S); + } - // System.arraycopy(points, inPos, curVertices, outPos, len); + if (outPos == ShortItem.SIZE) { + si = si.next = ShortPool.get(); + v = si.vertices; + outPos = 0; + } - // outPos += len; - // inPos += len; + v[outPos++] = (short) (points[pos + 0] * S); + v[outPos++] = (short) (points[pos + 1] * S); - remaining -= len; + pos += length; } - if (outPos == MAX) { - curVertices = getNextItem(); - outPos = 0; - } - - curVertices[outPos++] = (short) (points[pos + 0] * S); - curVertices[outPos++] = (short) (points[pos + 1] * S); - - curItem.used = outPos; + si.used = outPos; + curItem = si; } + } diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayers.java b/src/org/mapsforge/android/glrenderer/PolygonLayers.java index 049130f1..8a640dbc 100644 --- a/src/org/mapsforge/android/glrenderer/PolygonLayers.java +++ b/src/org/mapsforge/android/glrenderer/PolygonLayers.java @@ -260,7 +260,14 @@ class PolygonLayers { for (PolygonLayer l = layers; l != null; l = l.next) { for (ShortItem item = l.pool; item != null; item = item.next) { - sbuf.put(item.vertices, 0, item.used); + + if (item.next == null) { + sbuf.put(item.vertices, 0, item.used); + } else { + // item.used = ShortItem.SIZE; + sbuf.put(item.vertices); + } + last = item; }