From f262efee7fa449634cfe08fba15d6b6b7cf1b206 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Fri, 15 Mar 2013 15:27:04 +0100 Subject: [PATCH] Use native Matrix4 instead of float[16] --- jni/gl/utils.c | 489 ++++++++-------- src/org/oscim/overlay/ItemizedOverlay.java | 27 +- src/org/oscim/overlay/PathOverlay.java | 3 +- src/org/oscim/renderer/BaseMap.java | 50 +- src/org/oscim/renderer/GLRenderer.java | 76 +-- src/org/oscim/renderer/LineRenderer.java | 10 +- src/org/oscim/renderer/LineTexRenderer.java | 12 +- src/org/oscim/renderer/PolygonRenderer.java | 26 +- src/org/oscim/renderer/TextureRenderer.java | 9 +- .../oscim/renderer/overlays/BasicOverlay.java | 8 +- .../renderer/overlays/BuildingOverlay.java | 534 ------------------ .../renderer/overlays/CustomOverlay.java | 10 +- .../renderer/overlays/ExtrusionOverlay.java | 27 +- .../oscim/renderer/overlays/GridOverlay.java | 3 +- .../oscim/renderer/overlays/ModelOverlay.java | 255 --------- .../renderer/overlays/RenderOverlay.java | 13 +- .../renderer/overlays/TestLineOverlay.java | 440 --------------- .../oscim/renderer/overlays/TestOverlay.java | 3 +- .../oscim/renderer/overlays/TextOverlay.java | 18 +- src/org/oscim/utils/GlUtils.java | 130 ++--- src/org/oscim/utils/Matrix4.java | 226 ++++++++ src/org/oscim/view/MapViewPosition.java | 79 ++- 22 files changed, 731 insertions(+), 1717 deletions(-) delete mode 100644 src/org/oscim/renderer/overlays/BuildingOverlay.java delete mode 100644 src/org/oscim/renderer/overlays/ModelOverlay.java delete mode 100644 src/org/oscim/renderer/overlays/TestLineOverlay.java create mode 100644 src/org/oscim/utils/Matrix4.java diff --git a/jni/gl/utils.c b/jni/gl/utils.c index 883c6017..9786365c 100644 --- a/jni/gl/utils.c +++ b/jni/gl/utils.c @@ -9,13 +9,16 @@ static const char TAG[] = "org.oscim.utils.GLUtils"; -static void nativeClassInit(JNIEnv *_env) { +static void +nativeClassInit(JNIEnv *_env) +{ } -void JNI(init)(JNIEnv *env, jclass* clazz) { - nativeClassInit(env); - __android_log_print(ANDROID_LOG_INFO, TAG, "all initialized"); +void JNI(init)(JNIEnv *env, jclass* clazz) +{ + nativeClassInit(env); + __android_log_print(ANDROID_LOG_INFO, TAG, "all initialized"); } #undef JNI @@ -25,196 +28,217 @@ void JNI(init)(JNIEnv *env, jclass* clazz) { #define MAT_SIZE 16 * sizeof(float) static const float identity[] = - { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; + { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; -static inline void multiplyMM(float* r, const float* lhs, const float* rhs); +static inline void +multiplyMM(float* r, const float* lhs, const float* rhs); -static inline void mx4transform(float x, float y, float z, float w, - const float* pM, float* pDest); +static inline void +setRotateM(float* rm, int rmOffset, float a, float x, float y, float z); -static void setRotateM(float* rm, int rmOffset, float a, float x, float y, - float z); -static void transposeM(float* mTrans, int mTransOffset, float* m, int mOffset); +static inline void +transposeM(float* mTrans, int mTransOffset, float* m, int mOffset); -static inline void matrix4_proj(float* mat, float* vec); +static inline void +matrix4_proj(float* mat, float* vec); -jlong JNI(alloc)(JNIEnv *env, jclass* clazz) { - return (long) calloc(16, sizeof(float)); + +jlong JNI(alloc)(JNIEnv *env, jclass* clazz) +{ + return (long) calloc(16, sizeof(float)); } -void JNI(delete)(JNIEnv* env, jclass* clazz, jlong ptr) { - free(CAST(ptr)); +void JNI(delete)(JNIEnv* env, jclass* clazz, jlong ptr) +{ + free(CAST(ptr)); } -void JNI(setAsUniform)(JNIEnv* env, jclass* clazz, jlong ptr, jint location) { - float* m = CAST(ptr); +void JNI(setAsUniform)(JNIEnv* env, jclass* clazz, jlong ptr, jint location) +{ + float* m = CAST(ptr); - glUniformMatrix4fv((GLint) location, (GLsizei) 1, (GLboolean) 0, - (GLfloat *) m); + glUniformMatrix4fv((GLint) location, (GLsizei) 1, (GLboolean) 0, (GLfloat *) m); } -void JNI(setValueAt)(JNIEnv* env, jclass* clazz, jlong ptr, jint pos, - jfloat value) { - float* m = CAST(ptr); - if (pos > -1 && pos < 16) - m[pos] = value; +void JNI(setValueAt)(JNIEnv* env, jclass* clazz, jlong ptr, jint pos, jfloat value) +{ + float* m = CAST(ptr); + if (pos > -1 && pos < 16) + m[pos] = value; } -void JNI(identity)(JNIEnv* env, jclass* clazz, jlong ptr) { - float* m = CAST(ptr); - memcpy(m, identity, MAT_SIZE); +void JNI(identity)(JNIEnv* env, jclass* clazz, jlong ptr) +{ + float* m = CAST(ptr); + memcpy(m, identity, MAT_SIZE); } -void JNI(setScale)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat sx, jfloat sy, - jfloat sz) { - float* m = CAST(ptr); - memcpy(m, identity, MAT_SIZE); - m[0] = sx; - m[5] = sy; - m[10] = sz; +void JNI(setScale)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat sx, jfloat sy, jfloat sz) +{ + float* m = CAST(ptr); + memcpy(m, identity, MAT_SIZE); + m[0] = sx; + m[5] = sy; + m[10] = sz; } -void JNI(setRotate)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat a, jfloat x, - jfloat y, jfloat z) { - float* m = CAST(ptr); - setRotateM(m, 0, a, x, y, z); +void JNI(setTranslation)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat x, jfloat y, jfloat z) +{ + float* m = CAST(ptr); + memcpy(m, identity, MAT_SIZE); + m[12] = x; + m[13] = y; + m[14] = z; } -void JNI(setTransScale)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat tx, - jfloat ty, jfloat scale) { - float* m = CAST(ptr); - memcpy(m, identity, MAT_SIZE); - m[0] = scale; - m[5] = scale; - m[12] = tx; - m[13] = ty; +void JNI(setRotation)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat a, jfloat x, jfloat y, jfloat z) +{ + float* m = CAST(ptr); + setRotateM(m, 0, a, x, y, z); } -void JNI(set)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_mat) { - float* m = CAST(ptr); - float* mat = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_mat, 0); - - memcpy(m, mat, MAT_SIZE); - - (*env)->ReleasePrimitiveArrayCritical(env, obj_mat, mat, 0); +void JNI(setTransScale)(JNIEnv* env, jclass* clazz, jlong ptr, jfloat tx, jfloat ty, jfloat scale) +{ + float* m = CAST(ptr); + memcpy(m, identity, MAT_SIZE); + m[0] = scale; + m[5] = scale; + m[12] = tx; + m[13] = ty; } -void JNI(get)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_mat) { - float* m = CAST(ptr); - float* mat = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_mat, 0); +void JNI(set)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_mat) +{ + float* m = CAST(ptr); + float* mat = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_mat, 0); - memcpy(mat, m, MAT_SIZE); + memcpy(m, mat, MAT_SIZE); - (*env)->ReleasePrimitiveArrayCritical(env, obj_mat, mat, 0); + (*env)->ReleasePrimitiveArrayCritical(env, obj_mat, mat, 0); } -void JNI(mul)(JNIEnv* env, jclass* clazz, jlong ptr_a, jlong ptr_b) { - float* mata = CAST(ptr_a); - float* matb = CAST(ptr_b); +void JNI(get)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_mat) +{ + float* m = CAST(ptr); + float* mat = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_mat, 0); - multiplyMM(mata, mata, matb); + memcpy(mat, m, MAT_SIZE); + + (*env)->ReleasePrimitiveArrayCritical(env, obj_mat, mat, 0); } -void JNI(copy)(JNIEnv* env, jclass* clazz, jlong ptr_dst, jlong ptr_src) { - float* dst = CAST(ptr_dst); - float* src = CAST(ptr_src); +void JNI(mul)(JNIEnv* env, jclass* clazz, jlong ptr_a, jlong ptr_b) +{ + float* mata = CAST(ptr_a); + float* matb = CAST(ptr_b); - memcpy(dst, src, MAT_SIZE); + multiplyMM(mata, mata, matb); } -void JNI(smul)(JNIEnv* env, jclass* clazz, jlong ptr_r, jlong ptr_a, - jlong ptr_b) { - float* matr = CAST(ptr_r); - float* mata = CAST(ptr_a); - float* matb = CAST(ptr_b); +void JNI(copy)(JNIEnv* env, jclass* clazz, jlong ptr_dst, jlong ptr_src) +{ + float* dst = CAST(ptr_dst); + float* src = CAST(ptr_src); - multiplyMM(matr, mata, matb); + memcpy(dst, src, MAT_SIZE); } -void JNI(strans)(JNIEnv* env, jclass* clazz, jlong ptr_r, jlong ptr_a) { - float* matr = CAST(ptr_r); - float* mata = CAST(ptr_a); +void JNI(smul)(JNIEnv* env, jclass* clazz, jlong ptr_r, jlong ptr_a, jlong ptr_b) +{ + float* matr = CAST(ptr_r); + float* mata = CAST(ptr_a); + float* matb = CAST(ptr_b); - transposeM(matr, 0, mata, 0); + multiplyMM(matr, mata, matb); } -void JNI(prj)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_vec) { - float* m = CAST(ptr); - float* vec = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_vec, 0); +void JNI(strans)(JNIEnv* env, jclass* clazz, jlong ptr_r, jlong ptr_a) +{ + float* matr = CAST(ptr_r); + float* mata = CAST(ptr_a); - matrix4_proj(m, vec); + transposeM(matr, 0, mata, 0); +} - (*env)->ReleasePrimitiveArrayCritical(env, obj_vec, vec, 0); +void JNI(prj)(JNIEnv* env, jclass* clazz, jlong ptr, jfloatArray obj_vec) +{ + float* m = CAST(ptr); + float* vec = (float*) (*env)->GetPrimitiveArrayCritical(env, obj_vec, 0); + + matrix4_proj(m, vec); + + (*env)->ReleasePrimitiveArrayCritical(env, obj_vec, vec, 0); } static float someRandomEpsilon = 1.0f / (1 << 11); -void JNI(addDepthOffset)(JNIEnv* env, jclass* clazz, jlong ptr, jint delta) { - float* m = CAST(ptr); +void JNI(addDepthOffset)(JNIEnv* env, jclass* clazz, jlong ptr, jint delta) +{ + float* m = CAST(ptr); - // from http://www.mathfor3dgameprogramming.com/code/Listing9.1.cpp - // float n = MapViewPosition.VIEW_NEAR; - // float f = MapViewPosition.VIEW_FAR; - // float pz = 1; - // float epsilon = -2.0f * f * n * delta / ((f + n) * pz * (pz + delta)); + // from http://www.mathfor3dgameprogramming.com/code/Listing9.1.cpp + // float n = MapViewPosition.VIEW_NEAR; + // float f = MapViewPosition.VIEW_FAR; + // float pz = 1; + // float epsilon = -2.0f * f * n * delta / ((f + n) * pz * (pz + delta)); - m[10] *= 1.0f + someRandomEpsilon * delta; + m[10] *= 1.0f + someRandomEpsilon * delta; } -/** - ** Copyright 2007, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. +/* + * Copyright 2007, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ // from android/platform_frameworks_base/blob/master/core/jni/android/opengl/util.cpp #define I(_i, _j) ((_j)+ 4*(_i)) -static -void multiplyMM(float* r, const float* lhs, const float* rhs) { - for (int i = 0; i < 4; i++) { - register const float rhs_i0 = rhs[I(i,0)]; - register float ri0 = lhs[I(0,0)] * rhs_i0; - register float ri1 = lhs[I(0,1)] * rhs_i0; - register float ri2 = lhs[I(0,2)] * rhs_i0; - register float ri3 = lhs[I(0,3)] * rhs_i0; - for (int j = 1; j < 4; j++) { - register const float rhs_ij = rhs[I(i,j)]; - ri0 += lhs[I(j,0)] * rhs_ij; - ri1 += lhs[I(j,1)] * rhs_ij; - ri2 += lhs[I(j,2)] * rhs_ij; - ri3 += lhs[I(j,3)] * rhs_ij; - } - r[I(i,0)] = ri0; - r[I(i,1)] = ri1; - r[I(i,2)] = ri2; - r[I(i,3)] = ri3; - } +static inline void +multiplyMM(float* r, const float* lhs, const float* rhs) +{ + for (int i = 0; i < 4; i++) + { + register const float rhs_i0 = rhs[I(i,0)]; + register float ri0 = lhs[I(0,0)] * rhs_i0; + register float ri1 = lhs[I(0,1)] * rhs_i0; + register float ri2 = lhs[I(0,2)] * rhs_i0; + register float ri3 = lhs[I(0,3)] * rhs_i0; + for (int j = 1; j < 4; j++) + { + register const float rhs_ij = rhs[I(i,j)]; + ri0 += lhs[I(j,0)] * rhs_ij; + ri1 += lhs[I(j,1)] * rhs_ij; + ri2 += lhs[I(j,2)] * rhs_ij; + ri3 += lhs[I(j,3)] * rhs_ij; + } + r[I(i,0)] = ri0; + r[I(i,1)] = ri1; + r[I(i,2)] = ri2; + r[I(i,3)] = ri3; + } } -static inline -void mx4transform(float x, float y, float z, float w, const float* pM, - float* pDest) { - pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z - + pM[0 + 4 * 3] * w; - pDest[1] = pM[1 + 4 * 0] * x + pM[1 + 4 * 1] * y + pM[1 + 4 * 2] * z - + pM[1 + 4 * 3] * w; - pDest[2] = pM[2 + 4 * 0] * x + pM[2 + 4 * 1] * y + pM[2 + 4 * 2] * z - + pM[2 + 4 * 3] * w; - - pDest[3] = pM[3 + 4 * 0] * x + pM[3 + 4 * 1] * y + pM[3 + 4 * 2] * z - + pM[3 + 4 * 3] * w; -} +//static inline +//void +//mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) +//{ +// pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w; +// pDest[1] = pM[1 + 4 * 0] * x + pM[1 + 4 * 1] * y + pM[1 + 4 * 2] * z + pM[1 + 4 * 3] * w; +// pDest[2] = pM[2 + 4 * 0] * x + pM[2 + 4 * 1] * y + pM[2 + 4 * 2] * z + pM[2 + 4 * 3] * w; +// +// pDest[3] = pM[3 + 4 * 0] * x + pM[3 + 4 * 1] * y + pM[3 + 4 * 2] * z + pM[3 + 4 * 3] * w; +//} /** * Computes the length of a vector @@ -224,8 +248,10 @@ void mx4transform(float x, float y, float z, float w, const float* pM, * @param z z coordinate of a vector * @return the length of a vector */ -static float length(float x, float y, float z) { - return (float) sqrt(x * x + y * y + z * z); +static inline float +length(float x, float y, float z) +{ + return (float) sqrt(x * x + y * y + z * z); } /** * Rotates matrix m by angle a (in degrees) around the axis (x, y, z) @@ -237,73 +263,82 @@ static float length(float x, float y, float z) { * @param z scale factor z */ -static void setRotateM(float* rm, int rmOffset, float a, float x, float y, - float z) { - rm[rmOffset + 3] = 0; - rm[rmOffset + 7] = 0; - rm[rmOffset + 11] = 0; - rm[rmOffset + 12] = 0; - rm[rmOffset + 13] = 0; - rm[rmOffset + 14] = 0; - rm[rmOffset + 15] = 1; - a *= (float) (M_PI / 180.0f); - float s = (float) sin(a); - float c = (float) cos(a); - if (1.0f == x && 0.0f == y && 0.0f == z) { - rm[rmOffset + 5] = c; - rm[rmOffset + 10] = c; - rm[rmOffset + 6] = s; - rm[rmOffset + 9] = -s; - rm[rmOffset + 1] = 0; - rm[rmOffset + 2] = 0; - rm[rmOffset + 4] = 0; - rm[rmOffset + 8] = 0; - rm[rmOffset + 0] = 1; - } else if (0.0f == x && 1.0f == y && 0.0f == z) { - rm[rmOffset + 0] = c; - rm[rmOffset + 10] = c; - rm[rmOffset + 8] = s; - rm[rmOffset + 2] = -s; - rm[rmOffset + 1] = 0; - rm[rmOffset + 4] = 0; - rm[rmOffset + 6] = 0; - rm[rmOffset + 9] = 0; - rm[rmOffset + 5] = 1; - } else if (0.0f == x && 0.0f == y && 1.0f == z) { - rm[rmOffset + 0] = c; - rm[rmOffset + 5] = c; - rm[rmOffset + 1] = s; - rm[rmOffset + 4] = -s; - rm[rmOffset + 2] = 0; - rm[rmOffset + 6] = 0; - rm[rmOffset + 8] = 0; - rm[rmOffset + 9] = 0; - rm[rmOffset + 10] = 1; - } else { - float len = length(x, y, z); - if (1.0f != len) { - float recipLen = 1.0f / len; - x *= recipLen; - y *= recipLen; - z *= recipLen; - } - float nc = 1.0f - c; - float xy = x * y; - float yz = y * z; - float zx = z * x; - float xs = x * s; - float ys = y * s; - float zs = z * s; - rm[rmOffset + 0] = x * x * nc + c; - rm[rmOffset + 4] = xy * nc - zs; - rm[rmOffset + 8] = zx * nc + ys; - rm[rmOffset + 1] = xy * nc + zs; - rm[rmOffset + 5] = y * y * nc + c; - rm[rmOffset + 9] = yz * nc - xs; - rm[rmOffset + 2] = zx * nc - ys; - rm[rmOffset + 6] = yz * nc + xs; - rm[rmOffset + 10] = z * z * nc + c; - } +static inline void +setRotateM(float* rm, int rmOffset, float a, float x, float y, float z) +{ + rm[rmOffset + 3] = 0; + rm[rmOffset + 7] = 0; + rm[rmOffset + 11] = 0; + rm[rmOffset + 12] = 0; + rm[rmOffset + 13] = 0; + rm[rmOffset + 14] = 0; + rm[rmOffset + 15] = 1; + a *= (float) (M_PI / 180.0f); + float s = (float) sin(a); + float c = (float) cos(a); + if (1.0f == x && 0.0f == y && 0.0f == z) + { + rm[rmOffset + 5] = c; + rm[rmOffset + 10] = c; + rm[rmOffset + 6] = s; + rm[rmOffset + 9] = -s; + rm[rmOffset + 1] = 0; + rm[rmOffset + 2] = 0; + rm[rmOffset + 4] = 0; + rm[rmOffset + 8] = 0; + rm[rmOffset + 0] = 1; + } + else if (0.0f == x && 1.0f == y && 0.0f == z) + { + rm[rmOffset + 0] = c; + rm[rmOffset + 10] = c; + rm[rmOffset + 8] = s; + rm[rmOffset + 2] = -s; + rm[rmOffset + 1] = 0; + rm[rmOffset + 4] = 0; + rm[rmOffset + 6] = 0; + rm[rmOffset + 9] = 0; + rm[rmOffset + 5] = 1; + } + else if (0.0f == x && 0.0f == y && 1.0f == z) + { + rm[rmOffset + 0] = c; + rm[rmOffset + 5] = c; + rm[rmOffset + 1] = s; + rm[rmOffset + 4] = -s; + rm[rmOffset + 2] = 0; + rm[rmOffset + 6] = 0; + rm[rmOffset + 8] = 0; + rm[rmOffset + 9] = 0; + rm[rmOffset + 10] = 1; + } + else + { + float len = length(x, y, z); + if (1.0f != len) + { + float recipLen = 1.0f / len; + x *= recipLen; + y *= recipLen; + z *= recipLen; + } + float nc = 1.0f - c; + float xy = x * y; + float yz = y * z; + float zx = z * x; + float xs = x * s; + float ys = y * s; + float zs = z * s; + rm[rmOffset + 0] = x * x * nc + c; + rm[rmOffset + 4] = xy * nc - zs; + rm[rmOffset + 8] = zx * nc + ys; + rm[rmOffset + 1] = xy * nc + zs; + rm[rmOffset + 5] = y * y * nc + c; + rm[rmOffset + 9] = yz * nc - xs; + rm[rmOffset + 2] = zx * nc - ys; + rm[rmOffset + 6] = yz * nc + xs; + rm[rmOffset + 10] = z * z * nc + c; + } } /** @@ -315,14 +350,17 @@ static void setRotateM(float* rm, int rmOffset, float a, float x, float y, * @param m the input array * @param mOffset an offset into m where the matrix is stored. */ -static void transposeM(float* mTrans, int mTransOffset, float* m, int mOffset) { - for (int i = 0; i < 4; i++) { - int mBase = i * 4 + mOffset; - mTrans[i + mTransOffset] = m[mBase]; - mTrans[i + 4 + mTransOffset] = m[mBase + 1]; - mTrans[i + 8 + mTransOffset] = m[mBase + 2]; - mTrans[i + 12 + mTransOffset] = m[mBase + 3]; - } +static inline void +transposeM(float* mTrans, int mTransOffset, float* m, int mOffset) +{ + for (int i = 0; i < 4; i++) + { + int mBase = i * 4 + mOffset; + mTrans[i + mTransOffset] = m[mBase]; + mTrans[i + 4 + mTransOffset] = m[mBase + 1]; + mTrans[i + 8 + mTransOffset] = m[mBase + 2]; + mTrans[i + 12 + mTransOffset] = m[mBase + 3]; + } } /******************************************************************************* * Copyright 2011 See libgdx AUTHORS file. @@ -357,17 +395,14 @@ static void transposeM(float* mTrans, int mTransOffset, float* m, int mOffset) { #define M32 11 #define M33 15 -static inline void matrix4_proj(float* mat, float* vec) { - float inv_w = 1.0f - / (vec[0] * mat[M30] + vec[1] * mat[M31] + vec[2] * mat[M32] - + mat[M33]); - float x = (vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02] - + mat[M03]) * inv_w; - float y = (vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12] - + mat[M13]) * inv_w; - float z = (vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22] - + mat[M23]) * inv_w; - vec[0] = x; - vec[1] = y; - vec[2] = z; +static inline void +matrix4_proj(float* mat, float* vec) +{ + float inv_w = 1.0f / (vec[0] * mat[M30] + vec[1] * mat[M31] + vec[2] * mat[M32] + mat[M33]); + float x = (vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02] + mat[M03]) * inv_w; + float y = (vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12] + mat[M13]) * inv_w; + float z = (vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22] + mat[M23]) * inv_w; + vec[0] = x; + vec[1] = y; + vec[2] = z; } diff --git a/src/org/oscim/overlay/ItemizedOverlay.java b/src/org/oscim/overlay/ItemizedOverlay.java index 5b6d4f75..47aaccba 100644 --- a/src/org/oscim/overlay/ItemizedOverlay.java +++ b/src/org/oscim/overlay/ItemizedOverlay.java @@ -25,6 +25,7 @@ import org.oscim.core.GeoPoint; import org.oscim.core.MapPosition; import org.oscim.core.MercatorProjection; import org.oscim.overlay.OverlayItem.HotspotPlace; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.SymbolLayer; import org.oscim.renderer.overlays.BasicOverlay; import org.oscim.view.MapView; @@ -32,7 +33,6 @@ import org.oscim.view.MapView; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.opengl.Matrix; /* @author Marc Kurtz * @author Nicolas Gramlich @@ -77,8 +77,7 @@ public abstract class ItemizedOverlay extends Overlay class ItemOverlay extends BasicOverlay { private final SymbolLayer mSymbolLayer; - private final float[] mMvp = new float[16]; - private final float[] mVec = new float[4]; + private final float[] mVec = new float[3]; public ItemOverlay(MapView mapView) { super(mapView); @@ -89,7 +88,7 @@ public abstract class ItemizedOverlay extends Overlay @Override public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { if (!positionChanged && !mUpdate) return; @@ -100,12 +99,6 @@ public abstract class ItemizedOverlay extends Overlay int mx = (int) curPos.x; int my = (int) curPos.y; - // TODO could pass mvp as param - mMapView.getMapViewPosition().getMatrix(null, null, mMvp); - - float[] matrix = mMvp; - float[] vec = mVec; - // limit could be 1 if we update on every position change float limit = 1.5f; @@ -139,13 +132,13 @@ public abstract class ItemizedOverlay extends Overlay } // map points to screen - vec[0] = it.x; - vec[1] = it.y; - vec[2] = 0; - vec[3] = 1; - Matrix.multiplyMV(vec, 0, matrix, 0, vec, 0); - float sx = vec[0] / vec[3]; - float sy = vec[1] / vec[3]; + mVec[0] = it.x; + mVec[1] = it.y; + mVec[2] = 0; + matrices.viewproj.prj(mVec); + + float sx = mVec[0]; + float sy = mVec[1]; // check if it is visible if (sx < -limit || sx > limit || sy < -limit || sy > limit) { diff --git a/src/org/oscim/overlay/PathOverlay.java b/src/org/oscim/overlay/PathOverlay.java index 9e0d2496..9dd0f880 100644 --- a/src/org/oscim/overlay/PathOverlay.java +++ b/src/org/oscim/overlay/PathOverlay.java @@ -22,6 +22,7 @@ import java.util.List; import org.oscim.core.GeoPoint; import org.oscim.core.MapPosition; import org.oscim.core.MercatorProjection; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.LineLayer; import org.oscim.renderer.overlays.BasicOverlay; @@ -73,7 +74,7 @@ public class PathOverlay extends Overlay { @Override public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { if (!tilesChanged && !mUpdatePoints) return; diff --git a/src/org/oscim/renderer/BaseMap.java b/src/org/oscim/renderer/BaseMap.java index c3f10008..aac72366 100644 --- a/src/org/oscim/renderer/BaseMap.java +++ b/src/org/oscim/renderer/BaseMap.java @@ -22,10 +22,9 @@ import org.oscim.core.MapPosition; import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; +import org.oscim.utils.Matrix4; import android.opengl.GLES20; -import android.opengl.Matrix; /** * This class is for rendering the Line- and PolygonLayers of visible MapTiles. @@ -38,9 +37,9 @@ import android.opengl.Matrix; public class BaseMap { private final static String TAG = BaseMap.class.getName(); - private static float[] mMVPMatrix = new float[16]; - private static float[] mVPMatrix = new float[16]; - private static float[] mfProjMatrix = new float[16]; + //private static Matrix4 mMVPMatrix = new Matrix4(); + private static Matrix4 mVPMatrix = new Matrix4(); + private static Matrix4 mfProjMatrix = new Matrix4(); // used to increase polygon-offset for each tile drawn. private static int mDrawCnt; @@ -48,17 +47,26 @@ public class BaseMap { // used to not draw a tile twice per frame. private static int mDrawSerial = 0; - static void setProjection(float[] projMatrix) { - System.arraycopy(projMatrix, 0, mfProjMatrix, 0, 16); + static void setProjection(Matrix4 projMatrix) { + float[] tmp = new float[16]; + projMatrix.get(tmp); + //System.arraycopy(projMatrix, 0, mfProjMatrix, 0, 16); // set to zero: we modify the z value with polygon-offset for clipping - mfProjMatrix[10] = 0; - mfProjMatrix[14] = 0; + tmp[10] = 0; + tmp[14] = 0; + mfProjMatrix.set(tmp); } + private static Matrices mMatrices; + static void draw(MapTile[] tiles, int tileCnt, MapPosition pos, Matrices m) { mDrawCnt = 0; + mMatrices = m; - Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, m.view, 0); + // use our 'flat' projection matrix + mVPMatrix.multiplyMM(mfProjMatrix, m.view); + + //Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, m.view, 0); GLES20.glDepthFunc(GLES20.GL_LESS); @@ -95,8 +103,12 @@ public class BaseMap { LineRenderer.endLines(); mDrawSerial++; + + // dont keep the ref... + mMatrices = null; } + private static void drawTile(MapTile tile, MapPosition pos) { // draw parents only once if (tile.lastDraw == mDrawSerial) @@ -121,11 +133,11 @@ public class BaseMap { float y = (float) (tile.pixelY - pos.y * div); float scale = pos.scale / div; - float[] mvp = mMVPMatrix; - GlUtils.setTileMatrix(mvp, x, y, scale); + Matrices m = mMatrices; + m.mvp.setTransScale(x * scale, y * scale, scale / GLRenderer.COORD_SCALE); // add view-projection matrix - Matrix.multiplyMM(mvp, 0, mVPMatrix, 0, mvp, 0); + m.mvp.multiplyMM(mVPMatrix, m.mvp); // set depth offset (used for clipping to tile boundaries) GLES20.glPolygonOffset(1, mDrawCnt++); @@ -140,26 +152,26 @@ public class BaseMap { for (Layer l = t.layers.baseLayers; l != null;) { switch (l.type) { case Layer.POLYGON: - l = PolygonRenderer.draw(pos, l, mvp, !clipped, true); + l = PolygonRenderer.draw(pos, l, m, !clipped, true); clipped = true; break; case Layer.LINE: if (!clipped) { // draw stencil buffer clip region - PolygonRenderer.draw(pos, null, mvp, true, true); + PolygonRenderer.draw(pos, null, m, true, true); clipped = true; } - l = LineRenderer.draw(t.layers, l, pos, mvp, div, simpleShader); + l = LineRenderer.draw(t.layers, l, pos, m, div, simpleShader); break; case Layer.TEXLINE: if (!clipped) { // draw stencil buffer clip region - PolygonRenderer.draw(pos, null, mvp, true, true); + PolygonRenderer.draw(pos, null, m, true, true); clipped = true; } - l = LineTexRenderer.draw(t.layers, l, pos, mvp, div); + l = LineTexRenderer.draw(t.layers, l, pos, m, div); break; default: @@ -169,7 +181,7 @@ public class BaseMap { } // clear clip-region and could also draw 'fade-effect' - PolygonRenderer.drawOver(mvp); + PolygonRenderer.drawOver(m); } private static int drawProxyChild(MapTile tile, MapPosition pos) { diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java index 7fa82400..6056b354 100644 --- a/src/org/oscim/renderer/GLRenderer.java +++ b/src/org/oscim/renderer/GLRenderer.java @@ -37,12 +37,12 @@ import org.oscim.renderer.overlays.RenderOverlay; import org.oscim.theme.RenderTheme; import org.oscim.utils.FastMath; import org.oscim.utils.GlUtils; +import org.oscim.utils.Matrix4; import org.oscim.view.MapView; import org.oscim.view.MapViewPosition; import android.opengl.GLES20; import android.opengl.GLSurfaceView; -import android.opengl.Matrix; import android.os.SystemClock; import android.util.Log; @@ -75,15 +75,15 @@ public class GLRenderer implements GLSurfaceView.Renderer { private static int mBufferMemoryUsage; private static float[] mTileCoords = new float[8]; - private static float[] mDebugCoords = new float[8]; + //private static float[] mDebugCoords = new float[8]; public class Matrices { - public final float[] viewproj = new float[16]; - public final float[] proj = new float[16]; - public final float[] view = new float[16]; + public final Matrix4 viewproj = new Matrix4(); + public final Matrix4 proj = new Matrix4(); + public final Matrix4 view = new Matrix4(); // for temporary use by callee - public final float[] mvp = new float[16]; + public final Matrix4 mvp = new Matrix4(); } private static Matrices mMatrices; @@ -476,7 +476,7 @@ public class GLRenderer implements GLSurfaceView.Renderer { List overlays = mMapView.getOverlayManager().getRenderLayers(); for (int i = 0, n = overlays.size(); i < n; i++) - overlays.get(i).update(mMapPosition, positionChanged, tilesChanged); + overlays.get(i).update(mMapPosition, positionChanged, tilesChanged, mMatrices); /* draw base layer */ BaseMap.draw(tiles, tileCnt, pos, mMatrices); @@ -498,30 +498,30 @@ public class GLRenderer implements GLSurfaceView.Renderer { Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start)); } - if (debugView) { - GLState.test(false, false); - - float mm = 0.5f; - float min = -mm; - float max = mm; - float ymax = mm * mHeight / mWidth; - mDebugCoords[0] = min; - mDebugCoords[1] = ymax; - mDebugCoords[2] = max; - mDebugCoords[3] = ymax; - mDebugCoords[4] = min; - mDebugCoords[5] = -ymax; - mDebugCoords[6] = max; - mDebugCoords[7] = -ymax; - - PolygonRenderer.debugDraw(mMatrices.proj, mDebugCoords, 0); - - pos.zoomLevel = -1; - mMapViewPosition.getMapViewProjection(mDebugCoords); - - PolygonRenderer.debugDraw(mMatrices.viewproj, mDebugCoords, 1); - - } + //if (debugView) { + // GLState.test(false, false); + // + // float mm = 0.5f; + // float min = -mm; + // float max = mm; + // float ymax = mm * mHeight / mWidth; + // mDebugCoords[0] = min; + // mDebugCoords[1] = ymax; + // mDebugCoords[2] = max; + // mDebugCoords[3] = ymax; + // mDebugCoords[4] = min; + // mDebugCoords[5] = -ymax; + // mDebugCoords[6] = max; + // mDebugCoords[7] = -ymax; + // + // PolygonRenderer.debugDraw(mMatrices.proj, mDebugCoords, 0); + // + // pos.zoomLevel = -1; + // mMapViewPosition.getMapViewProjection(mDebugCoords); + // + // PolygonRenderer.debugDraw(mMatrices.viewproj, mDebugCoords, 1); + // + //} if (GlUtils.checkGlOutOfMemory("finish")) { checkBufferUsage(true); @@ -583,13 +583,13 @@ public class GLRenderer implements GLSurfaceView.Renderer { mMapViewPosition.getMatrix(null, mMatrices.proj, null); - if (debugView) { - // modify this to scale only the view, to see better which tiles are - // rendered - Matrix.setIdentityM(mMatrices.mvp, 0); - Matrix.scaleM(mMatrices.mvp, 0, 0.5f, 0.5f, 1); - Matrix.multiplyMM(mMatrices.proj, 0, mMatrices.mvp, 0, mMatrices.proj, 0); - } + //if (debugView) { + // // modify this to scale only the view, to see better which tiles are + // // rendered + // Matrix.setIdentityM(mMatrices.mvp, 0); + // Matrix.scaleM(mMatrices.mvp, 0, 0.5f, 0.5f, 1); + // Matrix.multiplyMM(mMatrices.proj, 0, mMatrices.mvp, 0, mMatrices.proj, 0); + //} BaseMap.setProjection(mMatrices.proj); diff --git a/src/org/oscim/renderer/LineRenderer.java b/src/org/oscim/renderer/LineRenderer.java index d49f289f..c73d9ca1 100644 --- a/src/org/oscim/renderer/LineRenderer.java +++ b/src/org/oscim/renderer/LineRenderer.java @@ -20,12 +20,11 @@ import static android.opengl.GLES20.glDrawArrays; import static android.opengl.GLES20.glGetAttribLocation; import static android.opengl.GLES20.glGetUniformLocation; import static android.opengl.GLES20.glUniform1f; -import static android.opengl.GLES20.glUniform4fv; -import static android.opengl.GLES20.glUniformMatrix4fv; import static android.opengl.GLES20.glVertexAttribPointer; import org.oscim.core.MapPosition; import org.oscim.generator.TileGenerator; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layers; import org.oscim.renderer.layer.LineLayer; @@ -109,7 +108,7 @@ public final class LineRenderer { } public static Layer draw(Layers layers, Layer curLayer, MapPosition pos, - float[] matrix, float div, int mode) { + Matrices m, float div, int mode) { if (curLayer == null) return null; @@ -128,7 +127,8 @@ public final class LineRenderer { glVertexAttribPointer(hLineVertexPosition[mode], 4, GL_SHORT, false, 0, layers.lineOffset + LINE_VERTICES_DATA_POS_OFFSET); - glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0); + //glUniformMatrix4fv(hLineMatrix[mode], 1, false, matrix, 0); + m.mvp.setAsUniform(hLineMatrix[mode]); int zoom = pos.zoomLevel; float scale = pos.scale; @@ -163,7 +163,7 @@ public final class LineRenderer { float width; if (line.fade < zoom) { - glUniform4fv(uLineColor, 1, line.color, 0); + GlUtils.setColor(uLineColor, line.color, 1); } else if (line.fade > zoom) { continue; } else { diff --git a/src/org/oscim/renderer/LineTexRenderer.java b/src/org/oscim/renderer/LineTexRenderer.java index ff9da1e8..6d3be5ae 100644 --- a/src/org/oscim/renderer/LineTexRenderer.java +++ b/src/org/oscim/renderer/LineTexRenderer.java @@ -19,6 +19,7 @@ import java.nio.ByteOrder; import java.nio.ShortBuffer; import org.oscim.core.MapPosition; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.Layers; import org.oscim.renderer.layer.LineLayer; @@ -57,7 +58,7 @@ public class LineTexRenderer { // batch up up to 64 quads in one draw call private static int maxQuads = 64; private static int maxIndices = maxQuads * 6; - private static int[] mTexID; + //private static int[] mTexID; public static void init() { shader = GlUtils.createProgram(vertexShader, fragmentShader); @@ -132,7 +133,7 @@ public class LineTexRenderer { private final static int LEN_OFFSET = 8; public static Layer draw(Layers layers, Layer curLayer, - MapPosition pos, float[] matrix, float div) { + MapPosition pos, Matrices m, float div) { GLState.blend(true); GLState.useProgram(shader); @@ -145,7 +146,8 @@ public class LineTexRenderer { GLES20.glEnableVertexAttribArray(hVertexLength1); GLES20.glEnableVertexAttribArray(hVertexFlip); - GLES20.glUniformMatrix4fv(hMatrix, 1, false, matrix, 0); + //GLES20.glUniformMatrix4fv(hMatrix, 1, false, matrix, 0); + m.mvp.setAsUniform(hMatrix); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); @@ -180,8 +182,6 @@ public class LineTexRenderer { // keep line width fixed GLES20.glUniform1f(hWidth, ll.width / s * COORD_SCALE_BY_DIR_SCALE); - GlUtils.checkGlError("0"); - // add offset vertex int vOffset = -STRIDE; @@ -246,7 +246,7 @@ public class LineTexRenderer { l = l.next; - GlUtils.checkGlError(TAG); + //GlUtils.checkGlError(TAG); } GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/src/org/oscim/renderer/PolygonRenderer.java b/src/org/oscim/renderer/PolygonRenderer.java index c26d1f02..ef5b1f34 100644 --- a/src/org/oscim/renderer/PolygonRenderer.java +++ b/src/org/oscim/renderer/PolygonRenderer.java @@ -37,6 +37,7 @@ import java.nio.ByteOrder; import java.nio.FloatBuffer; import org.oscim.core.MapPosition; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.PolygonLayer; import org.oscim.theme.renderinstruction.Area; @@ -105,12 +106,8 @@ public final class PolygonRenderer { } GLState.blend(true); - if (f < 1) { - GlUtils.setColor(hPolygonColor, a.color, - f * a.color[3]); - } else { - glUniform4fv(hPolygonColor, 1, a.color, 0); - } + GlUtils.setColor(hPolygonColor, a.color, f); + } else if (a.blend > 0 && a.blend <= zoom) { /* blend colors (not alpha) */ GLState.blend(false); @@ -119,7 +116,7 @@ public final class PolygonRenderer { GlUtils.setBlendColors(hPolygonColor, a.color, a.blendColor, scale - 1.0f); else - glUniform4fv(hPolygonColor, 1, a.blendColor, 0); + GlUtils.setColor(hPolygonColor, a.blendColor, 1); } else { if (a.color[3] != 1) @@ -127,7 +124,7 @@ public final class PolygonRenderer { else GLState.blend(false); - glUniform4fv(hPolygonColor, 1, a.color, 0); + GlUtils.setColor(hPolygonColor, a.color, 1); } // set stencil buffer mask used to draw this layer @@ -152,8 +149,8 @@ public final class PolygonRenderer { * in layer.area. * @param layer * layer to draw (referencing vertices in current vbo) - * @param matrix - * mvp matrix + * @param m + * current Matrices * @param first * pass true to clear stencil buffer region * @param clip @@ -162,7 +159,7 @@ public final class PolygonRenderer { * next layer */ public static Layer draw(MapPosition pos, Layer layer, - float[] matrix, boolean first, boolean clip) { + Matrices m, boolean first, boolean clip) { GLState.test(false, true); @@ -170,7 +167,8 @@ public final class PolygonRenderer { GLState.enableVertexArrays(hPolygonVertexPosition, -1); glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); - glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); + + m.mvp.setAsUniform(hPolygonMatrix); int zoom = pos.zoomLevel; int cur = mCount; @@ -296,7 +294,7 @@ public final class PolygonRenderer { } } - static void drawOver(float[] matrix) { + static void drawOver(Matrices m) { if (GLState.useProgram(polygonProgram)) { GLState.enableVertexArrays(hPolygonVertexPosition, -1); @@ -304,7 +302,7 @@ public final class PolygonRenderer { glVertexAttribPointer(hPolygonVertexPosition, 2, GL_SHORT, false, 0, POLYGON_VERTICES_DATA_POS_OFFSET); - glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); + m.mvp.setAsUniform(hPolygonMatrix); } /* diff --git a/src/org/oscim/renderer/TextureRenderer.java b/src/org/oscim/renderer/TextureRenderer.java index 23c66dcf..a4694756 100644 --- a/src/org/oscim/renderer/TextureRenderer.java +++ b/src/org/oscim/renderer/TextureRenderer.java @@ -19,6 +19,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ShortBuffer; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.TextureLayer; import org.oscim.utils.GlUtils; @@ -92,7 +93,7 @@ public final class TextureRenderer { GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); } - public static Layer draw(Layer layer, float scale, float[] projection, float matrix[]) { + public static Layer draw(Layer layer, float scale, Matrices m) { GLState.test(false, false); GLState.blend(true); @@ -109,8 +110,8 @@ public final class TextureRenderer { GLES20.glUniform1f(hTextureScreenScale, 1f / GLRenderer.mWidth); - GLES20.glUniformMatrix4fv(hTextureProjMatrix, 1, false, projection, 0); - GLES20.glUniformMatrix4fv(hTextureMVMatrix, 1, false, matrix, 0); + m.proj.setAsUniform(hTextureProjMatrix); + m.mvp.setAsUniform(hTextureMVMatrix); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesVBO); @@ -143,8 +144,6 @@ public final class TextureRenderer { GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - // GlUtils.checkGlError("< draw texture"); - return layer.next; } diff --git a/src/org/oscim/renderer/overlays/BasicOverlay.java b/src/org/oscim/renderer/overlays/BasicOverlay.java index 28fa5f82..6c914ee0 100644 --- a/src/org/oscim/renderer/overlays/BasicOverlay.java +++ b/src/org/oscim/renderer/overlays/BasicOverlay.java @@ -59,13 +59,13 @@ public abstract class BasicOverlay extends RenderOverlay { for (Layer l = layers.baseLayers; l != null;) { switch (l.type) { case Layer.POLYGON: - l = PolygonRenderer.draw(pos, l, m.mvp, true, false); + l = PolygonRenderer.draw(pos, l, m, true, false); break; case Layer.LINE: - l = LineRenderer.draw(layers, l, pos, m.mvp, div, 0); + l = LineRenderer.draw(layers, l, pos, m, div, 0); break; case Layer.TEXLINE: - l = LineTexRenderer.draw(layers, l, pos, m.mvp, div); + l = LineTexRenderer.draw(layers, l, pos, m, div); break; } } @@ -77,7 +77,7 @@ public abstract class BasicOverlay extends RenderOverlay { float scale = (mMapPosition.scale / pos.scale) * div; for (Layer l = layers.textureLayers; l != null;) { - l = TextureRenderer.draw(l, scale, m.proj, m.mvp); + l = TextureRenderer.draw(l, scale, m); } } } diff --git a/src/org/oscim/renderer/overlays/BuildingOverlay.java b/src/org/oscim/renderer/overlays/BuildingOverlay.java deleted file mode 100644 index 372d6b58..00000000 --- a/src/org/oscim/renderer/overlays/BuildingOverlay.java +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright 2013 Hannes Janetzek - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.renderer.overlays; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; - -import org.oscim.core.MapPosition; -import org.oscim.core.Tile; -import org.oscim.renderer.GLRenderer; -import org.oscim.renderer.GLRenderer.Matrices; -import org.oscim.renderer.GLState; -import org.oscim.renderer.layer.VertexPool; -import org.oscim.renderer.layer.VertexPoolItem; -import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; -import org.oscim.view.MapView; - -import android.opengl.GLES20; -import android.opengl.Matrix; -import android.util.Log; - -/** - * @author Hannes Janetzek - */ -public class BuildingOverlay extends RenderOverlay { - - public BuildingOverlay(MapView mapView) { - super(mapView); - } - - private static int buildingProgram; - private static int hBuildingVertexPosition; - private static int hBuildingLightPosition; - private static int hBuildingMatrix; - private static int hBuildingColor; - private static int hBuildingMode; - - private boolean initialized = false; - - private int mIndicesBufferID; - private int mVertexBufferID; - - private int mNumIndices = 0; - private int mNumVertices = 0; - private VertexPoolItem mVertices, mCurVertices; - private VertexPoolItem mIndices[], mCurIndices[]; - - private final int mIndiceCnt[] = { 0, 0, 0 }; - - private void addOutline(float[] points, float height) { - int len = points.length; - boolean oddFace = (len % 4 != 0); - int verticesCnt = len + (oddFace ? 2 : 0); - int indicesCnt = len / 2 * 6; - - short h = (short) height; - - float cx = points[len - 2]; - float cy = points[len - 1]; - float nx = points[0]; - float ny = points[1]; - - float vx = nx - cx; - float vy = ny - cy; - float a = vx / (float) Math.sqrt(vx * vx + vy * vy); - - short color1 = (short) (200 + (40 * (a > 0 ? a : -a))); - short fcolor = color1; - short color2 = 0; - - boolean even = true; - - short[] vertices = mCurVertices.vertices; - int v = mCurVertices.used; - - for (int i = 0; i < len; i += 2, v += 8) { - cx = nx; - cy = ny; - - if (v == VertexPoolItem.SIZE) { - mCurVertices.used = VertexPoolItem.SIZE; - mCurVertices.next = VertexPool.get(); - mCurVertices = mCurVertices.next; - vertices = mCurVertices.vertices; - v = 0; - } - - vertices[v + 0] = vertices[v + 4] = (short) cx; - vertices[v + 1] = vertices[v + 5] = (short) cy; - - vertices[v + 2] = 0; - vertices[v + 6] = h; - - if (i < len - 2) { - nx = points[i + 2]; - ny = points[i + 3]; - - vx = nx - cx; - vy = ny - cy; - a = vx / (float) Math.sqrt(vx * vx + vy * vy); - - color2 = (short) (200 + (40 * (a > 0 ? a : -a))); - } else { - color2 = fcolor; - } - - short c; - if (even) - c = (short) (color1 | color2 << 8); - else - c = (short) (color2 | color1 << 8); - - vertices[v + 3] = vertices[v + 7] = c; - - color1 = color2; - even = !even; - } - - if (oddFace) { - //int v = len * 4; - if (v == VertexPoolItem.SIZE) { - mCurVertices.used = VertexPoolItem.SIZE; - mCurVertices.next = VertexPool.get(); - mCurVertices = mCurVertices.next; - vertices = mCurVertices.vertices; - v = 0; - } - - cx = points[0]; - cy = points[1]; - - vertices[v + 0] = vertices[v + 4] = (short) cx; - vertices[v + 1] = vertices[v + 5] = (short) cy; - - 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) - for (int j = 0; j < 2; j++) { - short[] indices = mCurIndices[j].vertices; - int cnt = mCurIndices[j].used; - - for (int k = j * 2; k < len; k += 4) { - int i = mNumVertices + k; - - short s0 = (short) (i + 0); - short s1 = (short) (i + 1); - short s2 = (short) (i + 2); - short s3 = (short) (i + 3); - - if (cnt == VertexPoolItem.SIZE) { - mCurIndices[j].used = VertexPoolItem.SIZE; - mCurIndices[j].next = VertexPool.get(); - mCurIndices[j] = mCurIndices[j].next; - vertices = mCurIndices[j].vertices; - cnt = 0; - } - - // connect last to first (when number of faces is even) - if (k + 3 > verticesCnt) { - s2 -= verticesCnt; - s3 -= verticesCnt; - } - - indices[cnt++] = s0; - indices[cnt++] = s1; - indices[cnt++] = s2; - - indices[cnt++] = s1; - indices[cnt++] = s3; - indices[cnt++] = s2; - //System.out.println("indice:" + k + "\t" + s0 + "," + s1 + "," + s2); - //System.out.println("indice:" + k + "\t" + s1 + "," + s3 + "," + s2); - } - mCurIndices[j].used = cnt; - } - - // roof indices for convex shapes - int cnt = mCurIndices[2].used; - short[] indices = mCurIndices[2].vertices; - short first = (short) (mNumVertices + 1); - - for (int k = 0; k < len - 4; k += 2) { - - if (cnt == VertexPoolItem.SIZE) { - mCurIndices[2].used = VertexPoolItem.SIZE; - mCurIndices[2].next = VertexPool.get(); - mCurIndices[2] = mCurIndices[2].next; - vertices = mCurIndices[2].vertices; - cnt = 0; - } - indices[cnt++] = first; - indices[cnt++] = (short) (first + k + 4); - indices[cnt++] = (short) (first + k + 2); - - System.out.println("indice:" + k + "\t" + indices[cnt - 3] + "," + indices[cnt - 2] - + "," + indices[cnt - 1]); - - indicesCnt += 3; - } - mCurIndices[2].used = cnt; - - mNumVertices += verticesCnt; - mNumIndices += indicesCnt; - } - - @Override - public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { - - if (initialized) - return; - initialized = true; - - // Set up the program for rendering buildings - buildingProgram = GlUtils.createProgram(buildingVertexShader, - buildingFragmentShader); - if (buildingProgram == 0) { - Log.e("blah", "Could not create building program."); - return; - } - hBuildingMatrix = GLES20.glGetUniformLocation(buildingProgram, "u_mvp"); - hBuildingColor = GLES20.glGetUniformLocation(buildingProgram, "u_color"); - hBuildingMode = GLES20.glGetUniformLocation(buildingProgram, "u_mode"); - hBuildingVertexPosition = GLES20.glGetAttribLocation(buildingProgram, "a_position"); - hBuildingLightPosition = GLES20.glGetAttribLocation(buildingProgram, "a_light"); - - mVertices = mCurVertices = VertexPool.get(); - mIndices = new VertexPoolItem[3]; - mCurIndices = new VertexPoolItem[3]; - mIndices[0] = mCurIndices[0] = VertexPool.get(); - mIndices[1] = mCurIndices[1] = VertexPool.get(); - mIndices[2] = mCurIndices[2] = VertexPool.get(); - - float height = 450; - - float[] points = { - -200, -200, - 200, -200, - 200, 200, - -200, 200, - -300, 0 - }; - addOutline(points, height); - - float[] points2 = { - 300, -300, - 500, -300, - 600, 100, - 300, 100, - // 350, 0 - }; - - addOutline(points2, height); - - height = 650; - - float[] points4 = new float[80]; - for (int i = 0; i < 80; i += 2) { - points4[i + 0] = (float) (Math.sin(i / -40f * Math.PI) * 200); - points4[i + 1] = (float) (Math.cos(i / -40f * Math.PI) * 200) - 600; - } - - addOutline(points4, height); - - height = 950; - - points4 = new float[40]; - for (int i = 0; i < 40; i += 2) { - points4[i + 0] = (float) (Math.sin(i / -20f * Math.PI) * 100); - points4[i + 1] = (float) (Math.cos(i / -20f * Math.PI) * 100) - 550; - } - - addOutline(points4, height); - - float[] points3 = new float[24]; - for (int i = 0; i < 24; i += 2) { - points3[i + 0] = (float) (Math.sin(i / -12f * Math.PI) * 200) - 600; - points3[i + 1] = (float) (Math.cos(i / -12f * Math.PI) * 200) - 600; - } - - addOutline(points3, height); - - int bufferSize = Math.max(mNumVertices * 4 * 2, mNumIndices * 2); - ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize) - .order(ByteOrder.nativeOrder()); - - ShortBuffer sbuf = buf.asShortBuffer(); - - int[] mVboIds = new int[2]; - GLES20.glGenBuffers(2, mVboIds, 0); - mIndicesBufferID = mVboIds[0]; - mVertexBufferID = mVboIds[1]; - - // upload indices - for (int i = 0; i < 3; 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; - } - } - sbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); - GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, - mNumIndices * 2, sbuf, GLES20.GL_STATIC_DRAW); - sbuf.clear(); - - // upload vertices - for (VertexPoolItem vi = mVertices; vi != null; vi = vi.next) { - System.out.println("put vertices: " + vi.used + " " + mNumVertices); - sbuf.put(vi.vertices, 0, vi.used); - } - sbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, - mNumVertices * 4 * 2, sbuf, GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - - mMapView.getMapViewPosition().getMapPosition(mMapPosition); - - // tell GLRenderer to call 'render' - isReady = true; - } - - @Override - public synchronized void render(MapPosition pos, Matrices m) { - setMatrix(pos, m); - - GLState.useProgram(buildingProgram); - - GLES20.glUniformMatrix4fv(hBuildingMatrix, 1, false, m.mvp, 0); - GLES20.glUniform4f(hBuildingColor, 0.5f, 0.5f, 0.5f, 0.7f); - - GLState.enableVertexArrays(hBuildingVertexPosition, hBuildingLightPosition); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - - GLES20.glVertexAttribPointer(hBuildingVertexPosition, 3, - GLES20.GL_SHORT, false, 8, 0); - - GLES20.glVertexAttribPointer(hBuildingLightPosition, 2, - GLES20.GL_UNSIGNED_BYTE, false, 8, 6); - - // GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, - // GLES20.GL_UNSIGNED_SHORT, 0); - - // draw to depth buffer - GLES20.glUniform1i(hBuildingMode, 0); - GLES20.glColorMask(false, false, false, false); - GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); - GLState.test(true, false); - GLES20.glEnable(GLES20.GL_CULL_FACE); - - GLES20.glDepthMask(true); - GLES20.glDepthFunc(GLES20.GL_LESS); - - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, - GLES20.GL_UNSIGNED_SHORT, 0); - - // enable color buffer, use depth mask - GLES20.glColorMask(true, true, true, true); - GLES20.glDepthMask(false); - GLES20.glDepthFunc(GLES20.GL_EQUAL); - - // draw roof - GLES20.glUniform4f(hBuildingColor, 0.75f, 0.7f, 0.7f, 0.9f); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mIndiceCnt[0], - GLES20.GL_UNSIGNED_SHORT, (mIndiceCnt[0] + mIndiceCnt[1]) * 2); - - // draw sides 1 - //GLES20.glUniform4f(hBuildingColor, 0.8f, 0.8f, 0.8f, 1.0f); - GLES20.glUniform4f(hBuildingColor, 0.9f, 0.905f, 0.9f, 1.0f); - GLES20.glUniform1i(hBuildingMode, 1); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mIndiceCnt[0], - GLES20.GL_UNSIGNED_SHORT, 0); - - // draw sides 2 - GLES20.glUniform4f(hBuildingColor, 0.9f, 0.9f, 0.905f, 1.0f); - GLES20.glUniform1i(hBuildingMode, 2); - - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mIndiceCnt[1], - GLES20.GL_UNSIGNED_SHORT, mIndiceCnt[0] * 2); - - GLES20.glDisable(GLES20.GL_CULL_FACE); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - GlUtils.checkGlError("..."); - } - - @Override - protected void setMatrix(MapPosition curPos, Matrices m) { - - MapPosition oPos = mMapPosition; - - byte z = oPos.zoomLevel; - - float div = FastMath.pow(z - curPos.zoomLevel); - float x = (float) (oPos.x - curPos.x * div); - float y = (float) (oPos.y - curPos.y * div); - - // flip around date-line - float max = (Tile.TILE_SIZE << z); - if (x < -max / 2) - x = max + x; - else if (x > max / 2) - x = x - max; - - float scale = curPos.scale / div; - - Matrix.setIdentityM(m.mvp, 0); - - // translate relative to map center - m.mvp[12] = x * scale; - m.mvp[13] = y * scale; - // scale to current tile world coordinates - scale = (curPos.scale / oPos.scale) / div; - scale /= GLRenderer.COORD_SCALE; - m.mvp[0] = scale; - m.mvp[5] = scale; - m.mvp[10] = scale / 1000f; - - Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0); - } - - final static String buildingVertexShader = "" - + "precision mediump float;" - + "uniform mat4 u_mvp;" - + "uniform vec4 u_color;" - + "uniform int u_mode;" - + "uniform float u_scale;" - + "attribute vec4 a_position;" - + "attribute vec2 a_light;" - + "varying vec4 color;" - + "const float ff = 255.0;" - + "void main() {" - + " gl_Position = u_mvp * a_position;" - + " if (u_mode == 0)" - // roof / depth pass - + " color = u_color;" - + " else if (u_mode == 1)" - // sides 1 - use 0xff00 - + " color = vec4(u_color.rgb * (a_light.y / ff), 0.95);" - + " else" - // sides 2 - use 0x00ff - + " color = vec4(u_color.rgb * (a_light.x / ff), 0.95);" - + "}"; - - final static String buildingFragmentShader = "" - + "precision mediump float;" - + "varying vec4 color;" - + "void main() {" - + " gl_FragColor = color;" - + "}"; - - @Override - public void compile() { - // TODO Auto-generated method stub - - } - - // private short[] mVertices = { - // // 0 - north - // -200, -200, 0, - // (short) (220 | (200 << 8)), - // // 1 - // -200, -200, 950, - // (short) (220 | (200 << 8)), - // // 2 - // 200, -200, 0, - // (short) (170 | (200 << 8)), - // // 3 - // 200, -200, 950, - // (short) (170 | (200 << 8)), - // - // // 4 - south - // 200, 200, 0, - // (short) (170 | (180 << 8)), - // // 5 - // 200, 200, 950, - // (short) (170 | (180 << 8)), - // // 6 - // -200, 200, 0, - // (short) (220 | (180 << 8)), - // // 7 - // -200, 200, 950, - // (short) (220 | (180 << 8)), - //}; - // - //private short[] mIndices = { - // // north - // 0, 1, 2, - // 1, 3, 2, - // // south - // 4, 5, 6, - // 5, 7, 6, - // // east - // 2, 3, 4, - // 3, 5, 4, - // // west - // 6, 7, 0, - // 7, 1, 0, - // // top - // 1, 5, 3, - // 7, 5, 1 - //}; - // - // - //private int mNumIndices = mIndices.length; - //private int mNumVertices = mVertices.length / 4; -} diff --git a/src/org/oscim/renderer/overlays/CustomOverlay.java b/src/org/oscim/renderer/overlays/CustomOverlay.java index a2da2f98..2b57c0a6 100644 --- a/src/org/oscim/renderer/overlays/CustomOverlay.java +++ b/src/org/oscim/renderer/overlays/CustomOverlay.java @@ -54,7 +54,7 @@ public class CustomOverlay extends RenderOverlay { // ---------- everything below runs in GLRender Thread ---------- @Override - public void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) { + public void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged, Matrices matrices) { if (!mInitialized) { if (!init()) return; @@ -107,13 +107,7 @@ public class CustomOverlay extends RenderOverlay { // set mvp (tmp) matrix relative to mMapPosition // i.e. fixed on the map setMatrix(pos, m); - - //Matrix.multiplyMM(tmp, 0, proj, 0, tmp, 0); - - // or set mvp matrix fixed on screen center - // Matrix.multiplyMM(tmp, 0, proj, 0, pos.viewMatrix, 0); - - GLES20.glUniformMatrix4fv(hMatrixPosition, 1, false, m.mvp, 0); + m.mvp.setAsUniform(hMatrixPosition); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); diff --git a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java index 046673a4..ab89e5cb 100644 --- a/src/org/oscim/renderer/overlays/ExtrusionOverlay.java +++ b/src/org/oscim/renderer/overlays/ExtrusionOverlay.java @@ -31,7 +31,6 @@ import org.oscim.utils.GlUtils; import org.oscim.view.MapView; import android.opengl.GLES20; -import android.opengl.Matrix; import android.util.Log; /** @@ -63,7 +62,7 @@ public class ExtrusionOverlay extends RenderOverlay { @Override public void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { mMapView.getMapViewPosition().getMapPosition(mMapPosition); @@ -172,9 +171,6 @@ public class ExtrusionOverlay extends RenderOverlay { // TODO one could render in one pass to texture and then draw the texture // with alpha... might be faster. - //Matrix.multiplyMM(mVPMatrix, 0, proj, 0, pos.viewMatrix, 0); - //proj = mVPMatrix; - MapTile[] tiles = mTiles; float div = FastMath.pow(tiles[0].zoomLevel - pos.zoomLevel); @@ -200,7 +196,7 @@ public class ExtrusionOverlay extends RenderOverlay { ExtrusionLayer el = (ExtrusionLayer) tiles[i].layers.extrusionLayers; setMatrix(pos, m, tiles[i], div, 0); - GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0); + m.mvp.setAsUniform(uExtMatrix); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); @@ -252,7 +248,7 @@ public class ExtrusionOverlay extends RenderOverlay { ExtrusionLayer el = (ExtrusionLayer) t.layers.extrusionLayers; int d = GLRenderer.depthOffset(t) * 10; setMatrix(pos, m, t, div, d); - GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0); + m.mvp.setAsUniform(uExtMatrix); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); @@ -278,7 +274,7 @@ public class ExtrusionOverlay extends RenderOverlay { GLES20.glDepthFunc(GLES20.GL_EQUAL); int d = GLRenderer.depthOffset(t) * 10; setMatrix(pos, m, t, div, d); - GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0); + m.mvp.setAsUniform(uExtMatrix); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, el.mIndicesBufferID); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, el.mVertexBufferID); @@ -307,8 +303,9 @@ public class ExtrusionOverlay extends RenderOverlay { // drawing gl_lines with the same coordinates does not result in // same depth values as polygons, so add offset and draw gl_lequal: GLES20.glDepthFunc(GLES20.GL_LEQUAL); - GlUtils.addOffsetM(m.mvp, 100); - GLES20.glUniformMatrix4fv(uExtMatrix, 1, false, m.mvp, 0); + + m.mvp.addDepthOffset(100); + m.mvp.setAsUniform(uExtMatrix); GLES20.glUniform1i(uExtMode, 3); GLES20.glDrawElements(GLES20.GL_LINES, el.mIndiceCnt[3], @@ -331,13 +328,15 @@ public class ExtrusionOverlay extends RenderOverlay { float y = (float) (tile.pixelY - mapPosition.y * div); float scale = mapPosition.scale / div; - GlUtils.setTileMatrix(m.mvp, x, y, scale); + m.mvp.setTransScale(x * scale, y * scale, + scale / GLRenderer.COORD_SCALE); + // scale height - m.mvp[10] = scale / (1000f * GLRenderer.COORD_SCALE); + m.mvp.setValue(10, scale / (1000f * GLRenderer.COORD_SCALE)); - Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0); + m.mvp.multiplyMM(m.viewproj, m.mvp); - GlUtils.addOffsetM(m.mvp, delta); + m.mvp.addDepthOffset(delta); } private final float _a = 0.86f; diff --git a/src/org/oscim/renderer/overlays/GridOverlay.java b/src/org/oscim/renderer/overlays/GridOverlay.java index 85c5f78c..217a7542 100644 --- a/src/org/oscim/renderer/overlays/GridOverlay.java +++ b/src/org/oscim/renderer/overlays/GridOverlay.java @@ -16,6 +16,7 @@ package org.oscim.renderer.overlays; import org.oscim.core.MapPosition; import org.oscim.core.Tile; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.LineLayer; import org.oscim.renderer.layer.TextItem; @@ -105,7 +106,7 @@ public class GridOverlay extends BasicOverlay { @Override public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { updateMapPosition(); diff --git a/src/org/oscim/renderer/overlays/ModelOverlay.java b/src/org/oscim/renderer/overlays/ModelOverlay.java deleted file mode 100644 index 4e382f06..00000000 --- a/src/org/oscim/renderer/overlays/ModelOverlay.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright 2013 Hannes Janetzek - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.renderer.overlays; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.nio.ShortBuffer; - -import org.oscim.core.MapPosition; -import org.oscim.core.Tile; -import org.oscim.renderer.GLRenderer; -import org.oscim.renderer.GLRenderer.Matrices; -import org.oscim.renderer.GLState; -import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; -import org.oscim.view.MapView; - -import android.opengl.GLES20; -import android.opengl.Matrix; -import android.util.Log; - -/** - * @author Hannes Janetzek - */ -public class ModelOverlay extends RenderOverlay { - - public ModelOverlay(MapView mapView) { - super(mapView); - } - - private final float[] box = { - // north - -200f, -200f, 0, 0.9f, - 200f, -200f, 0, 0.9f, - -200f, -200f, 0.15f, 0.9f, - 200f, -200f, 0.15f, 0.9f, - - // west - -200f, -200f, 0, 0.8f, - -200f, 200f, 0, 0.8f, - -200f, -200f, 0.15f, 0.8f, - -200f, 200f, 0.15f, 0.8f, - - // south - 200f, 200f, 0, 0.7f, - -200f, 200f, 0, 0.7f, - 200f, 200f, 0.15f, 0.7f, - -200f, 200f, 0.15f, 0.7f, - - // east - 200f, -200f, 0, 1.0f, - 200f, 200f, 0, 1.0f, - 200f, -200f, 0.15f, 1.0f, - 200f, 200f, 0.15f, 1.0f, - }; - - private final short[] indices = { - // north - 0, 1, 2, - 2, 1, 3, - // west - 4, 5, 6, - 6, 5, 7, - // south - 8, 9, 10, - 10, 9, 11, - // east - 12, 13, 14, - 14, 13, 15, - // top - 2, 3, 10, - 10, 11, 2 - }; - - private static int polygonProgram; - private static int hPolygonVertexPosition; - private static int hPolygonLightPosition; - private static int hPolygonMatrix; - private static int hPolygonColor; - //private static int hPolygonScale; - - private boolean initialized = false; - - final static String polygonVertexShader = "" - + "precision mediump float;" - + "uniform mat4 u_mvp;" - + "uniform vec4 u_color;" - + "attribute vec4 a_position;" - + "attribute float a_light;" - + "varying vec4 color;" - + "void main() {" - + " gl_Position = u_mvp * a_position;" - + " if (u_color.a == 0.0)" - + " color = vec4(u_color.rgb * a_light, 0.8);" - + " else" - + " color = u_color;" - + "}"; - - final static String polygonFragmentShader = "" - + "precision mediump float;" - + "varying vec4 color;" - + "void main() {" - + " gl_FragColor = color;" - + "}"; - - private int mIndicesBufferID; - private int mVertexBufferID; - - @Override - public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { - - if (initialized) - return; - initialized = true; - - // Set up the program for rendering polygons - polygonProgram = GlUtils.createProgram(polygonVertexShader, - polygonFragmentShader); - if (polygonProgram == 0) { - Log.e("blah", "Could not create polygon program."); - return; - } - hPolygonMatrix = GLES20.glGetUniformLocation(polygonProgram, "u_mvp"); - hPolygonColor = GLES20.glGetUniformLocation(polygonProgram, "u_color"); - hPolygonVertexPosition = GLES20.glGetAttribLocation(polygonProgram, "a_position"); - hPolygonLightPosition = GLES20.glGetAttribLocation(polygonProgram, "a_light"); - - int[] mVboIds = new int[2]; - GLES20.glGenBuffers(2, mVboIds, 0); - mIndicesBufferID = mVboIds[0]; - mVertexBufferID = mVboIds[1]; - - ByteBuffer buf = ByteBuffer.allocateDirect(64 * 4) - .order(ByteOrder.nativeOrder()); - - ShortBuffer sbuf = buf.asShortBuffer(); - sbuf.put(indices); - sbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); - GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, 30 * 2, sbuf, GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - - FloatBuffer fbuf = buf.asFloatBuffer(); - fbuf.put(box); - fbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, 64 * 4, fbuf, GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - - mMapView.getMapViewPosition().getMapPosition(mMapPosition); - - // tell GLRenderer to call 'render' - isReady = true; - } - - @Override - public synchronized void render(MapPosition pos, Matrices m) { - - setMatrix(pos, m); - - GLState.useProgram(polygonProgram); - - GLState.enableVertexArrays(hPolygonVertexPosition, hPolygonLightPosition); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - - GLES20.glVertexAttribPointer(hPolygonVertexPosition, 3, GLES20.GL_FLOAT, false, 16, 0); - GLES20.glVertexAttribPointer(hPolygonLightPosition, 1, GLES20.GL_FLOAT, false, 16, 12); - - GLES20.glUniformMatrix4fv(hPolygonMatrix, 1, false, m.mvp, 0); - GLES20.glUniform4f(hPolygonColor, 0.5f, 0.5f, 0.5f, 0.7f); - - // draw to depth buffer - GLES20.glColorMask(false, false, false, false); - GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); - GLState.test(true, false); - GLES20.glDepthMask(true); - GLES20.glDepthFunc(GLES20.GL_LESS); - - GLES20.glDrawElements(GLES20.GL_TRIANGLES, 30, GLES20.GL_UNSIGNED_SHORT, 0); - - GLES20.glColorMask(true, true, true, true); - GLES20.glDepthMask(false); - GLES20.glDepthFunc(GLES20.GL_EQUAL); - - // draw sides - GLES20.glUniform4f(hPolygonColor, 0.7f, 0.7f, 0.7f, 0.0f); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, 24, GLES20.GL_UNSIGNED_SHORT, 0); - - // draw roof - GLES20.glUniform4f(hPolygonColor, 0.7f, 0.5f, 0.5f, 0.7f); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, 24 * 2); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - GlUtils.checkGlError("..."); - } - - @Override - protected void setMatrix(MapPosition curPos, Matrices m) { - // TODO if oPos == curPos this could be simplified - - MapPosition oPos = mMapPosition; - - byte z = oPos.zoomLevel; - - float div = FastMath.pow(z - curPos.zoomLevel); - float x = (float) (oPos.x - curPos.x * div); - float y = (float) (oPos.y - curPos.y * div); - - // flip around date-line - float max = (Tile.TILE_SIZE << z); - if (x < -max / 2) - x = max + x; - else if (x > max / 2) - x = x - max; - - float scale = curPos.scale / div; - - Matrix.setIdentityM(m.mvp, 0); - - // translate relative to map center - m.mvp[12] = x * scale; - m.mvp[13] = y * scale; - // scale to current tile world coordinates - scale = (curPos.scale / oPos.scale) / div; - scale /= GLRenderer.COORD_SCALE; - m.mvp[0] = scale; - m.mvp[5] = scale; - m.mvp[10] = scale; // 1000f; - - Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0); - } - - @Override - public void compile() { - // TODO Auto-generated method stub - - } - -} diff --git a/src/org/oscim/renderer/overlays/RenderOverlay.java b/src/org/oscim/renderer/overlays/RenderOverlay.java index cda73c44..fffbcf55 100644 --- a/src/org/oscim/renderer/overlays/RenderOverlay.java +++ b/src/org/oscim/renderer/overlays/RenderOverlay.java @@ -19,11 +19,8 @@ import org.oscim.core.Tile; import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; import org.oscim.view.MapView; -import android.opengl.Matrix; - public abstract class RenderOverlay { protected final MapView mMapView; @@ -52,8 +49,9 @@ public abstract class RenderOverlay { * true when MapPosition has changed * @param tilesChanged * true when current tiles changed + * @param matrices TODO */ - public abstract void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged); + public abstract void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged, Matrices matrices); /** * called 2. compile everything for drawing @@ -102,13 +100,10 @@ public abstract class RenderOverlay { // set scale to be relative to current scale float s = (curPos.scale / oPos.scale) / div; - GlUtils.setMatrix(m.mvp, x * scale, y * scale, + m.mvp.setTransScale(x * scale, y * scale, s / GLRenderer.COORD_SCALE); - if (project) - Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0); - else - Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0); + m.mvp.multiplyMM(project ? m.viewproj : m.view, m.mvp); } /** diff --git a/src/org/oscim/renderer/overlays/TestLineOverlay.java b/src/org/oscim/renderer/overlays/TestLineOverlay.java deleted file mode 100644 index c2024bb1..00000000 --- a/src/org/oscim/renderer/overlays/TestLineOverlay.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright 2013 Hannes Janetzek - * - * This program is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program. If not, see . - */ -package org.oscim.renderer.overlays; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; - -import org.oscim.core.MapPosition; -import org.oscim.core.Tile; -import org.oscim.renderer.GLRenderer; -import org.oscim.renderer.GLRenderer.Matrices; -import org.oscim.renderer.GLState; -import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; -import org.oscim.view.MapView; - -import android.opengl.GLES20; -import android.opengl.Matrix; -import android.util.Log; - -/** - * @author Hannes Janetzek - */ -public class TestLineOverlay extends RenderOverlay { - - public TestLineOverlay(MapView mapView) { - super(mapView); - } - - // Interleave two segment quads in one block to be able to use - // vertices twice. pos0 and pos1 use the same vertex array where - // pos1 is off-setted by one vertex. The vertex shader will use - // pos0 when the vertexId is even, pos1 when the Id is odd. - // - // As there is no gl_VertexId in gles 2.0 an additional 'flip' - // array is used. Depending on 'flip' extrusion is inverted. - // - // Indices and flip buffers can be static. - // - // First pass: using even vertex array positions - // (used vertices are in braces) - // vertex id 0 1 2 3 4 5 6 7 - // pos0 - (0) 1 (2) 3 (4) 5 (6) 7 - - // pos1 - (0) 1 (2) 3 (4) 5 (6) 7 - - // flip 0 1 0 1 0 1 0 1 - // - // Second pass: using odd vertex array positions - // vertex id 0 1 2 3 4 5 6 7 - // pos0 - 0 (1) 2 (3) 4 (5) 6 (7) - - // pos1 - 0 (1) 2 (3) 4 (5) 6 (7) - - // flip 0 1 0 1 0 1 0 1 - // - // Vertex layout: - // [2 short] position, - // [2 short] extrusion, - // [1 short] line length - // [1 short] unused - // - // indices: (two indice blocks) - // 0, 1, 2, - // 2, 1, 3, - // 4, 5, 6, - // 6, 5, 7, - - private static int testProgram; - private static int htestVertexPosition0; - private static int htestVertexPosition1; - private static int htestVertexLength0; - private static int htestVertexLength1; - private static int htestVertexFlip; - private static int htestMatrix; - private static int htestTexColor; - private static int htestBgColor; - private static int htestScale; - - private boolean initialized = false; - - final static String testVertexShader = "" - + "precision mediump float;" - + "uniform mat4 u_mvp;" - + "uniform vec4 u_color;" - + "uniform float u_scale;" - + "attribute vec4 a_pos0;" - + "attribute vec4 a_pos1;" - + "attribute vec2 a_len0;" - + "attribute vec2 a_len1;" - + "attribute float a_flip;" - + "varying vec2 v_st;" - + "void main() {" - + " float div = (8.0 * 16.0) / max(ceil(log(u_scale)),1.0);" - + " if (a_flip == 0.0){" - + " vec2 dir = a_pos0.zw/16.0;" - + " gl_Position = u_mvp * vec4(a_pos0.xy + dir / u_scale, 0.0, 1.0);" - + " v_st = vec2(a_len0.x/div, 1.0);" - + " }else {" - + " vec2 dir = a_pos1.zw/16.0;" - + " gl_Position = u_mvp * vec4(a_pos1.xy - dir / u_scale, 0.0, 1.0);" - + " v_st = vec2(a_len1.x/div, -1.0);" - + " }" - + "}"; - - final static String testFragmentShader = "" - + "precision mediump float;" - + "uniform sampler2D tex;" - + " uniform vec4 u_color;" - + " uniform vec4 u_bgcolor;" - + "varying vec2 v_st;" - + "void main() {" - + " float len = texture2D(tex, v_st).a;" - + " float tex_w = abs(v_st.t);" - + " float line_w = (1.0 - smoothstep(0.7, 1.0, tex_w));" - + " float stipple_w = (1.0 - smoothstep(0.1, 0.6, tex_w));" - + " float stipple_p = smoothstep(0.495, 0.505, len);" - + " gl_FragColor = line_w * mix(u_bgcolor, u_color, min(stipple_w, stipple_p));" - - //+ " gl_FragColor = u_color * min(abs(1.0 - mod(v_len, 20.0)/10.0), (1.0 - abs(v_st.x)));" - + "}"; - - private int mIndicesBufferID; - private int mVertexBufferID; - private int mVertexFlipID; - - //private int mNumVertices; - private int mNumIndices; - - private int mTexID; - - @Override - public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { - - if (initialized) - return; - initialized = true; - - // Set up the program for rendering tests - testProgram = GlUtils.createProgram(testVertexShader, - testFragmentShader); - if (testProgram == 0) { - Log.e("...", "Could not create test program."); - return; - } - htestMatrix = GLES20.glGetUniformLocation(testProgram, "u_mvp"); - htestTexColor = GLES20.glGetUniformLocation(testProgram, "u_color"); - htestBgColor = GLES20.glGetUniformLocation(testProgram, "u_bgcolor"); - htestScale = GLES20.glGetUniformLocation(testProgram, "u_scale"); - - htestVertexPosition0 = GLES20.glGetAttribLocation(testProgram, "a_pos0"); - htestVertexPosition1 = GLES20.glGetAttribLocation(testProgram, "a_pos1"); - htestVertexLength0 = GLES20.glGetAttribLocation(testProgram, "a_len0"); - htestVertexLength1 = GLES20.glGetAttribLocation(testProgram, "a_len1"); - htestVertexFlip = GLES20.glGetAttribLocation(testProgram, "a_flip"); - - int[] mVboIds = new int[3]; - GLES20.glGenBuffers(3, mVboIds, 0); - mIndicesBufferID = mVboIds[0]; - mVertexBufferID = mVboIds[1]; - mVertexFlipID = mVboIds[2]; - - float points[] = { - -800, -800, - 800, -800, - 800, 800, - -800, 800, - -800, -800, - }; - - // float[] points = new float[12 * 2]; - // for (int i = 0; i < 24; i += 2) { - // points[i + 0] = (float) Math.sin(-i / 11f * Math.PI) * 8*400; - // points[i + 1] = (float) Math.cos(-i / 11f * Math.PI) * 8*400; - // } - - boolean oddSegments = points.length % 4 == 0; - - int numVertices = points.length + (oddSegments ? 2 : 0); - - short[] vertices = new short[numVertices * 6]; - - int opos = 6; - - float x = points[0]; - float y = points[1]; - - float scale = 255; - boolean even = true; - float len = 0; - - for (int i = 2; i < points.length; i += 2) { - float nx = points[i + 0]; - float ny = points[i + 1]; - - // Calculate triangle corners for the given width - float vx = nx - x; - float vy = ny - y; - - float a = (float) Math.sqrt(vx * vx + vy * vy); - - // normal vector - vx /= a; - vy /= a; - - // perpendicular to line segment - float ux = -vy; - float uy = vx; - - short dx = (short) (ux * scale); - short dy = (short) (uy * scale); - - vertices[opos + 0] = (short) x; - vertices[opos + 1] = (short) y; - vertices[opos + 2] = dx; - vertices[opos + 3] = dy; - vertices[opos + 4] = (short) len; - vertices[opos + 5] = 0; - - len += a; - vertices[opos + 12] = (short) nx; - vertices[opos + 13] = (short) ny; - vertices[opos + 14] = dx; - vertices[opos + 15] = dy; - vertices[opos + 16] = (short) len; - vertices[opos + 17] = 0; - - x = nx; - y = ny; - - if (even) { - // go to second segment - opos += 6; - even = false; - } else { - // go to next block - even = true; - opos += 18; - } - - } - - // 0, 1, 0, 1 - byte[] flip = new byte[points.length]; - for (int i = 0; i < flip.length; i++) - flip[i] = (byte) (i % 2); - - short j = 0; - mNumIndices = ((points.length) >> 2) * 6; - - short[] indices = new short[mNumIndices]; - for (int i = 0; i < mNumIndices; i += 6, j += 4) { - indices[i + 0] = (short) (j + 0); - indices[i + 1] = (short) (j + 1); - indices[i + 2] = (short) (j + 2); - - indices[i + 3] = (short) (j + 2); - indices[i + 4] = (short) (j + 1); - indices[i + 5] = (short) (j + 3); - } - - ByteBuffer buf = ByteBuffer.allocateDirect(numVertices * 6 * 2) - .order(ByteOrder.nativeOrder()); - - ShortBuffer sbuf = buf.asShortBuffer(); - sbuf.put(indices); - sbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID); - GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.length * 2, sbuf, - GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - - sbuf.clear(); - sbuf.put(vertices); - sbuf.flip(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.length * 2, sbuf, - GLES20.GL_STATIC_DRAW); - - buf.clear(); - buf.put(flip); - buf.flip(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, flip.length, buf, - GLES20.GL_STATIC_DRAW); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - - byte[] stipple = new byte[2]; - stipple[0] = 8; - stipple[1] = 8; - //stipple[2] = 16; - //stipple[3] = 48; - - mTexID = GlUtils.loadStippleTexture(stipple); - - mMapView.getMapViewPosition().getMapPosition(mMapPosition); - - // tell GLRenderer to call 'render' - isReady = true; - } - - private final static int STRIDE = 12; - private final static int LEN_OFFSET = 8; - - @Override - public synchronized void render(MapPosition pos, Matrices m) { - - setMatrix(pos, m); - //Matrix.multiplyMM(mv, 0, proj, 0, mv, 0); - - GLState.useProgram(testProgram); - GLES20.glDisable(GLES20.GL_CULL_FACE); - GLState.test(false, false); - GLState.enableVertexArrays(-1, -1); - GLES20.glEnableVertexAttribArray(htestVertexPosition0); - GLES20.glEnableVertexAttribArray(htestVertexPosition1); - GlUtils.checkGlError("-4"); - GLES20.glEnableVertexAttribArray(htestVertexLength0); - GlUtils.checkGlError("-3"); - GLES20.glEnableVertexAttribArray(htestVertexLength1); - GlUtils.checkGlError("-2"); - GLES20.glEnableVertexAttribArray(htestVertexFlip); - - GLES20.glUniformMatrix4fv(htestMatrix, 1, false, m.mvp, 0); - float div = FastMath.pow(pos.zoomLevel - mMapPosition.zoomLevel); - GLES20.glUniform1f(htestScale, pos.scale / mMapPosition.scale * div); - - GLES20.glUniform4f(htestTexColor, 1.0f, 1.0f, 1.0f, 1.0f); - GLES20.glUniform4f(htestBgColor, 0.3f, 0.3f, 0.3f, 1.0f); - - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexID); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, - mIndicesBufferID); - GlUtils.checkGlError("-1"); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexFlipID); - GLES20.glVertexAttribPointer(htestVertexFlip, 1, - GLES20.GL_BYTE, false, 0, 0); - GlUtils.checkGlError("0"); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID); - GlUtils.checkGlError("1"); - - // first pass - GLES20.glVertexAttribPointer(htestVertexPosition0, - 4, GLES20.GL_SHORT, false, STRIDE, STRIDE); - GlUtils.checkGlError("2"); - - GLES20.glVertexAttribPointer(htestVertexLength0, - 2, GLES20.GL_SHORT, false, STRIDE, STRIDE + LEN_OFFSET); - GlUtils.checkGlError("3"); - - GLES20.glVertexAttribPointer(htestVertexPosition1, - 4, GLES20.GL_SHORT, false, STRIDE, 0); - GlUtils.checkGlError("4"); - - GLES20.glVertexAttribPointer(htestVertexLength1, - 2, GLES20.GL_SHORT, false, STRIDE, LEN_OFFSET); - GlUtils.checkGlError("5"); - - //GLES20.glUniform4f(htestColor, 0.5f, 0.5f, 1.0f, 1.0f); - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, - GLES20.GL_UNSIGNED_SHORT, 0); - - // second pass - GLES20.glVertexAttribPointer(htestVertexPosition0, - 4, GLES20.GL_SHORT, false, STRIDE, 2 * STRIDE); - - GLES20.glVertexAttribPointer(htestVertexLength0, - 2, GLES20.GL_SHORT, false, STRIDE, 2 * STRIDE + LEN_OFFSET); - - GLES20.glVertexAttribPointer(htestVertexPosition1, - 4, GLES20.GL_SHORT, false, STRIDE, STRIDE); - - GLES20.glVertexAttribPointer(htestVertexLength1, - 2, GLES20.GL_SHORT, false, STRIDE, STRIDE + LEN_OFFSET); - - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mNumIndices, - GLES20.GL_UNSIGNED_SHORT, 0); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - - GLES20.glDisableVertexAttribArray(htestVertexPosition0); - GLES20.glDisableVertexAttribArray(htestVertexPosition1); - GLES20.glDisableVertexAttribArray(htestVertexLength0); - GLES20.glDisableVertexAttribArray(htestVertexLength1); - GLES20.glDisableVertexAttribArray(htestVertexFlip); - GlUtils.checkGlError("..."); - - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0); - } - - @Override - protected void setMatrix(MapPosition curPos, Matrices m) { - MapPosition oPos = mMapPosition; - - byte z = oPos.zoomLevel; - - float div = FastMath.pow(z - curPos.zoomLevel); - float x = (float) (oPos.x - curPos.x * div); - float y = (float) (oPos.y - curPos.y * div); - - // flip around date-line - float max = (Tile.TILE_SIZE << z); - if (x < -max / 2) - x = max + x; - else if (x > max / 2) - x = x - max; - - float scale = curPos.scale / div; - - Matrix.setIdentityM(m.mvp, 0); - - // translate relative to map center - m.mvp[12] = x * scale; - m.mvp[13] = y * scale; - // scale to current tile world coordinates - scale = (curPos.scale / oPos.scale) / div; - scale /= GLRenderer.COORD_SCALE; - m.mvp[0] = scale; - m.mvp[5] = scale; - m.mvp[10] = 1; //scale; // 1000f; - - Matrix.multiplyMM(m.mvp, 0, m.viewproj, 0, m.mvp, 0); - } - - @Override - public void compile() { - } - -} diff --git a/src/org/oscim/renderer/overlays/TestOverlay.java b/src/org/oscim/renderer/overlays/TestOverlay.java index a49c7cf8..94c5db8c 100644 --- a/src/org/oscim/renderer/overlays/TestOverlay.java +++ b/src/org/oscim/renderer/overlays/TestOverlay.java @@ -15,6 +15,7 @@ package org.oscim.renderer.overlays; import org.oscim.core.MapPosition; +import org.oscim.renderer.GLRenderer.Matrices; import org.oscim.renderer.layer.Layer; import org.oscim.renderer.layer.LineTexLayer; import org.oscim.renderer.layer.TextItem; @@ -122,7 +123,7 @@ public class TestOverlay extends BasicOverlay { @Override public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { // keep position constant (or update layer relative to new position) //mMapView.getMapViewPosition().getMapPosition(mMapPosition, null); diff --git a/src/org/oscim/renderer/overlays/TextOverlay.java b/src/org/oscim/renderer/overlays/TextOverlay.java index 5a8e2bac..0cb01b63 100644 --- a/src/org/oscim/renderer/overlays/TextOverlay.java +++ b/src/org/oscim/renderer/overlays/TextOverlay.java @@ -44,7 +44,6 @@ import org.oscim.renderer.layer.TextItem; import org.oscim.renderer.layer.TextLayer; import org.oscim.theme.renderinstruction.Line; import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; import org.oscim.utils.OBB2D; import org.oscim.utils.PausableThread; import org.oscim.view.MapView; @@ -53,7 +52,6 @@ import org.oscim.view.MapViewPosition; import android.graphics.Color; import android.graphics.Paint.Cap; import android.opengl.GLES20; -import android.opengl.Matrix; import android.os.SystemClock; public class TextOverlay extends BasicOverlay { @@ -247,7 +245,7 @@ public class TextOverlay extends BasicOverlay { private Layers mDebugLayer; private final static float[] mDebugPoints = new float[4]; - private final float[] mMVP = new float[16]; + //private final Matrix4 mMVP = new Matrix4(); void addTile(MapTile t) { @@ -305,7 +303,7 @@ public class TextOverlay extends BasicOverlay { synchronized (mMapViewPosition) { mMapViewPosition.getMapPosition(pos); mMapViewPosition.getMapViewProjection(coords); - mMapViewPosition.getMatrix(null, null, mMVP); + //mMapViewPosition.getMatrix(null, null, mMVP); } int mw = (mMapView.getWidth() + Tile.TILE_SIZE) / 2; int mh = (mMapView.getHeight() + Tile.TILE_SIZE) / 2; @@ -617,7 +615,7 @@ public class TextOverlay extends BasicOverlay { @Override public synchronized void update(MapPosition curPos, boolean positionChanged, - boolean tilesChanged) { + boolean tilesChanged, Matrices matrices) { if (mNextLayer != null) { // keep text layer, not recrating its canvas each time @@ -687,10 +685,10 @@ public class TextOverlay extends BasicOverlay { for (Layer l = layers.baseLayers; l != null;) { if (l.type == Layer.POLYGON) { - l = PolygonRenderer.draw(pos, l, m.mvp, true, false); + l = PolygonRenderer.draw(pos, l, m, true, false); } else { float scale = pos.scale * div; - l = LineRenderer.draw(layers, l, pos, m.mvp, scale, 0); + l = LineRenderer.draw(layers, l, pos, m, scale, 0); } } } @@ -699,7 +697,7 @@ public class TextOverlay extends BasicOverlay { for (Layer l = layers.textureLayers; l != null;) { float scale = (mMapPosition.scale / pos.scale) * div; - l = TextureRenderer.draw(l, scale, m.proj, m.mvp); + l = TextureRenderer.draw(l, scale, m); } } @@ -714,10 +712,10 @@ public class TextOverlay extends BasicOverlay { float scale = (curPos.scale / mMapPosition.scale) / div; float s = curPos.scale / div; - GlUtils.setMatrix(m.mvp, x * s, y * s, + m.mvp.setTransScale(x * s, y * s, scale / GLRenderer.COORD_SCALE); - Matrix.multiplyMM(m.mvp, 0, m.view, 0, m.mvp, 0); + m.mvp.multiplyMM(m.view, m.mvp); } private boolean mHolding; diff --git a/src/org/oscim/utils/GlUtils.java b/src/org/oscim/utils/GlUtils.java index 3d7fff7b..3953c8bb 100644 --- a/src/org/oscim/utils/GlUtils.java +++ b/src/org/oscim/utils/GlUtils.java @@ -17,8 +17,6 @@ package org.oscim.utils; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import org.oscim.renderer.GLRenderer; - import android.graphics.Bitmap; import android.opengl.GLES20; import android.opengl.GLUtils; @@ -204,37 +202,33 @@ public class GlUtils { return oom; } - // this is save as it can only be called from glThread - private static float[] tmpColor = new float[4]; - public static void setBlendColors(int handle, float[] c1, float[] c2, float mix) { if (mix <= 0f) GLES20.glUniform4fv(handle, 1, c1, 0); else if (mix >= 1f) GLES20.glUniform4fv(handle, 1, c2, 0); else { - tmpColor[0] = c1[0] * (1 - mix) + c2[0] * mix; - tmpColor[1] = c1[1] * (1 - mix) + c2[1] * mix; - tmpColor[2] = c1[2] * (1 - mix) + c2[2] * mix; - tmpColor[3] = c1[3] * (1 - mix) + c2[3] * mix; - GLES20.glUniform4fv(handle, 1, tmpColor, 0); + GLES20.glUniform4f(handle, + c1[0] * (1 - mix) + c2[0] * mix, + c1[1] * (1 - mix) + c2[1] * mix, + c1[2] * (1 - mix) + c2[2] * mix, + c1[3] * (1 - mix) + c2[3] * mix); } } public static void setColor(int handle, float[] c, float alpha) { if (alpha >= 1) { - GLES20.glUniform4fv(handle, 1, c, 0); + GLES20.glUniform4f(handle, c[0], c[1], c[2], c[3]); } else { if (alpha < 0) { Log.d(TAG, "setColor: " + alpha); alpha = 0; + GLES20.glUniform4f(handle, 0, 0, 0, 0); } - tmpColor[0] = c[0] * alpha; - tmpColor[1] = c[1] * alpha; - tmpColor[2] = c[2] * alpha; - tmpColor[3] = c[3] * alpha; - GLES20.glUniform4fv(handle, 1, tmpColor, 0); + GLES20.glUniform4f(handle, + c[0] * alpha, c[1] * alpha, + c[2] * alpha, c[3] * alpha); } } @@ -280,56 +274,56 @@ public class GlUtils { color[2] = FastMath.clampN((float) (p + (b - p) * change)); } - private final static float[] mIdentity = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 }; - - public static void setTileMatrix(float[] matrix, float tx, float ty, float s) { - System.arraycopy(mIdentity, 0, matrix, 0, 16); - // scale tile relative to map scale - matrix[0] = matrix[5] = s / GLRenderer.COORD_SCALE; - // translate relative to map center - matrix[12] = tx * s; - matrix[13] = ty * s; - } - - public static void setTranslation(float[] matrix, float x, float y, float z) { - System.arraycopy(mIdentity, 0, matrix, 0, 16); - matrix[12] = x; - matrix[13] = y; - matrix[14] = z; - } - - public static void setMatrix(float[] matrix, float tx, float ty, float scale) { - System.arraycopy(mIdentity, 0, matrix, 0, 16); - matrix[12] = tx; - matrix[13] = ty; - matrix[0] = scale; - matrix[5] = scale; - //matrix[10] = scale; - } - - public static void setIdentity(float[] matrix) { - System.arraycopy(mIdentity, 0, matrix, 0, 16); - } - - public static void setScaleM(float[] matrix, float sx, float sy, float sz) { - System.arraycopy(mIdentity, 0, matrix, 0, 16); - matrix[0] = sx; - matrix[5] = sy; - matrix[10] = sz; - } - - public static void addOffsetM(float[] matrix, int delta) { - // from http://www.mathfor3dgameprogramming.com/code/Listing9.1.cpp - // float n = MapViewPosition.VIEW_NEAR; - // float f = MapViewPosition.VIEW_FAR; - // float pz = 1; - // float epsilon = -2.0f * f * n * delta / ((f + n) * pz * (pz + delta)); - float epsilon = 1.0f / (1 << 11); - - matrix[10] *= 1.0f + epsilon * delta; - } +// private final static float[] mIdentity = { +// 1, 0, 0, 0, +// 0, 1, 0, 0, +// 0, 0, 1, 0, +// 0, 0, 0, 1 }; +// +// public static void setTileMatrix(float[] matrix, float tx, float ty, float s) { +// System.arraycopy(mIdentity, 0, matrix, 0, 16); +// // scale tile relative to map scale +// matrix[0] = matrix[5] = s / GLRenderer.COORD_SCALE; +// // translate relative to map center +// matrix[12] = tx * s; +// matrix[13] = ty * s; +// } +// +// public static void setTranslation(float[] matrix, float x, float y, float z) { +// System.arraycopy(mIdentity, 0, matrix, 0, 16); +// matrix[12] = x; +// matrix[13] = y; +// matrix[14] = z; +// } +// +// public static void setMatrix(float[] matrix, float tx, float ty, float scale) { +// System.arraycopy(mIdentity, 0, matrix, 0, 16); +// matrix[12] = tx; +// matrix[13] = ty; +// matrix[0] = scale; +// matrix[5] = scale; +// //matrix[10] = scale; +// } +// +// public static void setIdentity(float[] matrix) { +// System.arraycopy(mIdentity, 0, matrix, 0, 16); +// } +// +// public static void setScaleM(float[] matrix, float sx, float sy, float sz) { +// System.arraycopy(mIdentity, 0, matrix, 0, 16); +// matrix[0] = sx; +// matrix[5] = sy; +// matrix[10] = sz; +// } +// +// public static void addOffsetM(float[] matrix, int delta) { +// // from http://www.mathfor3dgameprogramming.com/code/Listing9.1.cpp +// // float n = MapViewPosition.VIEW_NEAR; +// // float f = MapViewPosition.VIEW_FAR; +// // float pz = 1; +// // float epsilon = -2.0f * f * n * delta / ((f + n) * pz * (pz + delta)); +// float epsilon = 1.0f / (1 << 11); +// +// matrix[10] *= 1.0f + epsilon * delta; +// } } diff --git a/src/org/oscim/utils/Matrix4.java b/src/org/oscim/utils/Matrix4.java new file mode 100644 index 00000000..95712116 --- /dev/null +++ b/src/org/oscim/utils/Matrix4.java @@ -0,0 +1,226 @@ +/* + * Copyright 2013 Hannes Janetzek + * + * This program is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with + * this program. If not, see . + */ +package org.oscim.utils; + +public class Matrix4 { + + static { + System.loadLibrary("glutils"); + } + + private final static String TAG = Matrix4.class.getName(); + private final static boolean dbg = false; + + private native static long alloc(); + + private native static void delete(long self); + + private native static void set(long self, float[] m); + + private native static void copy(long self, long other); + + private native static void identity(long self); + + private native static void get(long self, float[] m); + + private native static void mul(long self, long lhs_ptr); + + private native static void smul(long self, long rhs_ptr, long lhs_ptr); + + private native static void strans(long self, long rhs_ptr); + + private native static void prj(long self, float[] vec3); + + private native static void setRotation(long self, float a, float x, float y, float z); + + private native static void setScale(long self, float x, float y, float z); + + private native static void setTranslation(long self, float x, float y, float z); + + private native static void setTransScale(long self, float tx, float ty, float scale); + + private native static void setAsUniform(long self, int handle); + + private native void setValueAt(long self, int pos, float value); + + private native void addDepthOffset(long self, int delta); + + private final long pointer; + + private final static String INVALID_INPUT = "Bad Array!"; + + public Matrix4() { + pointer = alloc(); + } + + /** + * Set the Matrix from float array + * + * @param m float array to copy + */ + public void set(float[] m) { + if (m == null || m.length != 16) + throw new IllegalArgumentException(INVALID_INPUT); + + set(pointer, m); + } + + /** + * Get the Matrix as float array + * + * @param m float array to store Matrix + */ + public void get(float[] m) { + if (m == null || m.length != 16) + throw new IllegalArgumentException(INVALID_INPUT); + + get(pointer, m); + } + + /** + * Copy values from mat + * + * @param mat Matrix to copy + */ + public void copy(Matrix4 mat) { + copy(pointer, mat.pointer); + } + + /** + * Project Vector with Matrix + * + * @param vec3 Vector to project + */ + public void prj(float[] vec3) { + if (vec3 == null || vec3.length < 3) + throw new IllegalArgumentException(INVALID_INPUT); + + prj(pointer, vec3); + } + + /** + * Multiply rhs onto Matrix + * + * @param rhs right hand side + */ + public void multiplyMM(Matrix4 rhs) { + smul(pointer, pointer, rhs.pointer); + } + + /** + * Multiply rhs onto lhs and store result in Matrix + * + * @param lhs left hand side + * @param rhs right hand side + */ + public void multiplyMM(Matrix4 lhs, Matrix4 rhs) { + smul(pointer, lhs.pointer, rhs.pointer); + } + + /** + * Transpose mat and store result in Matrix + * + * @param mat to transpose + */ + public void transposeM(Matrix4 mat) { + strans(pointer, mat.pointer); + } + + /** + * Set rotation + * + * @param a angle in degree + * @param x around x-axis + * @param y around y-axis + * @param z around z-axis + */ + public void setRotation(float a, float x, float y, float z) { + setRotation(pointer, a, x, y, z); + } + + /** + * Set translation + * + * @param x along x-axis + * @param y along y-axis + * @param z along z-axis + */ + public void setTranslation(float x, float y, float z) { + setTranslation(pointer, x, y, z); + } + + /** + * Set scale factor + * + * @param x axis + * @param y axis + * @param z axis + */ + public void setScale(float x, float y, float z) { + setScale(pointer, x, y, z); + } + + /** + * Set translation and x,y scale + * + * @param tx translate x + * @param ty translate y + * @param scale factor x,y + */ + public void setTransScale(float tx, float ty, float scale) { + setTransScale(pointer, tx, ty, scale); + } + + /** + * Set Matrix with glUniformMatrix + * + * @param location GL location id + */ + public void setAsUniform(int location) { + setAsUniform(pointer, location); + } + + /** + * Set single value + * + * @param pos at position + * @param value value to set + */ + public void setValue(int pos, float value) { + setValueAt(pointer, pos, value); + } + + /** + * add some offset (similar to glDepthOffset) + * + * @param delta offset + */ + public void addDepthOffset(int delta) { + addDepthOffset(pointer, delta); + } + + /** + * Set identity matrix + */ + public void setIdentity() { + identity(pointer); + } + + @Override + public void finalize() { + if (pointer != 0) + delete(pointer); + } +} diff --git a/src/org/oscim/view/MapViewPosition.java b/src/org/oscim/view/MapViewPosition.java index e417c3e0..c09258e0 100644 --- a/src/org/oscim/view/MapViewPosition.java +++ b/src/org/oscim/view/MapViewPosition.java @@ -25,7 +25,7 @@ import org.oscim.core.PointD; import org.oscim.core.PointF; import org.oscim.core.Tile; import org.oscim.utils.FastMath; -import org.oscim.utils.GlUtils; +import org.oscim.utils.Matrix4; import android.opengl.Matrix; import android.os.Handler; @@ -98,13 +98,13 @@ public class MapViewPosition { }); } - private final float[] mProjMatrix = new float[16]; - private final float[] mProjMatrixI = new float[16]; - private final float[] mUnprojMatrix = new float[16]; - private final float[] mViewMatrix = new float[16]; - private final float[] mVPMatrix = new float[16]; - private final float[] mRotMatrix = new float[16]; - private final float[] mTmpMatrix = new float[16]; + private final Matrix4 mProjMatrix = new Matrix4(); + private final Matrix4 mProjMatrixI = new Matrix4(); + private final Matrix4 mRotMatrix = new Matrix4(); + private final Matrix4 mViewMatrix = new Matrix4(); + private final Matrix4 mVPMatrix = new Matrix4(); + private final Matrix4 mUnprojMatrix = new Matrix4(); + private final Matrix4 mTmpMatrix = new Matrix4(); // temporary vars: only use in synchronized functions! private final PointD mMovePoint = new PointD(); @@ -123,14 +123,18 @@ public class MapViewPosition { void setViewport(int width, int height) { float s = VIEW_SCALE; float aspect = height / (float) width; + float[] tmp = new float[16]; - Matrix.frustumM(mProjMatrix, 0, -s, s, + Matrix.frustumM(tmp, 0, -s, s, aspect * s, -aspect * s, VIEW_NEAR, VIEW_FAR); - GlUtils.setTranslation(mTmpMatrix, 0, 0, -VIEW_DISTANCE); - Matrix.multiplyMM(mProjMatrix, 0, mProjMatrix, 0, mTmpMatrix, 0); + mProjMatrix.set(tmp); + mTmpMatrix.setTranslation(0, 0, -VIEW_DISTANCE); + mProjMatrix.multiplyMM(mTmpMatrix); + mProjMatrix.get(tmp); - Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0); + Matrix.invertM(tmp, 0, tmp, 0); + mProjMatrixI.set(tmp); mHeight = height; mWidth = width; @@ -180,15 +184,15 @@ public class MapViewPosition { * @param proj projection Matrix * @param vp view and projection */ - public synchronized void getMatrix(float[] view, float[] proj, float[] vp) { + public synchronized void getMatrix(Matrix4 view, Matrix4 proj, Matrix4 vp) { if (view != null) - System.arraycopy(mViewMatrix, 0, view, 0, 16); + view.copy(mViewMatrix); if (proj != null) - System.arraycopy(mProjMatrix, 0, proj, 0, 16); + proj.copy(mProjMatrix); if (vp != null) - System.arraycopy(mVPMatrix, 0, vp, 0, 16); + vp.copy(mVPMatrix); } /** @@ -233,23 +237,21 @@ public class MapViewPosition { mv[0] = 0; mv[1] = (float) (ry / ua); mv[2] = (float) (cx - cx / ua); - mv[3] = 1; - Matrix.multiplyMV(mv, 0, mProjMatrix, 0, mv, 0); + mProjMatrix.prj(mv); - return mv[2] / mv[3]; + return mv[2]; } private void unproject(float x, float y, float z, float[] coords, int position) { mv[0] = x; mv[1] = y; mv[2] = z; - mv[3] = 1; - Matrix.multiplyMV(mv, 0, mUnprojMatrix, 0, mv, 0); + mUnprojMatrix.prj(mv); - coords[position + 0] = mv[0] / mv[3]; - coords[position + 1] = mv[1] / mv[3]; + coords[position + 0] = mv[0]; + coords[position + 1] = mv[1]; } /** @return the current center point of the MapView. */ @@ -400,11 +402,9 @@ public class MapViewPosition { mv[2] = 0; mv[3] = 1; - Matrix.multiplyMV(mv, 0, mVPMatrix, 0, mv, 0); - - // positive direction is down and right; - out.x = (int) ((mv[0] / mv[3]) * (mWidth / 2)); - out.y = (int) -((mv[1] / mv[3]) * (mHeight / 2)); + mVPMatrix.prj(mv); + out.x = (int) (mv[0] * (mWidth / 2)); + out.y = (int) -(mv[1] * (mHeight / 2)); } private void updateMatrix() { @@ -417,37 +417,34 @@ public class MapViewPosition { // 4. translate to VIEW_DISTANCE // 5. apply projection - Matrix.setRotateM(mRotMatrix, 0, mRotation, 0, 0, 1); + mRotMatrix.setRotation(mRotation, 0, 0, 1); // tilt map - float tilt = mTilt; - Matrix.setRotateM(mTmpMatrix, 0, tilt, 1, 0, 0); + mTmpMatrix.setRotation(mTilt, 1, 0, 0); // apply first rotation, then tilt - Matrix.multiplyMM(mRotMatrix, 0, mTmpMatrix, 0, mRotMatrix, 0); + mRotMatrix.multiplyMM(mTmpMatrix, mRotMatrix); // scale to window coordinates - GlUtils.setScaleM(mTmpMatrix, 1 / mWidth, 1 / mWidth, 1); + mTmpMatrix.setScale(1 / mWidth, 1 / mWidth, 1); - Matrix.multiplyMM(mViewMatrix, 0, mRotMatrix, 0, mTmpMatrix, 0); + mViewMatrix.multiplyMM(mRotMatrix, mTmpMatrix); - Matrix.multiplyMM(mVPMatrix, 0, mProjMatrix, 0, mViewMatrix, 0); + mVPMatrix.multiplyMM(mProjMatrix, mViewMatrix); //--- unproject matrix: - // Matrix.multiplyMM(mTmpMatrix, 0, mProjMatrix, 0, mViewMatrix, 0); - // Matrix.invertM(mUnprojMatrix, 0, mTmpMatrix, 0); // inverse scale - GlUtils.setScaleM(mUnprojMatrix, mWidth, mWidth, 1); + mUnprojMatrix.setScale(mWidth, mWidth, 1); // inverse rotation and tilt - Matrix.transposeM(mTmpMatrix, 0, mRotMatrix, 0); + mTmpMatrix.transposeM(mRotMatrix); // (AB)^-1 = B^-1*A^-1, unapply scale, tilt and rotation - Matrix.multiplyMM(mTmpMatrix, 0, mUnprojMatrix, 0, mTmpMatrix, 0); + mTmpMatrix.multiplyMM(mUnprojMatrix, mTmpMatrix); // (AB)^-1 = B^-1*A^-1, unapply projection - Matrix.multiplyMM(mUnprojMatrix, 0, mTmpMatrix, 0, mProjMatrixI, 0); + mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixI); } /** @return true if this MapViewPosition is valid, false otherwise. */