extract ExtrusionLayers from ElementLayers

This commit is contained in:
Hannes Janetzek 2014-05-24 22:02:16 +02:00
parent 774dd43a18
commit 7466b6206f
7 changed files with 232 additions and 196 deletions

View File

@ -47,7 +47,9 @@ public class S3DBLayer extends TileLayer {
OffscreenRenderer or; OffscreenRenderer or;
public S3DBRenderer() { public S3DBRenderer() {
mExtRenderer = new ExtrusionRenderer(this, SRC_ZOOM, SRC_ZOOM, true, false); mExtRenderer = new ExtrusionRenderer(this, SRC_ZOOM, SRC_ZOOM,
true, false);
if (POST_FXAA) { if (POST_FXAA) {
or = new OffscreenRenderer(Mode.FXAA); or = new OffscreenRenderer(Mode.FXAA);
or.setRenderer(mExtRenderer); or.setRenderer(mExtRenderer);

View File

@ -11,8 +11,9 @@ import org.oscim.core.Tag;
import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileLoader; import org.oscim.layers.tile.TileLoader;
import org.oscim.layers.tile.TileManager; import org.oscim.layers.tile.TileManager;
import org.oscim.renderer.elements.ElementLayers; import org.oscim.layers.tile.vector.BuildingLayer;
import org.oscim.renderer.elements.ExtrusionLayer; import org.oscim.renderer.elements.ExtrusionLayer;
import org.oscim.renderer.elements.ExtrusionLayers;
import org.oscim.tiling.ITileDataSource; import org.oscim.tiling.ITileDataSource;
import org.oscim.tiling.TileSource; import org.oscim.tiling.TileSource;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -59,22 +60,6 @@ class S3DBTileLoader extends TileLoader {
protected boolean loadTile(MapTile tile) { protected boolean loadTile(MapTile tile) {
mTile = tile; mTile = tile;
double lat = MercatorProjection.toLatitude(tile.y);
mGroundScale = (float) MercatorProjection
.groundResolution(lat, 1 << mTile.zoomLevel);
mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(247, 249, 250));
mLayers = new ExtrusionLayer(0, mGroundScale, Color.get(255, 254, 252));
//mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(207, 209, 210));
mRoofs.next = mLayers;
ElementLayers layers = new ElementLayers();
layers.setExtrusionLayers(mRoofs);
tile.data = layers;
process(mTilePlane);
try { try {
/* query database, which calls process() callback */ /* query database, which calls process() callback */
mTileDataSource.query(mTile, this); mTileDataSource.query(mTile, this);
@ -86,6 +71,24 @@ class S3DBTileLoader extends TileLoader {
return true; return true;
} }
private void initTile(MapTile tile) {
double lat = MercatorProjection.toLatitude(tile.y);
mGroundScale = (float) MercatorProjection
.groundResolution(lat, 1 << mTile.zoomLevel);
mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(247, 249, 250));
mLayers = new ExtrusionLayer(0, mGroundScale, Color.get(255, 254, 252));
//mRoofs = new ExtrusionLayer(0, mGroundScale, Color.get(207, 209, 210));
mRoofs.next = mLayers;
ExtrusionLayers layers = BuildingLayer.get(tile);
layers.setLayers(mRoofs);
process(mTilePlane);
}
String COLOR_KEY = "c"; String COLOR_KEY = "c";
String MATERIAL_KEY = "m"; String MATERIAL_KEY = "m";
String ROOF_KEY = "roof"; String ROOF_KEY = "roof";
@ -93,12 +96,15 @@ class S3DBTileLoader extends TileLoader {
@Override @Override
public void process(MapElement element) { public void process(MapElement element) {
//log.debug("TAG {}", element.tags);
if (element.type != GeometryType.TRIS) { if (element.type != GeometryType.TRIS) {
log.debug("wrong type " + element.type); log.debug("wrong type " + element.type);
return; return;
} }
if (mLayers == null)
initTile(mTile);
boolean isRoof = element.tags.containsKey(ROOF_KEY); boolean isRoof = element.tags.containsKey(ROOF_KEY);
//if (isRoof) //if (isRoof)
// log.debug(element.tags.toString()); // log.debug(element.tags.toString());

View File

@ -30,6 +30,7 @@ import org.oscim.renderer.OffscreenRenderer;
import org.oscim.renderer.OffscreenRenderer.Mode; import org.oscim.renderer.OffscreenRenderer.Mode;
import org.oscim.renderer.elements.ElementLayers; import org.oscim.renderer.elements.ElementLayers;
import org.oscim.renderer.elements.ExtrusionLayer; import org.oscim.renderer.elements.ExtrusionLayer;
import org.oscim.renderer.elements.ExtrusionLayers;
import org.oscim.theme.styles.ExtrusionStyle; import org.oscim.theme.styles.ExtrusionStyle;
import org.oscim.theme.styles.RenderStyle; import org.oscim.theme.styles.RenderStyle;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
@ -43,6 +44,8 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
private final static int MAX_ZOOM = 17; private final static int MAX_ZOOM = 17;
private final static boolean POST_AA = false; private final static boolean POST_AA = false;
private static final Object BUILDING_DATA = BuildingLayer.class.getName();
private final int mMinZoom; private final int mMinZoom;
private final int mMaxZoom; private final int mMaxZoom;
@ -154,26 +157,34 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
if (v != null) if (v != null)
minHeight = Integer.parseInt(v); minHeight = Integer.parseInt(v);
ExtrusionLayer l = layers.getExtrusionLayers(); ExtrusionLayers el = get(tile);
if (l == null) { if (el.layers == null) {
double lat = MercatorProjection.toLatitude(tile.y); double lat = MercatorProjection.toLatitude(tile.y);
float groundScale = (float) MercatorProjection float groundScale = (float) MercatorProjection
.groundResolution(lat, 1 << tile.zoomLevel); .groundResolution(lat, 1 << tile.zoomLevel);
l = new ExtrusionLayer(0, groundScale, extrusion.colors); el.layers = new ExtrusionLayer(0, groundScale, extrusion.colors);
layers.setExtrusionLayers(l);
} }
/* 12m default */ /* 12m default */
if (height == 0) if (height == 0)
height = 12 * 100; height = 12 * 100;
l.add(element, height, minHeight); el.layers.add(element, height, minHeight);
return true; return true;
} }
public static ExtrusionLayers get(MapTile tile) {
ExtrusionLayers el = (ExtrusionLayers) tile.getData(BUILDING_DATA);
if (el == null) {
el = new ExtrusionLayers(tile);
tile.addData(BUILDING_DATA, el);
}
return el;
}
// private int multi; // private int multi;
// @Override // @Override
// public void onInputEvent(Event event, MotionEvent e) { // public void onInputEvent(Event event, MotionEvent e) {

View File

@ -19,23 +19,21 @@ package org.oscim.renderer;
import static org.oscim.layers.tile.MapTile.State.NEW_DATA; import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY; import static org.oscim.layers.tile.MapTile.State.READY;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile; import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.TileRenderer; import org.oscim.layers.tile.TileRenderer;
import org.oscim.layers.tile.TileSet; import org.oscim.layers.tile.TileSet;
import org.oscim.layers.tile.vector.BuildingLayer;
import org.oscim.renderer.elements.ElementLayers; import org.oscim.renderer.elements.ElementLayers;
import org.oscim.renderer.elements.ExtrusionLayer; import org.oscim.renderer.elements.ExtrusionLayer;
import org.oscim.renderer.elements.ExtrusionLayers;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
// TODO move MapTile part to BuildingLayer and make
// this class work on ExtrusionLayers
public class ExtrusionRenderer extends LayerRenderer { public class ExtrusionRenderer extends LayerRenderer {
static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class); static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class);
private final boolean debug = false;
private final TileRenderer mTileLayer; private final TileRenderer mTileLayer;
private final int mZoomMin; private final int mZoomMin;
@ -43,6 +41,7 @@ public class ExtrusionRenderer extends LayerRenderer {
private final boolean drawAlpha; private final boolean drawAlpha;
protected float mAlpha = 1; protected float mAlpha = 1;
private final int mMode;
public ExtrusionRenderer(TileRenderer tileRenderLayer, public ExtrusionRenderer(TileRenderer tileRenderLayer,
int zoomMin, int zoomMax, boolean mesh, boolean alpha) { int zoomMin, int zoomMax, boolean mesh, boolean alpha) {
@ -54,15 +53,11 @@ public class ExtrusionRenderer extends LayerRenderer {
drawAlpha = alpha; drawAlpha = alpha;
} }
private boolean initialized = false;
private final TileSet mTileSet; private final TileSet mTileSet;
private MapTile[] mTiles; private ExtrusionLayers[] mExtrusionLayerSet;
private int mTileCnt; private int mExtrusionLayerCnt;
private final int mMode; public static class Shader extends GLShader {
static class Shader extends GLShader {
int uMVP, uColor, uAlpha, uMode, aPos, aLight; int uMVP, uColor, uAlpha, uMode, aPos, aLight;
public Shader(String shader) { public Shader(String shader) {
@ -78,23 +73,20 @@ public class ExtrusionRenderer extends LayerRenderer {
} }
} }
private Shader mShader[] = { null, null }; protected Shader mShader;
private boolean initShader() {
initialized = true;
mShader[0] = new Shader("extrusion_layer_ext");
mShader[1] = new Shader("extrusion_layer_mesh");
@Override
protected boolean setup() {
if (mMode == 0)
mShader = new Shader("extrusion_layer_ext");
else
mShader = new Shader("extrusion_layer_mesh");
return true; return true;
} }
@Override @Override
public void update(GLViewport v) { public void update(GLViewport v) {
if (!initialized && !initShader())
return;
if (mAlpha == 0 || v.pos.zoomLevel < (mZoomMin - 1)) { if (mAlpha == 0 || v.pos.zoomLevel < (mZoomMin - 1)) {
setReady(false); setReady(false);
return; return;
@ -111,8 +103,8 @@ public class ExtrusionRenderer extends LayerRenderer {
} }
/* keep a list of tiles available for rendering */ /* keep a list of tiles available for rendering */
if (mTiles == null || mTiles.length < mTileSet.cnt * 4) if (mExtrusionLayerSet == null || mExtrusionLayerSet.length < mTileSet.cnt * 4)
mTiles = new MapTile[mTileSet.cnt * 4]; mExtrusionLayerSet = new ExtrusionLayers[mTileSet.cnt * 4];
int zoom = tiles[0].zoomLevel; int zoom = tiles[0].zoomLevel;
@ -120,41 +112,41 @@ public class ExtrusionRenderer extends LayerRenderer {
boolean compiled = false; boolean compiled = false;
if (zoom >= mZoomMin && zoom <= mZoomMax) { if (zoom >= mZoomMin && zoom <= mZoomMax) {
// TODO - if tile is not available try parent or children /* TODO - if tile is not available try parent or children */
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
ExtrusionLayer el = getLayer(tiles[i]); ExtrusionLayers els = getLayer(tiles[i]);
if (el == null) if (els == null)
continue; continue;
if (el.compiled) if (els.compiled)
mTiles[activeTiles++] = tiles[i]; mExtrusionLayerSet[activeTiles++] = els;
else if (!compiled && compileLayers(el)) { else if (!compiled && els.compileLayers()) {
mTiles[activeTiles++] = tiles[i]; mExtrusionLayerSet[activeTiles++] = els;
compiled = true; compiled = true;
} }
} }
} else if (zoom == mZoomMax + 1) { } else if (zoom == mZoomMax + 1) {
/* special case for s3db: render from parent tiles */ /* special case for s3db: render from parent tiles */
O: for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = tiles[i].node.parent(); MapTile t = tiles[i].node.parent();
if (t == null) if (t == null)
continue; continue;
for (MapTile c : mTiles) // for (MapTile c : mTiles)
if (c == t) // if (c == t)
continue O; // continue O;
ExtrusionLayer el = getLayer(t); ExtrusionLayers els = getLayer(t);
if (el == null) if (els == null)
continue; continue;
if (el.compiled) if (els.compiled)
mTiles[activeTiles++] = tiles[i]; mExtrusionLayerSet[activeTiles++] = els;
else if (!compiled && compileLayers(el)) { else if (!compiled && els.compileLayers()) {
mTiles[activeTiles++] = t; mExtrusionLayerSet[activeTiles++] = els;
compiled = true; compiled = true;
} }
} }
@ -167,12 +159,12 @@ public class ExtrusionRenderer extends LayerRenderer {
continue; continue;
MapTile c = t.node.child(j); MapTile c = t.node.child(j);
ExtrusionLayer el = getLayer(c); ExtrusionLayers el = getLayer(c);
if (el == null || !el.compiled) if (el == null || !el.compiled)
continue; continue;
mTiles[activeTiles++] = c; mExtrusionLayerSet[activeTiles++] = el;
} }
} }
} }
@ -181,7 +173,9 @@ public class ExtrusionRenderer extends LayerRenderer {
if (compiled) if (compiled)
MapRenderer.animate(); MapRenderer.animate();
mTileCnt = activeTiles; mExtrusionLayerCnt = activeTiles;
//log.debug("active tiles: {}", mExtrusionLayerCnt);
if (activeTiles > 0) if (activeTiles > 0)
setReady(true); setReady(true);
@ -189,71 +183,22 @@ public class ExtrusionRenderer extends LayerRenderer {
mTileLayer.releaseTiles(mTileSet); mTileLayer.releaseTiles(mTileSet);
} }
private boolean compileLayers(ExtrusionLayer el) { private static ExtrusionLayers getLayer(MapTile t) {
if (el == null)
return false;
if (el.compiled)
return true;
int sumIndices = 0;
int sumVertices = 0;
for (ExtrusionLayer l = el; l != null; l = l.next()) {
sumIndices += l.sumIndices;
sumVertices += l.sumVertices;
}
if (sumIndices == 0) {
return false;
}
ShortBuffer vbuf = MapRenderer.getShortBuffer(sumVertices * 4);
ShortBuffer ibuf = MapRenderer.getShortBuffer(sumIndices);
for (ExtrusionLayer l = el; l != null; l = l.next())
l.compile(vbuf, ibuf);
int size = sumIndices * 2;
if (ibuf.position() != sumIndices) {
int pos = ibuf.position();
log.error("invalid indice size: {} {}", sumIndices, pos);
size = pos * 2;
}
el.vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size);
el.vboIndices.loadBufferData(ibuf.flip(), size);
el.vboIndices.unbind();
size = sumVertices * 4 * 2;
if (vbuf.position() != sumVertices * 4) {
int pos = vbuf.position();
log.error("invalid vertex size: {} {}", sumVertices, pos);
size = pos * 2;
}
el.vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size);
el.vboVertices.loadBufferData(vbuf.flip(), size);
el.vboVertices.unbind();
GLUtils.checkGlError("extrusion layer");
return true;
}
private static ExtrusionLayer getLayer(MapTile t) {
ElementLayers layers = t.getLayers(); ElementLayers layers = t.getLayers();
if (layers == null || !t.state(READY | NEW_DATA)) if (layers != null && !t.state(READY | NEW_DATA))
return null; return null;
return layers.getExtrusionLayers(); return BuildingLayer.get(t);
} }
private final boolean debug = false; private void renderCombined(int vertexPointer, ExtrusionLayers els) {
if (els.vboIndices == null)
return;
private void renderCombined(int vertexPointer, ExtrusionLayer el) { els.vboIndices.bind();
for (; el != null; el = el.next()) { els.vboVertices.bind();
if (el.vboIndices == null) for (ExtrusionLayer el = els.layers; el != null; el = el.next()) {
continue;
el.vboIndices.bind();
el.vboVertices.bind();
GL.glVertexAttribPointer(vertexPointer, 3, GL.glVertexAttribPointer(vertexPointer, 3,
GL20.GL_SHORT, false, 8, 0); GL20.GL_SHORT, false, 8, 0);
@ -276,8 +221,8 @@ public class ExtrusionRenderer extends LayerRenderer {
// TODO one could render in one pass to texture and then draw the texture // TODO one could render in one pass to texture and then draw the texture
// with alpha... might be faster and would allow postprocessing outlines. // with alpha... might be faster and would allow postprocessing outlines.
MapTile[] tiles = mTiles; ExtrusionLayers[] els = mExtrusionLayerSet;
Shader s = mShader[mMode]; Shader s = mShader; //[mMode];
if (debug) { if (debug) {
s.useProgram(); s.useProgram();
@ -291,16 +236,16 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.test(false, false); GLState.test(false, false);
GLState.blend(true); GLState.blend(true);
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mExtrusionLayerCnt; i++) {
ExtrusionLayer el = tiles[i].getLayers().getExtrusionLayers(); ExtrusionLayer el = els[i].getLayers();
setMatrix(v, tiles[i], 0); setMatrix(v, els[i], 0);
v.mvp.setAsUniform(s.uMVP); v.mvp.setAsUniform(s.uMVP);
renderCombined(s.aPos, el); renderCombined(s.aPos, els[i]);
// just a temporary reference! /* just a temporary reference! */
tiles[i] = null; els[i] = null;
} }
return; return;
} }
@ -311,7 +256,6 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.test(true, false); GLState.test(true, false);
s.useProgram(); s.useProgram();
//GLState.useProgram(shaderProgram[mMode]);
GLState.enableVertexArrays(s.aPos, -1); GLState.enableVertexArrays(s.aPos, -1);
GLState.blend(false); GLState.blend(false);
@ -326,18 +270,17 @@ public class ExtrusionRenderer extends LayerRenderer {
//GLUtils.glUniform4fv(uExtColor, 4, mColor); //GLUtils.glUniform4fv(uExtColor, 4, mColor);
/* draw to depth buffer */ /* draw to depth buffer */
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mExtrusionLayerCnt; i++) {
MapTile t = tiles[i]; ExtrusionLayer el = els[i].getLayers();
ExtrusionLayer el = t.getLayers().getExtrusionLayers();
if (el == null) if (el == null)
continue; continue;
int d = MapTile.depthOffset(t) * 10; int d = 0; // FIXME MapTile.depthOffset(t) * 10;
setMatrix(v, t, d); setMatrix(v, els[i], d);
v.mvp.setAsUniform(s.uMVP); v.mvp.setAsUniform(s.uMVP);
renderCombined(s.aPos, el); renderCombined(s.aPos, els[i]);
} }
GL.glColorMask(true, true, true, true); GL.glColorMask(true, true, true, true);
@ -350,28 +293,28 @@ public class ExtrusionRenderer extends LayerRenderer {
float[] currentColor = null; float[] currentColor = null;
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mExtrusionLayerCnt; i++) {
MapTile t = tiles[i]; ExtrusionLayer el = els[i].getLayers();
ExtrusionLayer el = t.getLayers().getExtrusionLayers();
if (el == null) if (el == null)
continue; continue;
if (el.vboIndices == null) if (els[i].vboIndices == null)
continue; continue;
int d = 1; els[i].vboIndices.bind();
els[i].vboVertices.bind();
int d = 0;
if (drawAlpha) { if (drawAlpha) {
GL.glDepthFunc(GL20.GL_EQUAL); GL.glDepthFunc(GL20.GL_EQUAL);
d = MapTile.depthOffset(t) * 10;
// FIXME d = MapTile.depthOffset(t) * 10;
} }
setMatrix(v, t, d); setMatrix(v, els[i], d);
v.mvp.setAsUniform(s.uMVP); v.mvp.setAsUniform(s.uMVP);
el.vboIndices.bind();
el.vboVertices.bind();
for (; el != null; el = el.next()) { for (; el != null; el = el.next()) {
if (el.colors != currentColor) { if (el.colors != currentColor) {
@ -443,8 +386,9 @@ public class ExtrusionRenderer extends LayerRenderer {
GL20.GL_UNSIGNED_SHORT, offset); GL20.GL_UNSIGNED_SHORT, offset);
} }
} }
// just a temporary reference!
tiles[i] = null; /* just a temporary reference! */
els[i] = null;
} }
GL.glDepthMask(false); GL.glDepthMask(false);
@ -455,13 +399,13 @@ public class ExtrusionRenderer extends LayerRenderer {
mTileLayer.releaseTiles(mTileSet); mTileLayer.releaseTiles(mTileSet);
} }
private static void setMatrix(GLViewport v, MapTile tile, int delta) { private static void setMatrix(GLViewport v, ExtrusionLayers l, int delta) {
int z = tile.zoomLevel; int z = l.zoomLevel;
double curScale = Tile.SIZE * v.pos.scale; double curScale = Tile.SIZE * v.pos.scale;
float scale = (float) (v.pos.scale / (1 << z)); float scale = (float) (v.pos.scale / (1 << z));
float x = (float) ((tile.x - v.pos.x) * curScale); float x = (float) ((l.x - v.pos.x) * curScale);
float y = (float) ((tile.y - v.pos.y) * curScale); float y = (float) ((l.y - v.pos.y) * curScale);
v.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE); v.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE);
// scale height ??? // scale height ???

View File

@ -58,12 +58,6 @@ public class ElementLayers extends TileData {
/** Text- and SymbolLayer */ /** Text- and SymbolLayer */
private RenderElement textureLayers; private RenderElement textureLayers;
/**
* FIXME this is somewhat out-of-place, as it is not
* compiled with the other layers
*/
private 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:
@ -184,20 +178,6 @@ public class ElementLayers extends TileData {
return textureLayers; return textureLayers;
} }
/**
* Set new ExtrusionLayers and clear previous.
*/
public void setExtrusionLayers(ExtrusionLayer el) {
for (RenderElement l = extrusionLayers; l != null; l = l.next)
l.clear();
extrusionLayers = el;
}
public ExtrusionLayer getExtrusionLayers() {
return (ExtrusionLayer) extrusionLayers;
}
private RenderElement getLayer(int level, int type) { private RenderElement getLayer(int level, int type) {
RenderElement layer = null; RenderElement layer = null;
@ -364,14 +344,11 @@ public class ElementLayers extends TileData {
public void setFrom(ElementLayers layers) { public void setFrom(ElementLayers layers) {
setBaseLayers(layers.baseLayers); setBaseLayers(layers.baseLayers);
setTextureLayers((TextureLayer) layers.textureLayers); setTextureLayers((TextureLayer) layers.textureLayers);
setExtrusionLayers((ExtrusionLayer) layers.extrusionLayers);
mCurLayer = null; mCurLayer = null;
layers.baseLayers = null; layers.baseLayers = null;
layers.textureLayers = null; layers.textureLayers = null;
layers.extrusionLayers = null;
layers.mCurLayer = null; layers.mCurLayer = null;
} }
/** cleanup only when layers are not used by tile or layer anymore! */ /** cleanup only when layers are not used by tile or layer anymore! */
@ -379,7 +356,6 @@ public class ElementLayers extends TileData {
/* NB: set null calls clear() on each layer! */ /* NB: set null calls clear() on each layer! */
setBaseLayers(null); setBaseLayers(null);
setTextureLayers(null); setTextureLayers(null);
setExtrusionLayers(null);
mCurLayer = null; mCurLayer = null;
if (vbo != null) if (vbo != null)

View File

@ -23,7 +23,6 @@ import org.oscim.core.GeometryBuffer;
import org.oscim.core.GeometryBuffer.GeometryType; import org.oscim.core.GeometryBuffer.GeometryType;
import org.oscim.core.MapElement; import org.oscim.core.MapElement;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.MapRenderer; import org.oscim.renderer.MapRenderer;
import org.oscim.utils.FastMath; import org.oscim.utils.FastMath;
import org.oscim.utils.KeyMap; import org.oscim.utils.KeyMap;
@ -54,9 +53,6 @@ public class ExtrusionLayer extends RenderElement {
public int sumVertices = 0; public int sumVertices = 0;
public int sumIndices = 0; public int sumIndices = 0;
public BufferObject vboIndices;
public BufferObject vboVertices;
//private final static int IND_EVEN_SIDE = 0; //private final static int IND_EVEN_SIDE = 0;
//private final static int IND_ODD_SIDE = 1; //private final static int IND_ODD_SIDE = 1;
private final static int IND_ROOF = 2; private final static int IND_ROOF = 2;
@ -65,7 +61,6 @@ public class ExtrusionLayer extends RenderElement {
private final static int IND_OUTLINE = 3; private final static int IND_OUTLINE = 3;
private final static int IND_MESH = 4; private final static int IND_MESH = 4;
public boolean compiled = false;
private final float mGroundResolution; private final float mGroundResolution;
private KeyMap<Vertex> mVertexMap; private KeyMap<Vertex> mVertexMap;
@ -654,10 +649,6 @@ public class ExtrusionLayer extends RenderElement {
public void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) { public void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) {
mClipper = null; mClipper = null;
if (compiled) {
throw new IllegalStateException();
}
if (mVertexMap != null) { if (mVertexMap != null) {
vertexPool.releaseAll(mVertexMap.releaseItems()); vertexPool.releaseAll(mVertexMap.releaseItems());
mVertexMap = vertexMapPool.release(mVertexMap); mVertexMap = vertexMapPool.release(mVertexMap);
@ -665,7 +656,6 @@ public class ExtrusionLayer extends RenderElement {
} }
if (sumVertices == 0) { if (sumVertices == 0) {
compiled = true;
return; return;
} }
@ -686,7 +676,6 @@ public class ExtrusionLayer extends RenderElement {
vertexBuffer.put(vi.vertices, 0, vi.used); vertexBuffer.put(vi.vertices, 0, vi.used);
clear(); clear();
compiled = true;
} }
@Override @Override
@ -699,10 +688,7 @@ public class ExtrusionLayer extends RenderElement {
mVertexMap = null; mVertexMap = null;
} }
if (compiled) { if (mIndices != null) {
vboIndices = BufferObject.release(vboIndices);
vboVertices = BufferObject.release(vboVertices);
} else {
for (int i = 0; i <= IND_MESH; i++) for (int i = 0; i <= IND_MESH; i++)
mIndices[i] = VertexItem.pool.releaseAll(mIndices[i]); mIndices[i] = VertexItem.pool.releaseAll(mIndices[i]);
mIndices = null; mIndices = null;

View File

@ -0,0 +1,111 @@
package org.oscim.renderer.elements;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.layers.tile.MapTile;
import org.oscim.layers.tile.MapTile.TileData;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLUtils;
import org.oscim.renderer.MapRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExtrusionLayers extends TileData {
static final Logger log = LoggerFactory.getLogger(ExtrusionLayers.class);
public ExtrusionLayer layers;
public boolean compiled;
public final int zoomLevel;
public final double x;
public final double y;
public BufferObject vboIndices;
public BufferObject vboVertices;
public ExtrusionLayers(MapTile tile) {
zoomLevel = tile.zoomLevel;
x = tile.x;
y = tile.y;
}
/**
* Set new ExtrusionLayers and clear previous.
*/
public void setLayers(ExtrusionLayer el) {
for (RenderElement l = layers; l != null; l = l.next)
l.clear();
layers = el;
}
public ExtrusionLayer getLayers() {
return (ExtrusionLayer) layers;
}
@Override
protected void dispose() {
setLayers(null);
if (compiled) {
vboIndices = BufferObject.release(vboIndices);
vboVertices = BufferObject.release(vboVertices);
}
}
public boolean compileLayers() {
ExtrusionLayer el = layers;
if (el == null)
return false;
//if (el.compiled)
// return true;
int sumIndices = 0;
int sumVertices = 0;
for (ExtrusionLayer l = el; l != null; l = l.next()) {
sumIndices += l.sumIndices;
sumVertices += l.sumVertices;
}
if (sumIndices == 0) {
return false;
}
ShortBuffer vbuf = MapRenderer.getShortBuffer(sumVertices * 4);
ShortBuffer ibuf = MapRenderer.getShortBuffer(sumIndices);
for (ExtrusionLayer l = el; l != null; l = l.next())
l.compile(vbuf, ibuf);
int size = sumIndices * 2;
if (ibuf.position() != sumIndices) {
int pos = ibuf.position();
log.error("invalid indice size: {} {}", sumIndices, pos);
size = pos * 2;
}
vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size);
vboIndices.loadBufferData(ibuf.flip(), size);
vboIndices.unbind();
size = sumVertices * 4 * 2;
if (vbuf.position() != sumVertices * 4) {
int pos = vbuf.position();
log.error("invalid vertex size: {} {}", sumVertices, pos);
size = pos * 2;
}
vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size);
vboVertices.loadBufferData(vbuf.flip(), size);
vboVertices.unbind();
GLUtils.checkGlError("extrusion layer");
compiled = true;
return true;
}
}