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