- add building roof outlines

- create extrusion vertices and indices in one loop
This commit is contained in:
Hannes Janetzek 2013-01-04 08:53:18 +01:00
parent c01252f249
commit d5ba228fe5
2 changed files with 107 additions and 149 deletions

View File

@ -39,13 +39,13 @@ public class ExtrusionLayer extends Layer {
private VertexPoolItem mIndices[], mCurIndices[];
private LineClipper mClipper;
public int mIndiceCnt[] = { 0, 0, 0 };
public int mIndiceCnt[] = { 0, 0, 0, 0 };
public int mIndicesBufferID;
public int mVertexBufferID;
public int mNumIndices = 0;
private final static int IND_EVEN_SIDE = 0;
private final static int IND_ODD_SIDE = 1;
//private final static int IND_EVEN_SIDE = 0;
//private final static int IND_ODD_SIDE = 1;
private final static int IND_ROOF = 2;
private final static int IND_OUTLINE = 3;
@ -187,31 +187,38 @@ public class ExtrusionLayer extends Layer {
float nx = points[pos + 0];
float ny = points[pos + 1];
// vector to next point
float vx = nx - cx;
float vy = ny - cy;
float ca = (float) Math.sqrt(vx * vx + vy * vy);
float ux = vx;
float uy = vy;
// vector from previous point
float ux, uy;
float ca = (float) Math.sqrt(vx * vx + vy * vy);
float vlight = vx > 0 ? (vx / ca) : -(vx / ca) - 0.1f;
short color1 = (short) (200 + (50 * vlight));
short fcolor = color1;
short color2 = 0;
boolean even = true;
int even = 0;
int changeX = 0;
int changeY = 0;
// vertex offset for all vertices in layer
int vOffset = mNumVertices;
short[] vertices = mCurVertices.vertices;
int v = mCurVertices.used;
for (int i = 2; i < len + 2; i += 2, v += 8) {
for (int i = 2, n = vertexCnt + 2; i < n; i += 2, v += 8) {
/* add bottom and top vertex for each point */
cx = nx;
cy = ny;
ux = vx;
uy = vy;
if (v == VertexPoolItem.SIZE) {
mCurVertices.used = VertexPoolItem.SIZE;
mCurVertices.next = VertexPool.get();
@ -232,28 +239,35 @@ public class ExtrusionLayer extends Layer {
if (i < len) {
nx = points[pos + i + 0];
ny = points[pos + i + 1];
} else {
} else if (i == len) {
nx = points[pos + 0];
ny = points[pos + 1];
//color2 = fcolor;
} else { // if (addFace)
short c = (short) (color1 | fcolor << 8);
vertices[v + 3] = vertices[v + 7] = c;
v += 8;
break;
}
// vector to next point
vx = nx - cx;
vy = ny - cy;
ca = (float) Math.sqrt(vx * vx + vy * vy);
ca = (float) Math.sqrt(vx * vx + vy * vy);
vlight = vx > 0 ? (vx / ca) : -(vx / ca) - 0.1f;
color2 = (short) (200 + (50 * vlight));
short c;
if (even)
if (even == 0)
c = (short) (color1 | color2 << 8);
else
c = (short) (color2 | color1 << 8);
// set lighting (direction)
vertices[v + 3] = vertices[v + 7] = c;
color1 = color2;
// check if polygon is convex
if (convex) {
// TODO simple polys with only one concave arc
// could be handled without special triangulation
@ -267,113 +281,59 @@ public class ExtrusionLayer extends Layer {
convex = false;
}
ux = vx;
uy = vy;
color1 = color2;
even = !even;
}
if (addFace) {
if (v == VertexPoolItem.SIZE) {
mCurVertices.used = VertexPoolItem.SIZE;
mCurVertices.next = VertexPool.get();
mCurVertices = mCurVertices.next;
vertices = mCurVertices.vertices;
v = 0;
// check if face is within tile
if (!mClipper.clip((int) cx, (int) cy, (int) nx, (int) ny)) {
even = (even + 1) % 2;
continue;
}
cx = points[pos + 0];
cy = points[pos + 1];
// add ZigZagQuadIndices(tm) for sides
short[] indices = mCurIndices[even].vertices;
// index id relative to mCurIndices item
int ind = mCurIndices[even].used;
short vert = (short) (vOffset + (i - 2));
short s0 = vert++;
short s1 = vert++;
short s2 = vert++;
short s3 = vert++;
vertices[v + 0] = vertices[v + 4] = (short) (cx * S);
vertices[v + 1] = vertices[v + 5] = (short) (cy * S);
if (ind == VertexPoolItem.SIZE) {
//mCurIndices[even].used = VertexPoolItem.SIZE;
mCurIndices[even].next = VertexPool.get();
mCurIndices[even] = mCurIndices[even].next;
indices = mCurIndices[even].vertices;
ind = 0;
}
vertices[v + 2] = 0;
vertices[v + 6] = h;
// connect last to first (when number of faces is even)
if (!addFace && i == len) {
s2 -= len;
s3 -= len;
}
short c = (short) (color1 | fcolor << 8);
vertices[v + 3] = vertices[v + 7] = c;
indices[ind + 0] = s0;
indices[ind + 1] = s1;
indices[ind + 2] = s2;
v += 8;
indices[ind + 3] = s1;
indices[ind + 4] = s3;
indices[ind + 5] = s2;
mCurIndices[even].used += 6;
even = (even + 1) % 2;
// add outline indices
VertexPoolItem it = mCurIndices[IND_OUTLINE];
if (it.used == VertexPoolItem.SIZE) {
it.next = VertexPool.get();
it = mCurIndices[IND_OUTLINE] = it.next;
}
it.vertices[it.used++] = s1;
it.vertices[it.used++] = s3;
}
mCurVertices.used = v;
// fill ZigZagQuadIndices(tm) and outline indices
for (int j = 0; j < 2; j++) {
short[] indices = mCurIndices[j].vertices;
// index id relative to mCurIndices
int i = mCurIndices[j].used;
// vertex id
v = mNumVertices + (j * 2);
int ppos = pos + (j * 2);
for (int k = j * 2; k < len; k += 4, ppos += 4) {
boolean accept;
if (k + 2 < len) {
accept = mClipper.clip(
(int) points[ppos],
(int) points[ppos + 1],
(int) points[ppos + 2],
(int) points[ppos + 3]);
} else {
accept = mClipper.clip(
(int) points[ppos],
(int) points[ppos + 1],
(int) points[pos + 0],
(int) points[pos + 1]);
}
if (!accept) {
// Log.d(TAG, "omit line: "
// + points[ppos] + ":" + points[ppos + 1] + " "
// + points[ppos + 2] + ":" + points[ppos + 3]);
v += 4;
continue;
}
short s0 = (short) (v++);
short s1 = (short) (v++);
short s2 = (short) (v++);
short s3 = (short) (v++);
if (i == VertexPoolItem.SIZE) {
mCurIndices[j].used = VertexPoolItem.SIZE;
mCurIndices[j].next = VertexPool.get();
mCurIndices[j] = mCurIndices[j].next;
indices = mCurIndices[j].vertices;
i = 0;
}
if (k + 2 == len) {
// connect last to first (when number of faces is even)
if (!addFace) {
//Log.d(TAG, "connect last " + vertexCnt + " " + len);
s2 -= len;
s3 -= len;
}
}
indices[i++] = s0;
indices[i++] = s1;
indices[i++] = s2;
indices[i++] = s1;
indices[i++] = s3;
indices[i++] = s2;
//System.out.println(" i:" + (mNumIndices + (k * 6))
// + "\t(" + s0 + "," + s1 + "," + s2
// + ")\t(" + s1 + "," + s3 + "," + s2 + ")");
// outline[cOut++] = s1;
// outline[cOut++] = s3;
}
mCurIndices[j].used = i;
}
mNumVertices += vertexCnt;
return convex;
}
@ -391,33 +351,24 @@ public class ExtrusionLayer extends Layer {
// upload indices
sbuf.clear();
for (int i = 0; i < 3; i++) {
mNumIndices = 0;
for (int i = 0; i < 4; i++) {
for (VertexPoolItem vi = mIndices[i]; vi != null; vi = vi.next) {
//System.out.println("put indices: " + vi.used + " " + mNumIndices);
sbuf.put(vi.vertices, 0, vi.used);
mIndiceCnt[i] += vi.used;
}
mNumIndices += mIndiceCnt[i];
}
// Log.d(TAG,"put indices: " + mNumIndices + "=="
// + (mIndiceCnt[0] + mIndiceCnt[1] + mIndiceCnt[2])
// + " " + mIndiceCnt[0] + " " + mIndiceCnt[1] + " " + mIndiceCnt[2]);
mNumIndices = mIndiceCnt[0] + mIndiceCnt[1] + mIndiceCnt[2];
sbuf.flip();
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
mNumIndices * 2, sbuf, GLES20.GL_DYNAMIC_DRAW);
sbuf.clear();
// upload vertices
for (VertexPoolItem vi = mVertices; vi != null; vi = vi.next) {
//System.out.println("put vertices: " + vi.used + " " + mNumVertices);
sbuf.clear();
for (VertexPoolItem vi = mVertices; vi != null; vi = vi.next)
sbuf.put(vi.vertices, 0, vi.used);
}
sbuf.flip();
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);

View File

@ -150,13 +150,22 @@ public class BuildingOverlay2 extends RenderOverlay {
GLES20.glVertexAttribPointer(hBuildingLightPosition, 2,
GLES20.GL_UNSIGNED_BYTE, false, 8, 6);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mNumIndices,
GLES20.glUniform4f(hBuildingColor, 0.6f, 0.6f, 0.6f, 0.8f);
GLES20.glDrawElements(GLES20.GL_TRIANGLES,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]),
GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glUniform1i(hBuildingMode, 0);
GLES20.glUniform4f(hBuildingColor, 1.0f, 0.5f, 0.5f, 0.9f);
GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3],
GLES20.GL_UNSIGNED_SHORT,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]) * 2);
}
return;
}
int drawCount = 0;
//int drawCount = 2;
// draw to depth buffer
MapTile[] tiles = mTileSet.tiles;
for (int i = 0; i < mTileSet.cnt; i++) {
@ -183,13 +192,14 @@ public class BuildingOverlay2 extends RenderOverlay {
GLES20.glUniform1i(hBuildingMode, 0);
first = false;
}
GLES20.glPolygonOffset(1, 10);
GLES20.glPolygonOffset(0, drawCount += 10);
// seems there are not infinite offset units possible
// this should suffice for at least two rows, i.e.
// having not two neighbours with the same depth
if (drawCount == 100)
drawCount = 0;
// GLES20.glPolygonOffset(0, drawCount += 10);
// // seems there are not infinite offset units possible
// // this should suffice for at least two rows, i.e.
// // having not two neighbours with the same depth
// if (drawCount == 100)
// drawCount = 0;
setMatrix(pos, mv, proj, tiles[i], 1);
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
@ -200,7 +210,8 @@ public class BuildingOverlay2 extends RenderOverlay {
GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3,
GLES20.GL_SHORT, false, 8, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mNumIndices,
GLES20.glDrawElements(GLES20.GL_TRIANGLES,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]),
GLES20.GL_UNSIGNED_SHORT, 0);
}
@ -209,12 +220,12 @@ public class BuildingOverlay2 extends RenderOverlay {
// enable color buffer, use depth mask
GLRenderer.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition);
GLES20.glColorMask(true, true, true, true);
//GLES20.glDepthMask(false);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
GLES20.glDepthMask(false);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
//GLES20.glDepthFunc(GLES20.GL_EQUAL);
drawCount = 0;
//GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
//drawCount = 0;
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
//GLES20.glPolygonOffset(0, -2);
for (int i = 0; i < mTileSet.cnt; i++) {
@ -226,9 +237,9 @@ public class BuildingOverlay2 extends RenderOverlay {
if (!el.compiled)
continue;
GLES20.glPolygonOffset(0, drawCount += 10);
if (drawCount == 100)
drawCount = 0;
// GLES20.glPolygonOffset(0, drawCount += 10);
// if (drawCount == 100)
// drawCount = 0;
setMatrix(pos, mv, proj, tiles[i], 1);
GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, mv, 0);
@ -266,17 +277,13 @@ public class BuildingOverlay2 extends RenderOverlay {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[1],
GLES20.GL_UNSIGNED_SHORT, el.mIndiceCnt[0] * 2);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
GlUtils.checkGlError(".1.");
GLES20.glUniform1i(hBuildingMode, 0);
GLES20.glUniform4f(hBuildingColor, 0.7f, 0.7f, 0.72f, 1.0f);
GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3],
GLES20.GL_UNSIGNED_SHORT,
(el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]) * 2);
// GLRenderer.enableVertexArrays(hBuildingVertexPosition, -1);
// GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3,
// GLES20.GL_SHORT, false, 16, 8);
//
// GLES20.glUniform1i(hBuildingMode, 0);
// GLES20.glUniform4f(hBuildingColor, 1.0f, 0.5f, 0.5f, 0.9f);
// GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 10);
//
// GlUtils.checkGlError(".2.");
}