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.READY;
import java.nio.ShortBuffer;
import org.oscim.backend.GL20;
import org.oscim.core.Tile;
import org.oscim.layers.tile.MapTile;
@ -191,14 +193,46 @@ 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("...");
int sumIndices = 0;
int sumVertices = 0;
for (ExtrusionLayer l = el; l != null; l = (ExtrusionLayer) l.next) {
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;
}
@ -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],

View File

@ -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;

View File

@ -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,7 +470,7 @@ public class ExtrusionLayer extends RenderElement {
rings++;
}
Tessellator.tessellate(points, ppos, len, index, ipos, rings,
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;
}

View File

@ -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;
@ -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) {
}
}