Use native Matrix4 instead of float[16]

This commit is contained in:
Hannes Janetzek 2013-03-15 15:27:04 +01:00
parent af80759dae
commit f262efee7f
22 changed files with 731 additions and 1717 deletions

View File

@ -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;
}

View File

@ -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<Item extends OverlayItem> 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<Item extends OverlayItem> 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<Item extends OverlayItem> 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<Item extends OverlayItem> 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) {

View File

@ -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;

View File

@ -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) {

View File

@ -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<RenderOverlay> 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);

View File

@ -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 {

View File

@ -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);

View File

@ -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);
}
/*

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}

View File

@ -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);
}
/**

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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() {
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
// }
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -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. */