1f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen/* 2f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Copyright (C) 2011 The Android Open Source Project 3f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 4f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 5f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * you may not use this file except in compliance with the License. 6f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * You may obtain a copy of the License at 7f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 8f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 9f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * 10f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Unless required by applicable law or agreed to in writing, software 11f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 12f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * See the License for the specific language governing permissions and 14f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * limitations under the License. 15f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen */ 16f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 17f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 18b82d80d891077ccd74729e4143925a66eb89eef2Andres Moralespackage com.android.nfc.beam; 19f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 20f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.content.Context; 21f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.graphics.Bitmap; 22f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.graphics.BitmapFactory; 23f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.graphics.SurfaceTexture; 24f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.opengl.GLUtils; 25f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenimport android.util.Log; 26f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 27018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.io.IOException; 28018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.io.InputStream; 29018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.nio.ByteBuffer; 30018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.nio.ByteOrder; 31018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.nio.FloatBuffer; 32018e05b5f55cd444835e8dd751b30eaaccd2c9ffAndres Moralesimport java.nio.ShortBuffer; 33f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 3465ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.egl.EGL10; 3565ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.egl.EGLConfig; 3665ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.egl.EGLContext; 3765ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.egl.EGLDisplay; 3865ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.egl.EGLSurface; 3965ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Moralesimport javax.microedition.khronos.opengles.GL10; 4065ba8d0d2adb1d1994a0c40d11e28d9ca85f50d9Andres Morales 41f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenenpublic class FireflyRenderer { 42f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private static final String LOG_TAG = "NfcFireflyThread"; 43f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 44f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final int NUM_FIREFLIES = 200; 45f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 46f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float NEAR_CLIPPING_PLANE = 50f; 47f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float FAR_CLIPPING_PLANE = 100f; 48f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 49f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // All final variables below only need to be allocated once 50f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // and can be reused between subsequent Beams 51f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final int[] sEglConfig = { 52f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_RED_SIZE, 8, 53f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_GREEN_SIZE, 8, 54f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_BLUE_SIZE, 8, 55f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_ALPHA_SIZE, 0, 56f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_DEPTH_SIZE, 0, 57f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_STENCIL_SIZE, 0, 58f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_NONE 59f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen }; 60f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 61f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Vertices for drawing a 32x32 rect 62f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float mVertices[] = { 63f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 0.0f, 0.0f, 0.0f, // 0, Top Left 64f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 0.0f, 32.0f, 0.0f, // 1, Bottom Left 65f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 32.0f, 32.0f, 0.0f, // 2, Bottom Right 66f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 32.0f, 0.0f, 0.0f, // 3, Top Right 67f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen }; 68f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 69f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Mapping coordinates for the texture 70f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float mTextCoords[] = { 71f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 0.0f, 0.0f, 72f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 1.0f, 0.0f, 73f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 1.0f, 1.0f, 74f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 0.0f, 1.0f 75f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen }; 76f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 77f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Connecting order (draws a square) 78f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final short[] mIndices = { 0, 1, 2, 0, 2, 3 }; 79f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 80f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen final Context mContext; 81f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 82f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Buffer holding the vertices 83f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen final FloatBuffer mVertexBuffer; 84f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 85f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Buffer holding the indices 86f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen final ShortBuffer mIndexBuffer; 87f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 88f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Buffer holding the texture mapping coordinates 89f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen final FloatBuffer mTextureBuffer; 90f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 91f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen final Firefly[] mFireflies; 92f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 93f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen FireflyRenderThread mFireflyRenderThread; 94f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 95f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // The surface to render the flies on, including width and height 96f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen SurfaceTexture mSurface; 97f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mDisplayWidth; 98f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mDisplayHeight; 99f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 100f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public FireflyRenderer(Context context) { 101f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mContext = context; 102f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 103f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // First, build the vertex, texture and index buffers 104f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen ByteBuffer vbb = ByteBuffer.allocateDirect(mVertices.length * 4); // Float => 4 bytes 105f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen vbb.order(ByteOrder.nativeOrder()); 106f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mVertexBuffer = vbb.asFloatBuffer(); 107f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mVertexBuffer.put(mVertices); 108f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mVertexBuffer.position(0); 109f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 110f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen ByteBuffer ibb = ByteBuffer.allocateDirect(mIndices.length * 2); // Short => 2 bytes 111f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen ibb.order(ByteOrder.nativeOrder()); 112f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mIndexBuffer = ibb.asShortBuffer(); 113f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mIndexBuffer.put(mIndices); 114f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mIndexBuffer.position(0); 115f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 116f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen ByteBuffer tbb = ByteBuffer.allocateDirect(mTextCoords.length * 4); 117f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen tbb.order(ByteOrder.nativeOrder()); 118f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mTextureBuffer = tbb.asFloatBuffer(); 119f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mTextureBuffer.put(mTextCoords); 120f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mTextureBuffer.position(0); 121f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 122f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflies = new Firefly[NUM_FIREFLIES]; 123f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen for (int i = 0; i < NUM_FIREFLIES; i++) { 124f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflies[i] = new Firefly(); 125f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 126f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 127f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 128f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen /** 129f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Starts rendering fireflies on the given surface. 130f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Must be called from the UI-thread. 131f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen */ 132f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void start(SurfaceTexture surface, int width, int height) { 133f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mSurface = surface; 134f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mDisplayWidth = width; 135f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mDisplayHeight = height; 136f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 137f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderThread = new FireflyRenderThread(); 138f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderThread.start(); 139f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 140f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 141f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen /** 142f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Stops rendering fireflies. 143f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen * Must be called from the UI-thread. 144f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen */ 145f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void stop() { 146f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mFireflyRenderThread != null) { 147f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderThread.finish(); 148f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen try { 149f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderThread.join(); 150f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } catch (InterruptedException e) { 151f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "Couldn't wait for FireflyRenderThread."); 152f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 153f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFireflyRenderThread = null; 154f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 155f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 156f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 157f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private class FireflyRenderThread extends Thread { 158f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10 mEgl; 159f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGLDisplay mEglDisplay; 160f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGLConfig mEglConfig; 161f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGLContext mEglContext; 162f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGLSurface mEglSurface; 163f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GL10 mGL; 164f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 165f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Holding the handle to the texture 166f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int mTextureId; 167f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 168f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Read/written by multiple threads 169f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen volatile boolean mFinished; 170f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 171f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen @Override 172f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void run() { 173f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!initGL()) { 174f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "Failed to initialize OpenGL."); 175f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return; 176f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 177f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen loadStarTexture(); 178f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 179f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 180f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 181f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glViewport(0, 0, mDisplayWidth, mDisplayHeight); 182f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 183f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // make adjustments for screen ratio 184f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glMatrixMode(GL10.GL_PROJECTION); 185f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glLoadIdentity(); 186f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glFrustumf(-mDisplayWidth, mDisplayWidth, mDisplayHeight, -mDisplayHeight, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE); 187f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 188f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Switch back to modelview 189f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glMatrixMode(GL10.GL_MODELVIEW); 190f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glLoadIdentity(); 191f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 192f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 193f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glDepthMask(true); 194f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 195f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 196f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen for (Firefly firefly : mFireflies) { 197f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen firefly.reset(); 198f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 199f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 200f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen for (int i = 0; i < 3; i++) { 201f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Call eglSwapBuffers 3 times - this will allocate the necessary 202f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // buffers, and make sure the animation looks smooth from the start. 203525c260303268a83da4c3413b953d13c9084e834The Android Open Source Project mGL.glClear(GL10.GL_COLOR_BUFFER_BIT); 204f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 205f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "Could not swap buffers"); 206f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFinished = true; 207f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 208f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 209f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 210f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen long startTime = System.currentTimeMillis(); 211f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 212f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen while (!mFinished) { 213f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen long timeElapsedMs = System.currentTimeMillis() - startTime; 214f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen startTime = System.currentTimeMillis(); 215f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 216f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen checkCurrent(); 217f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 218f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glClear(GL10.GL_COLOR_BUFFER_BIT); 219f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glLoadIdentity(); 220f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 221f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glEnable(GL10.GL_TEXTURE_2D); 222f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glEnable(GL10.GL_BLEND); 223f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); 224f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 225f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen for (Firefly firefly : mFireflies) { 226f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen firefly.updatePositionAndScale(timeElapsedMs); 227f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen firefly.draw(mGL); 228f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 229f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 230f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { 231f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "Could not swap buffers"); 232f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFinished = true; 233f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 234f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 235f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen long elapsed = System.currentTimeMillis() - startTime; 236f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen try { 237f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Thread.sleep(Math.max(30 - elapsed, 0)); 238f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } catch (InterruptedException e) { 239f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 240f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 241f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 242f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen finishGL(); 243f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 244f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 245f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void finish() { 246f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mFinished = true; 247f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 248f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 249f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen void loadStarTexture() { 250f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int[] textureIds = new int[1]; 251f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glGenTextures(1, textureIds, 0); 252f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mTextureId = textureIds[0]; 253f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 254f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen InputStream in = null; 255f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen try { 256f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Remember that both texture dimensions must be a power of 2! 257f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen in = mContext.getAssets().open("star.png"); 258f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 259f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Bitmap bitmap = BitmapFactory.decodeStream(in); 260f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glBindTexture(GL10.GL_TEXTURE_2D, mTextureId); 261f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 262f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); 263f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 264f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 265f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); 266f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 267f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen bitmap.recycle(); 268f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 269f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } catch (IOException e) { 270f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "IOException opening assets."); 271f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } finally { 272f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (in != null) { 273f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen try { 274f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen in.close(); 275f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } catch (IOException e) { } 276f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 277f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 278f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 279f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 280f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private void checkCurrent() { 281f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEglContext.equals(mEgl.eglGetCurrentContext()) || 282f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) { 283f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 284f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen throw new RuntimeException("eglMakeCurrent failed " 285f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen + GLUtils.getEGLErrorString(mEgl.eglGetError())); 286f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 287f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 288f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 289f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 290f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen boolean initGL() { 291f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Initialize openGL engine 292f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEgl = (EGL10) EGLContext.getEGL(); 293f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 294f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); 295f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { 296f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "eglGetDisplay failed " + 297f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GLUtils.getEGLErrorString(mEgl.eglGetError())); 298f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return false; 299f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 300f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 301f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int[] version = new int[2]; 302f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglInitialize(mEglDisplay, version)) { 303f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "eglInitialize failed " + 304f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GLUtils.getEGLErrorString(mEgl.eglGetError())); 305f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return false; 306f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 307f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 308f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEglConfig = chooseEglConfig(); 309f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEglConfig == null) { 310f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "eglConfig not initialized."); 311f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return false; 312f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 313f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 314f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, null); 315f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 316f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null); 317f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 318f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { 319f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int error = mEgl.eglGetError(); 320f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG,"createWindowSurface returned error " + Integer.toString(error)); 321f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return false; 322f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 323f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 324f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { 325f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen Log.e(LOG_TAG, "eglMakeCurrent failed " + 326f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GLUtils.getEGLErrorString(mEgl.eglGetError())); 327f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return false; 328f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 329f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 330f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mGL = (GL10) mEglContext.getGL(); 331f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 332f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return true; 333f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 334f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 335f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private void finishGL() { 336f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEgl == null || mEglDisplay == null) { 337f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Nothing to free 338f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return; 339f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 340f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Unbind the current surface and context from the display 341f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, 342f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGL10.EGL_NO_CONTEXT); 343f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 344f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEglSurface != null) { 345f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEgl.eglDestroySurface(mEglDisplay, mEglSurface); 346f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 347f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 348f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (mEglContext != null) { 349f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mEgl.eglDestroyContext(mEglDisplay, mEglContext); 350f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 351f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 352f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 353f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private EGLConfig chooseEglConfig() { 354f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen int[] configsCount = new int[1]; 355f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen EGLConfig[] configs = new EGLConfig[1]; 356f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if (!mEgl.eglChooseConfig(mEglDisplay, sEglConfig, configs, 1, configsCount)) { 357f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen throw new IllegalArgumentException("eglChooseConfig failed " + 358f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen GLUtils.getEGLErrorString(mEgl.eglGetError())); 359f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } else if (configsCount[0] > 0) { 360f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return configs[0]; 361f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 362f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen return null; 363f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 364f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 365f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 366f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen private class Firefly { 367f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float TEXTURE_HEIGHT = 30f; // TODO use measurement of texture size 368f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen static final float SPEED = .5f; 369f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 370f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mX; // between -mDisplayHeight and mDisplayHeight 371f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mY; // between -mDisplayWidth and mDisplayWidth 372f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mZ; // between 0.0 (near) and 1.0 (far) 373f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mZ0; 374f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mT; 375f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mScale; 376f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen float mAlpha; 377f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 378f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public Firefly() { 379f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 380f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 381f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen void reset() { 382f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mX = (float) (Math.random() * mDisplayWidth) * 4 - 2 * mDisplayWidth; 383f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mY = (float) (Math.random() * mDisplayHeight) * 4 - 2 * mDisplayHeight; 384f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mZ0 = mZ = (float) (Math.random()) * 2 - 1; 385f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mT = 0f; 386f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mScale = 1.5f; 387f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mAlpha = 0f; 388f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 389f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 390f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void updatePositionAndScale(long timeElapsedMs) { 391f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mT += timeElapsedMs; 392f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mZ = mZ0 + mT/1000f * SPEED; 393f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mAlpha = 1f-mZ; 394f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen if(mZ > 1.0) reset(); 395f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 396f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 397f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen public void draw(GL10 gl) { 398f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glLoadIdentity(); 399f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 400f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // Counter clockwise winding 401f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glFrontFace(GL10.GL_CCW); 402f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 403f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 404f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 405f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 406f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); 407f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer); 408f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 409f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glTranslatef(mX, mY, -NEAR_CLIPPING_PLANE-mZ*(FAR_CLIPPING_PLANE-NEAR_CLIPPING_PLANE)); 410f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glColor4f(1, 1, 1, mAlpha); 411f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 412f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen // scale around center 413f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glTranslatef(TEXTURE_HEIGHT/2, TEXTURE_HEIGHT/2, 0); 414f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glScalef(mScale, mScale, 0); 415f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glTranslatef(-TEXTURE_HEIGHT/2, -TEXTURE_HEIGHT/2, 0); 416f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 417f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glDrawElements(GL10.GL_TRIANGLES, mIndices.length, GL10.GL_UNSIGNED_SHORT, 418f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen mIndexBuffer); 419f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen 420f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glColor4f(1, 1, 1, 1); 421f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 422f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 423f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 424f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen } 425f570dca6b0fa0ce883f5c950815e43acae4f51b2Martijn Coenen} 426