/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.pancho3.view.tabs.opengl; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; import android.graphics.Paint.Style; import android.opengl.GLUtils; import ch.ethz.dcg.jukefox.commons.utils.Log; import ch.ethz.dcg.jukefox.model.collection.MapTag; public class GlTagLabel { private final static int VERTS = 4; private final static float LABEL_HEIGHT = 1f; private static final float VERT_LABEL_SIZE = 0.5f; private static final float HORIZ_LABEL_SIZE = 1f; @SuppressWarnings("unused") private static final String TAG = GlTagLabel.class.getSimpleName(); private FloatBuffer mFVertexBuffer; private FloatBuffer mTexBuffer; private FloatBuffer mFVertexBuffer2; private FloatBuffer mTexBuffer2; private ShortBuffer mIndexBuffer; private String text; public boolean textureLoaded = false; public float zoomValue; public float posX; private float posY; private float posZ; private int ratio; public int[] textureId = new int[1]; public boolean horizontal = false; private MapTag mapTag; /** * Constructor * * @param x * xposition of the tag label * @param y * y position of the tag label * @param z * z position of the tag label * @param size * size of the tag label * @param String * to print on the label */ public GlTagLabel(MapTag mapTag, boolean horizontal) { this.horizontal = horizontal; this.mapTag = mapTag; posX = mapTag.getCoordsPca2D()[0]; posY = LABEL_HEIGHT; posZ = mapTag.getCoordsPca2D()[1]; createBuffers(); zoomValue = 10f / mapTag.getVarianceOverPCA(); text = mapTag.getName(); // Log.v(TAG, "created GL Tag at X: " + posX + " Z: " + posZ); } private void createBuffers() { ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 3 * 4); vbb.order(ByteOrder.nativeOrder()); mFVertexBuffer = vbb.asFloatBuffer(); ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4); tbb.order(ByteOrder.nativeOrder()); mTexBuffer = tbb.asFloatBuffer(); ByteBuffer vbb2 = ByteBuffer.allocateDirect(VERTS * 3 * 4); vbb2.order(ByteOrder.nativeOrder()); mFVertexBuffer2 = vbb2.asFloatBuffer(); ByteBuffer tbb2 = ByteBuffer.allocateDirect(VERTS * 2 * 4); tbb2.order(ByteOrder.nativeOrder()); mTexBuffer2 = tbb2.asFloatBuffer(); ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 2); ibb.order(ByteOrder.nativeOrder()); mIndexBuffer = ibb.asShortBuffer(); } private float[] getHorizontalCoords(float size) { float[] coords = { // x,y,z posX - ratio * size, posY - size, posZ, posX + 2 * ratio * size, posY - size, posZ, posX - ratio * size, posY - size, posZ + 2 * size, posX + 2 * ratio * size, posY - size, posZ + 2 * size }; return coords; } private float[] getVerticalCoords(float size) { // A square centered at x,y,z float[] coords = { // x,y,z posX - ratio * size, posY - size, posZ, posX + ratio * size, posY - size, posZ, posX - ratio * size, posY + size, posZ, posX + ratio * size, posY + size, posZ }; return coords; } private void init(GL10 gl) { createBitmap(gl); float[] coords = null; if (horizontal) { coords = getHorizontalCoords(HORIZ_LABEL_SIZE); } else { coords = getVerticalCoords(VERT_LABEL_SIZE); } for (int i = 0; i < VERTS; i++) { for (int j = 0; j < 3; j++) { mFVertexBuffer.put(3 * i + j, coords[i * 3 + j] * 1.0f); // Log.v(TAG, "Set coords " + i +"," + j + " to " + // mFVertexBuffer.get(3*i+j) ); } } mTexBuffer.put(0f); mTexBuffer.put(1f); mTexBuffer.put(1f); mTexBuffer.put(1f); mTexBuffer.put(0f); mTexBuffer.put(0f); mTexBuffer.put(1f); mTexBuffer.put(0f); // Do the pole of the label float[] coords2 = { // x,y,z posX - 0.1f * VERT_LABEL_SIZE, posY - VERT_LABEL_SIZE, posZ, posX + 0.1f * VERT_LABEL_SIZE, posY - VERT_LABEL_SIZE, posZ, posX - 0.1f * VERT_LABEL_SIZE, 0, posZ, posX + 0.1f * VERT_LABEL_SIZE, 0, posZ }; for (int i = 0; i < VERTS; i++) { for (int j = 0; j < 3; j++) { mFVertexBuffer2.put(coords2[i * 3 + j] * 1.0f); } } mTexBuffer2.put(0f); mTexBuffer2.put(1f); mTexBuffer2.put(1f); mTexBuffer2.put(1f); mTexBuffer2.put(0f); mTexBuffer2.put(0f); mTexBuffer2.put(1f); mTexBuffer2.put(0f); for (int i = 0; i < VERTS; i++) { mIndexBuffer.put((short) i); } mFVertexBuffer.position(0); mTexBuffer.position(0); mFVertexBuffer2.position(0); mTexBuffer2.position(0); mIndexBuffer.position(0); } /** * create the tag label bitmap * * @param tag * @return */ private void createBitmap(GL10 gl) { int height = 20; Paint paint = new Paint(); paint.setColor(Color.WHITE); paint.setStyle(Style.STROKE); paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setSubpixelText(true); paint.setAntiAlias(true); paint.setTextSize(height); float width = paint.measureText(text); int realWidth = 64; int realHeight = 32; if (width > realWidth) { while (realWidth < width) { realWidth *= 2; } } Bitmap label = null; try { label = Bitmap.createBitmap(realWidth, realHeight, Bitmap.Config.ARGB_8888); } catch (Error e) { System.gc(); Log.w("BitmapFactory", e); } if (label != null) { Canvas canvas = new Canvas(label); canvas.drawARGB(0, 125, 125, 125); Paint paint2 = new Paint(); // paint2.setARGB(255, 125, 125, 125); // TODO: activate transparency paint2.setARGB(175, 125, 125, 125); canvas.drawRect(0, 0, realWidth - 1, realHeight - 1, paint2); canvas.drawRect(0, 0, realWidth - 1, realHeight - 1, paint); canvas.drawRect(1, 1, realWidth - 2, realHeight - 2, paint); int offsetX = (realWidth - (int) width) / 2; canvas.drawText(text, offsetX, height, paint); gl.glGenTextures(1, textureId, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId[0]); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT); gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, label, 0); label.recycle(); textureLoaded = true; } ratio = realWidth / realHeight; } /** * Move the tag label to another position * * @param x * @param y * @param z * @param size */ public void setCoords(float x, float y, float z, float size) { posX = x; posY = y; posZ = z; float[] coords = null; if (horizontal) { coords = getHorizontalCoords(size); } else { coords = getVerticalCoords(size); } for (int i = 0; i < VERTS; i++) { for (int j = 0; j < 3; j++) { mFVertexBuffer.put(i * 3 + j, coords[i * 3 + j] * 1.0f); } } } public void setSizeInHorizontalMode(float magnify) { if (horizontal) { mFVertexBuffer.put(8, posZ - 2 * magnify * HORIZ_LABEL_SIZE); mFVertexBuffer.put(3, posX + 2 * magnify * ratio * HORIZ_LABEL_SIZE); mFVertexBuffer.put(9, posX + 2 * magnify * ratio * HORIZ_LABEL_SIZE); mFVertexBuffer.put(11, posZ - 2 * magnify * HORIZ_LABEL_SIZE); } } /** * draw the tag label * * @param gl * the OpenGl object */ public void draw(GL10 gl) { if (!textureLoaded) { init(gl); } gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer); gl.glEnable(GL10.GL_TEXTURE_2D); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId[0]); gl.glFrontFace(GL10.GL_CCW); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS, GL10.GL_UNSIGNED_SHORT, mIndexBuffer); // Log.v(TAG, "draw tag: " + text + " at x: " + mFVertexBuffer.get(0) + // " y: " + mFVertexBuffer.get(1) + " z: " + mFVertexBuffer.get(2)); // draw the pole only if the label is vertical if (!horizontal) { // set object color gl.glColor4f(1f, 1f, 1f, 1f); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer2); gl.glEnable(GL10.GL_TEXTURE_2D); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer2); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS, GL10.GL_UNSIGNED_SHORT, mIndexBuffer); } } public MapTag getMapTag() { return mapTag; } public void resetTexture() { textureLoaded = false; } public float getPosZ() { return posZ; } }