s3db: render meshes with ExtrusionRenderer
This commit is contained in:
parent
f929c15e2d
commit
a18d20a916
@ -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 = ""
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user