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

View File

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