use symbol bitmap directly as texture

This commit is contained in:
Hannes Janetzek 2013-06-18 10:25:42 +02:00
parent d7034e9eae
commit 9e00115b06
5 changed files with 167 additions and 86 deletions

View File

@ -89,6 +89,10 @@ public abstract class BasicRenderLayer extends RenderLayer {
l = BitmapRenderer.draw(l, 1, m); l = BitmapRenderer.draw(l, 1, m);
break; break;
// case Layer.SYMBOL:
// l = BitmapRenderer.draw(l, 1, m);
// break;
default: default:
l = TextureRenderer.draw(l, scale, m); l = TextureRenderer.draw(l, scale, m);
} }

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View File

@ -14,35 +14,32 @@
*/ */
package org.oscim.renderer.sublayers; 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.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.util.Log;
// TODO share one static texture for all poi map symabols // TODO share one static texture for all poi map symabols
public final class SymbolLayer extends TextureLayer { public final class SymbolLayer extends TextureLayer {
private final static String TAG = SymbolLayer.class.getSimpleName(); 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 float SCALE = 8.0f;
private final static int VERTICES_PER_SPRITE = 4;
SymbolItem symbols; private SymbolItem symbols;
private final Canvas mCanvas;
private final Rect mRect = new Rect();
public SymbolLayer() { public SymbolLayer() {
type = Layer.SYMBOL; type = Layer.SYMBOL;
fixed = true; fixed = true;
mCanvas = new Canvas();
} }
// TODO move sorting items to 'prepare'
public void addSymbol(SymbolItem item) { public void addSymbol(SymbolItem item) {
verticesCnt += 4; verticesCnt += VERTICES_PER_SPRITE;
for (SymbolItem it = symbols; it != null; it = it.next) { for (SymbolItem it = symbols; it != null; it = it.next) {
if (it.bitmap == item.bitmap) { 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) { public void addDrawable(Drawable drawable, int state, float x, float y) {
verticesCnt += 4; verticesCnt += VERTICES_PER_SPRITE;
SymbolItem item = SymbolItem.pool.get(); SymbolItem item = SymbolItem.pool.get();
item.drawable = drawable; item.drawable = drawable;
@ -83,31 +80,44 @@ public final class SymbolLayer extends TextureLayer {
private final static int LBIT_MASK = 0xfffffffe; private final static int LBIT_MASK = 0xfffffffe;
// TODO reuse texture when only symbol position changed
@Override @Override
public boolean prepare() { 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 numIndices = 0;
short offsetIndices = 0; //short offsetIndices = 0;
short curIndices = 0; //short curIndices = 0;
curItem = VertexItem.pool.get(); //curItem =
vertexItems = curItem; //vertexItems = curItem;
VertexItem si = curItem; VertexItem si = VertexItem.pool.get();
int pos = si.used; int pos = 0;
short buf[] = si.vertices; short buf[] = si.vertices;
int advanceY = 0; //int advanceY = 0;
float x = 0; final float x = 0;
float y = 0; final float y = 0;
TextureItem to = TextureItem.get(true); TextureItem prevTextures = textures;
textures = to; //TextureItem prev = textures;
mCanvas.setBitmap(to.bitmap);
textures = null;
TextureItem to = null;
//TextureItem to = TextureItem.get(true);
//textures = to;
//mCanvas.setBitmap(to.bitmap);
for (SymbolItem it = symbols; it != null;) { for (SymbolItem it = symbols; it != null;) {
float width, height; int width, height;
if (it.bitmap != null) { if (it.bitmap != null) {
// add bitmap // add bitmap
@ -118,61 +128,43 @@ public final class SymbolLayer extends TextureLayer {
height = it.drawable.getIntrinsicHeight(); height = it.drawable.getIntrinsicHeight();
} }
if (height > advanceY) for (to = prevTextures; to != null; to = to.next){
advanceY = (int) height; if (to.bitmap == it.bitmap){
prevTextures = Inlist.remove(prevTextures, to);
if (x + width > TEXTURE_WIDTH) { textures = Inlist.append(textures, to);
x = 0; break;
y += advanceY; }
advanceY = (int) (height + 0.5f);
} }
if (y + height > TEXTURE_HEIGHT) { if (to == null){
Log.d(TAG, "reached max symbols: " + numIndices); to = TextureItem.get(false);
to.bitmap = it.bitmap;
to.width = width;
to.height= height;
textures = Inlist.append(textures, to);
to.offset = offsetIndices; TextureItem.uploadTexture(to);
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;
} }
if (it.bitmap != null) { to.offset = numIndices;
mCanvas.drawBitmap(it.bitmap, x, y, null); to.vertices = 0;
} 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);
}
short x1, y1, x2, y2; short x1, y1, x2, y2;
if (it.bitmap != null) { if (it.bitmap != null) {
float hw = width / 2.0f; float hw = width / 2f;
float hh = height / 2.0f; float hh = height / 2f;
x1 = (short) (SCALE * (-hw)); x1 = (short) (SCALE * (-hw));
x2 = (short) (SCALE * (hw)); x2 = (short) (SCALE * (hw));
y1 = (short) (SCALE * (hh)); y1 = (short) (SCALE * (hh));
y2 = (short) (SCALE * (-hh)); y2 = (short) (SCALE * (-hh));
} else { } else {
// use drawable offsets (for marker hotspot) // use drawable offsets (for marker hotspot)
Rect mRect = it.drawable.getBounds();
x2 = (short) (SCALE * (mRect.left)); x2 = (short) (SCALE * (mRect.left));
y2 = (short) (SCALE * (mRect.top)); y2 = (short) (SCALE * (mRect.top));
x1 = (short) (SCALE * (mRect.right)); x1 = (short) (SCALE * (mRect.right));
y1 = (short) (SCALE * (mRect.bottom)); y1 = (short) (SCALE * (mRect.bottom));
} }
short u1 = (short) (SCALE * x); short u1 = (short) (SCALE * x);
@ -195,9 +187,7 @@ public final class SymbolLayer extends TextureLayer {
short ty = (short) (SCALE * it2.y); short ty = (short) (SCALE * it2.y);
if (pos == VertexItem.SIZE) { if (pos == VertexItem.SIZE) {
si.used = VertexItem.SIZE; sbuf.put(buf, 0, VertexItem.SIZE);
si = si.next = VertexItem.pool.get();
buf = si.vertices;
pos = 0; pos = 0;
} }
@ -231,26 +221,42 @@ public final class SymbolLayer extends TextureLayer {
buf[pos++] = v1; buf[pos++] = v1;
// six elements used to draw the four vertices // six elements used to draw the four vertices
curIndices += TextureRenderer.INDICES_PER_SPRITE; to.vertices += TextureRenderer.INDICES_PER_SPRITE;
}
x += width;
} }
to.offset = offsetIndices; numIndices += to.vertices;
to.vertices = curIndices; //offsetIndices = numIndices;
si.used = pos; //to.offset = offsetIndices;
curItem = si; //= curIndices;
//x += width;
return true;
} }
// if (to != null) {
// to.offset = offsetIndices;
// to.vertices = curIndices;
// }
//si.used = pos;
//curItem = si;
if (pos > 0)
sbuf.put(buf, 0, pos);
VertexItem.pool.release(si);
TextureItem.releaseAll(prevTextures);
prevTextures = null;
}
@Override @Override
protected void clear() { protected void clear() {
TextureItem.releaseAll(textures);
TextureItem.releaseAll(textures);
SymbolItem.pool.releaseAll(symbols); SymbolItem.pool.releaseAll(symbols);
VertexItem.pool.releaseAll(vertexItems);
//VertexItem.pool.releaseAll(vertexItems);
textures = null; textures = null;
symbols = null; symbols = null;
vertexItems = null; vertexItems = null;

View File

@ -45,6 +45,7 @@ public class TextureItem extends Inlist<TextureItem> {
// temporary Bitmap // temporary Bitmap
public Bitmap bitmap; public Bitmap bitmap;
// external bitmap (not from pool) use
boolean ownBitmap; boolean ownBitmap;
TextureItem(int id) { TextureItem(int id) {
@ -56,14 +57,21 @@ public class TextureItem extends Inlist<TextureItem> {
} }
/** /**
* Retrieve a TextureItem from pool with default Bitmap * Retrieve a TextureItem from pool.
* with dimension TextureRenderer.TEXTURE_WIDTH/HEIGHT. *
* */ * @param poolBitmap
public synchronized static TextureItem get(boolean initBitmap) { * initialize with pooled Bitmap with dimension
* TextureRenderer.TEXTURE_WIDTH/HEIGHT.
*/
public synchronized static TextureItem get(boolean poolBitmap) {
TextureItem ti = pool.get(); TextureItem ti = pool.get();
if (initBitmap) {
if (poolBitmap) {
ti.bitmap = getBitmap(); ti.bitmap = getBitmap();
ti.bitmap.eraseColor(Color.TRANSPARENT); ti.bitmap.eraseColor(Color.TRANSPARENT);
ti.ownBitmap = false;
} else {
ti.ownBitmap = true;
} }
return ti; return ti;
} }
@ -160,7 +168,7 @@ public class TextureItem extends Inlist<TextureItem> {
TextureItem.releaseBitmap(to); TextureItem.releaseBitmap(to);
else { else {
// FIXME when in doubt // FIXME when in doubt
to.bitmap = null; //to.bitmap = null;
} }
} }

View File

@ -16,8 +16,6 @@
package org.oscim.renderer.sublayers; package org.oscim.renderer.sublayers;
import static org.oscim.renderer.GLRenderer.COORD_SCALE; 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;
import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.GLRenderer.Matrices;
@ -37,6 +35,7 @@ public final class TextureRenderer {
private static int hTextureScale; private static int hTextureScale;
private static int hTextureScreenScale; private static int hTextureScreenScale;
private static int hTextureTexCoord; private static int hTextureTexCoord;
private static int hTextureSize;
public final static int INDICES_PER_SPRITE = 6; public final static int INDICES_PER_SPRITE = 6;
final static int VERTICES_PER_SPRITE = 4; final static int VERTICES_PER_SPRITE = 4;
@ -49,6 +48,7 @@ public final class TextureRenderer {
hTextureMVMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_mv"); hTextureMVMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_mv");
hTextureProjMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_proj"); hTextureProjMatrix = GLES20.glGetUniformLocation(mTextureProgram, "u_proj");
hTextureScale = GLES20.glGetUniformLocation(mTextureProgram, "u_scale"); hTextureScale = GLES20.glGetUniformLocation(mTextureProgram, "u_scale");
hTextureSize = GLES20.glGetUniformLocation(mTextureProgram, "u_div");
hTextureScreenScale = GLES20.glGetUniformLocation(mTextureProgram, "u_swidth"); hTextureScreenScale = GLES20.glGetUniformLocation(mTextureProgram, "u_swidth");
hTextureVertex = GLES20.glGetAttribLocation(mTextureProgram, "vertex"); hTextureVertex = GLES20.glGetAttribLocation(mTextureProgram, "vertex");
hTextureTexCoord = GLES20.glGetAttribLocation(mTextureProgram, "tex_coord"); hTextureTexCoord = GLES20.glGetAttribLocation(mTextureProgram, "tex_coord");
@ -81,6 +81,10 @@ public final class TextureRenderer {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ti.id); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, ti.id);
int maxVertices = GLRenderer.maxQuads * INDICES_PER_SPRITE; 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 // draw up to maxVertices in each iteration
for (int i = 0; i < ti.vertices; i += maxVertices) { for (int i = 0; i < ti.vertices; i += maxVertices) {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8) // to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
@ -106,8 +110,9 @@ public final class TextureRenderer {
return layer.next; return layer.next;
} }
private final static double TEX_COORD_DIV_X = 1.0 / (TEXTURE_WIDTH * 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 TEX_COORD_DIV_Y = 1.0 / (TEXTURE_HEIGHT * COORD_SCALE);
private final static double COORD_DIV = 1.0 / GLRenderer.COORD_SCALE; private final static double COORD_DIV = 1.0 / GLRenderer.COORD_SCALE;
private final static String textVertexShader = "" private final static String textVertexShader = ""
@ -118,8 +123,9 @@ public final class TextureRenderer {
+ "uniform mat4 u_proj;" + "uniform mat4 u_proj;"
+ "uniform float u_scale;" + "uniform float u_scale;"
+ "uniform float u_swidth;" + "uniform float u_swidth;"
+ "uniform vec2 u_div;"
+ "varying vec2 tex_c;" + "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 + ";" + "const float coord_scale = " + COORD_DIV + ";"
+ "void main() {" + "void main() {"
+ " vec4 pos;" + " vec4 pos;"
@ -131,7 +137,7 @@ public final class TextureRenderer {
+ " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.0, 0.0));" + " pos = u_proj * (center + vec4(dir * (coord_scale * u_swidth), 0.0, 0.0));"
+ " }" + " }"
+ " gl_Position = pos;" + " gl_Position = pos;"
+ " tex_c = tex_coord * div;" + " tex_c = tex_coord * u_div;"
+ "}"; + "}";
private final static String textFragmentShader = "" private final static String textFragmentShader = ""