refactor and cleanup RenderElement and related classes

This commit is contained in:
Hannes Janetzek 2014-01-29 16:23:21 +01:00
parent e38c9a11ff
commit 5235e8483b
23 changed files with 317 additions and 354 deletions

View File

@ -417,7 +417,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
if (v != null) if (v != null)
minHeight = Integer.parseInt(v); minHeight = Integer.parseInt(v);
ExtrusionLayer l = (ExtrusionLayer) mTile.layers.extrusionLayers; ExtrusionLayer l = mTile.layers.getExtrusionLayers();
if (l == null) { if (l == null) {
double lat = MercatorProjection.toLatitude(mTile.y); double lat = MercatorProjection.toLatitude(mTile.y);
@ -425,7 +425,8 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
* MercatorProjection.EARTH_CIRCUMFERENCE * MercatorProjection.EARTH_CIRCUMFERENCE
/ ((long) Tile.SIZE << mTile.zoomLevel)); / ((long) Tile.SIZE << mTile.zoomLevel));
mTile.layers.extrusionLayers = l = new ExtrusionLayer(0, groundScale, extrusion.colors); l = new ExtrusionLayer(0, groundScale, extrusion.colors);
mTile.layers.setExtrusionLayers(l);
} }
l.add(mElement, height, minHeight); l.add(mElement, height, minHeight);
} }

View File

@ -216,7 +216,7 @@ public class PathLayer extends Layer {
mMapPosition.copy(t.pos); mMapPosition.copy(t.pos);
// compile new layers // compile new layers
layers.baseLayers = t.layer.baseLayers; layers.setBaseLayers(t.layer.getBaseLayers());
compile(); compile();
} }
} }
@ -289,7 +289,7 @@ public class PathLayer extends Layer {
} }
if (size == 0) { if (size == 0) {
if (task.layer.baseLayers != null) { if (task.layer.getBaseLayers() != null) {
task.layer.clear(); task.layer.clear();
mMap.render(); mMap.render();
} }
@ -299,8 +299,6 @@ public class PathLayer extends Layer {
ElementLayers layers = task.layer; ElementLayers layers = task.layer;
LineLayer ll = layers.getLineLayer(0); LineLayer ll = layers.getLineLayer(0);
ll.clear();
ll.line = mLineStyle; ll.line = mLineStyle;
ll.width = ll.line.width; ll.width = ll.line.width;

View File

@ -115,7 +115,7 @@ public abstract class ItemizedLayer<Item extends MarkerItem> extends MarkerLayer
synchronized (lock) { synchronized (lock) {
if (mItems == null) { if (mItems == null) {
if (layers.textureLayers != null) { if (layers.getTextureLayers() != null) {
layers.clear(); layers.clear();
compile(); compile();
} }
@ -183,10 +183,9 @@ public abstract class ItemizedLayer<Item extends MarkerItem> extends MarkerLayer
mSymbolLayer.addSymbol(s); mSymbolLayer.addSymbol(s);
} }
} }
mSymbolLayer.prepare(); mSymbolLayer.prepare();
layers.textureLayers = mSymbolLayer; layers.setTextureLayers(mSymbolLayer);
compile(); compile();
} }

View File

@ -141,7 +141,7 @@ public class BitmapTileLayer extends TileLayer<TileLoader> {
BitmapLayer l = new BitmapLayer(false); BitmapLayer l = new BitmapLayer(false);
l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE); l.setBitmap(bitmap, Tile.SIZE, Tile.SIZE);
mTile.layers = new ElementLayers(); mTile.layers = new ElementLayers();
mTile.layers.textureLayers = l; mTile.layers.setTextureLayers(l);
} }
@Override @Override

View File

@ -441,7 +441,7 @@ public class VectorTileLoader extends TileLoader implements IRenderTheme.Callbac
/ ((long) Tile.SIZE << mTile.zoomLevel)); / ((long) Tile.SIZE << mTile.zoomLevel));
l = new ExtrusionLayer(0, groundScale, extrusion.colors); l = new ExtrusionLayer(0, groundScale, extrusion.colors);
mTile.layers.add(l); mTile.layers.setExtrusionLayers(l);
} }
l.add(mElement, height, minHeight); l.add(mElement, height, minHeight);
} }

View File

@ -69,7 +69,7 @@ class TextRenderer extends ElementRenderer {
} }
// set new TextLayer to be uploaded and rendered // set new TextLayer to be uploaded and rendered
layers.textureLayers = t.layers; layers.setTextureLayers(t.layers);
mMapPosition = t.pos; mMapPosition = t.pos;
compile(); compile();
} }
@ -85,7 +85,7 @@ class TextRenderer extends ElementRenderer {
setMatrix(pos, m, false); setMatrix(pos, m, false);
for (RenderElement l = layers.textureLayers; l != null;) for (RenderElement l = layers.getTextureLayers(); l != null;)
l = TextureLayer.Renderer.draw(l, scale, m); l = TextureLayer.Renderer.draw(l, scale, m);
} }

View File

@ -62,7 +62,7 @@ public class BitmapRenderer extends ElementRenderer {
BitmapLayer l = new BitmapLayer(true); BitmapLayer l = new BitmapLayer(true);
l.setBitmap(mBitmap, mWidth, mHeight); l.setBitmap(mBitmap, mWidth, mHeight);
layers.textureLayers = l; layers.setTextureLayers(l);
mUpdateBitmap = true; mUpdateBitmap = true;
} }
@ -86,6 +86,6 @@ public class BitmapRenderer extends ElementRenderer {
@Override @Override
protected synchronized void render(MapPosition pos, Matrices m) { protected synchronized void render(MapPosition pos, Matrices m) {
m.useScreenCoordinates(false, 8); m.useScreenCoordinates(false, 8);
BitmapLayer.Renderer.draw(layers.textureLayers, m, 1, 1); BitmapLayer.Renderer.draw(layers.getTextureLayers(), m, 1, 1);
} }
} }

