/** optimization for Line- and PolygonLayer: collect all pool items and add back in one go. */ private static int addLayerItems(ShortBuffer sbuf, RenderElement l, int type, int pos) { VertexItem last = null, items = null; int size = 0; for (; l != null; l = l.next) { if (l.type != type) continue; for (VertexItem it = l.vertexItems; it != null; it = it.next) { if (it.next == null) { size += it.used; sbuf.put(it.vertices, 0, it.used); } else { size += VertexItem.SIZE; sbuf.put(it.vertices, 0, VertexItem.SIZE); } last = it; } if (last == null) continue; l.offset = pos; pos += l.numVertices; last.next = items; items = l.vertexItems; last = null; l.vertexItems = null; } items = VertexItem.pool.releaseAll(items); return size; }
// private void encodeNormal(float v[], int offset) { // var p = Math.sqrt(cartesian.z * 8.0 + 8.0); // var result = new Cartesian2(); // result.x = cartesian.x / p + 0.5; // result.y = cartesian.y / p + 0.5; // return result; // } // public void addNoNormal(MapElement element) { if (element.type != GeometryType.TRIS) return; short[] index = element.index; float[] points = element.points; /* current vertex id */ int startVertex = sumVertices; /* 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; sumVertices += (vertexCnt / 3); }
private boolean addOutline( float[] points, int pos, int len, float minHeight, float height, boolean convex) { /* add two vertices for last face to make zigzag indices work */ boolean addFace = (len % 4 != 0); int vertexCnt = len + (addFace ? 2 : 0); short h = (short) height; short mh = (short) minHeight; float cx = points[pos + len - 2]; float cy = points[pos + len - 1]; float nx = points[pos + 0]; float ny = points[pos + 1]; /* vector to next point */ float vx = nx - cx; float vy = ny - cy; /* vector from previous point */ float ux, uy; float a = (float) Math.sqrt(vx * vx + vy * vy); short color1 = (short) ((1 + vx / a) * 127); short fcolor = color1; short color2 = 0; int even = 0; int changeX = 0; int changeY = 0; int angleSign = 0; /* vertex offset for all vertices in layer */ int vOffset = sumVertices; short[] vertices = mCurVertices.vertices; int v = mCurVertices.used; mClipper.clipStart((int) nx, (int) ny); for (int i = 2, n = vertexCnt + 2; i < n; i += 2, v += 8) { cx = nx; cy = ny; ux = vx; uy = vy; /* 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 + 0] = vertices[v + 4] = (short) (cx * S); vertices[v + 1] = vertices[v + 5] = (short) (cy * S); /* set height */ vertices[v + 2] = mh; vertices[v + 6] = h; /* get direction to next point */ if (i < len) { nx = points[pos + i + 0]; ny = points[pos + i + 1]; } else if (i == len) { nx = points[pos + 0]; ny = points[pos + 1]; } else { // if (addFace) short c = (short) (color1 | fcolor << 8); vertices[v + 3] = vertices[v + 7] = c; v += 8; break; } vx = nx - cx; vy = ny - cy; /* set lighting (by direction) */ a = (float) Math.sqrt(vx * vx + vy * vy); color2 = (short) ((1 + vx / a) * 127); short c; if (even == 0) c = (short) (color1 | color2 << 8); else c = (short) (color2 | color1 << 8); 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 */ if ((ux < 0 ? 1 : -1) != (vx < 0 ? 1 : -1)) changeX++; if ((uy < 0 ? 1 : -1) != (vy < 0 ? 1 : -1)) changeY++; if (changeX > 2 || changeY > 2) convex = false; float cross = ux * vy - uy * vy; if (cross > 0) { if (angleSign == -1) convex = false; angleSign = 1; } else if (cross < 0) { if (angleSign == 1) convex = false; angleSign = -1; } } /* check if face is within tile */ if (mClipper.clipNext((int) nx, (int) ny) == 0) { even = ++even % 2; continue; } /* add ZigZagQuadIndices(tm) for sides */ short vert = (short) (vOffset + (i - 2)); short s0 = vert++; short s1 = vert++; short s2 = vert++; short s3 = vert++; /* connect last to first (when number of faces is even) */ if (!addFace && i == len) { s2 -= len; s3 -= len; } VertexItem it = mCurIndices[even]; if (it.used == VertexItem.SIZE) { it = VertexItem.pool.getNext(it); mCurIndices[even] = it; } int ind = it.used; short[] indices = it.vertices; indices[ind + 0] = s0; indices[ind + 1] = s2; indices[ind + 2] = s1; indices[ind + 3] = s1; indices[ind + 4] = s2; indices[ind + 5] = s3; it.used += 6; sumIndices += 6; /* flipp even-odd */ even = ++even % 2; /* add roof outline indices */ it = mCurIndices[IND_OUTLINE]; if (it.used == VertexItem.SIZE) { it = VertexItem.pool.getNext(it); mCurIndices[IND_OUTLINE] = it; } ind = it.used; indices = it.vertices; indices[ind + 0] = s1; indices[ind + 1] = s3; it.used += 2; sumIndices += 2; } mCurVertices.used = v; sumVertices += vertexCnt; return convex; }