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.android.test;
18 /*
19  * Copyright (C) 2008 The Android Open Source Project
20  *
21  * Licensed under the Apache License, Version 2.0 (the "License");
22  * you may not use this file except in compliance with the License.
23  * You may obtain a copy of the License at
24  *
25  *      http://www.apache.org/licenses/LICENSE-2.0
26  *
27  * Unless required by applicable law or agreed to in writing, software
28  * distributed under the License is distributed on an "AS IS" BASIS,
29  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30  * See the License for the specific language governing permissions and
31  * limitations under the License.
32  */
33 
34 import java.nio.ByteBuffer;
35 import java.nio.ByteOrder;
36 import java.nio.CharBuffer;
37 import java.nio.FloatBuffer;
38 
39 import android.content.Context;
40 import android.opengl.GLSurfaceView;
41 import android.util.AttributeSet;
42 import android.util.Log;
43 import android.view.KeyEvent;
44 import android.view.MotionEvent;
45 
46 import javax.microedition.khronos.egl.EGL10;
47 import javax.microedition.khronos.egl.EGLConfig;
48 import javax.microedition.khronos.opengles.GL;
49 import javax.microedition.khronos.opengles.GL10;
50 import javax.microedition.khronos.opengles.GL11;
51 /**
52  * An implementation of SurfaceView that uses the dedicated surface for
53  * displaying an OpenGL animation.  This allows the animation to run in a
54  * separate thread, without requiring that it be driven by the update mechanism
55  * of the view hierarchy.
56  *
57  * The application-specific rendering code is delegated to a GLView.Renderer
58  * instance.
59  */
60 class TestView extends GLSurfaceView {
TestView(Context context)61     TestView(Context context) {
62         super(context);
63         init();
64     }
65 
TestView(Context context, AttributeSet attrs)66     public TestView(Context context, AttributeSet attrs) {
67         super(context, attrs);
68         init();
69     }
70 
init()71     private void init() {
72         setRenderer(new Renderer());
73         setRenderMode(RENDERMODE_WHEN_DIRTY);
74     }
75 
76         /** A grid is a topologically rectangular array of vertices.
77     *
78     * The vertex and index data are held in VBO objects because on most
79     * GPUs VBO objects are the fastest way of rendering static vertex
80     * and index data.
81     *
82     */
83 
84    private static class Grid {
85        // Size of vertex data elements in bytes:
86        final static int FLOAT_SIZE = 4;
87        final static int CHAR_SIZE = 2;
88 
89        // Vertex structure:
90        // float x, y, z;
91 
92        final static int VERTEX_SIZE = 3 * FLOAT_SIZE;
93 
94        private int mVertexBufferObjectId;
95        private int mElementBufferObjectId;
96 
97        // These buffers are used to hold the vertex and index data while
98        // constructing the grid. Once createBufferObjects() is called
99        // the buffers are nulled out to save memory.
100 
101        private ByteBuffer mVertexByteBuffer;
102        private FloatBuffer mVertexBuffer;
103        private CharBuffer mIndexBuffer;
104 
105        private int mW;
106        private int mH;
107        private int mIndexCount;
108 
Grid(int w, int h)109        public Grid(int w, int h) {
110            if (w < 0 || w >= 65536) {
111                throw new IllegalArgumentException("w");
112            }
113            if (h < 0 || h >= 65536) {
114                throw new IllegalArgumentException("h");
115            }
116            if (w * h >= 65536) {
117                throw new IllegalArgumentException("w * h >= 65536");
118            }
119 
120            mW = w;
121            mH = h;
122            int size = w * h;
123 
124            mVertexByteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * size)
125                .order(ByteOrder.nativeOrder());
126            mVertexBuffer = mVertexByteBuffer.asFloatBuffer();
127 
128            int quadW = mW - 1;
129            int quadH = mH - 1;
130            int quadCount = quadW * quadH;
131            int indexCount = quadCount * 6;
132            mIndexCount = indexCount;
133            mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount)
134                .order(ByteOrder.nativeOrder()).asCharBuffer();
135 
136            /*
137             * Initialize triangle list mesh.
138             *
139             *     [0]-----[  1] ...
140             *      |    /   |
141             *      |   /    |
142             *      |  /     |
143             *     [w]-----[w+1] ...
144             *      |       |
145             *
146             */
147 
148            {
149                int i = 0;
150                for (int y = 0; y < quadH; y++) {
151                    for (int x = 0; x < quadW; x++) {
152                        char a = (char) (y * mW + x);
153                        char b = (char) (y * mW + x + 1);
154                        char c = (char) ((y + 1) * mW + x);
155                        char d = (char) ((y + 1) * mW + x + 1);
156 
157                        mIndexBuffer.put(i++, a);
158                        mIndexBuffer.put(i++, c);
159                        mIndexBuffer.put(i++, b);
160 
161                        mIndexBuffer.put(i++, b);
162                        mIndexBuffer.put(i++, c);
163                        mIndexBuffer.put(i++, d);
164                    }
165                }
166            }
167 
168        }
169 
set(int i, int j, float x, float y, float z)170        public void set(int i, int j, float x, float y, float z) {
171            if (i < 0 || i >= mW) {
172                throw new IllegalArgumentException("i");
173            }
174            if (j < 0 || j >= mH) {
175                throw new IllegalArgumentException("j");
176            }
177 
178            int index = mW * j + i;
179 
180            mVertexBuffer.position(index * VERTEX_SIZE / FLOAT_SIZE);
181            mVertexBuffer.put(x);
182            mVertexBuffer.put(y);
183            mVertexBuffer.put(z);
184        }
185 
createBufferObjects(GL gl)186        public void createBufferObjects(GL gl) {
187            // Generate a the vertex and element buffer IDs
188            int[] vboIds = new int[2];
189            GL11 gl11 = (GL11) gl;
190            gl11.glGenBuffers(2, vboIds, 0);
191            mVertexBufferObjectId = vboIds[0];
192            mElementBufferObjectId = vboIds[1];
193 
194            // Upload the vertex data
195            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId);
196            mVertexByteBuffer.position(0);
197            gl11.glBufferData(GL11.GL_ARRAY_BUFFER, mVertexByteBuffer.capacity(), mVertexByteBuffer, GL11.GL_STATIC_DRAW);
198 
199            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId);
200            mIndexBuffer.position(0);
201            gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer.capacity() * CHAR_SIZE, mIndexBuffer, GL11.GL_STATIC_DRAW);
202 
203            // We don't need the in-memory data any more
204            mVertexBuffer = null;
205            mVertexByteBuffer = null;
206            mIndexBuffer = null;
207        }
208 
draw(GL10 gl)209        public void draw(GL10 gl) {
210            GL11 gl11 = (GL11) gl;
211 
212            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
213 
214            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId);
215            gl11.glVertexPointer(3, GL10.GL_FLOAT, VERTEX_SIZE, 0);
216 
217            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId);
218            gl11.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, 0);
219            gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
220            gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
221            gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
222        }
223    }
224 
225 
226     private class Renderer implements GLSurfaceView.Renderer {
227         private static final String TAG = "Renderer";
228         private Grid mGrid;
229 
onDrawFrame(GL10 gl)230         public void onDrawFrame(GL10 gl) {
231 			gl.glClearColor(0,0,1,1);
232 			gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
233             mGrid.draw(gl);
234         }
235 
onSurfaceChanged(GL10 gl, int width, int height)236         public void onSurfaceChanged(GL10 gl, int width, int height) {
237             gl.glViewport(0, 0, width, height);
238 			gl.glMatrixMode(GL11.GL_PROJECTION);
239 			gl.glLoadIdentity();
240 			gl.glOrthof(0, width, height, 0, -1, 1);
241 			gl.glMatrixMode(GL11.GL_MODELVIEW);
242             createGrid(gl, width, height);
243         }
244 
onSurfaceCreated(GL10 gl, EGLConfig config)245         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
246         }
247 
createGrid(GL10 gl, float w, float h)248         private void createGrid(GL10 gl, float w, float h) {
249         mGrid = new Grid(2, 2);
250 			for (int j = 0; j < 2; j++) {
251 				for (int i = 0; i < 2; i++) {
252 					float x = w * i;
253 					float y = h * j;
254 					float z = 0.0f;
255 					mGrid.set(i,j, x, y, z);
256 				}
257 			}
258 			mGrid.createBufferObjects(gl);
259 		}
260     }
261 }
262 
263