View File

@ -16,6 +16,13 @@
*/ */
package org.oscim.renderer; package org.oscim.renderer;
import static org.oscim.renderer.elements.RenderElement.BITMAP;
import static org.oscim.renderer.elements.RenderElement.LINE;
import static org.oscim.renderer.elements.RenderElement.MESH;
import static org.oscim.renderer.elements.RenderElement.POLYGON;
import static org.oscim.renderer.elements.RenderElement.SYMBOL;
import static org.oscim.renderer.elements.RenderElement.TEXLINE;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
@ -51,11 +58,15 @@ public abstract class ElementRenderer extends LayerRenderer {
/** /**
* Use mMapPosition.copy(position) to keep the position for which * Use mMapPosition.copy(position) to keep the position for which
* the Overlay is _compiled_. NOTE: required by setMatrix utility * the Overlay is *compiled*. NOTE: required by setMatrix utility
* functions to draw this layer fixed to the map * functions to draw this layer fixed to the map
*/ */
protected MapPosition mMapPosition; protected MapPosition mMapPosition;
/** Wrap around dateline */
protected boolean mFlipOnDateLine = true;
/** Layer data for rendering */
public final ElementLayers layers; public final ElementLayers layers;
public ElementRenderer() { public ElementRenderer() {
@ -67,59 +78,55 @@ public abstract class ElementRenderer extends LayerRenderer {
* Render all 'layers' * Render all 'layers'
*/ */
@Override @Override
protected synchronized void render(MapPosition curPos, Matrices m) { protected synchronized void render(MapPosition pos, Matrices m) {
MapPosition pos = mMapPosition; MapPosition layerPos = mMapPosition;
float div = (float) (curPos.scale / pos.scale);
//float div = FastMath.pow(pos.zoomLevel - curPos.zoomLevel);
layers.vbo.bind(); layers.vbo.bind();
GLState.test(false, false); GLState.test(false, false);
GLState.blend(true); GLState.blend(true);
if (layers.baseLayers != null) { float div = (float) (pos.scale / layerPos.scale);
setMatrix(curPos, m, true);
for (RenderElement l = layers.baseLayers; l != null;) { RenderElement l = layers.getBaseLayers();
switch (l.type) {
case RenderElement.POLYGON:
l = PolygonLayer.Renderer.draw(curPos, l, m, true, 1, false);
break;
case RenderElement.LINE: if (l != null)
l = LineLayer.Renderer.draw(layers, l, curPos, m, div); setMatrix(pos, m, true);
break;
case RenderElement.TEXLINE: while (l != null) {
l = LineTexLayer.Renderer.draw(layers, l, curPos, m, div); if (l.type == POLYGON) {
break; l = PolygonLayer.Renderer.draw(pos, l, m, true, 1, false);
continue;
case RenderElement.MESH: }
if (l.type == LINE) {
l = LineLayer.Renderer.draw(layers, l, pos, m, div);
continue;
}
if (l.type == TEXLINE) {
l = LineTexLayer.Renderer.draw(layers, l, pos, m, div);
continue;
}
if (l.type == MESH) {
l = MeshLayer.Renderer.draw(pos, l, m); l = MeshLayer.Renderer.draw(pos, l, m);
break; continue;
}
default: log.debug("invalid layer {}", l.type);
log.debug("invalid layer");
l = l.next;
break; break;
} }
}
}
if (layers.textureLayers != null) { l = layers.getTextureLayers();
setMatrix(curPos, m, false); if (l != null)
setMatrix(pos, m, false);
for (RenderElement l = layers.textureLayers; l != null;) { while (l != null) {
switch (l.type) { if (l.type == BITMAP) {
case RenderElement.BITMAP:
l = BitmapLayer.Renderer.draw(l, m, 1, 1); l = BitmapLayer.Renderer.draw(l, m, 1, 1);
break; continue;
}
default: if (l.type == SYMBOL) {
l = TextureLayer.Renderer.draw(l, 1 / div, m); l = TextureLayer.Renderer.draw(l, 1 / div, m);
continue;
} }
} log.debug("invalid layer {}", l.type);
break;
} }
} }
@ -147,7 +154,7 @@ public abstract class ElementRenderer extends LayerRenderer {
public static boolean uploadLayers(ElementLayers layers, int newSize, public static boolean uploadLayers(ElementLayers layers, int newSize,
boolean addFill) { boolean addFill) {
// add fill coordinates
if (addFill) if (addFill)
newSize += 8; newSize += 8;
@ -192,11 +199,13 @@ public abstract class ElementRenderer extends LayerRenderer {
double x = oPos.x - position.x; double x = oPos.x - position.x;
double y = oPos.y - position.y; double y = oPos.y - position.y;
// wrap around date-line if (mFlipOnDateLine) {
// while (x < -1) //wrap around date-line
// x += 1.0; while (x < 0.5)
// while (x > 2) x += 1.0;
// x -= 1.0; while (x > 0.5)
x -= 1.0;
}
matrices.mvp.setTransScale((float) (x * tileScale), matrices.mvp.setTransScale((float) (x * tileScale),
(float) (y * tileScale), (float) (y * tileScale),

View File

@ -168,9 +168,9 @@ public class ExtrusionRenderer extends LayerRenderer {
} }
private static ExtrusionLayer getLayer(MapTile t) { private static ExtrusionLayer getLayer(MapTile t) {
if (t.layers != null && t.layers.extrusionLayers != null if (t.layers != null && t.layers.getExtrusionLayers() != null
&& t.state(MapTile.STATE_READY)) && t.state(MapTile.STATE_READY))
return (ExtrusionLayer) t.layers.extrusionLayers; return (ExtrusionLayer) t.layers.getExtrusionLayers();
return null; return null;
} }
@ -200,7 +200,7 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.test(false, false); GLState.test(false, false);
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mTileCnt; i++) {
ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers; ExtrusionLayer el = tiles[i].layers.getExtrusionLayers();
setMatrix(pos, m, tiles[i], 0); setMatrix(pos, m, tiles[i], 0);
m.mvp.setAsUniform(uExtMatrix); m.mvp.setAsUniform(uExtMatrix);
@ -251,7 +251,7 @@ public class ExtrusionRenderer extends LayerRenderer {
// draw to depth buffer // draw to depth buffer
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mTileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers; ExtrusionLayer el = t.layers.getExtrusionLayers();
int d = MapRenderer.depthOffset(t) * 10; int d = MapRenderer.depthOffset(t) * 10;
setMatrix(pos, m, t, d); setMatrix(pos, m, t, d);
m.mvp.setAsUniform(uExtMatrix); m.mvp.setAsUniform(uExtMatrix);
@ -277,7 +277,7 @@ public class ExtrusionRenderer extends LayerRenderer {
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mTileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers; ExtrusionLayer el = t.layers.getExtrusionLayers();
if (el.colors == null) { if (el.colors == null) {
currentColor = mColor; currentColor = mColor;

View File

@ -137,7 +137,8 @@ public class GridRenderer extends ElementRenderer {
if (mText != null) { if (mText != null) {
addLabels(x, y, pos.zoomLevel); addLabels(x, y, pos.zoomLevel);
mLineLayer.clear();
layers.setBaseLayers(mLineLayer);
mLineLayer.addLine(mLines); mLineLayer.addLine(mLines);
} }

View File

@ -106,7 +106,7 @@ public class BitmapLayer extends TextureLayer {
buf[pos++] = texMax; buf[pos++] = texMax;
buf[pos++] = texMax; buf[pos++] = texMax;
setOffset(sbuf.position() * 2); this.offset = sbuf.position() * 2;
sbuf.put(buf); sbuf.put(buf);
} }
@ -215,7 +215,7 @@ public class BitmapLayer extends TextureLayer {
// draw up to maxVertices in each iteration // draw up to maxVertices in each iteration
for (int i = 0; i < t.vertices; i += maxVertices) { for (int i = 0; i < t.vertices; i += maxVertices) {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8) // to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
int off = (t.offset + i) * 8 + tl.getOffset(); int off = (t.offset + i) * 8 + tl.offset;
GL.glVertexAttribPointer(hTextureVertex, 4, GL.glVertexAttribPointer(hTextureVertex, 4,
GL20.GL_SHORT, false, 12, off); GL20.GL_SHORT, false, 12, off);

View File

@ -16,15 +16,24 @@
*/ */
package org.oscim.renderer.elements; package org.oscim.renderer.elements;
import static org.oscim.renderer.elements.RenderElement.LINE;
import static org.oscim.renderer.elements.RenderElement.MESH;
import static org.oscim.renderer.elements.RenderElement.POLYGON;
import static org.oscim.renderer.elements.RenderElement.TEXLINE;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
import org.oscim.renderer.BufferObject; import org.oscim.renderer.BufferObject;
import org.oscim.theme.styles.Line; import org.oscim.theme.styles.Line;
import org.oscim.utils.pool.Inlist;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/**
* This class is primarily intended for rendering the vector elements of a
* MapTile. It can be used for other purposes as well but some optimizations
* applied probably wont make sense in different contexts.
*/
public class ElementLayers { public class ElementLayers {
static final Logger log = LoggerFactory.getLogger(ElementLayers.class); static final Logger log = LoggerFactory.getLogger(ElementLayers.class);
@ -42,12 +51,13 @@ public class ElementLayers {
} }
/** mixed Polygon- and LineLayer */ /** mixed Polygon- and LineLayer */
public RenderElement baseLayers; private RenderElement baseLayers;
/** Text- and SymbolLayer */ /** Text- and SymbolLayer */
public RenderElement textureLayers; private RenderElement textureLayers;
private RenderElement extrusionLayers;
public RenderElement extrusionLayers;
/** /**
* VBO holds all vertex data to draw lines and polygons after compilation. * VBO holds all vertex data to draw lines and polygons after compilation.
* Layout: * Layout:
@ -62,10 +72,9 @@ public class ElementLayers {
* To not need to switch VertexAttribPointer positions all the time: * To not need to switch VertexAttribPointer positions all the time:
* 1. polygons are packed in VBO at offset 0 * 1. polygons are packed in VBO at offset 0
* 2. lines afterwards at lineOffset * 2. lines afterwards at lineOffset
* 3. other layers keep their byte offset in RenderElement.offset * 3. other layers keep their byte offset in offset
*/ */
public int lineOffset; public int[] offset = { 0, 0 };
public int texLineOffset;
private RenderElement mCurLayer; private RenderElement mCurLayer;
@ -74,7 +83,7 @@ public class ElementLayers {
* ordered from bottom (0) to top * ordered from bottom (0) to top
*/ */
public LineLayer addLineLayer(int level, Line style) { public LineLayer addLineLayer(int level, Line style) {
LineLayer ll = (LineLayer) getLayer(level, RenderElement.LINE); LineLayer ll = (LineLayer) getLayer(level, LINE);
if (ll == null) if (ll == null)
return null; return null;
@ -89,7 +98,7 @@ public class ElementLayers {
* bottom (0) to top * bottom (0) to top
*/ */
public LineLayer getLineLayer(int level) { public LineLayer getLineLayer(int level) {
return (LineLayer) getLayer(level, RenderElement.LINE); return (LineLayer) getLayer(level, LINE);
} }
/** /**
@ -97,7 +106,7 @@ public class ElementLayers {
* bottom (0) to top * bottom (0) to top
*/ */
public MeshLayer getMeshLayer(int level) { public MeshLayer getMeshLayer(int level) {
return (MeshLayer) getLayer(level, RenderElement.MESH); return (MeshLayer) getLayer(level, MESH);
} }
/** /**
@ -105,7 +114,7 @@ public class ElementLayers {
* bottom (0) to top * bottom (0) to top
*/ */
public PolygonLayer getPolygonLayer(int level) { public PolygonLayer getPolygonLayer(int level) {
return (PolygonLayer) getLayer(level, RenderElement.POLYGON); return (PolygonLayer) getLayer(level, POLYGON);
} }
/** /**
@ -113,7 +122,7 @@ public class ElementLayers {
* bottom (0) to top * bottom (0) to top
*/ */
public LineTexLayer getLineTexLayer(int level) { public LineTexLayer getLineTexLayer(int level) {
return (LineTexLayer) getLayer(level, RenderElement.TEXLINE); return (LineTexLayer) getLayer(level, TEXLINE);
} }
public TextLayer addTextLayer(TextLayer textLayer) { public TextLayer addTextLayer(TextLayer textLayer) {
@ -122,32 +131,76 @@ public class ElementLayers {
return textLayer; return textLayer;
} }
private RenderElement getLayer(int level, byte type) { public void setBaseLayers(RenderElement layers) {
RenderElement l = baseLayers; for (RenderElement l = baseLayers; l != null; l = l.next)
RenderElement renderElement = null; l.clear();
if (!(type == RenderElement.LINE baseLayers = layers;
|| type == RenderElement.POLYGON }
|| type == RenderElement.TEXLINE
|| type == RenderElement.MESH)) public RenderElement getBaseLayers() {
throw new IllegalArgumentException("invalid layer type"); return baseLayers;
}
public void setTextureLayers(TextureLayer tl) {
for (RenderElement l = textureLayers; l != null; l = l.next)
l.clear();
textureLayers = tl;
}
public RenderElement getTextureLayers() {
return textureLayers;
}
public void setExtrusionLayers(ExtrusionLayer el) {
for (RenderElement l = extrusionLayers; l != null; l = l.next)
l.clear();
extrusionLayers = el;
}
public ExtrusionLayer getExtrusionLayers() {
return (ExtrusionLayer) extrusionLayers;
}
/** cleanup only when layers are not used by tile or overlay anymore! */
public void clear() {
setBaseLayers(null);
setTextureLayers(null);
setExtrusionLayers(null);
mCurLayer = null;
if (vbo != null)
vbo = BufferObject.release(vbo);
}
private RenderElement getLayer(int level, int type) {
RenderElement layer = null;
if (mCurLayer != null && mCurLayer.level == level) { if (mCurLayer != null && mCurLayer.level == level) {
renderElement = mCurLayer; layer = mCurLayer;
} else { if (layer.type != type) {
log.error("BUG wrong layer {} {} on layer {}",
layer.type, type, level);
throw new IllegalArgumentException();
}
return layer;
}
RenderElement l = baseLayers;
if (l == null || l.level > level) { if (l == null || l.level > level) {
// insert new layer at start /** insert new layer at start */
l = null; l = null;
} else { } else {
while (true) { while (true) {
// found layer /** found layer */
if (l.level == level) { if (l.level == level) {
renderElement = l; layer = l;
break; break;
} }
/** insert layer between current and next layer */
// insert new layer between current and next layer
if (l.next == null || l.next.level > level) if (l.next == null || l.next.level > level)
break; break;
@ -155,53 +208,50 @@ public class ElementLayers {
} }
} }
if (renderElement == null) { if (layer == null) {
// add a new RenderElement /** add a new RenderElement */
if (type == RenderElement.LINE) if (type == LINE)
renderElement = new LineLayer(level); layer = new LineLayer(level);
else if (type == RenderElement.POLYGON) else if (type == POLYGON)
renderElement = new PolygonLayer(level); layer = new PolygonLayer(level);
else if (type == RenderElement.TEXLINE) else if (type == TEXLINE)
renderElement = new LineTexLayer(level); layer = new LineTexLayer(level);
else if (type == RenderElement.MESH) else if (type == MESH)
renderElement = new MeshLayer(level); layer = new MeshLayer(level);
if (renderElement == null) if (layer == null)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (l == null) { if (l == null) {
// insert at start /** insert at start */
renderElement.next = baseLayers; layer.next = baseLayers;
baseLayers = renderElement; baseLayers = layer;
} else { } else {
renderElement.next = l.next; layer.next = l.next;
l.next = renderElement; l.next = layer;
}
} }
} }
if (renderElement.type != type) { /** check if found layer matches requested type */
// check if found layer matches requested type if (layer.type != type) {
log.debug("BUG wrong layer " + renderElement.type + " " + type + log.error("BUG wrong layer {} {} on layer {}",
" on layer " + renderElement.level); layer.type, type, level);
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
mCurLayer = renderElement; mCurLayer = layer;
return renderElement; return layer;
} }
private final static int[] VERTEX_SHORT_CNT = { private final static int[] VERTEX_SHORT_CNT = {
4, // LINE_VERTEX_SHORTS 4, // LINE_VERTEX_SHORTS
6, // TEXLINE_VERTEX_SHORTS
2, // POLY_VERTEX_SHORTS 2, // POLY_VERTEX_SHORTS
2, // MESH_VERTEX_SHORTS 2, // MESH_VERTEX_SHORTS
6, // TEXLINE_VERTEX_SHORTS
}; };
private final static int TEXTURE_VERTEX_SHORTS = 6; private final static int TEXTURE_VERTEX_SHORTS = 6;
private final static int SHORT_BYTES = 2; private final static int SHORT_BYTES = 2;
public int getSize() { public int getSize() {
@ -217,51 +267,32 @@ public class ElementLayers {
} }
public void compile(ShortBuffer sbuf, boolean addFill) { public void compile(ShortBuffer sbuf, boolean addFill) {
// offset from fill coordinates
int pos = 0;
int size = 0;
if (addFill) { addLayerItems(sbuf, baseLayers, POLYGON, addFill ? 4 : 0);
pos = 4;
size = 8;
}
size += addLayerItems(sbuf, baseLayers, RenderElement.POLYGON, pos); offset[LINE] = sbuf.position() * SHORT_BYTES;
addLayerItems(sbuf, baseLayers, LINE, 0);
lineOffset = size * SHORT_BYTES; //offset[TEXLINE] = size * SHORT_BYTES;
size += addLayerItems(sbuf, baseLayers, RenderElement.LINE, 0);
texLineOffset = size * SHORT_BYTES;
for (RenderElement l = baseLayers; l != null; l = l.next) { for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == RenderElement.TEXLINE) { if (l.type == TEXLINE || l.type == MESH) {
addPoolItems(l, sbuf);
// add additional vertex for interleaving,
// see TexLineLayer.
sbuf.position(sbuf.position() + 6);
}
}
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == RenderElement.MESH)
l.compile(sbuf); l.compile(sbuf);
} }
}
for (RenderElement l = textureLayers; l != null; l = l.next) { for (RenderElement l = textureLayers; l != null; l = l.next) {
//TextureLayer tl = (TextureLayer) l;
l.compile(sbuf); l.compile(sbuf);
} }
// extrusion layers are compiled by extrusion overlay
// for (RenderElement l = extrusionLayers; l != null; l = l.next) {
// ExtrusionLayer tl = (ExtrusionLayer) l;
// tl.compile(sbuf);
// }
} }
// optimization for Line- and PolygonLayer: /**
// collect all pool items and add back in one go * optimization for Line- and PolygonLayer:
private static int addLayerItems(ShortBuffer sbuf, RenderElement l, byte type, int pos) { * collect all pool items and add back in one go.
*/
private static int addLayerItems(ShortBuffer sbuf, RenderElement l,
int type, int pos) {
VertexItem last = null, items = null; VertexItem last = null, items = null;
int size = 0; int size = 0;
@ -283,7 +314,7 @@ public class ElementLayers {
if (last == null) if (last == null)
continue; continue;
l.setOffset(pos); l.offset = pos;
pos += l.numVertices; pos += l.numVertices;
last.next = items; last.next = items;
@ -298,8 +329,8 @@ public class ElementLayers {
} }
static void addPoolItems(RenderElement l, ShortBuffer sbuf) { static void addPoolItems(RenderElement l, ShortBuffer sbuf) {
// offset of layer data in vbo /** keep offset of layer data in vbo */
l.setOffset(sbuf.position() * SHORT_BYTES); l.offset = sbuf.position() * SHORT_BYTES;
for (VertexItem it = l.vertexItems; it != null; it = it.next) { for (VertexItem it = l.vertexItems; it != null; it = it.next) {
if (it.next == null) if (it.next == null)
@ -310,39 +341,4 @@ public class ElementLayers {
l.vertexItems = VertexItem.pool.releaseAll(l.vertexItems); l.vertexItems = VertexItem.pool.releaseAll(l.vertexItems);
} }
// cleanup only when layers are not used by tile or overlay anymore!
public void clear() {
// clear line and polygon layers directly
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.vertexItems != null)
l.vertexItems = VertexItem.pool.releaseAll(l.vertexItems);
l.numVertices = 0;
}
for (RenderElement l = textureLayers; l != null; l = l.next)
l.clear();
for (RenderElement l = extrusionLayers; l != null; l = l.next)
l.clear();
baseLayers = null;
textureLayers = null;
extrusionLayers = null;
mCurLayer = null;
// if (vbo != null){
// BufferObject.release(vbo);
// vbo = null;
// }
}
public void add(ExtrusionLayer l) {
extrusionLayers = Inlist.appendItem(extrusionLayers, l);
}
public ExtrusionLayer getExtrusionLayers() {
return (ExtrusionLayer) extrusionLayers;
}
} }

View File

@ -16,8 +16,6 @@
*/ */
package org.oscim.renderer.elements; package org.oscim.renderer.elements;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter; import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Paint.Cap; import org.oscim.backend.canvas.Paint.Cap;
@ -556,16 +554,6 @@ public final class LineLayer extends RenderElement {
si.used = opos; si.used = opos;
} }
@Override
public void clear() {
vertexItems = VertexItem.pool.releaseAll(vertexItems);
numVertices = 0;
}
@Override
protected void compile(ShortBuffer sbuf) {
}
public static final class Renderer { public static final class Renderer {
// TODO: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html // TODO: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html
@ -668,7 +656,7 @@ public final class LineLayer extends RenderElement {
GLState.enableVertexArrays(hLineVertexPosition[mode], -1); GLState.enableVertexArrays(hLineVertexPosition[mode], -1);
GL.glVertexAttribPointer(hLineVertexPosition[mode], 4, GL20.GL_SHORT, GL.glVertexAttribPointer(hLineVertexPosition[mode], 4, GL20.GL_SHORT,
false, 0, layers.lineOffset); false, 0, layers.offset[LINE]);
m.mvp.setAsUniform(hLineMatrix[mode]); m.mvp.setAsUniform(hLineMatrix[mode]);
@ -745,7 +733,7 @@ public final class LineLayer extends RenderElement {
} }
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP,
l.getOffset(), l.numVertices); l.offset, l.numVertices);
continue; continue;
} }
@ -781,7 +769,7 @@ public final class LineLayer extends RenderElement {
} }
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP, GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP,
o.getOffset(), o.numVertices); o.offset, o.numVertices);
} }
} }

View File

@ -246,12 +246,12 @@ public final class LineTexLayer extends RenderElement {
si.used = opos; si.used = opos;
} }
@Override
protected void clear() {
}
@Override @Override
protected void compile(ShortBuffer sbuf) { protected void compile(ShortBuffer sbuf) {
ElementLayers.addPoolItems(this, sbuf);
// add additional vertex for interleaving,
// see TexLineLayer.
sbuf.position(sbuf.position() + 6);
} }
public final static class Renderer { public final static class Renderer {
@ -369,7 +369,6 @@ public final class LineTexLayer extends RenderElement {
for (; l != null && l.type == RenderElement.TEXLINE; l = l.next) { for (; l != null && l.type == RenderElement.TEXLINE; l = l.next) {
LineTexLayer ll = (LineTexLayer) l; LineTexLayer ll = (LineTexLayer) l;
Line line = ll.line; Line line = ll.line;
int lOffset = l.getOffset();
GLUtils.setColor(hTexColor, line.stippleColor, 1); GLUtils.setColor(hTexColor, line.stippleColor, 1);
GLUtils.setColor(hBgColor, line.color, 1); GLUtils.setColor(hBgColor, line.color, 1);
@ -396,7 +395,7 @@ public final class LineTexLayer extends RenderElement {
numIndices = maxIndices; numIndices = maxIndices;
// i / 6 * (24 shorts per block * 2 short bytes) // i / 6 * (24 shorts per block * 2 short bytes)
int add = (lOffset + i * 8) + vOffset; int add = (l.offset + i * 8) + vOffset;
GL.glVertexAttribPointer(hVertexPosition0, GL.glVertexAttribPointer(hVertexPosition0,
4, GL20.GL_SHORT, false, STRIDE, 4, GL20.GL_SHORT, false, STRIDE,
@ -425,7 +424,7 @@ public final class LineTexLayer extends RenderElement {
if (numIndices > maxIndices) if (numIndices > maxIndices)
numIndices = maxIndices; numIndices = maxIndices;
// i / 6 * (24 shorts per block * 2 short bytes) // i / 6 * (24 shorts per block * 2 short bytes)
int add = (lOffset + i * 8) + vOffset; int add = (l.offset + i * 8) + vOffset;
GL.glVertexAttribPointer(hVertexPosition0, GL.glVertexAttribPointer(hVertexPosition0,
4, GL20.GL_SHORT, false, STRIDE, 4, GL20.GL_SHORT, false, STRIDE,

View File

@ -144,7 +144,7 @@ public class MeshLayer extends RenderElement {
GLUtils.setColor(hColor, ml.area.color, 1); GLUtils.setColor(hColor, ml.area.color, 1);
GL.glVertexAttribPointer(hVertexPosition, 2, GL20.GL_SHORT, GL.glVertexAttribPointer(hVertexPosition, 2, GL20.GL_SHORT,
false, 0, ml.getOffset()); false, 0, ml.offset);
GL.glDrawElements(GL20.GL_TRIANGLES, ml.numIndices, GL.glDrawElements(GL20.GL_TRIANGLES, ml.numIndices,
GL20.GL_UNSIGNED_SHORT, 0); GL20.GL_UNSIGNED_SHORT, 0);

View File

@ -19,7 +19,6 @@ package org.oscim.renderer.elements;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter; import org.oscim.backend.GLAdapter;
@ -117,14 +116,6 @@ public final class PolygonLayer extends RenderElement {
si.used = outPos; si.used = outPos;
} }
@Override
protected void compile(ShortBuffer sbuf) {
}
@Override
protected void clear() {
}
public static final class Renderer { public static final class Renderer {
private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0; private static final int POLYGON_VERTICES_DATA_POS_OFFSET = 0;
@ -326,7 +317,7 @@ public final class PolygonLayer extends RenderElement {
// set stencil mask to draw to // set stencil mask to draw to
GL.glStencilMask(1 << cur++); GL.glStencilMask(1 << cur++);
GL.glDrawArrays(GL20.GL_TRIANGLE_FAN, l.getOffset(), l.numVertices); GL.glDrawArrays(GL20.GL_TRIANGLE_FAN, l.offset, l.numVertices);
// draw up to 7 layers into stencil buffer // draw up to 7 layers into stencil buffer
if (cur == STENCIL_BITS - 1) { if (cur == STENCIL_BITS - 1) {

View File

@ -24,45 +24,45 @@ import org.oscim.utils.pool.Inlist;
public abstract class RenderElement extends Inlist<RenderElement> { public abstract class RenderElement extends Inlist<RenderElement> {
protected static GL20 GL; protected static GL20 GL;
public final static byte LINE = 0; public final static int LINE = 0;
public final static byte POLYGON = 1; public final static int TEXLINE = 1;
public final static byte MESH = 2; public final static int POLYGON = 2;
public final static byte TEXLINE = 3; public final static int MESH = 3;
public final static byte SYMBOL = 4; public final static int SYMBOL = 4;
public final static byte BITMAP = 5; public final static int BITMAP = 5;
public final static byte EXTRUSION = 6; public final static int EXTRUSION = 6;
protected RenderElement(byte type) { public final int type;
/** drawing order from bottom to top. */
int level;
/** number of vertices for this layer. */
protected int numVertices;
/** temporary list of vertex data. */
protected VertexItem vertexItems;
protected RenderElement(int type) {
this.type = type; this.type = type;
} }
public final byte type; /** clear all resources. */
protected void clear() {
if (vertexItems != null)
vertexItems = VertexItem.pool.releaseAll(vertexItems);
numVertices = 0;
}
/** drawing order from bottom to top */ /** compile vertex data to vbo. */
int level; protected void compile(ShortBuffer sbuf) {
/** number of vertices for this layer */ }
protected int numVertices;
protected VertexItem vertexItems;
abstract protected void compile(ShortBuffer sbuf);
abstract protected void clear();
/** /**
* for line and polygon layers: * For line- and polygon-layers this is the offset
* - number of VERTICES mOffset for this layertype in VBO * of VERTICES in its layers.vbo.
* otherwise: * For all other types it is the byte offset in vbo.
* - offset in byte in VBO
*/ */
private int mOffset; protected int offset;
public int getOffset() {
return mOffset;
}
public void setOffset(int offset) {
mOffset = offset;
}
} }

View File

@ -62,7 +62,7 @@ public final class SymbolLayer extends TextureLayer {
@Override @Override
protected void compile(ShortBuffer sbuf) { protected void compile(ShortBuffer sbuf) {
// offset of layer data in vbo // offset of layer data in vbo
setOffset(sbuf.position() * 2); //SHORT_BYTES; this.offset = sbuf.position() * 2; //SHORT_BYTES;
short numIndices = 0; short numIndices = 0;

View File

@ -42,7 +42,7 @@ public abstract class TextureLayer extends RenderElement {
TEXTURE_WIDTH, TEXTURE_WIDTH,
TEXTURE_HEIGHT); TEXTURE_HEIGHT);
protected TextureLayer(byte type) { protected TextureLayer(int type) {
super(type); super(type);
} }
@ -174,7 +174,7 @@ public abstract class TextureLayer extends RenderElement {
// draw up to maxVertices in each iteration // draw up to maxVertices in each iteration
for (int i = 0; i < t.vertices; i += maxVertices) { for (int i = 0; i < t.vertices; i += maxVertices) {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8) // to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
int off = (t.offset + i) * 8 + tl.getOffset(); int off = (t.offset + i) * 8 + tl.offset;
GL.glVertexAttribPointer(hTextureVertex, 4, GL.glVertexAttribPointer(hTextureVertex, 4,
GL20.GL_SHORT, false, 12, off); GL20.GL_SHORT, false, 12, off);

View File

@ -56,7 +56,7 @@ public class AtlasRenderLayer extends ElementRenderer {
TextLayer tl = new TextLayer(); TextLayer tl = new TextLayer();
Text t = Text.createText(20, 0, Color.BLACK, 0, false); Text t = Text.createText(20, 0, Color.BLACK, 0, false);
layers.textureLayers = tl; layers.setTextureLayers(tl);
float[] points = new float[10]; float[] points = new float[10];

View File

@ -28,7 +28,7 @@ public class SymbolRenderLayer extends ElementRenderer {
public SymbolRenderLayer() { public SymbolRenderLayer() {
SymbolLayer l = new SymbolLayer(); SymbolLayer l = new SymbolLayer();
layers.textureLayers = l; layers.setTextureLayers(l);
SymbolItem it = SymbolItem.pool.get(); SymbolItem it = SymbolItem.pool.get();
it.billboard = false; it.billboard = false;

View File

@ -17,7 +17,6 @@
package org.oscim.tiling; package org.oscim.tiling;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.elements.ElementLayers; import org.oscim.renderer.elements.ElementLayers;
import org.oscim.renderer.elements.SymbolItem; import org.oscim.renderer.elements.SymbolItem;
import org.oscim.renderer.elements.TextItem; import org.oscim.renderer.elements.TextItem;
@ -226,8 +225,6 @@ public class MapTile extends Tile {
*/ */
protected void clear() { protected void clear() {
if (layers != null) { if (layers != null) {
// TODO move this to layers clear
layers.vbo = BufferObject.release(layers.vbo);
layers.clear(); layers.clear();
layers = null; layers = null;
} }

View File

@ -16,6 +16,11 @@
*/ */
package org.oscim.tiling; package org.oscim.tiling;
import static org.oscim.renderer.elements.RenderElement.BITMAP;
import static org.oscim.renderer.elements.RenderElement.LINE;
import static org.oscim.renderer.elements.RenderElement.MESH;
import static org.oscim.renderer.elements.RenderElement.POLYGON;
import static org.oscim.renderer.elements.RenderElement.TEXLINE;
import static org.oscim.tiling.MapTile.STATE_NEW_DATA; import static org.oscim.tiling.MapTile.STATE_NEW_DATA;
import static org.oscim.tiling.MapTile.STATE_READY; import static org.oscim.tiling.MapTile.STATE_READY;
@ -178,7 +183,8 @@ public class TileRenderer extends LayerRenderer {
return 1; return 1;
int newSize = tile.layers.getSize(); int newSize = tile.layers.getSize();
if (newSize > 0) { if (newSize <= 0)
return 1;
if (tile.layers.vbo == null) if (tile.layers.vbo == null)
tile.layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize); tile.layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize);
@ -191,7 +197,6 @@ public class TileRenderer extends LayerRenderer {
tile.layers = null; tile.layers = null;
return 0; return 0;
} }
}
return 1; return 1;
} }
@ -395,7 +400,8 @@ public class TileRenderer extends LayerRenderer {
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
if (t.isVisible && (t.state != STATE_READY) && (t.holder == null)) { if (t.isVisible && (t.state != STATE_READY) && (t.holder == null)) {
boolean preferParent = (scale > 1.5) || (pos.zoomLevel - t.zoomLevel < 0); boolean preferParent = (scale > 1.5)
|| (pos.zoomLevel - t.zoomLevel < 0);
drawProxyTile(t, pos, true, preferParent); drawProxyTile(t, pos, true, preferParent);
} }
} }
@ -416,33 +422,29 @@ public class TileRenderer extends LayerRenderer {
} }
private void drawTile(MapTile tile, MapPosition pos) { private void drawTile(MapTile tile, MapPosition pos) {
// draw parents only once /** ensure to draw parents only once */
if (tile.lastDraw == mDrawSerial) if (tile.lastDraw == mDrawSerial)
return; return;
tile.lastDraw = mDrawSerial; tile.lastDraw = mDrawSerial;
MapTile t = tile; /** use holder proxy when it is set */
if (t.holder != null) MapTile t = tile.holder == null ? tile : tile.holder;
t = t.holder;
if (t.layers == null || t.layers.vbo == null) { if (t.layers == null || t.layers.vbo == null)
//log.debug("missing data " + (t.layers == null) + " " + (t.vbo == null)); //throw new IllegalStateException(t + "no data " + (t.layers == null));
return; return;
}
t.layers.vbo.bind(); t.layers.vbo.bind();
// place tile relative to map position /** place tile relative to map position */
int z = tile.zoomLevel; int z = tile.zoomLevel;
float div = FastMath.pow(z - pos.zoomLevel); float div = FastMath.pow(z - pos.zoomLevel);
double tileScale = Tile.SIZE * pos.scale; double tileScale = Tile.SIZE * pos.scale;
float x = (float) ((tile.x - pos.x) * tileScale); float x = (float) ((tile.x - pos.x) * tileScale);
float y = (float) ((tile.y - pos.y) * tileScale); float y = (float) ((tile.y - pos.y) * tileScale);
// scale relative to zoom-level of this tile /** scale relative to zoom-level of this tile */
float scale = (float) (pos.scale / (1 << z)); float scale = (float) (pos.scale / (1 << z));
Matrices m = mMatrices; Matrices m = mMatrices;
@ -450,64 +452,46 @@ public class TileRenderer extends LayerRenderer {
m.mvp.multiplyLhs(m.viewproj); m.mvp.multiplyLhs(m.viewproj);
boolean clipped = false; boolean clipped = false;
RenderElement l = t.layers.getBaseLayers();
for (RenderElement l = t.layers.baseLayers; l != null;) { while (l != null) {
switch (l.type) { if (l.type == POLYGON) {
case RenderElement.POLYGON:
l = PolygonLayer.Renderer.draw(pos, l, m, !clipped, div, true); l = PolygonLayer.Renderer.draw(pos, l, m, !clipped, div, true);
clipped = true; clipped = true;
break; continue;
case RenderElement.LINE:
if (!clipped) {
clipped = true;
PolygonLayer.Renderer.draw(pos, null, m, true, div, true);
} }
l = LineLayer.Renderer.draw(t.layers, l, pos, m, scale);
break;
case RenderElement.TEXLINE:
if (!clipped) {
clipped = true;
PolygonLayer.Renderer.draw(pos, null, m, true, div, true);
}
l = LineTexLayer.Renderer.draw(t.layers, l, pos, m, div);
break;
case RenderElement.MESH:
if (!clipped) {
clipped = true;
PolygonLayer.Renderer.draw(pos, null, m, true, div, true);
}
l = MeshLayer.Renderer.draw(pos, l, m);
break;
default:
// just in case
l = l.next;
}
}
for (RenderElement l = t.layers.textureLayers; l != null;) {
if (!clipped) { if (!clipped) {
// draw stencil buffer clip region // draw stencil buffer clip region
PolygonLayer.Renderer.draw(pos, null, m, true, div, true); PolygonLayer.Renderer.draw(pos, null, m, true, div, true);
clipped = true; clipped = true;
} }
// if (!clipped) { if (l.type == LINE) {
// // draw stencil buffer clip region l = LineLayer.Renderer.draw(t.layers, l, pos, m, scale);
// PolygonRenderer.clip(m); continue;
// clipped = true; }
// } if (l.type == TEXLINE) {
//GLState.test(false, false); l = LineTexLayer.Renderer.draw(t.layers, l, pos, m, div);
switch (l.type) { continue;
case RenderElement.BITMAP: }
l = BitmapLayer.Renderer.draw(l, m, 1, mRenderAlpha); if (l.type == MESH) {
break; l = MeshLayer.Renderer.draw(pos, l, m);
continue;
default: }
// just in case
l = l.next; l = l.next;
} }
l = t.layers.getTextureLayers();
while (l != null) {
if (!clipped) {
PolygonLayer.Renderer.draw(pos, null, m, true, div, true);
clipped = true;
}
if (l.type == BITMAP) {
l = BitmapLayer.Renderer.draw(l, m, 1, mRenderAlpha);
continue;
}
l = l.next;
} }
if (t.fadeTime == 0) if (t.fadeTime == 0)