• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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.cooliris.media;
18 
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.nio.CharBuffer;
22 import java.nio.FloatBuffer;
23 
24 import javax.microedition.khronos.opengles.GL10;
25 import javax.microedition.khronos.opengles.GL11;
26 
27 /**
28  * A 2D rectangular mesh. Can be drawn textured or untextured. This version is
29  * modified from the original Grid.java (found in the SpriteText package in the
30  * APIDemos Android sample) to support hardware vertex buffers.
31  */
32 final class GridQuadMesh {
33     private FloatBuffer mVertexBuffer;
34     private FloatBuffer mTexCoordBuffer;
35     private CharBuffer mIndexBuffer;
36 
37     private int mW;
38     private int mH;
39     private int mIndexCount;
40     private int mVertBufferIndex;
41     private int mIndexBufferIndex;
42     private int mTextureCoordBufferIndex;
43 
GridQuadMesh(int vertsAcross, int vertsDown)44     public GridQuadMesh(int vertsAcross, int vertsDown) {
45         if (vertsAcross < 0 || vertsAcross >= 65536) {
46             throw new IllegalArgumentException("vertsAcross");
47         }
48         if (vertsDown < 0 || vertsDown >= 65536) {
49             throw new IllegalArgumentException("vertsDown");
50         }
51         if (vertsAcross * vertsDown >= 65536) {
52             throw new IllegalArgumentException("vertsAcross * vertsDown >= 65536");
53         }
54 
55         mW = vertsAcross;
56         mH = vertsDown;
57         int size = vertsAcross * vertsDown;
58         final int FLOAT_SIZE = 4;
59         final int CHAR_SIZE = 2;
60         mVertexBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 3).order(ByteOrder.nativeOrder()).asFloatBuffer();
61         mTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
62 
63         int quadW = mW - 1;
64         int quadH = mH - 1;
65         int quadCount = quadW * quadH;
66         int indexCount = quadCount * 6;
67         mIndexCount = indexCount;
68         mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount).order(ByteOrder.nativeOrder()).asCharBuffer();
69 
70         /*
71          * Initialize triangle list mesh.
72          *
73          * [0]-----[ 1] ... | / | | / | | / | [w]-----[w+1] ... | |
74          */
75 
76         {
77             int i = 0;
78             for (int y = 0; y < quadH; y++) {
79                 for (int x = 0; x < quadW; x++) {
80                     char a = (char) (y * mW + x);
81                     char b = (char) (y * mW + x + 1);
82                     char c = (char) ((y + 1) * mW + x);
83                     char d = (char) ((y + 1) * mW + x + 1);
84 
85                     mIndexBuffer.put(i++, a);
86                     mIndexBuffer.put(i++, b);
87                     mIndexBuffer.put(i++, c);
88 
89                     mIndexBuffer.put(i++, b);
90                     mIndexBuffer.put(i++, c);
91                     mIndexBuffer.put(i++, d);
92                 }
93             }
94         }
95 
96         mVertBufferIndex = 0;
97     }
98 
set(int i, int j, float x, float y, float z, float u, float v)99     void set(int i, int j, float x, float y, float z, float u, float v) {
100         if (i < 0 || i >= mW) {
101             throw new IllegalArgumentException("i");
102         }
103         if (j < 0 || j >= mH) {
104             throw new IllegalArgumentException("j");
105         }
106 
107         int index = mW * j + i;
108 
109         int posIndex = index * 3;
110         mVertexBuffer.put(posIndex, x);
111         mVertexBuffer.put(posIndex + 1, y);
112         mVertexBuffer.put(posIndex + 2, z);
113 
114         int texIndex = index * 2;
115         mTexCoordBuffer.put(texIndex, u);
116         mTexCoordBuffer.put(texIndex + 1, v);
117     }
118 
draw(GL10 gl, boolean useTexture)119     public void draw(GL10 gl, boolean useTexture) {
120         if (mVertBufferIndex == 0) {
121             gl.glVertexPointer(3, GL11.GL_FLOAT, 0, mVertexBuffer);
122 
123             if (useTexture) {
124                 gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, mTexCoordBuffer);
125             }
126 
127             gl.glDrawElements(GL11.GL_TRIANGLES, mIndexCount, GL11.GL_UNSIGNED_SHORT, mIndexBuffer);
128         } else {
129             GL11 gl11 = (GL11) gl;
130             // draw using hardware buffers
131             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
132             gl11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
133 
134             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
135             gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
136 
137             gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
138             gl11.glDrawElements(GL11.GL_TRIANGLES, mIndexCount, GL11.GL_UNSIGNED_SHORT, 0);
139 
140             gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
141             gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
142 
143         }
144     }
145 
usingHardwareBuffers()146     public boolean usingHardwareBuffers() {
147         return mVertBufferIndex != 0;
148     }
149 
150     /**
151      * When the OpenGL ES device is lost, GL handles become invalidated. In that
152      * case, we just want to "forget" the old handles (without explicitly
153      * deleting them) and make new ones.
154      */
forgetHardwareBuffers()155     public void forgetHardwareBuffers() {
156         mVertBufferIndex = 0;
157         mIndexBufferIndex = 0;
158         mTextureCoordBufferIndex = 0;
159     }
160 
161     /**
162      * Deletes the hardware buffers allocated by this object (if any).
163      */
freeHardwareBuffers(GL10 gl)164     public void freeHardwareBuffers(GL10 gl) {
165         if (mVertBufferIndex != 0) {
166             if (gl instanceof GL11) {
167                 GL11 gl11 = (GL11) gl;
168                 int[] buffer = new int[1];
169                 buffer[0] = mVertBufferIndex;
170                 gl11.glDeleteBuffers(1, buffer, 0);
171 
172                 buffer[0] = mTextureCoordBufferIndex;
173                 gl11.glDeleteBuffers(1, buffer, 0);
174 
175                 buffer[0] = mIndexBufferIndex;
176                 gl11.glDeleteBuffers(1, buffer, 0);
177             }
178 
179             forgetHardwareBuffers();
180         }
181     }
182 
183     /**
184      * Allocates hardware buffers on the graphics card and fills them with data
185      * if a buffer has not already been previously allocated. Note that this
186      * function uses the GL_OES_vertex_buffer_object extension, which is not
187      * guaranteed to be supported on every device.
188      *
189      * @param gl
190      *            A pointer to the OpenGL ES context.
191      */
generateHardwareBuffers(GL10 gl)192     public void generateHardwareBuffers(GL10 gl) {
193         if (mVertBufferIndex == 0) {
194             if (gl instanceof GL11) {
195                 GL11 gl11 = (GL11) gl;
196                 int[] buffer = new int[1];
197 
198                 // Allocate and fill the vertex buffer.
199                 gl11.glGenBuffers(1, buffer, 0);
200                 mVertBufferIndex = buffer[0];
201                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
202                 final int vertexSize = mVertexBuffer.capacity() * 4;
203                 mVertexBuffer.position(0);
204                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertexSize, mVertexBuffer, GL11.GL_STATIC_DRAW);
205 
206                 // Allocate and fill the texture coordinate buffer.
207                 gl11.glGenBuffers(1, buffer, 0);
208                 mTextureCoordBufferIndex = buffer[0];
209                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
210                 final int texCoordSize = mTexCoordBuffer.capacity() * 4;
211                 mTexCoordBuffer.position(0);
212                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize, mTexCoordBuffer, GL11.GL_STATIC_DRAW);
213 
214                 // Unbind the array buffer.
215                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
216 
217                 // Allocate and fill the index buffer.
218                 gl11.glGenBuffers(1, buffer, 0);
219                 mIndexBufferIndex = buffer[0];
220                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
221                 // A char is 2 bytes.
222                 final int indexSize = mIndexBuffer.capacity() * 2;
223                 mIndexBuffer.position(0);
224                 gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indexSize, mIndexBuffer, GL11.GL_STATIC_DRAW);
225 
226                 // Unbind the element array buffer.
227                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
228             }
229         }
230     }
231 
232 }
233