unify Indexed- and RenderElement

- remove IndexedRenderElement

- ExtrusionLayer: clear temporary data in prepare()
  - ie. dont wait to release shared Vertexs until compile()
- ExtrusionLayer: make naming consistent with ElementLayers
  - in particular use of 'numIndices', 'numVertices'
This commit is contained in:
Hannes Janetzek 2014-09-09 22:45:35 +02:00
parent 8741357c9a
commit b4a567884f
20 changed files with 337 additions and 378 deletions

View File

@ -20,11 +20,9 @@ import static org.oscim.layers.tile.MapTile.PROXY_PARENT;
import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
import static org.oscim.layers.tile.MapTile.State.READY;
import org.oscim.backend.GL20;
import org.oscim.core.MapPosition;
import org.oscim.layers.tile.MapTile.TileNode;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.ElementRenderer;
import org.oscim.renderer.GLViewport;
import org.oscim.renderer.LayerRenderer;
import org.oscim.renderer.MapRenderer;
@ -179,23 +177,12 @@ public abstract class TileRenderer extends LayerRenderer {
tile.state = READY;
ElementLayers layers = tile.getLayers();
/* tile might contain extrusion or label layers */
/* tile might only contain label layers */
if (layers == null)
return 1;
return 0;
int newSize = layers.getSize();
if (newSize <= 0)
return 1;
if (layers.vbo == null)
layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize);
if (!ElementRenderer.uploadLayers(layers, newSize, true)) {
log.error("{} uploadTileData failed!", tile);
layers.vbo = BufferObject.release(layers.vbo);
if (!layers.compile(true)) {
layers.clear();
/* throw Exception? */
//FIXME tile.layers = null;
return 0;
}

View File

@ -157,8 +157,6 @@ public class VectorTileRenderer extends TileRenderer {
if (layers == null || layers.vbo == null)
return;
layers.vbo.bind();
MapPosition pos = v.pos;
/* place tile relative to map position */
int z = tile.zoomLevel;
@ -176,6 +174,8 @@ public class VectorTileRenderer extends TileRenderer {
mClipMVP.setTransScale(x, y, scale / COORD_SCALE);
mClipMVP.multiplyLhs(mClipProj);
layers.bind();
RenderElement l = layers.getBaseLayers();
PolygonLayer.Renderer.clip(mClipMVP, mClipMode);
@ -187,8 +187,6 @@ public class VectorTileRenderer extends TileRenderer {
/* set test for clip to tile region */
GL.glStencilFunc(GL_EQUAL, 0x80, 0x80);
// clipped = true;
continue;
}
if (l.type == LINE) {
@ -197,6 +195,8 @@ public class VectorTileRenderer extends TileRenderer {
}
if (l.type == TEXLINE) {
l = LineTexLayer.Renderer.draw(l, v, div, layers);
if (layers.ibo != null)
layers.ibo.bind();
continue;
}
if (l.type == MESH) {

View File

@ -125,6 +125,10 @@ public class BuildingLayer extends Layer implements TileLoaderThemeHook {
@Override
public void complete(MapTile tile, boolean success) {
if (success)
get(tile).prepare();
else
get(tile).setLayers(null);
}
// private int multi;

View File

@ -30,7 +30,6 @@ package org.oscim.layers.tile.vector.labeling;
// 5 QuadTree might be handy
//
import org.oscim.backend.GL20;
import org.oscim.layers.tile.vector.labeling.LabelLayer.Worker;
import org.oscim.renderer.ElementRenderer;
import org.oscim.renderer.GLState;
@ -78,10 +77,7 @@ class TextRenderer extends ElementRenderer {
GLState.test(false, false);
//Debug.draw(pos, layers);
if (layers.useVBO)
layers.vbo.bind();
else
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
layers.vbo.bind();
float scale = (float) (v.pos.scale / mMapPosition.scale);

View File

@ -48,6 +48,9 @@ public final class BufferObject extends Inlist<BufferObject> {
this.target = target;
}
/**
* @param newSize size required in bytes
*/
public void loadBufferData(Buffer buf, int newSize) {
boolean clear = false;

View File

@ -23,11 +23,6 @@ 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.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.core.MapPosition;
import org.oscim.core.Tile;
import org.oscim.renderer.elements.BitmapLayer;
@ -51,13 +46,6 @@ public abstract class ElementRenderer extends LayerRenderer {
public static final Logger log = LoggerFactory.getLogger(ElementRenderer.class);
private static short[] fillCoords;
static {
short s = (short) (Tile.SIZE * MapRenderer.COORD_SCALE);
fillCoords = new short[] { 0, s, s, s, 0, 0, s, 0 };
}
/**
* Use mMapPosition.copy(position) to keep the position for which
* the Overlay is *compiled*. NOTE: required by setMatrix utility
@ -77,16 +65,13 @@ public abstract class ElementRenderer extends LayerRenderer {
}
/**
* Render all 'layers'
* Render all 'buckets'
*/
@Override
protected synchronized void render(GLViewport v) {
MapPosition layerPos = mMapPosition;
if (layers.useVBO)
layers.vbo.bind();
else
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
layers.bind();
GLState.test(false, false);
GLState.blend(true);
@ -109,6 +94,8 @@ public abstract class ElementRenderer extends LayerRenderer {
}
if (l.type == TEXLINE) {
l = LineTexLayer.Renderer.draw(l, v, div, layers);
// rebind
layers.ibo.bind();
continue;
}
if (l.type == MESH) {
@ -142,60 +129,13 @@ public abstract class ElementRenderer extends LayerRenderer {
}
/**
* Compiles all layers into one BufferObject. Sets renderer to be ready
* when successful. When no data is available (layer.getSize() == 0) then
* BufferObject will be released and layers will not be rendered.
* Compile all layers into one BufferObject. Sets renderer to be ready
* when successful. When no data is available (layer.countVboSize() == 0)
* then BufferObject will be released and layers will not be rendered.
*/
protected synchronized void compile() {
int newSize = layers.getSize();
if (newSize <= 0) {
layers.vbo = BufferObject.release(layers.vbo);
setReady(false);
return;
}
if (layers.useVBO && layers.vbo == null)
layers.vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, newSize);
if (uploadLayers(layers, newSize, true))
setReady(true);
}
public static boolean uploadLayers(ElementLayers layers, int newSize,
boolean addFill) {
if (addFill)
newSize += 8;
ShortBuffer sbuf;
if (layers.useVBO) {
sbuf = MapRenderer.getShortBuffer(newSize);
} else {
layers.vertexArrayBuffer = ByteBuffer
.allocateDirect(newSize * 2)
.order(ByteOrder.nativeOrder());
sbuf = layers.vertexArrayBuffer.asShortBuffer();
}
if (addFill)
sbuf.put(fillCoords, 0, 8);
layers.compile(sbuf, addFill);
if (newSize != sbuf.position()) {
log.debug("wrong size: "
+ " new size: " + newSize
+ " buffer pos: " + sbuf.position()
+ " buffer limit: " + sbuf.limit()
+ " buffer fill: " + sbuf.remaining());
return false;
}
if (layers.useVBO)
layers.vbo.loadBufferData(sbuf.flip(), newSize * 2);
return true;
boolean ok = layers.compile(true);
setReady(ok);
}
/**

View File

@ -72,14 +72,14 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
GL.glVertexAttribPointer(vertexPointer, 3,
GL20.GL_SHORT, false, 8, 0);
int sumIndices = el.numIndices[0] + el.numIndices[1] + el.numIndices[2];
int sumIndices = el.idx[0] + el.idx[1] + el.idx[2];
if (sumIndices > 0)
GL.glDrawElements(GL20.GL_TRIANGLES, sumIndices,
GL20.GL_UNSIGNED_SHORT, 0);
if (el.numIndices[2] > 0) {
if (el.idx[2] > 0) {
int offset = sumIndices * 2;
GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4],
GL.glDrawElements(GL20.GL_TRIANGLES, el.idx[4],
GL20.GL_UNSIGNED_SHORT, offset);
}
}
@ -114,11 +114,11 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
GL.glUniform1i(s.uMode, -1);
for (int i = 0; i < mExtrusionLayerCnt; i++) {
if (els[i].vboIndices == null)
if (els[i].ibo == null)
return;
els[i].vboIndices.bind();
els[i].vboVertices.bind();
els[i].ibo.bind();
els[i].vbo.bind();
setMatrix(v, els[i], true);
v.mvp.setAsUniform(s.uMVP);
@ -139,11 +139,11 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
float[] currentColor = null;
for (int i = 0; i < mExtrusionLayerCnt; i++) {
if (els[i].vboIndices == null)
if (els[i].ibo == null)
continue;
els[i].vboIndices.bind();
els[i].vboVertices.bind();
els[i].ibo.bind();
els[i].vbo.bind();
if (!mTranslucent) {
setMatrix(v, els[i], false);
@ -161,14 +161,14 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
}
GL.glVertexAttribPointer(s.aPos, 3, GL20.GL_SHORT,
false, 8, el.getOffset());
false, 8, el.getVertexOffset());
GL.glVertexAttribPointer(s.aLight, 2,
GL20.GL_UNSIGNED_BYTE,
false, 8, el.getOffset() + 6);
false, 8, el.getVertexOffset() + 6);
/* draw extruded outlines */
if (el.numIndices[0] > 0) {
if (el.idx[0] > 0) {
if (mTranslucent) {
GL.glDepthFunc(GL20.GL_EQUAL);
setMatrix(v, els[i], true);
@ -178,23 +178,23 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
/* draw roof */
GL.glUniform1i(s.uMode, 0);
GL.glDrawElements(GL20.GL_TRIANGLES,
el.numIndices[2],
el.idx[2],
GL20.GL_UNSIGNED_SHORT,
(el.numIndices[0]
+ el.numIndices[1]) * 2);
(el.idx[0]
+ el.idx[1]) * 2);
/* draw sides 1 */
GL.glUniform1i(s.uMode, 1);
GL.glDrawElements(GL20.GL_TRIANGLES,
el.numIndices[0],
el.idx[0],
GL20.GL_UNSIGNED_SHORT, 0);
/* draw sides 2 */
GL.glUniform1i(s.uMode, 2);
GL.glDrawElements(GL20.GL_TRIANGLES,
el.numIndices[1],
el.idx[1],
GL20.GL_UNSIGNED_SHORT,
el.numIndices[0] * 2);
el.idx[0] * 2);
if (mTranslucent) {
/* drawing gl_lines with the same coordinates does not
@ -207,27 +207,24 @@ public abstract class ExtrusionRenderer extends LayerRenderer {
GL.glUniform1i(s.uMode, 3);
int offset = 2 * (el.indexOffset
+ el.numIndices[0]
+ el.numIndices[1]
+ el.numIndices[2]);
+ el.idx[0] + el.idx[1]
+ el.idx[2]);
GL.glDrawElements(GL20.GL_LINES,
el.numIndices[3],
el.idx[3],
GL20.GL_UNSIGNED_SHORT,
offset);
}
/* draw triangle meshes */
if (el.numIndices[4] > 0) {
if (el.idx[4] > 0) {
int offset = 2 * (el.indexOffset
+ el.numIndices[0]
+ el.numIndices[1]
+ el.numIndices[2]
+ el.numIndices[3]);
+ el.idx[0] + el.idx[1]
+ el.idx[2] + el.idx[3]);
GL.glDrawElements(GL20.GL_TRIANGLES,
el.numIndices[4],
el.idx[4],
GL20.GL_UNSIGNED_SHORT,
offset);
}

View File

@ -78,7 +78,7 @@ public class BitmapLayer extends TextureLayer {
t.indices = TextureLayer.INDICES_PER_SPRITE;
}
private void setVertices(ShortBuffer sbuf) {
private void setVertices(ShortBuffer vboData) {
short[] buf = mVertices;
short w = (short) (mWidth * MapRenderer.COORD_SCALE);
short h = (short) (mHeight * MapRenderer.COORD_SCALE);
@ -118,17 +118,17 @@ public class BitmapLayer extends TextureLayer {
buf[pos++] = texMax;
buf[pos++] = texMax;
this.offset = sbuf.position() * 2;
sbuf.put(buf);
this.vertexOffset = vboData.position() * 2;
vboData.put(buf);
}
@Override
protected void compile(ShortBuffer sbuf) {
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
if (mBitmap == null)
return;
setVertices(sbuf);
setVertices(vboData);
textures.upload();
@ -215,7 +215,7 @@ public class BitmapLayer extends TextureLayer {
// draw up to maxVertices in each iteration
for (int i = 0; i < t.indices; i += maxIndices) {
// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
int off = (t.offset + i) * 8 + tl.offset;
int off = (t.offset + i) * 8 + tl.vertexOffset;
GL.glVertexAttribPointer(s.aPos, 2,
GL20.GL_SHORT, false, 12, off);

View File

@ -22,12 +22,13 @@ 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.ByteBuffer;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile.TileData;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.MapRenderer;
import org.oscim.theme.styles.AreaStyle;
import org.oscim.theme.styles.LineStyle;
import org.slf4j.Logger;
@ -69,10 +70,7 @@ public class ElementLayers extends TileData {
* ...
*/
public BufferObject vbo;
public boolean useVBO = true;
/* holds vertex data for rendering when not using VBO */
public ByteBuffer vertexArrayBuffer;
public BufferObject ibo;
/**
* To not need to switch VertexAttribPointer positions all the time:
@ -273,55 +271,28 @@ public class ElementLayers extends TileData {
return layer;
}
// TODO move to specific layer implementation
public int getSize() {
int size = 0;
private int countVboSize() {
int vboShorts = 0;
for (RenderElement l = baseLayers; l != null; l = l.next)
size += l.numVertices * VERTEX_SHORT_CNT[l.type];
vboShorts += l.numVertices * VERTEX_SHORT_CNT[l.type];
for (RenderElement l = textureLayers; l != null; l = l.next)
size += l.numVertices * TEXTURE_VERTEX_SHORTS;
vboShorts += l.numVertices * TEXTURE_VERTEX_SHORTS;
return size;
return vboShorts;
}
public void compile(ShortBuffer sbuf, boolean addFill) {
private int countIboSize() {
int numIndices = 0;
int pos = addFill ? 4 : 0;
for (RenderElement l = baseLayers; l != null; l = l.next)
numIndices += l.numIndices;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == POLYGON) {
l.compile(sbuf);
for (RenderElement l = textureLayers; l != null; l = l.next)
numIndices += l.numIndices;
//log.debug("offset {} {}", l.offset, pos);
l.offset = pos;
pos += l.numVertices;
}
}
offset[LINE] = sbuf.position() * SHORT_BYTES;
pos = 0;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == LINE) {
l.compile(sbuf);
l.offset = pos;
pos += l.numVertices;
}
}
//offset[TEXLINE] = size * SHORT_BYTES;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == TEXLINE || l.type == MESH || l.type == HAIRLINE) {
l.compile(sbuf);
}
}
for (RenderElement l = textureLayers; l != null; l = l.next) {
l.compile(sbuf);
}
return numIndices;
}
public void setFrom(ElementLayers layers) {
@ -341,10 +312,8 @@ public class ElementLayers extends TileData {
setTextureLayers(null);
mCurLayer = null;
if (vbo != null)
vbo = BufferObject.release(vbo);
vertexArrayBuffer = null;
vbo = BufferObject.release(vbo);
ibo = BufferObject.release(ibo);
}
@Override
@ -352,6 +321,125 @@ public class ElementLayers extends TileData {
clear();
}
public void prepare() {
for (RenderElement l = baseLayers; l != null; l = l.next)
l.prepare();
for (RenderElement l = textureLayers; l != null; l = l.next)
l.prepare();
}
public void bind() {
if (vbo != null)
vbo.bind();
if (ibo != null)
ibo.bind();
}
public boolean compile(boolean addFill) {
int vboSize = countVboSize();
if (vboSize <= 0) {
// FIXME just clear?
vbo = BufferObject.release(vbo);
ibo = BufferObject.release(ibo);
return false;
}
if (addFill)
vboSize += 8;
ShortBuffer vboData = MapRenderer.getShortBuffer(vboSize);
if (addFill)
vboData.put(fillCoords, 0, 8);
ShortBuffer iboData = null;
int iboSize = countIboSize();
if (iboSize > 0) {
iboData = MapRenderer.getShortBuffer(iboSize);
}
//>>compile(vboData, iboData, addFill);
int pos = addFill ? 4 : 0;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == POLYGON) {
l.compile(vboData, iboData);
//log.debug("offset {} {}", l.offset, pos);
l.vertexOffset = pos;
pos += l.numVertices;
}
}
offset[LINE] = vboData.position() * SHORT_BYTES;
pos = 0;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == LINE) {
l.compile(vboData, iboData);
l.vertexOffset = pos;
pos += l.numVertices;
}
}
//offset[TEXLINE] = size * SHORT_BYTES;
for (RenderElement l = baseLayers; l != null; l = l.next) {
if (l.type == TEXLINE || l.type == MESH || l.type == HAIRLINE) {
l.compile(vboData, iboData);
}
}
for (RenderElement l = textureLayers; l != null; l = l.next) {
l.compile(vboData, iboData);
}
//<<
if (vboSize != vboData.position()) {
log.debug("wrong vertex buffer size: "
+ " new size: " + vboSize
+ " buffer pos: " + vboData.position()
+ " buffer limit: " + vboData.limit()
+ " buffer fill: " + vboData.remaining());
return false;
}
if (iboSize > 0 && iboSize != iboData.position()) {
log.debug("wrong indice buffer size: "
+ " new size: " + iboSize
+ " buffer pos: " + iboData.position()
+ " buffer limit: " + iboData.limit()
+ " buffer fill: " + iboData.remaining());
return false;
}
if (vbo == null)
vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, vboSize);
vbo.loadBufferData(vboData.flip(), vboSize * 2);
if (iboSize > 0) {
if (ibo == null)
ibo = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, iboSize);
ibo.loadBufferData(iboData.flip(), iboSize * 2);
}
return true;
}
private static short[] fillCoords;
static {
short s = (short) (Tile.SIZE * MapRenderer.COORD_SCALE);
fillCoords = new short[] { 0, s, s, s, 0, 0, s, 0 };
}
public static void initRenderer(GL20 gl) {
RenderElement.GL = gl;
@ -365,12 +453,4 @@ public class ElementLayers extends TileData {
TextureItem.init(gl);
}
public void prepare() {
for (RenderElement l = baseLayers; l != null; l = l.next)
l.prepare();
for (RenderElement l = textureLayers; l != null; l = l.next)
l.prepare();
}
}

View File

@ -46,9 +46,7 @@ public class ExtrusionLayer extends RenderElement {
public final int color;
/** indices for: 0. even sides, 1. odd sides, 2. roof, 3. roof outline */
public int numIndices[] = { 0, 0, 0, 0, 0 };
public int sumVertices = 0;
public int sumIndices = 0;
public int idx[] = { 0, 0, 0, 0, 0 };
//private final static int IND_EVEN_SIDE = 0;
//private final static int IND_ODD_SIDE = 1;
@ -156,7 +154,7 @@ public class ExtrusionLayer extends RenderElement {
int[] index = element.index;
float[] points = element.points;
int vertexCnt = sumVertices;
int vertexCnt = numVertices;
synchronized (vertexPool) {
Vertex key = vertexPool.get();
@ -263,7 +261,7 @@ public class ExtrusionLayer extends RenderElement {
vertexPool.release(key);
}
sumVertices = vertexCnt;
numVertices = vertexCnt;
}
private void addIndex(Vertex v, boolean addVertex) {
@ -271,7 +269,7 @@ public class ExtrusionLayer extends RenderElement {
vertexItems.add(v.x, v.y, v.z, v.n);
mIndices[IND_MESH].add((short) v.id);
sumIndices++;
numIndices++;
}
// private void encodeNormal(float v[], int offset) {
@ -354,7 +352,7 @@ public class ExtrusionLayer extends RenderElement {
boolean simpleOutline = true;
/* current vertex id */
int startVertex = sumVertices;
int startVertex = numVertices;
int length = 0, ipos = 0, ppos = 0;
for (int n = index.length; ipos < n; ipos++, ppos += length) {
@ -366,7 +364,7 @@ public class ExtrusionLayer extends RenderElement {
/* start next polygon */
if (length == 0) {
startVertex = sumVertices;
startVertex = numVertices;
simpleOutline = true;
complexOutline = false;
continue;
@ -410,7 +408,7 @@ public class ExtrusionLayer extends RenderElement {
(short) (first + k + 2),
(short) (first + k + 4));
}
sumIndices += (len / 2) * 3;
numIndices += (len / 2) * 3;
}
/** roof indices for concave shapes */
@ -427,11 +425,10 @@ public class ExtrusionLayer extends RenderElement {
numRings++;
}
sumIndices += Tessellator.tessellate(points, ppos, numPoints,
numIndices += Tessellator.tessellate(points, ppos, numPoints,
index, ipos, numRings,
startVertex + 1,
mIndices[IND_ROOF]);
}
private boolean extrudeOutline(float[] points, int pos, int len,
@ -463,7 +460,7 @@ public class ExtrusionLayer extends RenderElement {
int changeX = 0, changeY = 0, angleSign = 0;
/* vertex offset for all vertices in layer */
int vOffset = sumVertices;
int vOffset = numVertices;
mClipper.clipStart((int) nx, (int) ny);
@ -556,38 +553,36 @@ public class ExtrusionLayer extends RenderElement {
mIndices[even].add(s0, s2, s1);
mIndices[even].add(s1, s2, s3);
sumIndices += 6;
numIndices += 6;
/* flipp even-odd */
even = ++even % 2;
/* add roof outline indices */
mIndices[IND_OUTLINE].add(s1, s3);
sumIndices += 2;
numIndices += 2;
}
sumVertices += vertexCnt;
numVertices += vertexCnt;
return convex;
}
@Override
public void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) {
mClipper = null;
releaseVertexPool();
public void compile(ShortBuffer vboData, ShortBuffer iboData) {
if (sumVertices == 0)
if (numVertices == 0)
return;
indexOffset = indexBuffer.position();
indexOffset = iboData.position();
for (int i = 0; i <= IND_MESH; i++) {
if (mIndices[i] == null)
continue;
numIndices[i] += mIndices[i].compile(indexBuffer);
idx[i] += mIndices[i].compile(iboData);
}
offset = vertexBuffer.position() * 2;
vertexOffset = vboData.position() * 2;
vertexItems.compile(vertexBuffer);
vertexItems.compile(vboData);
clear();
}
@ -609,6 +604,12 @@ public class ExtrusionLayer extends RenderElement {
}
}
@Override
protected void prepare() {
mClipper = null;
releaseVertexPool();
}
void releaseVertexPool() {
if (mVertexMap == null)
return;

View File

@ -22,8 +22,8 @@ public class ExtrusionLayers extends TileData {
public final double x;
public final double y;
public BufferObject vboIndices;
public BufferObject vboVertices;
public BufferObject ibo;
public BufferObject vbo;
public ExtrusionLayers(MapTile tile) {
zoomLevel = tile.zoomLevel;
@ -50,12 +50,17 @@ public class ExtrusionLayers extends TileData {
setLayers(null);
if (compiled) {
vboIndices = BufferObject.release(vboIndices);
vboVertices = BufferObject.release(vboVertices);
ibo = BufferObject.release(ibo);
vbo = BufferObject.release(vbo);
}
}
public void prepare() {
for (RenderElement l = layers; l != null; l = l.next)
l.prepare();
}
public boolean compileLayers() {
if (layers == null)
@ -65,38 +70,38 @@ public class ExtrusionLayers extends TileData {
int sumVertices = 0;
for (ExtrusionLayer l = layers; l != null; l = l.next()) {
sumIndices += l.sumIndices;
sumVertices += l.sumVertices;
sumIndices += l.numIndices;
sumVertices += l.numVertices;
}
if (sumIndices == 0)
return false;
ShortBuffer vbuf = MapRenderer.getShortBuffer(sumVertices * 4);
ShortBuffer ibuf = MapRenderer.getShortBuffer(sumIndices);
ShortBuffer vboData = MapRenderer.getShortBuffer(sumVertices * 4);
ShortBuffer iboData = MapRenderer.getShortBuffer(sumIndices);
for (ExtrusionLayer l = layers; l != null; l = l.next()) {
l.compile(vbuf, ibuf);
l.compile(vboData, iboData);
}
int size = sumIndices * 2;
if (ibuf.position() != sumIndices) {
int pos = ibuf.position();
if (iboData.position() != sumIndices) {
int pos = iboData.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();
ibo = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size);
ibo.loadBufferData(iboData.flip(), size);
ibo.unbind();
size = sumVertices * 4 * 2;
if (vbuf.position() != sumVertices * 4) {
int pos = vbuf.position();
if (vboData.position() != sumVertices * 4) {
int pos = vboData.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();
vbo = BufferObject.get(GL20.GL_ARRAY_BUFFER, size);
vbo.loadBufferData(vboData.flip(), size);
vbo.unbind();
compiled = true;

View File

@ -1,6 +1,5 @@
package org.oscim.renderer.elements;
import static org.oscim.backend.GL20.GL_ELEMENT_ARRAY_BUFFER;
import static org.oscim.backend.GL20.GL_LINES;
import static org.oscim.backend.GL20.GL_SHORT;
import static org.oscim.backend.GL20.GL_UNSIGNED_SHORT;
@ -15,7 +14,7 @@ import org.oscim.theme.styles.LineStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HairLineLayer extends IndexedRenderElement {
public class HairLineLayer extends RenderElement {
static final Logger log = LoggerFactory.getLogger(HairLineLayer.class);
public LineStyle line;
@ -108,7 +107,7 @@ public class HairLineLayer extends IndexedRenderElement {
v.mvp.setAsUniform(uMVP);
GL.glUniform2f(uScreen, v.getWidth() / 2, v.getHeight() / 2);
GL.glUniform1f(uWidth, 1.5f);
GL.glLineWidth(2);
}
}
@ -117,34 +116,23 @@ public class HairLineLayer extends IndexedRenderElement {
GLState.blend(true);
Shader s = shader;
s.useProgram();
GLState.enableVertexArrays(s.aPos, -1);
v.mvp.setAsUniform(s.uMVP);
GL.glUniform2f(s.uScreen, v.getWidth() / 2, v.getHeight() / 2);
GL.glLineWidth(2);
s.set(v);
for (; l != null && l.type == HAIRLINE; l = l.next) {
HairLineLayer ll = (HairLineLayer) l;
if (ll.indicesVbo == null)
continue;
ll.indicesVbo.bind();
GLUtils.setColor(s.uColor, ll.line.color, 1);
GL.glVertexAttribPointer(s.aPos, 2, GL_SHORT,
false, 0, ll.offset);
false, 0, ll.vertexOffset);
GL.glDrawElements(GL_LINES, ll.numIndices,
GL_UNSIGNED_SHORT, 0);
GL.glDrawElements(GL_LINES,
ll.numIndices,
GL_UNSIGNED_SHORT,
ll.indiceOffset);
}
GL.glLineWidth(1);
GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//GL.glLineWidth(1);
return l;
}

View File

@ -1,48 +0,0 @@
package org.oscim.renderer.elements;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.renderer.BufferObject;
import org.oscim.renderer.MapRenderer;
public abstract class IndexedRenderElement extends RenderElement {
BufferObject indicesVbo;
int numIndices;
VertexData indiceItems = new VertexData();
protected IndexedRenderElement(int type) {
super(type);
}
@Override
protected void compile(ShortBuffer sbuf) {
if (numIndices <= 0) {
indicesVbo = BufferObject.release(indicesVbo);
return;
}
/* add vertices to shared VBO */
compileVertexItems(sbuf);
/* add indices to indicesVbo */
ShortBuffer ibuf = MapRenderer.getShortBuffer(numIndices);
indiceItems.compile(ibuf);
if (indicesVbo == null)
indicesVbo = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
indicesVbo.loadBufferData(ibuf.flip(), ibuf.limit() * 2);
}
@Override
protected void clear() {
indicesVbo = BufferObject.release(indicesVbo);
vertexItems.dispose();
indiceItems.dispose();
numIndices = 0;
numVertices = 0;
}
}

View File

@ -686,7 +686,7 @@ public final class LineLayer extends RenderElement {
}
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP,
l.offset, l.numVertices);
l.vertexOffset, l.numVertices);
continue;
}
@ -733,7 +733,7 @@ public final class LineLayer extends RenderElement {
}
GL.glDrawArrays(GL20.GL_TRIANGLE_STRIP,
ref.offset, ref.numVertices);
ref.vertexOffset, ref.numVertices);
}
}

View File

@ -223,10 +223,10 @@ public final class LineTexLayer extends RenderElement {
}
@Override
protected void compile(ShortBuffer sbuf) {
compileVertexItems(sbuf);
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
compileVertexItems(vboData);
/* add additional vertex for interleaving, see TexLineLayer. */
sbuf.position(sbuf.position() + 6);
vboData.position(vboData.position() + 6);
}
static class Shader extends GLShader {
@ -374,7 +374,7 @@ public final class LineTexLayer extends RenderElement {
numIndices = maxIndices;
/* i / 6 * (24 shorts per block * 2 short bytes) */
int add = (l.offset + i * 8) + vOffset;
int add = (l.vertexOffset + i * 8) + vOffset;
GL.glVertexAttribPointer(aPos0, 4, GL20.GL_SHORT, false, STRIDE,
add + STRIDE);
@ -399,7 +399,7 @@ public final class LineTexLayer extends RenderElement {
if (numIndices > maxIndices)
numIndices = maxIndices;
/* i / 6 * (24 shorts per block * 2 short bytes) */
int add = (l.offset + i * 8) + vOffset;
int add = (l.vertexOffset + i * 8) + vOffset;
GL.glVertexAttribPointer(aPos0, 4, GL20.GL_SHORT, false, STRIDE,
add + 2 * STRIDE);

View File

@ -16,7 +16,6 @@
*/
package org.oscim.renderer.elements;
import static org.oscim.backend.GL20.GL_ELEMENT_ARRAY_BUFFER;
import static org.oscim.backend.GL20.GL_LINES;
import static org.oscim.backend.GL20.GL_SHORT;
import static org.oscim.backend.GL20.GL_TRIANGLES;
@ -37,7 +36,7 @@ import org.oscim.utils.TessJNI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MeshLayer extends IndexedRenderElement {
public class MeshLayer extends RenderElement {
static final Logger log = LoggerFactory.getLogger(MeshLayer.class);
static final boolean dbgRender = false;
@ -132,6 +131,7 @@ public class MeshLayer extends IndexedRenderElement {
GLState.blend(true);
Shader s = shader;
s.useProgram();
GLState.enableVertexArrays(s.aPos, -1);
@ -143,8 +143,8 @@ public class MeshLayer extends IndexedRenderElement {
for (; l != null && l.type == MESH; l = l.next) {
MeshLayer ml = (MeshLayer) l;
if (ml.indicesVbo == null)
continue;
//if (ml.indicesVbo == null)
// continue;
if (ml.heightOffset != heightOffset) {
heightOffset = ml.heightOffset;
@ -153,7 +153,7 @@ public class MeshLayer extends IndexedRenderElement {
MercatorProjection.groundResolution(v.pos));
}
ml.indicesVbo.bind();
//ml.indicesVbo.bind();
if (ml.area == null)
GLUtils.setColor(s.uColor, Color.BLUE, 0.4f);
@ -161,10 +161,14 @@ public class MeshLayer extends IndexedRenderElement {
GLUtils.setColor(s.uColor, ml.area.color, 1);
GL.glVertexAttribPointer(s.aPos, 2, GL_SHORT,
false, 0, ml.offset);
false, 0, ml.vertexOffset);
GL.glDrawElements(GL_TRIANGLES, ml.numIndices,
GL_UNSIGNED_SHORT, 0);
//System.out.println("draw " + ml.numIndices + " / " + ml.indiceOffset);
GL.glDrawElements(GL_TRIANGLES,
ml.numIndices,
GL_UNSIGNED_SHORT,
ml.indiceOffset);
if (dbgRender) {
int c = (ml.area == null) ? Color.BLUE : ml.area.color;
@ -176,7 +180,7 @@ public class MeshLayer extends IndexedRenderElement {
}
}
GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
return l;
}

View File

@ -17,7 +17,6 @@
package org.oscim.renderer.elements;
import static org.oscim.backend.GL20.GL_ALWAYS;
import static org.oscim.backend.GL20.GL_ELEMENT_ARRAY_BUFFER;
import static org.oscim.backend.GL20.GL_EQUAL;
import static org.oscim.backend.GL20.GL_INVERT;
import static org.oscim.backend.GL20.GL_KEEP;
@ -49,7 +48,7 @@ import org.slf4j.LoggerFactory;
/**
* Special Renderer for drawing tile polygons using the stencil buffer method
*/
public final class PolygonLayer extends IndexedRenderElement {
public final class PolygonLayer extends RenderElement {
static final Logger log = LoggerFactory.getLogger(PolygonLayer.class);
@ -81,8 +80,6 @@ public final class PolygonLayer extends IndexedRenderElement {
public void addPolygon(float[] points, int[] index) {
short center = (short) ((Tile.SIZE >> 1) * S);
short id = (short) numVertices;
boolean outline = area.strokeWidth > 0;
for (int i = 0, pos = 0, n = index.length; i < n; i++) {
@ -96,9 +93,8 @@ public final class PolygonLayer extends IndexedRenderElement {
continue;
}
//numVertices += length / 2 + 2;
vertexItems.add(center, center);
id++;
numVertices++;
int inPos = pos;
@ -115,33 +111,34 @@ public final class PolygonLayer extends IndexedRenderElement {
if (y < ymin)
ymin = y;
if (outline) {
indiceItems.add((short) numVertices);
numIndices++;
}
vertexItems.add((short) x, (short) y);
numVertices++;
if (outline) {
indiceItems.add(id++);
indiceItems.add((short) numVertices);
numIndices++;
indiceItems.add(id);
numIndices++;
} else {
id++;
}
}
vertexItems.add((short) (points[pos + 0] * S),
(short) (points[pos + 1] * S));
id++;
numVertices++;
pos += length;
}
numVertices = id;
}
// FIXME move to prepare
@Override
protected void compile(ShortBuffer sbuf) {
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
if (area.strokeWidth == 0) {
/* add vertices to shared VBO */
compileVertexItems(sbuf);
compileVertexItems(vboData);
return;
}
@ -158,7 +155,7 @@ public final class PolygonLayer extends IndexedRenderElement {
bbox[7] = xmax;
/* compile with indexed outline */
super.compile(sbuf);
super.compile(vboData, iboData);
}
static class Shader extends GLShader {
@ -267,34 +264,35 @@ public final class PolygonLayer extends IndexedRenderElement {
/* draw tile fill coordinates */
GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (l.indicesVbo == null)
if (a.strokeWidth <= 0)
continue;
GL.glStencilFunc(GL_EQUAL, CLIP_BIT, CLIP_BIT);
GLState.blend(true);
//GLState.testDepth(false);
HairLineLayer.Renderer.shader.set(v);
l.indicesVbo.bind();
GLUtils.setColor(HairLineLayer.Renderer.shader.uColor,
l.area.strokeColor, 1);
GLUtils.setColor(HairLineLayer.Renderer.shader.uColor, l.area.strokeColor, 1);
GL.glVertexAttribPointer(HairLineLayer.Renderer.shader.aPos,
2, GL_SHORT, false, 0,
// 4 bytes per vertex
l.vertexOffset << 2);
GL.glVertexAttribPointer(HairLineLayer.Renderer.shader.aPos, 2, GL_SHORT,
false, 0, l.offset << 2);
GL.glUniform1f(HairLineLayer.Renderer.shader.uWidth,
a.strokeWidth);
//GL.glUniform1f(HairLineLayer.Renderer.shader.uWidth, );
GL.glDrawElements(GL_LINES, l.numIndices,
GL_UNSIGNED_SHORT, 0);
GL.glDrawElements(GL_LINES,
l.numIndices,
GL_UNSIGNED_SHORT,
l.indiceOffset);
GL.glLineWidth(1);
GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
///* disable texture shader */
//if (s != polyShader)
//s = setShader(polyShader, v, false);
// s = setShader(polyShader, v.mvp, false);
}
}
@ -406,7 +404,7 @@ public final class PolygonLayer extends IndexedRenderElement {
GL.glStencilMask(stencilMask);
}
GL.glDrawArrays(GL_TRIANGLE_FAN, l.offset, l.numVertices);
GL.glDrawArrays(GL_TRIANGLE_FAN, l.vertexOffset, l.numVertices);
/* draw up to 7 layers into stencil buffer */
if (cur == STENCIL_BITS - 1) {

View File

@ -40,9 +40,11 @@ public abstract class RenderElement extends Inlist<RenderElement> {
/** Number of vertices for this layer. */
protected int numVertices;
protected int numIndices;
/** Temporary list of vertex data. */
protected final VertexData vertexItems = new VertexData();
protected final VertexData indiceItems = new VertexData();
protected RenderElement(int type) {
this.type = type;
@ -52,6 +54,7 @@ public abstract class RenderElement extends Inlist<RenderElement> {
protected void clear() {
vertexItems.dispose();
numVertices = 0;
numIndices = 0;
}
/**
@ -62,10 +65,10 @@ public abstract class RenderElement extends Inlist<RenderElement> {
}
/** Compile vertex data to vbo. */
protected void compile(ShortBuffer sbuf) {
compileVertexItems(sbuf);
}
// /** Compile vertex data to vbo. */
// protected void compile(ShortBuffer sbuf) {
// compileVertexItems(sbuf);
// }
/**
* For line- and polygon-layers this is the offset
@ -73,24 +76,35 @@ public abstract class RenderElement extends Inlist<RenderElement> {
* For all other types it is the byte offset in vbo.
* FIXME - always use byte offset?
*/
public int getOffset() {
return offset;
public int getVertexOffset() {
return vertexOffset;
}
public void setOffset(int offset) {
this.offset = offset;
public void setVertexOffset(int offset) {
this.vertexOffset = offset;
}
protected int offset;
protected int vertexOffset;
protected void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) {
protected int indiceOffset;
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
compileVertexItems(vboData);
compileIndiceItems(iboData);
}
protected void compileVertexItems(ShortBuffer sbuf) {
protected void compileVertexItems(ShortBuffer vboData) {
/* keep offset of layer data in vbo */
offset = sbuf.position() * 2;
vertexItems.compile(sbuf);
vertexOffset = vboData.position() * 2; // FIXME 2? - should be vertex stride / num shorts
vertexItems.compile(vboData);
}
protected void compileIndiceItems(ShortBuffer iboData) {
/* keep offset of layer data in vbo */
if (indiceItems.empty())
return;
indiceOffset = iboData.position() * 2; // needs byte offset...
indiceItems.compile(iboData);
}
}

View File

@ -64,9 +64,9 @@ public final class SymbolLayer extends TextureLayer {
}
@Override
protected void compile(ShortBuffer sbuf) {
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
/* offset of layer data in vbo */
this.offset = sbuf.position() * 2; //SHORT_BYTES;
this.vertexOffset = vboData.position() * 2; //SHORT_BYTES;
short numIndices = 0;
@ -165,7 +165,7 @@ public final class SymbolLayer extends TextureLayer {
numIndices += t.indices;
}
vertexItems.compile(sbuf);
vertexItems.compile(vboData);
for (t = prevTextures; t != null; t = t.dispose());
prevTextures = null;

View File

@ -57,13 +57,13 @@ public abstract class TextureLayer extends RenderElement {
public boolean fixed;
@Override
protected void compile(ShortBuffer sbuf) {
protected void compile(ShortBuffer vboData, ShortBuffer iboData) {
for (TextureItem t = textures; t != null; t = t.next)
t.upload();
/* add vertices to vbo */
compileVertexItems(sbuf);
compileVertexItems(vboData);
}
@ -139,26 +139,16 @@ public abstract class TextureLayer extends RenderElement {
for (int i = 0; i < t.indices; i += maxIndices) {
/* to.offset * (24(shorts) * 2(short-bytes)
* / 6(indices) == 8) */
int off = (t.offset + i) * 8 + tl.offset;
int off = (t.offset + i) * 8 + tl.vertexOffset;
if (layers.useVBO) {
GL.glVertexAttribPointer(shader.aPos, 4,
GL20.GL_SHORT,
false, 12, off);
GL.glVertexAttribPointer(shader.aPos, 4,
GL20.GL_SHORT,
false, 12, off);
GL.glVertexAttribPointer(shader.aTexCoord, 2,
GL20.GL_SHORT,
false, 12, off + 8);
GL.glVertexAttribPointer(shader.aTexCoord, 2,
GL20.GL_SHORT,
false, 12, off + 8);
} else {
layers.vertexArrayBuffer.position(off);
GL.glVertexAttribPointer(shader.aPos, 4,
GL20.GL_SHORT, false, 12,
layers.vertexArrayBuffer);
layers.vertexArrayBuffer.position(off + 8);
GL.glVertexAttribPointer(shader.aTexCoord,
2, GL20.GL_SHORT, false, 12,
layers.vertexArrayBuffer);
}
int numIndices = t.indices - i;
if (numIndices > maxIndices)
numIndices = maxIndices;