/* * 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.Color; import android.opengl.GLUtils; import ch.ethz.dcg.jukefox.model.collection.MapAlbum; public class GlAlbumCover { private final static int VERTS = 4; public final static float COVER_SIZE = 0.35f; @SuppressWarnings("unused") private static final String TAG = GlAlbumCover.class.getSimpleName(); private FloatBuffer mFVertexBuffer; private FloatBuffer mTexBuffer; private ShortBuffer mIndexBuffer; private boolean horizontal = false; private boolean textureLoaded = false; private int textureId = -1; private boolean loadTextureBitmap = false; private Bitmap textureBitmap; private MapAlbum mapAlbum; public GlAlbumCover(MapAlbum mapAlbum, boolean horizontal) { this.mapAlbum = mapAlbum; this.horizontal = horizontal; float x = mapAlbum.getGridCoords()[0]; float y = mapAlbum.getGridCoords()[1]; // Log.v(TAG, "Map album with coords X. " + x + " y: " + y); createBuffers(); float coords[] = null; if (horizontal) { coords = getHorizontalCoords(x, 0, y); } else { coords = getVerticalCoords(x, 0, y); } fillVertexBuffer(coords); fillTextureBuffer(); fillIndexBuffer(); mFVertexBuffer.position(0); mTexBuffer.position(0); mIndexBuffer.position(0); // Log.v(TAG, "Returned map album with color " + // Integer.toHexString(mapAlbum.getColor()) + " r: " + // Color.red(mapAlbum.getColor()) + " g: " + // Color.green(mapAlbum.getColor())); } private float[] getVerticalCoords(float x, float y, float z) { float[] coords = { // x,y,z x - COVER_SIZE, y - COVER_SIZE, z, x + COVER_SIZE, y - COVER_SIZE, z, x - COVER_SIZE, y + COVER_SIZE, z, x + COVER_SIZE, y + COVER_SIZE, z }; return coords; } private float[] getHorizontalCoords(float x, float y, float z) { float[] coords = { // x,y,z x - 2 * COVER_SIZE, y, z + 2 * COVER_SIZE, x + 2 * COVER_SIZE, y, z + 2 * COVER_SIZE, x - 2 * COVER_SIZE, y, z - 2 * COVER_SIZE, x + 2 * COVER_SIZE, y, z - 2 * COVER_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); } } } /** * draw the cover * * @param gl * the OpenGl object */ public void draw(GL10 gl, boolean drawTexture) { if (loadTextureBitmap) { loadBitmapForGl(gl); } gl.glEnable(GL10.GL_TEXTURE_2D); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer); if (drawTexture && textureLoaded) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId); } else { gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); gl.glColor4f(Color.red(mapAlbum.getColor()) / 255f, Color.green(mapAlbum.getColor()) / 255f, Color .blue(mapAlbum.getColor()) / 255f, 1f); } 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 loadBitmapForGl(GL10 gl) { // Log.v(TAG, "loading Bitmap for album " + mapAlbum.getName()); loadTextureBitmap = false; if (textureBitmap != null) { gl.glBindTexture(GL10.GL_TEXTURE_2D, 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, textureBitmap, 0); textureLoaded = true; textureBitmap = null; } } public void loadTexture(Bitmap bitmap, int textureId) { // Log.v(TAG, "Set to load texture at " + textureId + " for " // + mapAlbum.getName()); textureBitmap = bitmap; this.textureId = textureId; loadTextureBitmap = true; } public void moveCover(float dX, float dY, float dZ) { mFVertexBuffer.put(0, mFVertexBuffer.get(0) + dX); mFVertexBuffer.put(3, mFVertexBuffer.get(3) + dX); mFVertexBuffer.put(6, mFVertexBuffer.get(6) + dX); mFVertexBuffer.put(9, mFVertexBuffer.get(9) + dX); mFVertexBuffer.put(1, mFVertexBuffer.get(1) + dY); mFVertexBuffer.put(4, mFVertexBuffer.get(4) + dY); mFVertexBuffer.put(7, mFVertexBuffer.get(7) + dY); mFVertexBuffer.put(10, mFVertexBuffer.get(10) + dY); mFVertexBuffer.put(2, mFVertexBuffer.get(2) + dZ); mFVertexBuffer.put(5, mFVertexBuffer.get(5) + dZ); mFVertexBuffer.put(8, mFVertexBuffer.get(8) + dZ); mFVertexBuffer.put(11, mFVertexBuffer.get(11) + dZ); } /** * Flip the label for the overview mode and back */ public void flipCover() { if (!horizontal) { float posX = mFVertexBuffer.get(0) + COVER_SIZE; float posY = mFVertexBuffer.get(1) + COVER_SIZE; float posZ = mFVertexBuffer.get(2); mFVertexBuffer.put(0, posX - 2 * COVER_SIZE); mFVertexBuffer.put(1, posY); mFVertexBuffer.put(2, posZ + 2 * COVER_SIZE); mFVertexBuffer.put(3, posX + 2 * COVER_SIZE); mFVertexBuffer.put(4, posY); mFVertexBuffer.put(5, posZ + 2 * COVER_SIZE); mFVertexBuffer.put(6, posX - 2 * COVER_SIZE); mFVertexBuffer.put(7, posY); mFVertexBuffer.put(8, posZ - 2 * COVER_SIZE); mFVertexBuffer.put(9, posX + 2 * COVER_SIZE); mFVertexBuffer.put(10, posY); mFVertexBuffer.put(11, posZ - 2 * COVER_SIZE); horizontal = true; } else { float posX = mFVertexBuffer.get(0) + 2 * COVER_SIZE; float posY = mFVertexBuffer.get(1); float posZ = mFVertexBuffer.get(2) - 2 * COVER_SIZE; mFVertexBuffer.put(0, posX - COVER_SIZE); mFVertexBuffer.put(1, posY - COVER_SIZE); mFVertexBuffer.put(2, posZ); mFVertexBuffer.put(3, posX + COVER_SIZE); mFVertexBuffer.put(4, posY - COVER_SIZE); mFVertexBuffer.put(5, posZ); mFVertexBuffer.put(6, posX - COVER_SIZE); mFVertexBuffer.put(7, posY + COVER_SIZE); mFVertexBuffer.put(8, posZ); mFVertexBuffer.put(9, posX + COVER_SIZE); mFVertexBuffer.put(10, posY + COVER_SIZE); mFVertexBuffer.put(11, posZ); horizontal = false; } } public MapAlbum getMapAlbum() { return mapAlbum; } public int getTextureId() { return textureId; } public boolean isTextureLoaded() { return textureLoaded || textureBitmap != null; } public void resetTexture() { loadTextureBitmap = false; textureBitmap = null; textureLoaded = false; textureId = 0; } public void drawForSelection(GL10 gl, int red, int green, int blue) { // Log.v(TAG, "Drawn selection mode for " // + mapAlbum.getName() + " with red " +red + " green " + green + // " blue " + blue); gl.glColor4f(red / 255f, green / 255f, blue / 255f, 1f); // gl.glColor4x(red, green, blue, 255); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); 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); } }