s3db: render meshes with ExtrusionRenderer

This commit is contained in:
Hannes Janetzek 2014-03-21 01:53:17 +01:00
parent f929c15e2d
commit a18d20a916
2 changed files with 345 additions and 88 deletions

View File

@ -37,12 +37,14 @@ public class ExtrusionRenderer extends LayerRenderer {
static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class); static final Logger log = LoggerFactory.getLogger(ExtrusionRenderer.class);
private final TileRenderer mTileLayer; private final TileRenderer mTileLayer;
private final int mTileZoom;
protected float mAlpha = 1; protected float mAlpha = 1;
public ExtrusionRenderer(TileRenderer tileRenderLayer) { public ExtrusionRenderer(TileRenderer tileRenderLayer, int tileZoom) {
mTileLayer = tileRenderLayer; mTileLayer = tileRenderLayer;
mTileSet = new TileSet(); mTileSet = new TileSet();
mTileZoom = tileZoom;
} }
private static int[] shaderProgram = new int[2]; private static int[] shaderProgram = new int[2];
@ -90,7 +92,7 @@ public class ExtrusionRenderer extends LayerRenderer {
} }
@Override @Override
protected void update(GLViewport v) { public void update(GLViewport v) {
if (!initialized && !initShader()) if (!initialized && !initShader())
return; return;
@ -98,17 +100,17 @@ public class ExtrusionRenderer extends LayerRenderer {
if (shaderProgram[0] == 0) if (shaderProgram[0] == 0)
return; return;
if (mAlpha == 0 || v.pos.zoomLevel < 16) { if (mAlpha == 0 || v.pos.zoomLevel < mTileZoom) {
setReady(false); setReady(false);
return; return;
} }
if (mUpdateColors) { // if (mUpdateColors) {
synchronized (this) { // synchronized (this) {
System.arraycopy(mNewColors, 0, mColor, 0, 16); // System.arraycopy(mNewColors, 0, mColor, 0, 16);
mUpdateColors = false; // mUpdateColors = false;
} // }
} // }
int activeTiles = 0; int activeTiles = 0;
mTileLayer.getVisibleTiles(mTileSet); mTileLayer.getVisibleTiles(mTileSet);
@ -127,7 +129,7 @@ public class ExtrusionRenderer extends LayerRenderer {
int zoom = tiles[0].zoomLevel; int zoom = tiles[0].zoomLevel;
ExtrusionLayer el; ExtrusionLayer el;
if (zoom == 17) { if (zoom == mTileZoom) {
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
el = getLayer(tiles[i]); el = getLayer(tiles[i]);
if (el == null) if (el == null)
@ -142,7 +144,31 @@ public class ExtrusionRenderer extends LayerRenderer {
if (el.compiled) if (el.compiled)
mTiles[activeTiles++] = tiles[i]; mTiles[activeTiles++] = tiles[i];
} }
} else if (zoom == 16) { } else if (zoom == mTileZoom + 1) {
O: for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = tiles[i].node.parent();
if (t == null)
continue;
for (MapTile c : mTiles)
if (c == t)
continue O;
el = getLayer(t);
if (el == null)
continue;
if (!el.compiled) {
int numShorts = el.mNumVertices * 8;
el.compile(MapRenderer.getShortBuffer(numShorts));
GLUtils.checkGlError("...");
}
if (el.compiled)
mTiles[activeTiles++] = t;
}
} else if (zoom == mTileZoom - 1) {
// check if proxy children are ready // check if proxy children are ready
for (int i = 0; i < mTileSet.cnt; i++) { for (int i = 0; i < mTileSet.cnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
@ -161,7 +187,26 @@ public class ExtrusionRenderer extends LayerRenderer {
} }
} }
// // check if proxy children are ready
// for (int i = 0; i < mTileSet.cnt; i++) {
// MapTile t = tiles[i];
// for (byte j = 0; j < 4; j++) {
// if (!t.hasProxy(1 << j))
// continue;
//
// MapTile c = t.rel.get(j);
// el = getLayer(c);
//
// if (el == null || !el.compiled)
// continue;
//
// mTiles[activeTiles++] = c;
// }
// }
// }
mTileCnt = activeTiles; mTileCnt = activeTiles;
//log.debug("" + activeTiles + " " + zoom);
if (activeTiles > 0) if (activeTiles > 0)
setReady(true); setReady(true);
@ -179,8 +224,10 @@ public class ExtrusionRenderer extends LayerRenderer {
private final boolean debug = false; private final boolean debug = false;
private final boolean drawAlpha = false;
@Override @Override
protected void render(GLViewport v) { public void render(GLViewport v) {
// 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.
@ -199,9 +246,10 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition); GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition);
GL.glUniform1i(uExtMode, 0); GL.glUniform1i(uExtMode, 0);
GLUtils.glUniform4fv(uExtColor, 4, mColor); GLUtils.glUniform4fv(uExtColor, 4, mColor);
GL.glUniform1f(uExtAlpha, 1);
GLState.test(false, false); GLState.test(false, false);
GLState.blend(true);
for (int i = 0; i < mTileCnt; i++) { for (int i = 0; i < mTileCnt; i++) {
ExtrusionLayer el = tiles[i].getLayers().getExtrusionLayers(); ExtrusionLayer el = tiles[i].getLayers().getExtrusionLayers();
@ -240,41 +288,46 @@ public class ExtrusionRenderer extends LayerRenderer {
GLState.useProgram(shaderProgram[SHADER]); GLState.useProgram(shaderProgram[SHADER]);
GLState.enableVertexArrays(uExtVertexPosition, -1); GLState.enableVertexArrays(uExtVertexPosition, -1);
if (v.pos.scale < (1 << 18)) { GLState.blend(false);
// chances are high that one moves through a building
// with scale > 2 also draw back sides in this case. GL.glEnable(GL20.GL_CULL_FACE);
GL.glEnable(GL20.GL_CULL_FACE);
}
GL.glDepthFunc(GL20.GL_LESS); GL.glDepthFunc(GL20.GL_LESS);
GL.glColorMask(false, false, false, false);
GL.glUniform1i(uExtMode, -1);
//GLUtils.glUniform4fv(uExtColor, 4, mColor);
GL.glUniform1f(uExtAlpha, mAlpha);
// draw to depth buffer //GL.glUniform1f(uExtAlpha, mAlpha);
for (int i = 0; i < mTileCnt; i++) { GL.glUniform1f(uExtAlpha, 1);
MapTile t = tiles[i];
ExtrusionLayer el = t.getLayers().getExtrusionLayers();
int d = MapTile.depthOffset(t) * 10;
setMatrix(v, t, d);
v.mvp.setAsUniform(uExtMatrix);
el.vboIndices.bind(); if (drawAlpha) {
el.vboVertices.bind();
GL.glVertexAttribPointer(uExtVertexPosition, 3, GL.glColorMask(false, false, false, false);
GL20.GL_SHORT, false, 8, 0); GL.glUniform1i(uExtMode, -1);
//GLUtils.glUniform4fv(uExtColor, 4, mColor);
GL.glDrawElements(GL20.GL_TRIANGLES, // draw to depth buffer
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]), for (int i = 0; i < mTileCnt; i++) {
GL20.GL_UNSIGNED_SHORT, 0); MapTile t = tiles[i];
ExtrusionLayer el = t.getLayers().getExtrusionLayers();
int d = MapTile.depthOffset(t) * 10;
setMatrix(v, t, d);
v.mvp.setAsUniform(uExtMatrix);
el.vboIndices.bind();
el.vboVertices.bind();
GL.glVertexAttribPointer(uExtVertexPosition, 3,
GL20.GL_SHORT, false, 8, 0);
GL.glDrawElements(GL20.GL_TRIANGLES,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]),
GL20.GL_UNSIGNED_SHORT, 0);
}
GL.glColorMask(true, true, true, true);
GL.glDepthMask(false);
GLState.blend(true);
} }
// enable color buffer, use depth mask // enable color buffer, use depth mask
GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition); GLState.enableVertexArrays(uExtVertexPosition, uExtLightPosition);
GL.glColorMask(true, true, true, true);
GL.glDepthMask(false);
GLState.blend(true);
float[] currentColor = null; float[] currentColor = null;
@ -290,8 +343,12 @@ public class ExtrusionRenderer extends LayerRenderer {
GLUtils.glUniform4fv(uExtColor, 4, currentColor); GLUtils.glUniform4fv(uExtColor, 4, currentColor);
} }
GL.glDepthFunc(GL20.GL_EQUAL); int d = 1;
int d = MapTile.depthOffset(t) * 10; if (drawAlpha) {
GL.glDepthFunc(GL20.GL_EQUAL);
d = MapTile.depthOffset(t) * 10;
}
setMatrix(v, t, d); setMatrix(v, t, d);
v.mvp.setAsUniform(uExtMatrix); v.mvp.setAsUniform(uExtMatrix);
@ -304,62 +361,75 @@ public class ExtrusionRenderer extends LayerRenderer {
GL.glVertexAttribPointer(uExtLightPosition, 2, GL.glVertexAttribPointer(uExtLightPosition, 2,
GL20.GL_UNSIGNED_BYTE, false, 8, 6); GL20.GL_UNSIGNED_BYTE, false, 8, 6);
// draw roof // draw extruded outlines
GL.glUniform1i(uExtMode, 0); if (el.mIndiceCnt[0] > 0) {
GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[2], // draw roof
GL20.GL_UNSIGNED_SHORT, (el.mIndiceCnt[0] + el.mIndiceCnt[1]) * 2); GL.glUniform1i(uExtMode, 0);
GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[2],
GL20.GL_UNSIGNED_SHORT,
(el.mIndiceCnt[0] + el.mIndiceCnt[1]) * 2);
// draw sides 1 // draw sides 1
GL.glUniform1i(uExtMode, 1); GL.glUniform1i(uExtMode, 1);
GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[0], GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[0],
GL20.GL_UNSIGNED_SHORT, 0); GL20.GL_UNSIGNED_SHORT, 0);
// draw sides 2 // draw sides 2
GL.glUniform1i(uExtMode, 2); GL.glUniform1i(uExtMode, 2);
GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[1], GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[1],
GL20.GL_UNSIGNED_SHORT, el.mIndiceCnt[0] * 2); GL20.GL_UNSIGNED_SHORT, el.mIndiceCnt[0] * 2);
// drawing gl_lines with the same coordinates does not result in if (drawAlpha) {
// same depth values as polygons, so add offset and draw gl_lequal: // drawing gl_lines with the same coordinates does not result in
GL.glDepthFunc(GL20.GL_LEQUAL); // same depth values as polygons, so add offset and draw gl_lequal:
GL.glDepthFunc(GL20.GL_LEQUAL);
}
v.mvp.addDepthOffset(100); v.mvp.addDepthOffset(100);
v.mvp.setAsUniform(uExtMatrix); v.mvp.setAsUniform(uExtMatrix);
GL.glUniform1i(uExtMode, 3); GL.glUniform1i(uExtMode, 3);
GL.glDrawElements(GL20.GL_LINES, el.mIndiceCnt[3], GL.glDrawElements(GL20.GL_LINES, el.mIndiceCnt[3],
GL20.GL_UNSIGNED_SHORT, GL20.GL_UNSIGNED_SHORT,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]) * 2); (el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]) * 2);
}
// draw triangle meshes
if (el.mIndiceCnt[4] > 0) {
int offset = (el.mIndiceCnt[0] + el.mIndiceCnt[1]
+ el.mIndiceCnt[2] + el.mIndiceCnt[3]) * 2;
GL.glUniform1i(uExtMode, 4);
GL.glDrawElements(GL20.GL_TRIANGLES, el.mIndiceCnt[4],
GL20.GL_UNSIGNED_SHORT, offset);
}
// just a temporary reference! // just a temporary reference!
tiles[i] = null; tiles[i] = null;
} }
if (v.pos.scale < (1 << 18)) GL.glDepthMask(false);
GL.glDisable(GL20.GL_CULL_FACE); GL.glDisable(GL20.GL_CULL_FACE);
GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0); GL.glBindBuffer(GL20.GL_ELEMENT_ARRAY_BUFFER, 0);
mTileLayer.releaseTiles(mTileSet); mTileLayer.releaseTiles(mTileSet);
} }
private static void setMatrix(GLViewport m, private static void setMatrix(GLViewport v, MapTile tile, int delta) {
MapTile tile, int delta) {
int z = tile.zoomLevel; int z = tile.zoomLevel;
double curScale = Tile.SIZE * m.pos.scale; double curScale = Tile.SIZE * v.pos.scale;
float scale = (float) (m.pos.scale / (1 << z)); float scale = (float) (v.pos.scale / (1 << z));
float x = (float) ((tile.x - m.pos.x) * curScale); float x = (float) ((tile.x - v.pos.x) * curScale);
float y = (float) ((tile.y - m.pos.y) * curScale); float y = (float) ((tile.y - v.pos.y) * curScale);
m.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE); v.mvp.setTransScale(x, y, scale / MapRenderer.COORD_SCALE);
// scale height // scale height ???
m.mvp.setValue(10, scale / 10); v.mvp.setValue(10, scale / 10);
m.mvp.multiplyLhs(m.viewproj); v.mvp.multiplyLhs(v.viewproj);
m.mvp.addDepthOffset(delta); v.mvp.addDepthOffset(delta);
} }
public synchronized void setColors(float[] colors) { public synchronized void setColors(float[] colors) {
@ -394,7 +464,7 @@ public class ExtrusionRenderer extends LayerRenderer {
mNewColors[15] = Color.aToFloat(lines); mNewColors[15] = Color.aToFloat(lines);
} }
private boolean mUpdateColors; private volatile boolean mUpdateColors;
private final float[] mNewColors = new float[16]; private final float[] mNewColors = new float[16];
private final float _a = 0.88f; private final float _a = 0.88f;
@ -404,6 +474,7 @@ public class ExtrusionRenderer extends LayerRenderer {
private final float _o = 20; private final float _o = 20;
private final float _s = 4; private final float _s = 4;
private final float _l = 0; private final float _l = 0;
private final float[] mColor = { private final float[] mColor = {
// roof color // roof color
_a * ((_r + _l) / 255), _a * ((_r + _l) / 255),
@ -445,10 +516,10 @@ public class ExtrusionRenderer extends LayerRenderer {
+ " if (u_mode == -1) ;" + " if (u_mode == -1) ;"
// roof / depth pass // roof / depth pass
//+ " color = u_color[0] * u_alpha;" //+ " color = u_color[0] * u_alpha;"
+ " else if (u_mode == 0)" + " else if (u_mode == 0){"
// roof / depth pass // roof / depth pass
+ " color = u_color[0] * u_alpha;" + " color = u_color[0] * u_alpha;"
+ " else {" + " } else {"
// decrease contrast with distance // decrease contrast with distance
+ " if (u_mode == 1){" + " if (u_mode == 1){"
// sides 1 - use 0xff00 // sides 1 - use 0xff00
@ -467,10 +538,22 @@ public class ExtrusionRenderer extends LayerRenderer {
+ " color = u_color[2];" + " color = u_color[2];"
+ " color.rgb *= (0.8 + dir * 0.2) * z * h;" + " color.rgb *= (0.8 + dir * 0.2) * z * h;"
+ " color *= u_alpha;" + " color *= u_alpha;"
+ " } else {" + " } else if (u_mode == 3) {"
// outline // outline
+ " float z = (0.98 - gl_Position.z * 0.02);" + " float z = (0.98 - gl_Position.z * 0.02);"
+ " color = u_color[3] * z;" + " color = u_color[3] * z;"
+ " } else {"
// normalize face x/y direction
+ " vec2 n = (a_light / 255.0 - 0.5) * 2.0;"
// normal points up or down (1,-1)
+ " float dir = 1.0 - (2.0 * abs(mod(a_light.x,2.0)));"
// recreate face normal vector
+ " vec3 r_norm = vec3(n.xy, dir * (1.0 - length(n.xy)));"
+ " vec3 light = normalize(vec3(-0.4,0.4,-1.0));"
+ " float l = (1.0 + dot(r_norm, light)) / 2.0;"
+ " l = 0.4 + l * 0.6;"
+ " l = (l + (0.9 + clamp(a_pos.z / 4096.0, 0.0, 0.2))) / 2.0;"
+ " color = vec4(l, l, l-0.02, 1.0);"
+ "}}}"; + "}}}";
final static String extrusionFragmentShader = "" final static String extrusionFragmentShader = ""

View File

@ -21,10 +21,12 @@ import java.nio.ShortBuffer;
import org.oscim.backend.GL20; import org.oscim.backend.GL20;
import org.oscim.backend.GLAdapter; import org.oscim.backend.GLAdapter;
import org.oscim.core.GeometryBuffer; import org.oscim.core.GeometryBuffer;
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.BufferObject;
import org.oscim.renderer.MapRenderer; import org.oscim.renderer.MapRenderer;
import org.oscim.utils.FastMath;
import org.oscim.utils.Tessellator; import org.oscim.utils.Tessellator;
import org.oscim.utils.geom.LineClipper; import org.oscim.utils.geom.LineClipper;
import org.oscim.utils.pool.Inlist; import org.oscim.utils.pool.Inlist;
@ -50,7 +52,7 @@ public class ExtrusionLayer extends RenderElement {
// indices for: // indices for:
// 0. even sides, 1. odd sides, 2. roof, 3. roof outline // 0. even sides, 1. odd sides, 2. roof, 3. roof outline
public int mIndiceCnt[] = { 0, 0, 0, 0 }; public int mIndiceCnt[] = { 0, 0, 0, 0, 0 };
public int mNumIndices = 0; public int mNumIndices = 0;
public int mNumVertices = 0; public int mNumVertices = 0;
@ -61,10 +63,15 @@ public class ExtrusionLayer extends RenderElement {
//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;
private final static int IND_OUTLINE = 3; private final static int IND_OUTLINE = 3;
private final static int IND_MESH = 4;
private static final int NORMAL_DIR_MASK = 0xFFFFFFFE;
public boolean compiled = false; public boolean compiled = false;
private final float mGroundResolution; private final float mGroundResolution;
boolean filled;
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;
@ -73,14 +80,179 @@ public class ExtrusionLayer extends RenderElement {
mGroundResolution = groundResolution; mGroundResolution = groundResolution;
mVertices = mCurVertices = VertexItem.pool.get(); mVertices = mCurVertices = VertexItem.pool.get();
mIndices = new VertexItem[4]; mIndices = new VertexItem[5];
mCurIndices = new VertexItem[4]; mCurIndices = new VertexItem[5];
for (int i = 0; i < 4; i++) for (int i = 0; i <= IND_MESH; i++)
mIndices[i] = mCurIndices[i] = VertexItem.pool.get(); mIndices[i] = mCurIndices[i] = VertexItem.pool.get();
mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE); mClipper = new LineClipper(0, 0, Tile.SIZE, Tile.SIZE);
} }
public void add(MapElement element) {
if (element.type != GeometryType.TRIS)
return;
short[] index = element.index;
float[] points = element.points;
// roof indices for convex shapes
int i = mCurIndices[IND_MESH].used;
short[] indices = mCurIndices[IND_MESH].vertices;
int first = mNumVertices;
short[] vertices = mCurVertices.vertices;
int v = mCurVertices.used;
int vertexCnt = 0;
for (int k = 0, n = index.length; k < n;) {
if (index[k] < 0)
break;
// FIXME: workaround: dont overflow max index id.
if (mNumVertices + vertexCnt >= 1 << 16)
break;
if (i == VertexItem.SIZE) {
mCurIndices[IND_MESH].used = VertexItem.SIZE;
mCurIndices[IND_MESH].next = VertexItem.pool.get();
mCurIndices[IND_MESH] = mCurIndices[IND_MESH].next;
indices = mCurIndices[IND_MESH].vertices;
i = 0;
}
indices[i++] = (short) (first + vertexCnt);
indices[i++] = (short) (first + vertexCnt + 1);
indices[i++] = (short) (first + vertexCnt + 2);
int vtx1 = index[k++] * 3;
int vtx2 = index[k++] * 3;
int vtx3 = index[k++] * 3;
float vx1 = points[vtx1 + 0];
float vy1 = points[vtx1 + 1];
float vz1 = points[vtx1 + 2];
float vx2 = points[vtx2 + 0];
float vy2 = points[vtx2 + 1];
float vz2 = points[vtx2 + 2];
float vx3 = points[vtx3 + 0];
float vy3 = points[vtx3 + 1];
float vz3 = points[vtx3 + 2];
float ax = vx2 - vx1;
float ay = vy2 - vy1;
float az = vz2 - vz1;
float bx = vx3 - vx1;
float by = vy3 - vy1;
float bz = vz3 - vz1;
float cx = ay * bz - az * by;
float cy = az * bx - ax * bz;
float cz = ax * by - ay * bx;
double len = Math.sqrt(cx * cx + cy * cy + cz * cz);
// packing the normal in two bytes
int mx = FastMath.clamp(127 + (int) ((cx / len) * 128), 0, 0xff);
int my = FastMath.clamp(127 + (int) ((cy / len) * 128), 0, 0xff);
short normal = (short) ((my << 8) | (mx & NORMAL_DIR_MASK) | (cz > 0 ? 1 : 0));
if (v == VertexItem.SIZE) {
mCurVertices.used = VertexItem.SIZE;
mCurVertices.next = VertexItem.pool.get();
mCurVertices = mCurVertices.next;
vertices = mCurVertices.vertices;
v = 0;
}
double s = S * Tile.SIZE / 4096;
vertices[v++] = (short) (vx1 * s);
vertices[v++] = (short) (vy1 * s);
vertices[v++] = (short) (vz1 * s);
vertices[v++] = (short) normal;
vertices[v++] = (short) (vx2 * s);
vertices[v++] = (short) (vy2 * s);
vertices[v++] = (short) (vz2 * s);
vertices[v++] = (short) normal;
vertices[v++] = (short) (vx3 * s);
vertices[v++] = (short) (vy3 * s);
vertices[v++] = (short) (vz3 * s);
vertices[v++] = (short) normal;
vertexCnt += 3;
}
mCurIndices[IND_MESH].used = i;
mCurVertices.used = v;
mNumVertices += vertexCnt; //(vertexCnt / 3);
}
public void addNoNormal(MapElement element) {
if (element.type != GeometryType.TRIS)
return; //FIXME throw
short[] index = element.index;
float[] points = element.points;
//log.debug("add " + Arrays.toString(index));
//log.debug("add " + Arrays.toString(points));
// current vertex id
int startVertex = mNumVertices;
// roof indices for convex shapes
int i = mCurIndices[IND_MESH].used;
short[] indices = mCurIndices[IND_MESH].vertices;
int first = startVertex;
for (int k = 0, n = index.length; k < n;) {
if (index[k] < 0)
break;
if (i == VertexItem.SIZE) {
mCurIndices[IND_MESH].used = VertexItem.SIZE;
mCurIndices[IND_MESH].next = VertexItem.pool.get();
mCurIndices[IND_MESH] = mCurIndices[IND_MESH].next;
indices = mCurIndices[IND_MESH].vertices;
i = 0;
}
indices[i++] = (short) (first + index[k++]);
indices[i++] = (short) (first + index[k++]);
indices[i++] = (short) (first + index[k++]);
}
mCurIndices[IND_MESH].used = i;
short[] vertices = mCurVertices.vertices;
int v = mCurVertices.used;
int vertexCnt = element.pointPos;
for (int j = 0; j < vertexCnt;) {
/* add bottom and top vertex for each point */
if (v == VertexItem.SIZE) {
mCurVertices.used = VertexItem.SIZE;
mCurVertices.next = VertexItem.pool.get();
mCurVertices = mCurVertices.next;
vertices = mCurVertices.vertices;
v = 0;
}
// set coordinate
vertices[v++] = (short) (points[j++] * S);
vertices[v++] = (short) (points[j++] * S);
vertices[v++] = (short) (points[j++] * S);
v++;
}
mCurVertices.used = v;
mNumVertices += (vertexCnt / 3);
}
public void add(MapElement element, float height, float minHeight) { public void add(MapElement element, float height, float minHeight) {
short[] index = element.index; short[] index = element.index;
@ -156,7 +328,7 @@ public class ExtrusionLayer extends RenderElement {
if (i == VertexItem.SIZE) { if (i == VertexItem.SIZE) {
mCurIndices[IND_ROOF].used = VertexItem.SIZE; mCurIndices[IND_ROOF].used = VertexItem.SIZE;
mCurIndices[IND_ROOF].next = VertexItem.pool.get(); mCurIndices[IND_ROOF].next = VertexItem.pool.get();
mCurIndices[IND_ROOF] = mCurIndices[2].next; mCurIndices[IND_ROOF] = mCurIndices[IND_ROOF].next;
indices = mCurIndices[IND_ROOF].vertices; indices = mCurIndices[IND_ROOF].vertices;
i = 0; i = 0;
} }
@ -367,7 +539,7 @@ public class ExtrusionLayer extends RenderElement {
return; return;
mNumIndices = 0; mNumIndices = 0;
for (int i = 0; i < 4; 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); sbuf.put(vi.vertices, 0, vi.used);
mIndiceCnt[i] += vi.used; mIndiceCnt[i] += vi.used;
@ -375,6 +547,8 @@ public class ExtrusionLayer extends RenderElement {
mNumIndices += mIndiceCnt[i]; mNumIndices += mIndiceCnt[i];
} }
//log.debug("compile" + mNumIndices + " / " + mNumVertices);
int size = mNumIndices * 2; int size = mNumIndices * 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(sbuf.flip(), size);
@ -405,7 +579,7 @@ public class ExtrusionLayer extends RenderElement {
vboIndices = BufferObject.release(vboIndices); vboIndices = BufferObject.release(vboIndices);
vboVertices = BufferObject.release(vboVertices); vboVertices = BufferObject.release(vboVertices);
} else { } else {
for (int i = 0; i < 4; 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;