/* * 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.util.ArrayList; import java.util.Collection; import java.util.List; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.content.Intent; import android.opengl.GLU; import ch.ethz.dcg.jukefox.commons.DataUnavailableException; import ch.ethz.dcg.jukefox.commons.utils.Log; import ch.ethz.dcg.jukefox.commons.utils.RandomProvider; import ch.ethz.dcg.jukefox.model.AndroidCollectionModelManager; import ch.ethz.dcg.jukefox.model.collection.BaseAlbum; import ch.ethz.dcg.jukefox.model.collection.MapAlbum; import ch.ethz.dcg.jukefox.model.collection.MapTag; import ch.ethz.dcg.jukefox.model.libraryimport.ImportState; import ch.ethz.dcg.pancho3.commons.settings.ISettingsReader; public class MapRenderer extends BaseAlbumRenderer { public static final float DEFAULT_CAMERA_HEIGHT = 13; protected static final String TAG = MapRenderer.class.getSimpleName(); private static final int PLANE_TAG_THRESHHOLD = 50; // private static final int NUM_MAP_TAGS = 100; private final AndroidCollectionModelManager data; private final ISettingsReader settings; private CurrentAlbumProvider currentAlbumProvider; private RegionPlaylistCreator regionPlaylist = null; private boolean highlightCurrentAlbum; private GlHighlight glHighlight; private boolean atLeastOneAlbumWasVisible = false; public MapRenderer(ISettingsReader settings, AndroidCollectionModelManager model, ImportState importState, Context context, CurrentAlbumProvider currentAlbumProvider, Intent intent) { super(model, importState, context); this.data = model; this.settings = settings; this.currentAlbumProvider = currentAlbumProvider; Collection<MapAlbum> mapAlbums; try { mapAlbums = data.getAlbumProvider().getAllMapAlbums(); } catch (DataUnavailableException e) { mapAlbums = new ArrayList<MapAlbum>(); Log.w(TAG, e); } Log.v(TAG, "Got " + mapAlbums.size() + " mapAlbums"); createGlAlbums(mapAlbums, true); Log.v(TAG, "Created GL albums"); List<MapTag> mapTags = data.getTagProvider().getAllMapTags(); createGlTags(mapTags, true); Log.v(TAG, "Created " + mapTags.size() + " GlTags"); highlightCurrentAlbum = settings.isCurrentAlbumHighlighted(); glHighlight = new GlHighlight(0, 0, 0, true, context); gotoCurrentAlbum(); float posX = settings.getLastPositionInPcaMapX(); float posZ = settings.getLastPositionInPcaMapY(); // First set map to last position camera.setCameraPosition(posX, MapRenderer.DEFAULT_CAMERA_HEIGHT, posZ, false); } /** * Interface which tells the renderer which is the current album so it can * be highlighted. */ public static interface CurrentAlbumProvider { MapAlbum getCurrentAlbum(); } public void setCurrentAlbumProvider(CurrentAlbumProvider currentAlbumProvider) { this.currentAlbumProvider = currentAlbumProvider; gotoCurrentAlbum(); } private void gotoCurrentAlbum() { if (settings.isGotoCurrentAlbumEnabled() && currentAlbumProvider != null) { MapAlbum album = currentAlbumProvider.getCurrentAlbum(); if (album != null) { goToAlbum(album); Log.v(TAG, "Set camera to album: " + album.getName()); return; } } } public void goToAlbum(BaseAlbum album) { if (album == null) { return; } MapAlbum mapAlbum; try { mapAlbum = data.getAlbumProvider().getMapAlbum(album); camera.setCameraPosition(mapAlbum.getGridCoords()[0], DEFAULT_CAMERA_HEIGHT, mapAlbum.getGridCoords()[1], false); } catch (DataUnavailableException e) { Log.w(TAG, e); } } @Override public void drawFrame(GL10 gl) { super.drawFrame(gl); float camPosZ = getCamera().getPosZ(); float camPosX = getCamera().getPosX(); float camPosY = getCamera().getPosY(); updateModelViewWithCamera(gl, camPosZ, camPosX, camPosY); float widthFactor = getViewRatio() / getCamera().getFrontClippingPlane(); float heightFactor = 1f / getCamera().getFrontClippingPlane(); float visibleMinX = camPosX - camPosY * widthFactor - 2 * GlAlbumCover.COVER_SIZE; float visibleMaxX = camPosX + camPosY * widthFactor + 2 * GlAlbumCover.COVER_SIZE; float visibleMinZ = camPosZ - camPosY * heightFactor - 2 * GlAlbumCover.COVER_SIZE; float visibleMaxZ = camPosZ + camPosY * heightFactor + 2 * GlAlbumCover.COVER_SIZE; doRegionPlaylist(gl); drawHighlight(gl); boolean drawTagsInsteadOfTextures = camPosY > PLANE_TAG_THRESHHOLD; drawAlbums(gl, camPosZ, camPosX, drawTagsInsteadOfTextures, visibleMinZ, visibleMaxZ, visibleMinX, visibleMaxX); if (drawTagsInsteadOfTextures) { drawTags(gl, camPosY, visibleMinX, visibleMaxX, visibleMinZ, visibleMaxZ); } } private void drawTags(GL10 gl, float camPosY, float visibleMinX, float visibleMaxX, float visibleMinZ, float visibleMaxZ) { // float proportional = (camPosY - PLANE_TAG_THRESHHOLD) // / (getCamera().getRearClippingPlane() - PLANE_TAG_THRESHHOLD); // int num_labels = (int) ((1 - proportional) * NUM_MAP_TAGS / 6f + // NUM_MAP_TAGS / 6f); int u = 0; for (GlTagLabel glTagLabel : tags) { MapTag mapTag = glTagLabel.getMapTag(); if (mapTag.getCoordsPca2D()[1] < visibleMinZ) { continue; } if (mapTag.getCoordsPca2D()[1] > visibleMaxZ) { break; } // Check if tag labels should be drawn // if (u < num_labels) { glTagLabel.setSizeInHorizontalMode(camPosY / PLANE_TAG_THRESHHOLD); glTagLabel.draw(gl); u++; // } // if (u == num_labels) // break; } } private void updateModelViewWithCamera(GL10 gl, float camPosZ, float camPosX, float camPosY) { gl.glDisable(GL10.GL_DITHER); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); GLU.gluLookAt(gl, camPosX, camPosY, camPosZ, camPosX, camPosY - 1, camPosZ, 0f, 0.0f, -1.0f); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } private void drawAlbums(GL10 gl, float camPosZ, float camPosX, boolean drawTagsInsteadOfTextures, float visibleMinZ, float visibleMaxZ, float visibleMinX, float visibleMaxX) { float minDistToCenter = Float.MAX_VALUE; GlAlbumCover albumForCoverLoad = null; for (GlAlbumCover glAlbumCover : albums) { MapAlbum mapAlbum = glAlbumCover.getMapAlbum(); if (mapAlbum.getGridCoords()[1] < visibleMinZ) { continue; } if (mapAlbum.getGridCoords()[1] > visibleMaxZ) { break; } if (!drawTagsInsteadOfTextures && !glAlbumCover.isTextureLoaded()) { float diffX = Math.abs(camPosX - mapAlbum.getGridCoords()[0]); float diffZ = Math.abs(camPosZ - mapAlbum.getGridCoords()[1]); float dist = diffX + diffZ; if (dist < minDistToCenter) { minDistToCenter = dist; albumForCoverLoad = glAlbumCover; } } glAlbumCover.draw(gl, !drawTagsInsteadOfTextures); if (!atLeastOneAlbumWasVisible) { checkIfAlbumIsVisible(glAlbumCover, visibleMinX, visibleMaxX); } } setAlbumToLoadAlbumArt(albumForCoverLoad); if (!atLeastOneAlbumWasVisible && albums.size() > 0) { goToRandomAlbum(); } } private void goToRandomAlbum() { int rnd = RandomProvider.getRandom().nextInt(albums.size()); MapAlbum album = albums.get(rnd).getMapAlbum(); camera.setCameraPosition(album.getGridCoords()[0], DEFAULT_CAMERA_HEIGHT, album.getGridCoords()[1], false); } private void checkIfAlbumIsVisible(GlAlbumCover glAlbumCover, float visibleMinX, float visibleMaxX) { MapAlbum mapAlbum = glAlbumCover.getMapAlbum(); if (mapAlbum.getGridCoords()[0] > visibleMinX && mapAlbum.getGridCoords()[0] < visibleMaxX) { atLeastOneAlbumWasVisible = true; } } private void drawHighlight(GL10 gl) { if (currentAlbumProvider != null) { // Maybe draw a highlight MapAlbum album = currentAlbumProvider.getCurrentAlbum(); if (highlightCurrentAlbum && album != null) { glHighlight.setCoords(album.getGridCoords()[0], -0.01f, album.getGridCoords()[1]); glHighlight.draw(gl, albumTextures[0]); } } } private void doRegionPlaylist(GL10 gl) { if (regionPlaylist != null) { regionPlaylist.draw(gl); if (regionPlaylist.hasToGetAlbums()) { regionPlaylist.getAlbumsInPlaylist(gl); regionPlaylist = null; } } } public void startDrawingRegionPlaylist(RegionPlaylistCreator regionPlaylist) { this.regionPlaylist = regionPlaylist; } public void stopDrawingRegionPlaylist() { if (regionPlaylist != null) { regionPlaylist.createPlaylist(); } } public void onResume() { for (GlAlbumCover albumCover : albums) { albumCover.resetTexture(); } for (GlTagLabel tag : tags) { tag.resetTexture(); } glHighlight = new GlHighlight(0, 0, 0, true, context); atLeastOneAlbumWasVisible = false; } public void onPause() { if (albumArtTextureLoader != null) { albumArtTextureLoader.terminate(); } } public void newCurrentAlbum() { if (settings.isGotoCurrentAlbumEnabled() && currentAlbumProvider != null) { MapAlbum album = currentAlbumProvider.getCurrentAlbum(); if (album != null) { goToAlbum(album); Log.v(TAG, "Set camera to album: " + album.getName()); return; } } } }