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