/* * 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.content.Context; import android.graphics.BitmapFactory; import android.opengl.GLUtils; import ch.ethz.dcg.pancho3.R; public class GlHighlight { public static final String TAG = GlHighlight.class.getSimpleName(); private final static int VERTS = 4; private final static float HIGHLIGHT_SIZE = 2f; private FloatBuffer mFVertexBuffer; private FloatBuffer mTexBuffer; private ShortBuffer mIndexBuffer; private boolean horizontal = false; private boolean textureLoaded = false; private int textureId; private Context context; /** * Constructor * @param x xposition of the highlight * @param y y position of the highlight * @param z z position of the highlight * @param size size of the highlight */ public GlHighlight(float x, float y, float z, boolean horizontal, Context context) { this.context = context; this.horizontal = horizontal; createBuffers(); float coords[] = null; if (horizontal){ coords = getHorizontalCoords(x,y,0); } else { coords = getVerticalCoords(x,y,0); } fillVertexBuffer(coords); fillTextureBuffer(); fillIndexBuffer(); mFVertexBuffer.position(0); mTexBuffer.position(0); mIndexBuffer.position(0); } private float[] getVerticalCoords(float x, float y, float z) { float[] coords = { // x,y,z x-HIGHLIGHT_SIZE, y-HIGHLIGHT_SIZE, z, x+HIGHLIGHT_SIZE, y-HIGHLIGHT_SIZE, z, x-HIGHLIGHT_SIZE, y+HIGHLIGHT_SIZE, z, x+HIGHLIGHT_SIZE, y+HIGHLIGHT_SIZE, z }; return coords; } private float[] getHorizontalCoords(float x, float y, float z) { float[] coords = { // x,y,z x-2*HIGHLIGHT_SIZE, y, z+2*HIGHLIGHT_SIZE, x+2*HIGHLIGHT_SIZE, y, z+2*HIGHLIGHT_SIZE, x-2*HIGHLIGHT_SIZE, y, z-2*HIGHLIGHT_SIZE, x+2*HIGHLIGHT_SIZE, y, z-2*HIGHLIGHT_SIZE }; return coords; } private void createBuffers() { // Buffers to be passed to gl*Pointer() functions // must be direct, i.e., they must be placed on the // native heap where the garbage collector cannot // move them. // // Buffers with multi-byte datatypes (e.g., short, int, float) // must have their byte order set to native order 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 ibb = ByteBuffer.allocateDirect(VERTS * 2); ibb.order(ByteOrder.nativeOrder()); mIndexBuffer = ibb.asShortBuffer(); } private void fillTextureBuffer() { mTexBuffer.put(0f); mTexBuffer.put(1f); mTexBuffer.put(1f); mTexBuffer.put(1f); mTexBuffer.put(0f); mTexBuffer.put(0f); mTexBuffer.put(1f); mTexBuffer.put(0f); } private void fillIndexBuffer() { for(int i = 0; i < VERTS; i++) { mIndexBuffer.put((short) i); } } private void fillVertexBuffer(float[] coords) { for (int i = 0; i < VERTS; i++) { for(int j = 0; j < 3; j++) { mFVertexBuffer.put(coords[i*3+j] * 1.0f); } } } /** * Move the highlight to another location * @param x new x position * @param y new y position * @param z new z position * @param size new size */ public void setCoords(float x, float y, float z) { float coords[] = null; if (horizontal){ coords = getHorizontalCoords(x,y,z); } else { coords = getVerticalCoords(x,y,z); } 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); } } } /** * draw the highlight * @param gl the OpenGl object */ public void draw(GL10 gl, int tid) { if (!textureLoaded) { loadTexture(gl); } gl.glEnable(GL10.GL_TEXTURE_2D); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); gl.glFrontFace(GL10.GL_CCW); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer); gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,GL10.GL_UNSIGNED_SHORT, mIndexBuffer); } private void loadTexture(GL10 gl) { int[] tempTextureId = new int[1]; gl.glGenTextures(1, tempTextureId, 0); this.textureId = tempTextureId[0]; gl.glBindTexture(GL10.GL_TEXTURE_2D, this.textureId); 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, BitmapFactory.decodeResource( context.getResources(), R.drawable.d045_highlight_noscale), 0); textureLoaded = true; } /** * Flip the highlight for the overview mode and back */ public void flipHighlight() { if (!horizontal) { float posX = mFVertexBuffer.get(0) + HIGHLIGHT_SIZE; float posY = mFVertexBuffer.get(1) + HIGHLIGHT_SIZE; float posZ = mFVertexBuffer.get(2); mFVertexBuffer.put(0, posX - 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(1, posY); mFVertexBuffer.put(2, posZ + 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(3, posX + 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(4, posY); mFVertexBuffer.put(5, posZ + 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(6, posX - 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(7, posY); mFVertexBuffer.put(8, posZ - 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(9, posX + 2*HIGHLIGHT_SIZE); mFVertexBuffer.put(10, posY); mFVertexBuffer.put(11, posZ - 2*HIGHLIGHT_SIZE); horizontal = true; } else { float posX = mFVertexBuffer.get(0) + 2*HIGHLIGHT_SIZE; float posY = mFVertexBuffer.get(1); float posZ = mFVertexBuffer.get(2) - 2*HIGHLIGHT_SIZE; mFVertexBuffer.put(0, posX - HIGHLIGHT_SIZE); mFVertexBuffer.put(1, posY - HIGHLIGHT_SIZE); mFVertexBuffer.put(2, posZ); mFVertexBuffer.put(3, posX + HIGHLIGHT_SIZE); mFVertexBuffer.put(4, posY - HIGHLIGHT_SIZE); mFVertexBuffer.put(5, posZ); mFVertexBuffer.put(6, posX - HIGHLIGHT_SIZE); mFVertexBuffer.put(7, posY + HIGHLIGHT_SIZE); mFVertexBuffer.put(8, posZ); mFVertexBuffer.put(9, posX + HIGHLIGHT_SIZE); mFVertexBuffer.put(10, posY + HIGHLIGHT_SIZE); mFVertexBuffer.put(11, posZ); horizontal = false; } } public boolean isHorizontal() { return horizontal; } }