From 9e00115b06116a4f17dd2a67cc35311395f7fa68 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Tue, 18 Jun 2013 10:25:42 +0200 Subject: [PATCH] use symbol bitmap directly as texture --- .../renderer/layers/BasicRenderLayer.java | 4 + .../layers/test/SymbolRenderLayer.java | 57 +++++++ .../oscim/renderer/sublayers/SymbolLayer.java | 152 +++++++++--------- .../oscim/renderer/sublayers/TextureItem.java | 22 ++- .../renderer/sublayers/TextureRenderer.java | 18 ++- 5 files changed, 167 insertions(+), 86 deletions(-) create mode 100644 src/org/oscim/renderer/layers/test/SymbolRenderLayer.java diff --git a/src/org/oscim/renderer/layers/BasicRenderLayer.java b/src/org/oscim/renderer/layers/BasicRenderLayer.java index b8ee51c7..b541c955 100644 --- a/src/org/oscim/renderer/layers/BasicRenderLayer.java +++ b/src/org/oscim/renderer/layers/BasicRenderLayer.java @@ -89,6 +89,10 @@ public abstract class BasicRenderLayer extends RenderLayer { l = BitmapRenderer.draw(l, 1, m); break; +// case Layer.SYMBOL: +// l = BitmapRenderer.draw(l, 1, m); +// break; + default: l = TextureRenderer.draw(l, scale, m); } diff --git a/src/org/oscim/renderer/layers/test/SymbolRenderLayer.java b/src/org/oscim/renderer/layers/test/SymbolRenderLayer.java new file mode 100644 index 00000000..68f4a8df --- /dev/null +++ b/src/org/oscim/renderer/layers/test/SymbolRenderLayer.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.renderer.layers.test; + +import java.io.IOException; + +import org.oscim.core.MapPosition; +import org.oscim.renderer.GLRenderer.Matrices; +import org.oscim.renderer.layers.BasicRenderLayer; +import org.oscim.renderer.sublayers.SymbolItem; +import org.oscim.renderer.sublayers.SymbolLayer; +import org.oscim.theme.renderinstruction.BitmapUtils; +import org.oscim.view.MapView; + +public class SymbolRenderLayer extends BasicRenderLayer { + boolean initialize = true; + + public SymbolRenderLayer(MapView mapView) { + super(mapView); + SymbolLayer l = new SymbolLayer(); + layers.textureLayers = l; + + SymbolItem it = SymbolItem.pool.get(); + it.billboard = false; + + try { + it.bitmap = BitmapUtils.createBitmap("jar:symbols/cafe.png"); + } catch (IOException e) { + e.printStackTrace(); + + } + l.addSymbol(it); + + // compile layer on next frame + newData = true; + } + + @Override + public void update(MapPosition position, boolean changed, Matrices matrices) { + if (initialize){ + initialize = false; + mMapPosition.copy(position); + } + } +} diff --git a/src/org/oscim/renderer/sublayers/SymbolLayer.java b/src/org/oscim/renderer/sublayers/SymbolLayer.java index 06e842e3..f057825b 100644 --- a/src/org/oscim/renderer/sublayers/SymbolLayer.java +++ b/src/org/oscim/renderer/sublayers/SymbolLayer.java @@ -14,35 +14,32 @@ */ package org.oscim.renderer.sublayers; +import java.nio.ShortBuffer; + +import org.oscim.utils.pool.Inlist; -import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.util.Log; // TODO share one static texture for all poi map symabols public final class SymbolLayer extends TextureLayer { private final static String TAG = SymbolLayer.class.getSimpleName(); - private final static int TEXTURE_WIDTH = TextureItem.TEXTURE_WIDTH; - private final static int TEXTURE_HEIGHT = TextureItem.TEXTURE_HEIGHT; private final static float SCALE = 8.0f; + private final static int VERTICES_PER_SPRITE = 4; - SymbolItem symbols; - - private final Canvas mCanvas; - private final Rect mRect = new Rect(); + private SymbolItem symbols; public SymbolLayer() { type = Layer.SYMBOL; fixed = true; - mCanvas = new Canvas(); } + // TODO move sorting items to 'prepare' public void addSymbol(SymbolItem item) { - verticesCnt += 4; + verticesCnt += VERTICES_PER_SPRITE; for (SymbolItem it = symbols; it != null; it = it.next) { if (it.bitmap == item.bitmap) { @@ -59,7 +56,7 @@ public final class SymbolLayer extends TextureLayer { public void addDrawable(Drawable drawable, int state, float x, float y) { - verticesCnt += 4; + verticesCnt += VERTICES_PER_SPRITE; SymbolItem item = SymbolItem.pool.get(); item.drawable = drawable; @@ -83,31 +80,44 @@ public final class SymbolLayer extends TextureLayer { private final static int LBIT_MASK = 0xfffffffe; - // TODO reuse texture when only symbol position changed @Override public boolean prepare() { + return true; + } + + @Override + protected void compile(ShortBuffer sbuf) { + // offset of layer data in vbo + this.offset = sbuf.position() * 2; //SHORT_BYTES; + short numIndices = 0; - short offsetIndices = 0; - short curIndices = 0; + //short offsetIndices = 0; + //short curIndices = 0; - curItem = VertexItem.pool.get(); - vertexItems = curItem; - VertexItem si = curItem; + //curItem = + //vertexItems = curItem; + VertexItem si = VertexItem.pool.get(); - int pos = si.used; + int pos = 0; short buf[] = si.vertices; - int advanceY = 0; - float x = 0; - float y = 0; + //int advanceY = 0; + final float x = 0; + final float y = 0; - TextureItem to = TextureItem.get(true); - textures = to; - mCanvas.setBitmap(to.bitmap); + TextureItem prevTextures = textures; + //TextureItem prev = textures; + + textures = null; + TextureItem to = null; + + //TextureItem to = TextureItem.get(true); + //textures = to; + //mCanvas.setBitmap(to.bitmap); for (SymbolItem it = symbols; it != null;) { - float width, height; + int width, height; if (it.bitmap != null) { // add bitmap @@ -118,61 +128,43 @@ public final class SymbolLayer extends TextureLayer { height = it.drawable.getIntrinsicHeight(); } - if (height > advanceY) - advanceY = (int) height; - - if (x + width > TEXTURE_WIDTH) { - x = 0; - y += advanceY; - advanceY = (int) (height + 0.5f); - + for (to = prevTextures; to != null; to = to.next){ + if (to.bitmap == it.bitmap){ + prevTextures = Inlist.remove(prevTextures, to); + textures = Inlist.append(textures, to); + break; + } } - if (y + height > TEXTURE_HEIGHT) { - Log.d(TAG, "reached max symbols: " + numIndices); + if (to == null){ + to = TextureItem.get(false); + to.bitmap = it.bitmap; + to.width = width; + to.height= height; + textures = Inlist.append(textures, to); - to.offset = offsetIndices; - to.vertices = curIndices; - - numIndices += curIndices; - offsetIndices = numIndices; - curIndices = 0; - - to.next = TextureItem.get(true); - to = to.next; - - mCanvas.setBitmap(to.bitmap); - - x = 0; - y = 0; - advanceY = (int) height; + TextureItem.uploadTexture(to); } - if (it.bitmap != null) { - mCanvas.drawBitmap(it.bitmap, x, y, null); - } else { - it.drawable.copyBounds(mRect); - it.drawable.setBounds((int) x, (int) y, (int) (x + width), (int) (y + height)); - it.drawable.draw(mCanvas); - it.drawable.setBounds(mRect); - } + to.offset = numIndices; + to.vertices = 0; short x1, y1, x2, y2; if (it.bitmap != null) { - float hw = width / 2.0f; - float hh = height / 2.0f; + float hw = width / 2f; + float hh = height / 2f; x1 = (short) (SCALE * (-hw)); x2 = (short) (SCALE * (hw)); y1 = (short) (SCALE * (hh)); y2 = (short) (SCALE * (-hh)); } else { // use drawable offsets (for marker hotspot) + Rect mRect = it.drawable.getBounds(); x2 = (short) (SCALE * (mRect.left)); y2 = (short) (SCALE * (mRect.top)); x1 = (short) (SCALE * (mRect.right)); y1 = (short) (SCALE * (mRect.bottom)); - } short u1 = (short) (SCALE * x); @@ -195,9 +187,7 @@ public final class SymbolLayer extends TextureLayer { short ty = (short) (SCALE * it2.y); if (pos == VertexItem.SIZE) { - si.used = VertexItem.SIZE; - si = si.next = VertexItem.pool.get(); - buf = si.vertices; + sbuf.put(buf, 0, VertexItem.SIZE); pos = 0; } @@ -231,26 +221,42 @@ public final class SymbolLayer extends TextureLayer { buf[pos++] = v1; // six elements used to draw the four vertices - curIndices += TextureRenderer.INDICES_PER_SPRITE; + to.vertices += TextureRenderer.INDICES_PER_SPRITE; } - x += width; + + numIndices += to.vertices; + //offsetIndices = numIndices; + + //to.offset = offsetIndices; + //= curIndices; + //x += width; + } +// if (to != null) { +// to.offset = offsetIndices; +// to.vertices = curIndices; +// } + //si.used = pos; + //curItem = si; - to.offset = offsetIndices; - to.vertices = curIndices; + if (pos > 0) + sbuf.put(buf, 0, pos); - si.used = pos; - curItem = si; + VertexItem.pool.release(si); - return true; + TextureItem.releaseAll(prevTextures); + prevTextures = null; } + @Override protected void clear() { - TextureItem.releaseAll(textures); + TextureItem.releaseAll(textures); SymbolItem.pool.releaseAll(symbols); - VertexItem.pool.releaseAll(vertexItems); + + //VertexItem.pool.releaseAll(vertexItems); + textures = null; symbols = null; vertexItems = null; diff --git a/src/org/oscim/renderer/sublayers/TextureItem.java b/src/org/oscim/renderer/sublayers/TextureItem.java index fe4fd75a..89688d5d 100644 --- a/src/org/oscim/renderer/sublayers/TextureItem.java +++ b/src/org/oscim/renderer/sublayers/TextureItem.java @@ -45,6 +45,7 @@ public class TextureItem extends Inlist { // temporary Bitmap public Bitmap bitmap; + // external bitmap (not from pool) use boolean ownBitmap; TextureItem(int id) { @@ -56,14 +57,21 @@ public class TextureItem extends Inlist { } /** - * Retrieve a TextureItem from pool with default Bitmap - * with dimension TextureRenderer.TEXTURE_WIDTH/HEIGHT. - * */ - public synchronized static TextureItem get(boolean initBitmap) { + * Retrieve a TextureItem from pool. + * + * @param poolBitmap + * initialize with pooled Bitmap with dimension + * TextureRenderer.TEXTURE_WIDTH/HEIGHT. + */ + public synchronized static TextureItem get(boolean poolBitmap) { TextureItem ti = pool.get(); - if (initBitmap) { + + if (poolBitmap) { ti.bitmap = getBitmap(); ti.bitmap.eraseColor(Color.TRANSPARENT); + ti.ownBitmap = false; + } else { + ti.ownBitmap = true; } return ti; } @@ -158,9 +166,9 @@ public class TextureItem extends Inlist { if (!to.ownBitmap) TextureItem.releaseBitmap(to); - else{ + else { // FIXME when in doubt - to.bitmap = null; + //to.bitmap = null; } } diff --git a/src/org/oscim/renderer/sublayers/TextureRenderer.java b/src/org/oscim/renderer/sublayers/TextureRenderer.java index 3df8441b..0514a4c4 100644 --- a/src/org/oscim/renderer/sublayers/TextureRenderer.java +++ b/src/org/oscim/renderer/sublayers/TextureRenderer.java @@ -16,8 +16,6 @@ package org.oscim.renderer.sublayers; import static org.oscim.renderer.GLRenderer.COORD_SCALE; -import static org.oscim.renderer.sublayers.TextureItem.TEXTURE_HEIGHT; -import static org.oscim.renderer.sublayers.TextureItem.TEXTURE_WIDTH; import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer.Matrices; @@ -37,6 +35,7 @@ public final class TextureRenderer { private static int hTextureScale; private static int hTextureScreenScale; private static int hTextureTexCoord; + private static int hTextureSize; public final static int INDICES_PER_SPRITE = 6; final static int VERTICES_PER_SPRITE = 4; @@ -49,6 +48,7 @@ public final class TextureRenderer { hTextureMVMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_mv"); hTextureProjMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_proj"); hTextureScale = GLES20.glGetUniformLocation(mTextureProgram, "u_scale"); + hTextureSize = GLES20.glGetUniformLocation(mTextureProgram, "u_div"); hTextureScreenScale = GLES20.glGetUniformLocation(mTextureProgram, "u_swidth"); hTextureVertex = GLES20.glGetAttribLocation(mTextureProgram, "vertex"); hTextureTexCoord = GLES20.glGetAttribLocation(mTextureProgram, "tex_coord"); @@ -81,6 +81,10 @@ public final class TextureRenderer { GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ti.id); int maxVertices = GLRenderer.maxQuads * INDICES_PER_SPRITE; + GLES20.glUniform2f(hTextureSize, + 1f / (ti.width * COORD_SCALE), + 1f / (ti.height * COORD_SCALE)); + // draw up to maxVertices in each iteration for (int i = 0; i < ti.vertices; i += maxVertices) { // to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8) @@ -106,8 +110,9 @@ public final class TextureRenderer { return layer.next; } - private final static double TEX_COORD_DIV_X = 1.0 / (TEXTURE_WIDTH * COORD_SCALE); - private final static double TEX_COORD_DIV_Y = 1.0 / (TEXTURE_HEIGHT * COORD_SCALE); + //private final static double TEX_COORD_DIV_X = 1.0 / (TEXTURE_WIDTH * COORD_SCALE); + //private final static double TEX_COORD_DIV_Y = 1.0 / (TEXTURE_HEIGHT * COORD_SCALE); + private final static double COORD_DIV = 1.0 / GLRenderer.COORD_SCALE; private final static String textVertexShader = "" @@ -118,8 +123,9 @@ public final class TextureRenderer { + "uniform mat4 u_proj;" + "uniform float u_scale;" + "uniform float u_swidth;" + + "uniform vec2 u_div;" + "varying vec2 tex_c;" - + "const vec2 div = vec2(" + TEX_COORD_DIV_X + "," + TEX_COORD_DIV_Y + ");" + //+ "const vec2 div = vec2(" + TEX_COORD_DIV_X + "," + TEX_COORD_DIV_Y + ");" + "const float coord_scale = " + COORD_DIV + ";" + "void main() {" + " vec4 pos;" @@ -131,7 +137,7 @@ public final class TextureRenderer { + " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.0, 0.0));" + " }" + " gl_Position = pos;" - + " tex_c = tex_coord * div;" + + " tex_c = tex_coord * u_div;" + "}"; private final static String textFragmentShader = ""