1*5eae8ebbSCole Faust /* 2*5eae8ebbSCole Faust * Copyright (C) 2010 The Android Open Source Project 3*5eae8ebbSCole Faust * 4*5eae8ebbSCole Faust * Licensed under the Apache License, Version 2.0 (the "License"); 5*5eae8ebbSCole Faust * you may not use this file except in compliance with the License. 6*5eae8ebbSCole Faust * You may obtain a copy of the License at 7*5eae8ebbSCole Faust * 8*5eae8ebbSCole Faust * http://www.apache.org/licenses/LICENSE-2.0 9*5eae8ebbSCole Faust * 10*5eae8ebbSCole Faust * Unless required by applicable law or agreed to in writing, software 11*5eae8ebbSCole Faust * distributed under the License is distributed on an "AS IS" BASIS, 12*5eae8ebbSCole Faust * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*5eae8ebbSCole Faust * See the License for the specific language governing permissions and 14*5eae8ebbSCole Faust * limitations under the License. 15*5eae8ebbSCole Faust */ 16*5eae8ebbSCole Faust 17*5eae8ebbSCole Faust package com.replica.replicaisland; 18*5eae8ebbSCole Faust 19*5eae8ebbSCole Faust import javax.microedition.khronos.opengles.GL10; 20*5eae8ebbSCole Faust 21*5eae8ebbSCole Faust public class TiledVertexGrid extends BaseObject { 22*5eae8ebbSCole Faust private static final float GL_MAGIC_OFFSET = 0.375f; 23*5eae8ebbSCole Faust private Grid mTileMap; 24*5eae8ebbSCole Faust private TiledWorld mWorld; 25*5eae8ebbSCole Faust private int mTileWidth; 26*5eae8ebbSCole Faust private int mTileHeight; 27*5eae8ebbSCole Faust 28*5eae8ebbSCole Faust private int mWidth; 29*5eae8ebbSCole Faust private int mHeight; 30*5eae8ebbSCole Faust private Texture mTexture; 31*5eae8ebbSCole Faust 32*5eae8ebbSCole Faust private float mWorldPixelWidth; 33*5eae8ebbSCole Faust private float mWorldPixelHeight; 34*5eae8ebbSCole Faust 35*5eae8ebbSCole Faust private int mTilesPerRow; 36*5eae8ebbSCole Faust private int mTilesPerColumn; 37*5eae8ebbSCole Faust 38*5eae8ebbSCole Faust private Boolean mGenerated; 39*5eae8ebbSCole Faust TiledVertexGrid(Texture texture, int width, int height, int tileWidth, int tileHeight)40*5eae8ebbSCole Faust public TiledVertexGrid(Texture texture, int width, int height, int tileWidth, int tileHeight) { 41*5eae8ebbSCole Faust super(); 42*5eae8ebbSCole Faust mTileWidth = tileWidth; 43*5eae8ebbSCole Faust mTileHeight = tileHeight; 44*5eae8ebbSCole Faust mWidth = width; 45*5eae8ebbSCole Faust mHeight = height; 46*5eae8ebbSCole Faust mTexture = texture; 47*5eae8ebbSCole Faust mGenerated = false; 48*5eae8ebbSCole Faust } 49*5eae8ebbSCole Faust 50*5eae8ebbSCole Faust @Override reset()51*5eae8ebbSCole Faust public void reset() { 52*5eae8ebbSCole Faust } 53*5eae8ebbSCole Faust setWorld(TiledWorld world)54*5eae8ebbSCole Faust public void setWorld(TiledWorld world) { 55*5eae8ebbSCole Faust mWorld = world; 56*5eae8ebbSCole Faust 57*5eae8ebbSCole Faust } 58*5eae8ebbSCole Faust generateGrid(int width, int height, int startTileX, int startTileY)59*5eae8ebbSCole Faust private Grid generateGrid(int width, int height, int startTileX, int startTileY) { 60*5eae8ebbSCole Faust final int tileWidth = mTileWidth; 61*5eae8ebbSCole Faust final int tileHeight = mTileHeight; 62*5eae8ebbSCole Faust final int tilesAcross = width / tileWidth; 63*5eae8ebbSCole Faust final int tilesDown = height / tileHeight; 64*5eae8ebbSCole Faust final Texture texture = mTexture; 65*5eae8ebbSCole Faust final float texelWidth = 1.0f / texture.width; 66*5eae8ebbSCole Faust final float texelHeight = 1.0f / texture.height; 67*5eae8ebbSCole Faust final int textureTilesAcross = texture.width / tileWidth; 68*5eae8ebbSCole Faust final int textureTilesDown = texture.height / tileHeight; 69*5eae8ebbSCole Faust final int tilesPerWorldColumn = mWorld.getHeight(); 70*5eae8ebbSCole Faust final int totalTextureTiles = textureTilesAcross * textureTilesDown; 71*5eae8ebbSCole Faust // Check to see if this entire grid is empty tiles. If so, we don't need to do anything. 72*5eae8ebbSCole Faust boolean entirelyEmpty = true; 73*5eae8ebbSCole Faust for (int tileY = 0; tileY < tilesDown && entirelyEmpty; tileY++) { 74*5eae8ebbSCole Faust for (int tileX = 0; tileX < tilesAcross && entirelyEmpty; tileX++) { 75*5eae8ebbSCole Faust int tileIndex = mWorld.getTile(startTileX + tileX, 76*5eae8ebbSCole Faust (tilesPerWorldColumn - 1 - (startTileY + tileY))); 77*5eae8ebbSCole Faust if (tileIndex >= 0) { 78*5eae8ebbSCole Faust entirelyEmpty = false; 79*5eae8ebbSCole Faust break; 80*5eae8ebbSCole Faust } 81*5eae8ebbSCole Faust } 82*5eae8ebbSCole Faust } 83*5eae8ebbSCole Faust 84*5eae8ebbSCole Faust Grid grid = null; 85*5eae8ebbSCole Faust if (!entirelyEmpty) { 86*5eae8ebbSCole Faust grid = new Grid(tilesAcross, tilesDown, false); 87*5eae8ebbSCole Faust for (int tileY = 0; tileY < tilesDown; tileY++) { 88*5eae8ebbSCole Faust for (int tileX = 0; tileX < tilesAcross; tileX++) { 89*5eae8ebbSCole Faust final float offsetX = tileX * tileWidth; 90*5eae8ebbSCole Faust final float offsetY = tileY * tileHeight; 91*5eae8ebbSCole Faust int tileIndex = mWorld.getTile(startTileX + tileX, 92*5eae8ebbSCole Faust (tilesPerWorldColumn - 1 - (startTileY + tileY))); 93*5eae8ebbSCole Faust if (tileIndex < 0) { 94*5eae8ebbSCole Faust tileIndex = totalTextureTiles - 1; // Assume that the last tile is empty. 95*5eae8ebbSCole Faust } 96*5eae8ebbSCole Faust int textureOffsetX = (tileIndex % textureTilesAcross) * tileWidth; 97*5eae8ebbSCole Faust int textureOffsetY = (tileIndex / textureTilesAcross) * tileHeight; 98*5eae8ebbSCole Faust if (textureOffsetX < 0 || 99*5eae8ebbSCole Faust textureOffsetX > texture.width - tileWidth || 100*5eae8ebbSCole Faust textureOffsetY < 0 || 101*5eae8ebbSCole Faust textureOffsetY > texture.height - tileHeight) { 102*5eae8ebbSCole Faust textureOffsetX = 0; 103*5eae8ebbSCole Faust textureOffsetY = 0; 104*5eae8ebbSCole Faust } 105*5eae8ebbSCole Faust final float u = (textureOffsetX + GL_MAGIC_OFFSET) * texelWidth; 106*5eae8ebbSCole Faust final float v = (textureOffsetY + GL_MAGIC_OFFSET) * texelHeight; 107*5eae8ebbSCole Faust final float u2 = ((textureOffsetX + tileWidth - GL_MAGIC_OFFSET) * texelWidth); 108*5eae8ebbSCole Faust final float v2 = ((textureOffsetY + tileHeight - GL_MAGIC_OFFSET) * texelHeight); 109*5eae8ebbSCole Faust 110*5eae8ebbSCole Faust final float[] p0 = { offsetX, offsetY, 0.0f }; 111*5eae8ebbSCole Faust final float[] p1 = { offsetX + tileWidth, offsetY, 0.0f }; 112*5eae8ebbSCole Faust final float[] p2 = { offsetX, offsetY + tileHeight, 0.0f }; 113*5eae8ebbSCole Faust final float[] p3 = { offsetX + tileWidth, offsetY + tileHeight, 0.0f }; 114*5eae8ebbSCole Faust final float[] uv0 = { u, v2 }; 115*5eae8ebbSCole Faust final float[] uv1 = { u2, v2 }; 116*5eae8ebbSCole Faust final float[] uv2 = { u, v }; 117*5eae8ebbSCole Faust final float[] uv3 = { u2, v }; 118*5eae8ebbSCole Faust 119*5eae8ebbSCole Faust final float[][] positions = { p0, p1, p2, p3 }; 120*5eae8ebbSCole Faust final float[][] uvs = { uv0, uv1, uv2, uv3 }; 121*5eae8ebbSCole Faust 122*5eae8ebbSCole Faust grid.set(tileX, tileY, positions, uvs); 123*5eae8ebbSCole Faust 124*5eae8ebbSCole Faust } 125*5eae8ebbSCole Faust } 126*5eae8ebbSCole Faust } 127*5eae8ebbSCole Faust return grid; 128*5eae8ebbSCole Faust } 129*5eae8ebbSCole Faust draw(float x, float y, float scrollOriginX, float scrollOriginY)130*5eae8ebbSCole Faust public void draw(float x, float y, float scrollOriginX, float scrollOriginY) { 131*5eae8ebbSCole Faust TiledWorld world = mWorld; 132*5eae8ebbSCole Faust GL10 gl = OpenGLSystem.getGL(); 133*5eae8ebbSCole Faust if (!mGenerated && world != null && gl != null && mTexture != null) { 134*5eae8ebbSCole Faust final int tilesAcross = mWorld.getWidth(); 135*5eae8ebbSCole Faust final int tilesDown = mWorld.getHeight(); 136*5eae8ebbSCole Faust 137*5eae8ebbSCole Faust mWorldPixelWidth = mWorld.getWidth() * mTileWidth; 138*5eae8ebbSCole Faust mWorldPixelHeight = mWorld.getHeight() * mTileHeight; 139*5eae8ebbSCole Faust mTilesPerRow = tilesAcross; 140*5eae8ebbSCole Faust mTilesPerColumn = tilesDown; 141*5eae8ebbSCole Faust 142*5eae8ebbSCole Faust 143*5eae8ebbSCole Faust BufferLibrary bufferLibrary = sSystemRegistry.bufferLibrary; 144*5eae8ebbSCole Faust 145*5eae8ebbSCole Faust Grid grid = generateGrid((int)mWorldPixelWidth, (int)mWorldPixelHeight, 0, 0); 146*5eae8ebbSCole Faust mTileMap = grid; 147*5eae8ebbSCole Faust mGenerated = true; 148*5eae8ebbSCole Faust if (grid != null) { 149*5eae8ebbSCole Faust bufferLibrary.add(grid); 150*5eae8ebbSCole Faust if (sSystemRegistry.contextParameters.supportsVBOs) { 151*5eae8ebbSCole Faust grid.generateHardwareBuffers(gl); 152*5eae8ebbSCole Faust } 153*5eae8ebbSCole Faust } 154*5eae8ebbSCole Faust 155*5eae8ebbSCole Faust } 156*5eae8ebbSCole Faust 157*5eae8ebbSCole Faust final Grid tileMap = mTileMap; 158*5eae8ebbSCole Faust if (tileMap != null) { 159*5eae8ebbSCole Faust final Texture texture = mTexture; 160*5eae8ebbSCole Faust if (gl != null && texture != null) { 161*5eae8ebbSCole Faust 162*5eae8ebbSCole Faust int originX = (int) (x - scrollOriginX); 163*5eae8ebbSCole Faust int originY = (int) (y - scrollOriginY); 164*5eae8ebbSCole Faust 165*5eae8ebbSCole Faust 166*5eae8ebbSCole Faust final float worldPixelWidth = mWorldPixelWidth; 167*5eae8ebbSCole Faust 168*5eae8ebbSCole Faust final float percentageScrollRight = 169*5eae8ebbSCole Faust scrollOriginX != 0.0f ? scrollOriginX / worldPixelWidth : 0.0f; 170*5eae8ebbSCole Faust final float tileSpaceX = percentageScrollRight * mTilesPerRow; 171*5eae8ebbSCole Faust final int leftTile = (int)tileSpaceX; 172*5eae8ebbSCole Faust 173*5eae8ebbSCole Faust // calculate the top tile index 174*5eae8ebbSCole Faust final float worldPixelHeight = mWorldPixelHeight; 175*5eae8ebbSCole Faust 176*5eae8ebbSCole Faust final float percentageScrollUp = 177*5eae8ebbSCole Faust scrollOriginY != 0.0f ? scrollOriginY / worldPixelHeight : 0.0f; 178*5eae8ebbSCole Faust final float tileSpaceY = percentageScrollUp * mTilesPerColumn; 179*5eae8ebbSCole Faust final int bottomTile = (int)tileSpaceY; 180*5eae8ebbSCole Faust 181*5eae8ebbSCole Faust // calculate any sub-tile slop that our scroll position may require. 182*5eae8ebbSCole Faust final int horizontalSlop = ((tileSpaceX - leftTile) * mTileWidth) > 0 ? 1 : 0; 183*5eae8ebbSCole Faust final int verticalSlop = ((tileSpaceY - bottomTile) * mTileHeight) > 0 ? 1 : 0; 184*5eae8ebbSCole Faust 185*5eae8ebbSCole Faust 186*5eae8ebbSCole Faust OpenGLSystem.bindTexture(GL10.GL_TEXTURE_2D, texture.name); 187*5eae8ebbSCole Faust tileMap.beginDrawingStrips(gl, true); 188*5eae8ebbSCole Faust 189*5eae8ebbSCole Faust final int horzTileCount = (int)Math.ceil((float)mWidth / mTileWidth); 190*5eae8ebbSCole Faust final int vertTileCount = (int)Math.ceil((float)mHeight / mTileHeight); 191*5eae8ebbSCole Faust // draw vertex strips 192*5eae8ebbSCole Faust final int startX = leftTile; 193*5eae8ebbSCole Faust final int startY = bottomTile; 194*5eae8ebbSCole Faust final int endX = startX + horizontalSlop + horzTileCount; 195*5eae8ebbSCole Faust final int endY = startY + verticalSlop + vertTileCount; 196*5eae8ebbSCole Faust 197*5eae8ebbSCole Faust gl.glPushMatrix(); 198*5eae8ebbSCole Faust gl.glLoadIdentity(); 199*5eae8ebbSCole Faust gl.glTranslatef( 200*5eae8ebbSCole Faust originX, 201*5eae8ebbSCole Faust originY, 202*5eae8ebbSCole Faust 0.0f); 203*5eae8ebbSCole Faust 204*5eae8ebbSCole Faust 205*5eae8ebbSCole Faust final int indexesPerTile = 6; 206*5eae8ebbSCole Faust final int indexesPerRow = mTilesPerRow * indexesPerTile; 207*5eae8ebbSCole Faust final int startOffset = (startX * indexesPerTile); 208*5eae8ebbSCole Faust final int count = (endX - startX) * indexesPerTile; 209*5eae8ebbSCole Faust for (int tileY = startY; tileY < endY && tileY < mTilesPerColumn; tileY++) { 210*5eae8ebbSCole Faust final int row = tileY * indexesPerRow; 211*5eae8ebbSCole Faust tileMap.drawStrip(gl, true, row + startOffset, count); 212*5eae8ebbSCole Faust } 213*5eae8ebbSCole Faust 214*5eae8ebbSCole Faust gl.glPopMatrix(); 215*5eae8ebbSCole Faust 216*5eae8ebbSCole Faust Grid.endDrawing(gl); 217*5eae8ebbSCole Faust 218*5eae8ebbSCole Faust } 219*5eae8ebbSCole Faust } 220*5eae8ebbSCole Faust } 221*5eae8ebbSCole Faust 222*5eae8ebbSCole Faust } 223