diff --git a/src/org/oscim/renderer/layer/ExtrusionLayer.java b/src/org/oscim/renderer/layer/ExtrusionLayer.java index 31e29027..42563230 100644 --- a/src/org/oscim/renderer/layer/ExtrusionLayer.java +++ b/src/org/oscim/renderer/layer/ExtrusionLayer.java @@ -78,10 +78,11 @@ public class ExtrusionLayer extends Layer { boolean simple = true; int startVertex = mNumVertices; + // just a guess to make it look ok if (height == 0) - height = 400; + height = 320; else - height *= 40; + height *= 30; int length = 0; for (int ipos = 0, ppos = 0, n = index.length; ipos < n; ipos++, ppos += length) { @@ -212,7 +213,8 @@ public class ExtrusionLayer extends Layer { float ux, uy; float a = (float) Math.sqrt(vx * vx + vy * vy); - short color1 = getColor(vx, a); + //float vlight = vx > 0 ? (vx / a) : -(vx / a); + short color1 = (short) ((1 + vx / a) * 127); short fcolor = color1; short color2 = 0; @@ -226,6 +228,8 @@ public class ExtrusionLayer extends Layer { 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; @@ -269,7 +273,7 @@ public class ExtrusionLayer extends Layer { // set lighting (by direction) a = (float) Math.sqrt(vx * vx + vy * vy); - color2 = getColor(vx, a); + color2 = (short) ((1 + vx / a) * 127); //getColor(vx, a); short c; if (even == 0) @@ -294,7 +298,7 @@ public class ExtrusionLayer extends Layer { } /* check if face is within tile */ - if (!mClipper.clip((int) cx, (int) cy, (int) nx, (int) ny)) { + if (!mClipper.clipNext((int) nx, (int) ny)) { even = (even + 1) % 2; continue; } diff --git a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java index 213aab56..f8d23fe8 100644 --- a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java +++ b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java @@ -146,11 +146,15 @@ public class ExtrusionOverlay extends RenderOverlay { return null; } - boolean debug = false; + private boolean debug = false; + private final float[] mVPMatrix = new float[16]; @Override public synchronized void render(MapPosition pos, float[] mv, float[] proj) { + Matrix.multiplyMM(mVPMatrix, 0, proj, 0, pos.viewMatrix, 0); + proj = mVPMatrix; + MapTile[] tiles = mTiles; float div = FastMath.pow(tiles[0].zoomLevel - pos.zoomLevel); @@ -162,7 +166,7 @@ public class ExtrusionOverlay extends RenderOverlay { GLState.enableVertexArrays(hExtrusionVertexPosition, hExtrusionLightPosition); GLES20.glUniform1i(hExtrusionMode, 0); - GLES20.glUniform4f(hExtrusionColor, 0.6f, 0.6f, 0.6f, 0.8f); + GLES20.glUniform4fv(hExtrusionColor, 4, mColor, 0); GLState.test(false, false); @@ -209,6 +213,7 @@ public class ExtrusionOverlay extends RenderOverlay { GLES20.glDepthMask(true); GLES20.glColorMask(false, false, false, false); GLES20.glUniform1i(hExtrusionMode, 0); + GLES20.glUniform4fv(hExtrusionColor, 4, mColor, 0); // draw to depth buffer for (int i = 0; i < mTileCnt; i++) { @@ -255,30 +260,23 @@ public class ExtrusionOverlay extends RenderOverlay { // draw roof GLES20.glUniform1i(hExtrusionMode, 0); - GLES20.glUniform4fv(hExtrusionColor, 1, mRoofColor, 0); GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[2], GLES20.GL_UNSIGNED_SHORT, (el.mIndiceCnt[0] + el.mIndiceCnt[1]) * 2); // draw sides 1 - GLES20.glUniform4fv(hExtrusionColor, 1, mColor, 0); GLES20.glUniform1i(hExtrusionMode, 1); GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[0], GLES20.GL_UNSIGNED_SHORT, 0); // draw sides 2 - GLES20.glUniform4fv(hExtrusionColor, 1, mColor2, 0); GLES20.glUniform1i(hExtrusionMode, 2); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, el.mIndiceCnt[1], GLES20.GL_UNSIGNED_SHORT, el.mIndiceCnt[0] * 2); - //GLES20.glDepthFunc(GLES20.GL_LEQUAL); GLES20.glUniform1i(hExtrusionMode, 3); - GLES20.glUniform4f(hExtrusionColor, 0.7f, 0.7f, 0.7f, 1.0f); GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3], GLES20.GL_UNSIGNED_SHORT, (el.mIndiceCnt[0] + el.mIndiceCnt[1] + el.mIndiceCnt[2]) * 2); - //GLES20.glDepthFunc(GLES20.GL_EQUAL); // just a temporary reference! tiles[i] = null; @@ -309,48 +307,46 @@ public class ExtrusionOverlay extends RenderOverlay { matrix[5] = scale; matrix[10] = scale / 1000f; - Matrix.multiplyMM(matrix, 0, mapPosition.viewMatrix, 0, matrix, 0); Matrix.multiplyMM(matrix, 0, proj, 0, matrix, 0); } - // sligthly differ adjacent faces to improve contrast - //float mColor[] = { 0.76872549f, 0.751960784f, 0.740196078f, 0.8f }; - //float mColor2[] = { 0.76372549f, 0.751960784f, 0.745196078f, 0.8f }; + private final float _a = 0.8f; - float mColor[] = { 201 / 255f, 200 / 255f, 198 / 255f, 0.8f }; - float mColor2[] = { 201 / 255f, 200 / 255f, 199 / 255f, 0.8f }; - - //float mRoofColor[] = { 0.895f, 0.89f, 0.88f, 0.9f }; - float _a = 0.8f; - float mRoofColor[] = { 236 / 255f * _a, 235 / 255f * _a, 234 / 255f * _a, _a }; + private final float[] mColor = { + // roof color + 236 / 255f * _a, 235 / 255f * _a, 234 / 255f * _a, _a, + // sligthly differ adjacent side faces to improve contrast + 201 / 255f, 200 / 255f, 198 / 255f, _a, + 200 / 255f, 200 / 255f, 196 / 255f, _a, + // roof outline + 0.75f, 0.75f, 0.75f, 1.0f + }; final static String extrusionVertexShader = "" + "precision mediump float;" + "uniform mat4 u_mvp;" - + "uniform vec4 u_color;" + + "uniform vec4 u_color[4];" + "uniform int u_mode;" + "attribute vec4 a_position;" + "attribute vec2 a_light;" + "varying vec4 color;" + "const float ff = 255.0;" + + "const float a = 0.8;" + "void main() {" + " gl_Position = u_mvp * a_position;" + " if (u_mode == 0)" // roof / depth pass - + " color = u_color;" - + " else {" - // decrease contrast with distance - + " float alpha = 0.95 + gl_Position.z * 0.05;" - + " if (u_mode == 1)" + + " color = u_color[0];" + + " else if (u_mode == 1)" // sides 1 - use 0xff00 - + " color = vec4(u_color.rgb * (a_light.y / ff * alpha), 1.0) * (0.8 * alpha);" + + " color = vec4(u_color[1].rgb * ((0.90 + (0.5 - (a_light.y / ff)) * 0.2) * a), a);" + " else if (u_mode == 2)" // sides 2 - use 0x00ff - + " color = vec4(u_color.rgb * (a_light.x / ff * alpha), 1.0) * (0.8 * alpha);" + + " color = vec4(u_color[2].rgb * ((0.90 + (0.5 - (a_light.x / ff)) * 0.2) * a), a);" + " else" - // sides 2 - use 0x00ff - + " color = u_color * alpha;" - + "}}"; + // outline - decrease contrast with distance + + " color = u_color[3] * (0.98 + gl_Position.z * 0.02);" + + "}"; // final static String extrusionVertexAnimShader = "" // + "precision mediump float;" diff --git a/src/org/oscim/utils/LineClipper.java b/src/org/oscim/utils/LineClipper.java index d795b256..04fdb141 100644 --- a/src/org/oscim/utils/LineClipper.java +++ b/src/org/oscim/utils/LineClipper.java @@ -14,8 +14,6 @@ */ package org.oscim.utils; -import android.graphics.Point; - /** * @author Hannes Janetzek * taken from http://en.wikipedia.org/wiki/Cohen%E2%80%93 @@ -24,14 +22,11 @@ import android.graphics.Point; public class LineClipper { - public static final int INSIDE = 0; // 0000 - public static final int LEFT = 1; // 0001 - public static final int RIGHT = 2; // 0010 - public static final int BOTTOM = 4; // 0100 - public static final int TOP = 8; // 1000 - - // Compute the bit code for a point (x, y) using the clip rectangle - // bounded diagonally by (xmin, ymin), and (xmax, ymax) + private static final int INSIDE = 0; // 0000 + private static final int LEFT = 1; // 0001 + private static final int RIGHT = 2; // 0010 + private static final int BOTTOM = 4; // 0100 + private static final int TOP = 8; // 1000 private int xmin, xmax, ymin, ymax; @@ -42,41 +37,71 @@ public class LineClipper { this.ymax = maxy; } - public boolean clip(Point p1, Point p2) { - return clip(p1.x, p1.y, p2.x, p2.y); + private int mPrevOutcode; + private int mPrevX; + private int mPrevY; + + public void clipStart(int x0, int y0) { + mPrevX = x0; + mPrevY = y0; + + int outcode = INSIDE; + if (x0 < xmin) + outcode |= LEFT; + else if (x0 > xmax) + outcode |= RIGHT; + if (y0 < ymin) + outcode |= BOTTOM; + else if (y0 > ymax) + outcode |= TOP; + + mPrevOutcode = outcode; } - public int outCode(int x, int y) { - int code; + public boolean clipNext(int x1, int y1) { + boolean accept; - code = INSIDE; // initialised as being inside of clip window + int outcode = INSIDE; + if (x1 < xmin) + outcode |= LEFT; + else if (x1 > xmax) + outcode |= RIGHT; + if (y1 < ymin) + outcode |= BOTTOM; + else if (y1 > ymax) + outcode |= TOP; - if (x < xmin) // to the left of clip window - code |= LEFT; - else if (x > xmax) // to the right of clip window - code |= RIGHT; - if (y < ymin) // below the clip window - code |= BOTTOM; - else if (y > ymax) // above the clip window - code |= TOP; + if ((mPrevOutcode | outcode) == 0) { + // Bitwise OR is 0. Trivially accept + accept = true; + } else if ((mPrevOutcode & outcode) != 0) { + // Bitwise AND is not 0. Trivially reject + accept = false; + } else { + accept = clip(mPrevX, mPrevY, x1, y1, xmin, ymin, xmax, ymax, mPrevOutcode, outcode); + } + mPrevOutcode = outcode; + mPrevX = x1; + mPrevY = y1; - return code; + return accept; } // CohenSutherland clipping algorithm clips a line from // P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with // diagonal from (xmin, ymin) to (xmax, ymax). - public boolean clip(int x0, int y0, int x1, int y1) { - // compute outcodes for P0, P1, and whatever point lies outside the clip rectangle - int outcode0 = outCode(x0, y0); - int outcode1 = outCode(x1, y1); + private static boolean clip(int x0, int y0, int x1, int y1, + int xmin, int ymin, int xmax, int ymax, int outcode0, int outcode1) { + boolean accept = false; while (true) { - if ((outcode0 | outcode1) == 0) { // Bitwise OR is 0. Trivially accept and get out of loop + if ((outcode0 | outcode1) == 0) { + // Bitwise OR is 0. Trivially accept and get out of loop accept = true; break; - } else if ((outcode0 & outcode1) != 0) { // Bitwise AND is not 0. Trivially reject and get out of loop + } else if ((outcode0 & outcode1) != 0) { + // Bitwise AND is not 0. Trivially reject and get out of loop break; } else { // failed both tests, so calculate the line segment to clip @@ -92,32 +117,45 @@ public class LineClipper { if ((outcodeOut & TOP) != 0) { // point is above the clip rectangle x = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0); y = ymax; - } else if ((outcodeOut & BOTTOM) != 0) { // point is below the clip rectangle + } else if ((outcodeOut & BOTTOM) != 0) { + // point is below the clip rectangle x = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0); y = ymin; - } else if ((outcodeOut & RIGHT) != 0) { // point is to the right of clip rectangle + } else if ((outcodeOut & RIGHT) != 0) { + // point is to the right of clip rectangle y = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0); x = xmax; - } else if ((outcodeOut & LEFT) != 0) { // point is to the left of clip rectangle + } else if ((outcodeOut & LEFT) != 0) { + // point is to the left of clip rectangle y = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0); x = xmin; } + int outcode = INSIDE; + if (x < xmin) + outcode |= LEFT; + else if (x > xmax) + outcode |= RIGHT; + if (y < ymin) + outcode |= BOTTOM; + else if (y > ymax) + outcode |= TOP; + // Now we move outside point to intersection point to clip // and get ready for next pass. if (outcodeOut == outcode0) { x0 = x; y0 = y; - outcode0 = outCode(x0, y0); + outcode0 = outcode; } else { x1 = x; y1 = y; - outcode1 = outCode(x1, y1); + outcode1 = outcode; } } } - // TODO do sth with the result x0... + // TODO could do sth with the result x0... return accept; }