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