• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.replica.replicaisland;
18 
19 import java.nio.Buffer;
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.nio.CharBuffer;
23 import java.nio.FloatBuffer;
24 import java.nio.IntBuffer;
25 
26 import javax.microedition.khronos.opengles.GL10;
27 import javax.microedition.khronos.opengles.GL11;
28 
29 import android.util.Log;
30 
31 /**
32  * A 2D rectangular mesh. Can be drawn textured or untextured.
33  * This version is modified from the original Grid.java (found in
34  * the SpriteText package in the APIDemos Android sample) to support hardware
35  * vertex buffers and to insert edges between grid squares for tiling.
36  */
37 class Grid {
38 	private static final int FLOAT_SIZE = 4;
39 	private static final int FIXED_SIZE = 4;
40 	private static final int CHAR_SIZE = 2;
41 
42     private FloatBuffer mFloatVertexBuffer;
43     private FloatBuffer mFloatTexCoordBuffer;
44     private IntBuffer mFixedVertexBuffer;
45     private IntBuffer mFixedTexCoordBuffer;
46     private CharBuffer mIndexBuffer;
47 
48     private Buffer mVertexBuffer;
49     private Buffer mTexCoordBuffer;
50     private int mCoordinateSize;
51     private int mCoordinateType;
52 
53     private int mVertsAcross;
54     private int mVertsDown;
55     private int mIndexCount;
56     private boolean mUseHardwareBuffers;
57     private int mVertBufferIndex;
58     private int mIndexBufferIndex;
59     private int mTextureCoordBufferIndex;
60 
Grid(int quadsAcross, int quadsDown, boolean useFixedPoint)61     public Grid(int quadsAcross, int quadsDown, boolean useFixedPoint) {
62     	final int vertsAcross = quadsAcross * 2;
63     	final int vertsDown = quadsDown * 2;
64         if (vertsAcross < 0 || vertsAcross >= 65536) {
65             throw new IllegalArgumentException("quadsAcross");
66         }
67         if (vertsDown < 0 || vertsDown >= 65536) {
68             throw new IllegalArgumentException("quadsDown");
69         }
70         if (vertsAcross * vertsDown >= 65536) {
71             throw new IllegalArgumentException("quadsAcross * quadsDown >= 32768");
72         }
73 
74         mUseHardwareBuffers = false;
75 
76         mVertsAcross = vertsAcross;
77         mVertsDown = vertsDown;
78         int size = vertsAcross * vertsDown;
79 
80 
81         if (useFixedPoint) {
82         	mFixedVertexBuffer = ByteBuffer.allocateDirect(FIXED_SIZE * size * 3)
83             	.order(ByteOrder.nativeOrder()).asIntBuffer();
84         	mFixedTexCoordBuffer = ByteBuffer.allocateDirect(FIXED_SIZE * size * 2)
85             	.order(ByteOrder.nativeOrder()).asIntBuffer();
86 
87         	mVertexBuffer = mFixedVertexBuffer;
88         	mTexCoordBuffer = mFixedTexCoordBuffer;
89         	mCoordinateSize = FIXED_SIZE;
90         	mCoordinateType = GL10.GL_FIXED;
91 
92         } else {
93         	mFloatVertexBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 3)
94             	.order(ByteOrder.nativeOrder()).asFloatBuffer();
95         	mFloatTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2)
96             	.order(ByteOrder.nativeOrder()).asFloatBuffer();
97 
98         	mVertexBuffer = mFloatVertexBuffer;
99         	mTexCoordBuffer = mFloatTexCoordBuffer;
100         	mCoordinateSize = FLOAT_SIZE;
101         	mCoordinateType = GL10.GL_FLOAT;
102         }
103 
104 
105 
106 
107         int quadCount = quadsAcross * quadsDown;
108         int indexCount = quadCount * 6;
109         mIndexCount = indexCount;
110         mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount)
111             .order(ByteOrder.nativeOrder()).asCharBuffer();
112 
113         /*
114          * Initialize triangle list mesh.
115          *
116          *     [0]------[1]   [2]------[3] ...
117          *      |    /   |     |    /   |
118          *      |   /    |     |   /    |
119          *      |  /     |     |  /     |
120          *     [w]-----[w+1] [w+2]----[w+3]...
121          *      |       |
122          *
123          */
124 
125         {
126             int i = 0;
127             for (int y = 0; y < quadsDown; y++) {
128             	final int indexY = y * 2;
129                 for (int x = 0; x < quadsAcross; x++) {
130                 	final int indexX = x * 2;
131                     char a = (char) (indexY * mVertsAcross + indexX);
132                     char b = (char) (indexY * mVertsAcross + indexX + 1);
133                     char c = (char) ((indexY + 1) * mVertsAcross + indexX);
134                     char d = (char) ((indexY + 1) * mVertsAcross + indexX + 1);
135 
136                     mIndexBuffer.put(i++, a);
137                     mIndexBuffer.put(i++, b);
138                     mIndexBuffer.put(i++, c);
139 
140                     mIndexBuffer.put(i++, b);
141                     mIndexBuffer.put(i++, c);
142                     mIndexBuffer.put(i++, d);
143                 }
144             }
145         }
146 
147         mVertBufferIndex = 0;
148     }
149 
set(int quadX, int quadY, float[][] positions, float[][] uvs)150     public void set(int quadX, int quadY, float[][] positions, float[][] uvs) {
151         if (quadX < 0 || quadX * 2 >= mVertsAcross) {
152             throw new IllegalArgumentException("quadX");
153         }
154         if (quadY < 0 || quadY * 2 >= mVertsDown) {
155             throw new IllegalArgumentException("quadY");
156         }
157         if (positions.length < 4) {
158             throw new IllegalArgumentException("positions");
159         }
160         if (uvs.length < 4) {
161             throw new IllegalArgumentException("quadY");
162         }
163 
164         int i = quadX * 2;
165         int j = quadY * 2;
166 
167         setVertex(i, j, 		positions[0][0], positions[0][1], positions[0][2], uvs[0][0], uvs[0][1]);
168         setVertex(i + 1, j, 	positions[1][0], positions[1][1], positions[1][2], uvs[1][0], uvs[1][1]);
169         setVertex(i, j + 1, 	positions[2][0], positions[2][1], positions[2][2], uvs[2][0], uvs[2][1]);
170         setVertex(i + 1, j + 1, positions[3][0], positions[3][1], positions[3][2], uvs[3][0], uvs[3][1]);
171     }
172 
173 
setVertex(int i, int j, float x, float y, float z, float u, float v)174     private void setVertex(int i, int j, float x, float y, float z, float u, float v) {
175 	  if (i < 0 || i >= mVertsAcross) {
176 	       throw new IllegalArgumentException("i");
177 	   }
178 	   if (j < 0 || j >= mVertsDown) {
179 	       throw new IllegalArgumentException("j");
180 	   }
181 
182 	   final int index = mVertsAcross * j + i;
183 
184 	   final int posIndex = index * 3;
185 	   final int texIndex = index * 2;
186 
187 
188 	   if (mCoordinateType == GL10.GL_FLOAT) {
189 	    mFloatVertexBuffer.put(posIndex, x);
190 	    mFloatVertexBuffer.put(posIndex + 1, y);
191 	    mFloatVertexBuffer.put(posIndex + 2, z);
192 
193 	    mFloatTexCoordBuffer.put(texIndex, u);
194 	    mFloatTexCoordBuffer.put(texIndex + 1, v);
195 	   } else {
196 	    mFixedVertexBuffer.put(posIndex, (int)(x * (1 << 16)));
197 	    mFixedVertexBuffer.put(posIndex + 1, (int)(y * (1 << 16)));
198 	    mFixedVertexBuffer.put(posIndex + 2, (int)(z * (1 << 16)));
199 
200 	    mFixedTexCoordBuffer.put(texIndex, (int)(u * (1 << 16)));
201 	    mFixedTexCoordBuffer.put(texIndex + 1, (int)(v * (1 << 16)));
202 	   }
203 	}
204 
beginDrawing(GL10 gl, boolean useTexture)205     public static void beginDrawing(GL10 gl, boolean useTexture) {
206         gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
207 
208         if (useTexture) {
209             gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
210             gl.glEnable(GL10.GL_TEXTURE_2D);
211         } else {
212             gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
213             gl.glDisable(GL10.GL_TEXTURE_2D);
214         }
215     }
216 
beginDrawingStrips(GL10 gl, boolean useTexture)217     public void beginDrawingStrips(GL10 gl, boolean useTexture) {
218         beginDrawing(gl, useTexture);
219         if (!mUseHardwareBuffers) {
220             gl.glVertexPointer(3, mCoordinateType, 0, mVertexBuffer);
221 
222             if (useTexture) {
223                 gl.glTexCoordPointer(2, mCoordinateType, 0, mTexCoordBuffer);
224             }
225 
226         } else {
227             GL11 gl11 = (GL11)gl;
228             // draw using hardware buffers
229             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
230             gl11.glVertexPointer(3, mCoordinateType, 0, 0);
231 
232             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
233             gl11.glTexCoordPointer(2, mCoordinateType, 0, 0);
234 
235             gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
236         }
237     }
238 
239     // Assumes beginDrawingStrips() has been called before this.
drawStrip(GL10 gl, boolean useTexture, int startIndex, int indexCount)240     public void drawStrip(GL10 gl, boolean useTexture, int startIndex, int indexCount) {
241     	int count = indexCount;
242     	if (startIndex + indexCount >= mIndexCount) {
243     		count = mIndexCount - startIndex;
244     	}
245     	if (!mUseHardwareBuffers) {
246             gl.glDrawElements(GL10.GL_TRIANGLES, count,
247                     GL10.GL_UNSIGNED_SHORT, mIndexBuffer.position(startIndex));
248         } else {
249         	GL11 gl11 = (GL11)gl;
250             gl11.glDrawElements(GL11.GL_TRIANGLES, count,
251                     GL11.GL_UNSIGNED_SHORT, startIndex * CHAR_SIZE);
252 
253         }
254     }
255 
draw(GL10 gl, boolean useTexture)256     public void draw(GL10 gl, boolean useTexture) {
257         if (!mUseHardwareBuffers) {
258             gl.glVertexPointer(3, mCoordinateType, 0, mVertexBuffer);
259 
260             if (useTexture) {
261                 gl.glTexCoordPointer(2, mCoordinateType, 0, mTexCoordBuffer);
262             }
263 
264             gl.glDrawElements(GL10.GL_TRIANGLES, mIndexCount,
265                     GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
266         } else {
267             GL11 gl11 = (GL11)gl;
268             // draw using hardware buffers
269             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
270             gl11.glVertexPointer(3, mCoordinateType, 0, 0);
271 
272             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
273             gl11.glTexCoordPointer(2, mCoordinateType, 0, 0);
274 
275             gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
276             gl11.glDrawElements(GL11.GL_TRIANGLES, mIndexCount,
277                     GL11.GL_UNSIGNED_SHORT, 0);
278 
279             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
280             gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
281 
282 
283         }
284     }
285 
endDrawing(GL10 gl)286     public static void endDrawing(GL10 gl) {
287         gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
288     }
289 
usingHardwareBuffers()290     public boolean usingHardwareBuffers() {
291         return mUseHardwareBuffers;
292     }
293 
294     /**
295      * When the OpenGL ES device is lost, GL handles become invalidated.
296      * In that case, we just want to "forget" the old handles (without
297      * explicitly deleting them) and make new ones.
298      */
invalidateHardwareBuffers()299     public void invalidateHardwareBuffers() {
300         mVertBufferIndex = 0;
301         mIndexBufferIndex = 0;
302         mTextureCoordBufferIndex = 0;
303         mUseHardwareBuffers = false;
304     }
305 
306     /**
307      * Deletes the hardware buffers allocated by this object (if any).
308      */
releaseHardwareBuffers(GL10 gl)309     public void releaseHardwareBuffers(GL10 gl) {
310         if (mUseHardwareBuffers) {
311             if (gl instanceof GL11) {
312                 GL11 gl11 = (GL11)gl;
313                 int[] buffer = new int[1];
314                 buffer[0] = mVertBufferIndex;
315                 gl11.glDeleteBuffers(1, buffer, 0);
316 
317                 buffer[0] = mTextureCoordBufferIndex;
318                 gl11.glDeleteBuffers(1, buffer, 0);
319 
320                 buffer[0] = mIndexBufferIndex;
321                 gl11.glDeleteBuffers(1, buffer, 0);
322             }
323 
324             invalidateHardwareBuffers();
325         }
326     }
327 
328     /**
329      * Allocates hardware buffers on the graphics card and fills them with
330      * data if a buffer has not already been previously allocated.  Note that
331      * this function uses the GL_OES_vertex_buffer_object extension, which is
332      * not guaranteed to be supported on every device.
333      * @param gl  A pointer to the OpenGL ES context.
334      */
generateHardwareBuffers(GL10 gl)335     public void generateHardwareBuffers(GL10 gl) {
336         if (!mUseHardwareBuffers) {
337         	DebugLog.i("Grid", "Using Hardware Buffers");
338             if (gl instanceof GL11) {
339                 GL11 gl11 = (GL11)gl;
340                 int[] buffer = new int[1];
341 
342                 // Allocate and fill the vertex buffer.
343                 gl11.glGenBuffers(1, buffer, 0);
344                 mVertBufferIndex = buffer[0];
345                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
346                 final int vertexSize = mVertexBuffer.capacity() * mCoordinateSize;
347                 // too fast task switching leaves buffers in the middle pos which
348                 // crashes app
349                 mVertexBuffer.position(0);
350                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertexSize,
351                         mVertexBuffer, GL11.GL_STATIC_DRAW);
352 
353                 // Allocate and fill the texture coordinate buffer.
354                 gl11.glGenBuffers(1, buffer, 0);
355                 mTextureCoordBufferIndex = buffer[0];
356                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER,
357                         mTextureCoordBufferIndex);
358                 final int texCoordSize =
359                     mTexCoordBuffer.capacity() * mCoordinateSize;
360                 mTexCoordBuffer.position(0);
361                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize,
362                         mTexCoordBuffer, GL11.GL_STATIC_DRAW);
363 
364                 // Unbind the array buffer.
365                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
366 
367                 // Allocate and fill the index buffer.
368                 gl11.glGenBuffers(1, buffer, 0);
369                 mIndexBufferIndex = buffer[0];
370                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER,
371                         mIndexBufferIndex);
372                 // A char is 2 bytes.
373                 final int indexSize = mIndexBuffer.capacity() * 2;
374 
375                 mIndexBuffer.position(0);
376                 gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indexSize, mIndexBuffer,
377                         GL11.GL_STATIC_DRAW);
378 
379                 // Unbind the element array buffer.
380                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
381 
382                 mUseHardwareBuffers = true;
383 
384                 assert mVertBufferIndex != 0;
385                 assert mTextureCoordBufferIndex != 0;
386                 assert mIndexBufferIndex != 0;
387                 assert gl11.glGetError() == 0;
388 
389 
390             }
391         }
392     }
393 
394 }
395