compile extrusion layers into one vbo

This commit is contained in:
Hannes Janetzek 2014-03-17 00:27:26 +01:00
parent 0a76dafd9c
commit bda73374ca
4 changed files with 142 additions and 68 deletions

View File

@ -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.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;
@ -191,14 +193,46 @@ public class ExtrusionRenderer extends LayerRenderer {
return true; return true;
boolean compiled = false; boolean compiled = false;
for (; el != null; el = (ExtrusionLayer) el.next) {
if (!el.compiled) { int sumIndices = 0;
int numShorts = el.sumVertices * 8; int sumVertices = 0;
el.compile(MapRenderer.getShortBuffer(numShorts)); for (ExtrusionLayer l = el; l != null; l = (ExtrusionLayer) l.next) {
GLUtils.checkGlError("..."); sumIndices += l.sumIndices;
sumVertices += l.sumVertices;
} }
compiled |= el.compiled;
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; return compiled;
} }
@ -238,7 +272,6 @@ public class ExtrusionRenderer extends LayerRenderer {
int offset = sumIndices * 2; int offset = sumIndices * 2;
GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4], GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4],
GL20.GL_UNSIGNED_SHORT, offset); GL20.GL_UNSIGNED_SHORT, offset);
} }
} }
} }
@ -337,6 +370,9 @@ public class ExtrusionRenderer extends LayerRenderer {
if (el == null) if (el == null)
continue; continue;
if (el.vboIndices == null)
continue;
int d = 1; int d = 1;
if (drawAlpha) { if (drawAlpha) {
GL.glDepthFunc(GL20.GL_EQUAL); GL.glDepthFunc(GL20.GL_EQUAL);
@ -346,10 +382,10 @@ public class ExtrusionRenderer extends LayerRenderer {
setMatrix(v, t, d); setMatrix(v, t, d);
v.mvp.setAsUniform(uExtMatrix); v.mvp.setAsUniform(uExtMatrix);
for (; el != null; el = (ExtrusionLayer) el.next) { el.vboIndices.bind();
el.vboVertices.bind();
if (el.vboIndices == null) for (; el != null; el = (ExtrusionLayer) el.next) {
continue;
if (el.colors != currentColor) { if (el.colors != currentColor) {
currentColor = el.colors; currentColor = el.colors;
@ -357,14 +393,16 @@ public class ExtrusionRenderer extends LayerRenderer {
el.colors); el.colors);
} }
el.vboIndices.bind(); /* indices offset */
el.vboVertices.bind(); int indexOffset = el.indexOffset;
/* vertex byte offset */
int vertexOffset = el.getOffset();
GL.glVertexAttribPointer(uExtVertexPosition, 3, GL.glVertexAttribPointer(uExtVertexPosition, 3,
GL20.GL_SHORT, false, 8, 0); GL20.GL_SHORT, false, 8, vertexOffset);
GL.glVertexAttribPointer(uExtLightPosition, 2, GL.glVertexAttribPointer(uExtLightPosition, 2,
GL20.GL_UNSIGNED_BYTE, false, 8, 6); GL20.GL_UNSIGNED_BYTE, false, 8, vertexOffset + 6);
/* draw extruded outlines */ /* draw extruded outlines */
if (el.numIndices[0] > 0) { if (el.numIndices[0] > 0) {
@ -395,16 +433,23 @@ public class ExtrusionRenderer extends LayerRenderer {
v.mvp.setAsUniform(uExtMatrix); v.mvp.setAsUniform(uExtMatrix);
GL.glUniform1i(uExtMode, 3); 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], GL.glDrawElements(GL20.GL_LINES, el.numIndices[3],
GL20.GL_UNSIGNED_SHORT, GL20.GL_UNSIGNED_SHORT, offset);
(el.numIndices[0] + el.numIndices[1]
+ el.numIndices[2]) * 2);
} }
/* draw triangle meshes */ /* draw triangle meshes */
if (el.numIndices[4] > 0) { if (el.numIndices[4] > 0) {
int offset = (el.numIndices[0] + el.numIndices[1] int offset = 2 * (indexOffset
+ el.numIndices[2] + el.numIndices[3]) * 2; + el.numIndices[0]
+ el.numIndices[1]
+ el.numIndices[2]
+ el.numIndices[3]);
GL.glUniform1i(uExtMode, 4); GL.glUniform1i(uExtMode, 4);
GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4], GL.glDrawElements(GL20.GL_TRIANGLES, el.numIndices[4],

View File

@ -269,16 +269,18 @@ public class ElementLayers extends TileData {
return layer; return layer;
} }
private final static int[] VERTEX_SHORT_CNT = { public final static int[] VERTEX_SHORT_CNT = {
4, // LINE_VERTEX_SHORTS 4, // LINE_VERTEX
6, // TEXLINE_VERTEX_SHORTS 6, // TEXLINE_VERTEX
2, // POLY_VERTEX_SHORTS 2, // POLY_VERTEX
2, // MESH_VERTEX_SHORTS 2, // MESH_VERTEX
4, // EXTRUSION_VERTEX
}; };
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;
// TODO move to specific layer implementation
public int getSize() { public int getSize() {
int size = 0; int size = 0;

View File

@ -19,8 +19,6 @@ package org.oscim.renderer.elements;
import java.nio.ShortBuffer; import java.nio.ShortBuffer;
import java.util.HashMap; import java.util.HashMap;
import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter;
import org.oscim.backend.canvas.Color; import org.oscim.backend.canvas.Color;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;
import org.oscim.core.GeometryBuffer.GeometryType; 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 numIndices[] = { 0, 0, 0, 0, 0 };
//public int sumIndices = 0; //public int sumIndices = 0;
public int sumVertices = 0; public int sumVertices = 0;
public int sumIndices = 0;
public BufferObject vboIndices; public BufferObject vboIndices;
public BufferObject vboVertices; 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_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;
// FIXME flip OUTLINE / MESH!
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;
@ -68,8 +69,18 @@ public class ExtrusionLayer extends RenderElement {
public boolean compiled = false; public boolean compiled = false;
private final float mGroundResolution; 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) { public ExtrusionLayer(int level, float groundResolution, float[] colors) {
super(RenderElement.EXTRUSION); super(RenderElement.EXTRUSION);
this.level = level; 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) { public ExtrusionLayer(int level, float groundResolution, int color) {
super(RenderElement.EXTRUSION); 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) { public void add(MapElement element) {
if (element.type != GeometryType.TRIS) if (element.type != GeometryType.TRIS)
return; return;
@ -221,7 +228,7 @@ public class ExtrusionLayer extends RenderElement {
addIndex(vertexCnt); addIndex(vertexCnt);
mVertexMap.put(new Vertex(key), vertexCnt++); mVertexMap.put(new Vertex(key), vertexCnt++);
} else { } else {
numIndexHits++; //numIndexHits++;
addIndex(vertexId.intValue()); addIndex(vertexId.intValue());
} }
@ -236,7 +243,7 @@ public class ExtrusionLayer extends RenderElement {
addIndex(vertexCnt); addIndex(vertexCnt);
mVertexMap.put(new Vertex(key), vertexCnt++); mVertexMap.put(new Vertex(key), vertexCnt++);
} else { } else {
numIndexHits++; //numIndexHits++;
addIndex(vertexId.intValue()); addIndex(vertexId.intValue());
} }
@ -251,7 +258,7 @@ public class ExtrusionLayer extends RenderElement {
addIndex(vertexCnt); addIndex(vertexCnt);
mVertexMap.put(new Vertex(key), vertexCnt++); mVertexMap.put(new Vertex(key), vertexCnt++);
} else { } else {
numIndexHits++; //numIndexHits++;
addIndex(vertexId.intValue()); addIndex(vertexId.intValue());
} }
} }
@ -264,8 +271,9 @@ public class ExtrusionLayer extends RenderElement {
if (vi.used == VertexItem.SIZE) { if (vi.used == VertexItem.SIZE) {
mCurVertices.used = VertexItem.SIZE; mCurVertices.used = VertexItem.SIZE;
mCurVertices.next = VertexItem.pool.get(); mCurVertices = VertexItem.pool.getNext(vi);
mCurVertices = mCurVertices.next; //mCurVertices.next = VertexItem.pool.get();
//mCurVertices = mCurVertices.next;
vi = mCurVertices; vi = mCurVertices;
} }
@ -280,12 +288,16 @@ public class ExtrusionLayer extends RenderElement {
if (vi.used == VertexItem.SIZE) { if (vi.used == VertexItem.SIZE) {
mCurIndices[IND_MESH].used = VertexItem.SIZE; mCurIndices[IND_MESH].used = VertexItem.SIZE;
mCurIndices[IND_MESH].next = VertexItem.pool.get(); mCurIndices[IND_MESH] = VertexItem.pool.getNext(vi);
mCurIndices[IND_MESH] = mCurIndices[IND_MESH].next;
vi = mCurIndices[IND_MESH]; 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; //indices = mCurIndices[IND_MESH].vertices;
//i = 0; //i = 0;
} }
sumIndices++;
vi.vertices[vi.used++] = (short) id; vi.vertices[vi.used++] = (short) id;
} }
@ -436,9 +448,11 @@ public class ExtrusionLayer extends RenderElement {
indices = mCurIndices[IND_ROOF].vertices; indices = mCurIndices[IND_ROOF].vertices;
i = 0; i = 0;
} }
indices[i++] = first; indices[i++] = first;
indices[i++] = (short) (first + k + 2); indices[i++] = (short) (first + k + 2);
indices[i++] = (short) (first + k + 4); indices[i++] = (short) (first + k + 4);
sumIndices += 3;
} }
mCurIndices[IND_ROOF].used = i; mCurIndices[IND_ROOF].used = i;
} }
@ -456,7 +470,7 @@ public class ExtrusionLayer extends RenderElement {
rings++; rings++;
} }
Tessellator.tessellate(points, ppos, len, index, ipos, rings, sumIndices += Tessellator.tessellate(points, ppos, len, index, ipos, rings,
startVertex + 1, mCurIndices[IND_ROOF]); startVertex + 1, mCurIndices[IND_ROOF]);
mCurIndices[IND_ROOF] = Inlist.last(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 + 3] = s1;
indices[ind + 4] = s2; indices[ind + 4] = s2;
indices[ind + 5] = s3; indices[ind + 5] = s3;
sumIndices += 6;
mCurIndices[even].used += 6; mCurIndices[even].used += 6;
even = (even == 0 ? 1 : 0); even = (even == 0 ? 1 : 0);
@ -636,44 +651,52 @@ public class ExtrusionLayer extends RenderElement {
return convex; return convex;
} }
@Override public void complete() {
public void compile(ShortBuffer sbuf) {
mVertexMap.clear(); mVertexMap.clear();
}
@Override
public void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) {
mVertexMap.clear();
if (sumVertices == 0 || compiled) if (sumVertices == 0 || compiled)
return; return;
int sumIndices = 0; indexOffset = indexBuffer.position();
//int sumIndices = 0;
for (int i = 0; i <= IND_MESH; i++) { for (int i = 0; i <= IND_MESH; i++) {
for (VertexItem vi = mIndices[i]; vi != null; vi = vi.next) { 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; numIndices[i] += vi.used;
} }
sumIndices += numIndices[i]; //sumIndices += numIndices[i];
} }
//log.debug("INDEX HITS " + numIndexHits + " / " + sumVertices + " / " + sumIndices); //log.debug("INDEX HITS " + numIndexHits + " / " + sumVertices + " / " + sumIndices);
int size = sumIndices * 2; //int size = sumIndices * 2;
vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size); //vboIndices = BufferObject.get(GL20.GL_ELEMENT_ARRAY_BUFFER, size);
vboIndices.loadBufferData(sbuf.flip(), size); //vboIndices.loadBufferData(vertexBuffer.flip(), size);
//
GL20 GL = GLAdapter.get(); //GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
// upload vertices // upload vertices
sbuf.clear(); //vertexBuffer.clear();
offset = vertexBuffer.position() * 2;
for (VertexItem vi = mVertices; vi != null; vi = vi.next) 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; // size = sumVertices * 4 * 2;
vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size); // vboVertices = BufferObject.get(GL20.GL_ARRAY_BUFFER, size);
vboVertices.loadBufferData(sbuf.flip(), size); // vboVertices.loadBufferData(vertexBuffer.flip(), size);
//
GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0); // GL.glBindBuffer(GL20.GL_ARRAY_BUFFER, 0);
clear(); clear();
compiled = true; compiled = true;
mClipper = null; mClipper = null;
} }

View File

@ -28,9 +28,9 @@ public abstract class RenderElement extends Inlist<RenderElement> {
public final static int TEXLINE = 1; public final static int TEXLINE = 1;
public final static int POLYGON = 2; public final static int POLYGON = 2;
public final static int MESH = 3; public final static int MESH = 3;
public final static int SYMBOL = 4; public final static int EXTRUSION = 4;
public final static int BITMAP = 5; public final static int SYMBOL = 5;
public final static int EXTRUSION = 6; public final static int BITMAP = 6;
public final int type; public final int type;
@ -73,4 +73,8 @@ public abstract class RenderElement extends Inlist<RenderElement> {
* For all other types it is the byte offset in vbo. * For all other types it is the byte offset in vbo.
*/ */
protected int offset; protected int offset;
protected void compile(ShortBuffer vertexBuffer, ShortBuffer indexBuffer) {
}
} }