From bda73374ca50798a145fd262c8b247e4eba58534 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek <hannes.janetzek@gmail.com> Date: Mon, 17 Mar 2014 00:27:26 +0100 Subject: [PATCH] compile extrusion layers into one vbo --- .../org/oscim/renderer/ExtrusionRenderer.java | 85 +++++++++++++---- .../renderer/elements/ElementLayers.java | 12 ++- .../renderer/elements/ExtrusionLayer.java | 95 ++++++++++++------- .../renderer/elements/RenderElement.java | 18 ++-- 4 files changed, 142 insertions(+), 68 deletions(-) diff --git a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java index 7eded407..8055b77f 100644 --- a/vtm/src/org/oscim/renderer/ExtrusionRenderer.java +++ b/vtm/src/org/oscim/renderer/ExtrusionRenderer.java @@ -19,6 +19,8 @@ package org.oscim.renderer; import static org.oscim.layers.tile.MapTile.State.NEW_DATA; import static org.oscim.layers.tile.MapTile.State.READY; +import java.nio.ShortBuffer; + import org.oscim.backend.GL20; import org.oscim.core.Tile; import org.oscim.layers.tile.MapTile; @@ -191,15 +193,47 @@ public class ExtrusionRenderer extends LayerRenderer { return true; boolean compiled = false; - for (; el != null; el = (ExtrusionLayer) el.next) { - if (!el.compiled) { - int numShorts = el.sumVertices * 8; - el.compile(MapRenderer.getShortBuffer(numShorts)); - GLUtils.checkGlError("..."); - } - compiled |= el.compiled; + + int sumIndices = 0; + int sumVertices = 0; + for (ExtrusionLayer l = el; l != null; l = (ExtrusionLayer) l.next) { + sumIndices += l.sumIndices; + sumVertices += l.sumVertices; } + ShortBuffer vbuf = MapRenderer.getShortBuffer(sumVertices * 4); + ShortBuffer ibuf = MapRenderer.getShortBuffer(sumIndices); + + for (ExtrusionLayer l = el; l != null; l = (ExtrusionLayer) 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(); + + //GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); + + 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(); + + //GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0); + + GLUtils.checkGlError("compile extrusion layer"); + return compiled; } @@ -238,7 +272,6 @@ public class ExtrusionRenderer extends LayerRenderer { int offset = sumIndices * 2; GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4], GL20.GL_UNSIGNED_SHORT, offset); - } } } @@ -337,6 +370,9 @@ public class ExtrusionRenderer extends LayerRenderer { if (el == null) continue; + if (el.vboIndices == null) + continue; + int d = 1; if (drawAlpha) { GL.glDepthFunc(GL20.GL_EQUAL); @@ -346,10 +382,10 @@ public class ExtrusionRenderer extends LayerRenderer { setMatrix(v, t, d); v.mvp.setAsUniform(uExtMatrix); - for (; el != null; el = (ExtrusionLayer) el.next) { + el.vboIndices.bind(); + el.vboVertices.bind(); - if (el.vboIndices == null) - continue; + for (; el != null; el = (ExtrusionLayer) el.next) { if (el.colors != currentColor) { currentColor = el.colors; @@ -357,14 +393,16 @@ public class ExtrusionRenderer extends LayerRenderer { el.colors); } - el.vboIndices.bind(); - el.vboVertices.bind(); + /* indices offset */ + int indexOffset = el.indexOffset; + /* vertex byte offset */ + int vertexOffset = el.getOffset(); GL.glVertexAttribPointer(uExtVertexPosition, 3, - GL20.GL_SHORT, false, 8, 0); + GL20.GL_SHORT, false, 8, vertexOffset); GL.glVertexAttribPointer(uExtLightPosition, 2, - GL20.GL_UNSIGNED_BYTE, false, 8, 6); + GL20.GL_UNSIGNED_BYTE, false, 8, vertexOffset + 6); /* draw extruded outlines */ if (el.numIndices[0] > 0) { @@ -395,16 +433,23 @@ public class ExtrusionRenderer extends LayerRenderer { v.mvp.setAsUniform(uExtMatrix); GL.glUniform1i(uExtMode, 3); + + int offset = 2 * (indexOffset + + el.numIndices[0] + + el.numIndices[1] + + el.numIndices[2]); + GL.glDrawElements(GL20.GL_LINES, el.numIndices[3], - GL20.GL_UNSIGNED_SHORT, - (el.numIndices[0] + el.numIndices[1] - + el.numIndices[2]) * 2); + GL20.GL_UNSIGNED_SHORT, offset); } /* draw triangle meshes */ if (el.numIndices[4] > 0) { - int offset = (el.numIndices[0] + el.numIndices[1] - + el.numIndices[2] + el.numIndices[3]) * 2; + int offset = 2 * (indexOffset + + el.numIndices[0] + + el.numIndices[1] + + el.numIndices[2] + + el.numIndices[3]); GL.glUniform1i(uExtMode, 4); GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4], diff --git a/vtm/src/org/oscim/renderer/elements/ElementLayers.java b/vtm/src/org/oscim/renderer/elements/ElementLayers.java index 9179ef49..7b2ba56b 100644 --- a/vtm/src/org/oscim/renderer/elements/ElementLayers.java +++ b/vtm/src/org/oscim/renderer/elements/ElementLayers.java @@ -269,16 +269,18 @@ public class ElementLayers extends TileData { return layer; } - private final static int[] VERTEX_SHORT_CNT = { - 4, // LINE_VERTEX_SHORTS - 6, // TEXLINE_VERTEX_SHORTS - 2, // POLY_VERTEX_SHORTS - 2, // MESH_VERTEX_SHORTS + public final static int[] VERTEX_SHORT_CNT = { + 4, // LINE_VERTEX + 6, // TEXLINE_VERTEX + 2, // POLY_VERTEX + 2, // MESH_VERTEX + 4, // EXTRUSION_VERTEX }; private final static int TEXTURE_VERTEX_SHORTS = 6; private final static int SHORT_BYTES = 2; + // TODO move to specific layer implementation public int getSize() { int size = 0; diff --git a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java index 4d818a42..3a3613ea 100644 --- a/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java +++ b/vtm/src/org/oscim/renderer/elements/ExtrusionLayer.java @@ -19,8 +19,6 @@ package org.oscim.renderer.elements; import java.nio.ShortBuffer; import java.util.HashMap; -import org.oscim.backend.GL20; -import org.oscim.backend.GLAdapter; import org.oscim.backend.canvas.Color; import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer.GeometryType; @@ -53,6 +51,7 @@ public class ExtrusionLayer extends RenderElement { public int numIndices[] = { 0, 0, 0, 0, 0 }; //public int sumIndices = 0; public int sumVertices = 0; + public int sumIndices = 0; public BufferObject vboIndices; public BufferObject vboVertices; @@ -60,6 +59,8 @@ public class ExtrusionLayer extends RenderElement { //private final static int IND_EVEN_SIDE = 0; //private final static int IND_ODD_SIDE = 1; private final static int IND_ROOF = 2; + + // FIXME flip OUTLINE / MESH! private final static int IND_OUTLINE = 3; private final static int IND_MESH = 4; @@ -68,8 +69,18 @@ public class ExtrusionLayer extends RenderElement { public boolean compiled = false; private final float mGroundResolution; - boolean filled; + private HashMap<Vertex, Integer> mVertexMap = new HashMap<Vertex, Integer>(); + private Vertex mTmpVertex = new Vertex(); + public int indexOffset; + + //private int numIndexHits = 0; + + //boolean filled; + + /** + * ExtrusionLayer for polygon geometries. + */ public ExtrusionLayer(int level, float groundResolution, float[] colors) { super(RenderElement.EXTRUSION); this.level = level; @@ -88,7 +99,7 @@ public class ExtrusionLayer extends RenderElement { } /** - * ExtrusionLayer for Mesh elements only. + * ExtrusionLayer for triangle geometries. */ public ExtrusionLayer(int level, float groundResolution, int color) { super(RenderElement.EXTRUSION); @@ -146,10 +157,6 @@ public class ExtrusionLayer extends RenderElement { } } - private HashMap<Vertex, Integer> mVertexMap = new HashMap<Vertex, Integer>(); - private Vertex mTmpVertex = new Vertex(); - private int numIndexHits = 0; - public void add(MapElement element) { if (element.type != GeometryType.TRIS) return; @@ -221,7 +228,7 @@ public class ExtrusionLayer extends RenderElement { addIndex(vertexCnt); mVertexMap.put(new Vertex(key), vertexCnt++); } else { - numIndexHits++; + //numIndexHits++; addIndex(vertexId.intValue()); } @@ -236,7 +243,7 @@ public class ExtrusionLayer extends RenderElement { addIndex(vertexCnt); mVertexMap.put(new Vertex(key), vertexCnt++); } else { - numIndexHits++; + //numIndexHits++; addIndex(vertexId.intValue()); } @@ -251,7 +258,7 @@ public class ExtrusionLayer extends RenderElement { addIndex(vertexCnt); mVertexMap.put(new Vertex(key), vertexCnt++); } else { - numIndexHits++; + //numIndexHits++; addIndex(vertexId.intValue()); } } @@ -264,8 +271,9 @@ public class ExtrusionLayer extends RenderElement { if (vi.used == VertexItem.SIZE) { mCurVertices.used = VertexItem.SIZE; - mCurVertices.next = VertexItem.pool.get(); - mCurVertices = mCurVertices.next; + mCurVertices = VertexItem.pool.getNext(vi); + //mCurVertices.next = VertexItem.pool.get(); + //mCurVertices = mCurVertices.next; vi = mCurVertices; } @@ -280,12 +288,16 @@ public class ExtrusionLayer extends RenderElement { if (vi.used == VertexItem.SIZE) { mCurIndices[IND_MESH].used = VertexItem.SIZE; - mCurIndices[IND_MESH].next = VertexItem.pool.get(); - mCurIndices[IND_MESH] = mCurIndices[IND_MESH].next; + mCurIndices[IND_MESH] = VertexItem.pool.getNext(vi); vi = mCurIndices[IND_MESH]; + + //mCurIndices[IND_MESH].next = VertexItem.pool.get(); + //mCurIndices[IND_MESH] = mCurIndices[IND_MESH].next; + //vi = mCurIndices[IND_MESH]; //indices = mCurIndices[IND_MESH].vertices; //i = 0; } + sumIndices++; vi.vertices[vi.used++] = (short) id; } @@ -436,9 +448,11 @@ public class ExtrusionLayer extends RenderElement { indices = mCurIndices[IND_ROOF].vertices; i = 0; } + indices[i++] = first; indices[i++] = (short) (first + k + 2); indices[i++] = (short) (first + k + 4); + sumIndices += 3; } mCurIndices[IND_ROOF].used = i; } @@ -456,8 +470,8 @@ public class ExtrusionLayer extends RenderElement { rings++; } - Tessellator.tessellate(points, ppos, len, index, ipos, rings, - startVertex + 1, mCurIndices[IND_ROOF]); + sumIndices += Tessellator.tessellate(points, ppos, len, index, ipos, rings, + startVertex + 1, mCurIndices[IND_ROOF]); mCurIndices[IND_ROOF] = Inlist.last(mCurIndices[IND_ROOF]); } @@ -617,6 +631,7 @@ public class ExtrusionLayer extends RenderElement { indices[ind + 3] = s1; indices[ind + 4] = s2; indices[ind + 5] = s3; + sumIndices += 6; mCurIndices[even].used += 6; even = (even == 0 ? 1 : 0); @@ -636,44 +651,52 @@ public class ExtrusionLayer extends RenderElement { return convex; } - @Override - public void compile(ShortBuffer sbuf) { + public void complete() { mVertexMap.clear(); + } + + @Override + public void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) { + mVertexMap.clear(); + if (sumVertices == 0 || compiled) return; - int sumIndices = 0; + indexOffset = indexBuffer.position(); + + //int sumIndices = 0; for (int i = 0; i <= IND_MESH; i++) { for (VertexItem vi = mIndices[i]; vi != null; vi = vi.next) { - sbuf.put(vi.vertices, 0, vi.used); + indexBuffer.put(vi.vertices, 0, vi.used); numIndices[i] += vi.used; } - sumIndices += numIndices[i]; + //sumIndices += numIndices[i]; } //log.debug("INDEX HITS " + numIndexHits + " / " + sumVertices + " / " + sumIndices); - int size = sumIndices * 2; - vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size); - vboIndices.loadBufferData(sbuf.flip(), size); - - GL20 GL = GLAdapter.get(); - GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); + //int size = sumIndices * 2; + //vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size); + //vboIndices.loadBufferData(vertexBuffer.flip(), size); + // + //GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); // upload vertices - sbuf.clear(); + //vertexBuffer.clear(); + + offset = vertexBuffer.position() * 2; + for (VertexItem vi = mVertices; vi != null; vi = vi.next) - sbuf.put(vi.vertices, 0, vi.used); + vertexBuffer.put(vi.vertices, 0, vi.used); - size = sumVertices * 4 * 2; - vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size); - vboVertices.loadBufferData(sbuf.flip(), size); - - GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0); + // size = sumVertices * 4 * 2; + // vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size); + // vboVertices.loadBufferData(vertexBuffer.flip(), size); + // + // GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0); clear(); compiled = true; - mClipper = null; } diff --git a/vtm/src/org/oscim/renderer/elements/RenderElement.java b/vtm/src/org/oscim/renderer/elements/RenderElement.java index cfab11b9..ecd8d2e8 100644 --- a/vtm/src/org/oscim/renderer/elements/RenderElement.java +++ b/vtm/src/org/oscim/renderer/elements/RenderElement.java @@ -28,9 +28,9 @@ public abstract class RenderElement extends Inlist<RenderElement> { public final static int TEXLINE = 1; public final static int POLYGON = 2; public final static int MESH = 3; - public final static int SYMBOL = 4; - public final static int BITMAP = 5; - public final static int EXTRUSION = 6; + public final static int EXTRUSION = 4; + public final static int SYMBOL = 5; + public final static int BITMAP = 6; public final int type; @@ -60,12 +60,12 @@ public abstract class RenderElement extends Inlist<RenderElement> { } public int getOffset() { - return offset; - } + return offset; + } public void setOffset(int offset) { - this.offset = offset; - } + this.offset = offset; + } /** * For line- and polygon-layers this is the offset @@ -73,4 +73,8 @@ public abstract class RenderElement extends Inlist<RenderElement> { * For all other types it is the byte offset in vbo. */ protected int offset; + + protected void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) { + + } }