MyGLSurfaceView.java revision 3bbd3bb7fcb082eba313614f072c11c41b38ebfe
1b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten/* 2b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Copyright (C) 2011 The Android Open Source Project 3b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 4b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * you may not use this file except in compliance with the License. 6b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * You may obtain a copy of the License at 7b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 8b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * 10b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * See the License for the specific language governing permissions and 14b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * limitations under the License. 15b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 16b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 17b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenpackage com.example.nativemedia; 18b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 19b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.graphics.SurfaceTexture; 20b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.util.Log; 21b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 22b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.ByteBuffer; 23b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.ByteOrder; 24b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.nio.FloatBuffer; 25b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 26b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport javax.microedition.khronos.egl.EGLConfig; 27b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport javax.microedition.khronos.opengles.GL10; 28b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 29b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.view.MotionEvent; 30b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.content.Context; 31b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 32b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.GLES20; 33b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.GLSurfaceView; 34b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.opengl.Matrix; 35b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 36b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorManager; 37b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorEvent; 38b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.SensorEventListener; 39b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.hardware.Sensor; 40b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 41b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten// Remove once surfacetexture timestamps are in 42b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport java.lang.System; 43b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 44b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenimport android.util.AttributeSet; 45b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 46b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenpublic class MyGLSurfaceView extends GLSurfaceView implements SensorEventListener { 47b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 48b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public MyGLSurfaceView(Context context, AttributeSet attributeSet) { 49b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super(context, attributeSet); 50b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten init(context); 51b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 52b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 53b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public MyGLSurfaceView(Context context) { 54b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super(context); 55b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten init(context); 56b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 57b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 58b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private void init(Context context) { 59b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten setEGLContextClientVersion(2); 60b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRenderer = new MyRenderer(context); 61b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten setRenderer(mRenderer); 62b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 63b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); 64b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mAcceleration = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); 65b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 66b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 67b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public boolean onTouchEvent(final MotionEvent event) { 68b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten queueEvent(new Runnable(){ 69b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void run() { 70b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRenderer.setPosition(event.getX() / getWidth(), 71b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten event.getY() / getHeight()); 72b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten }}); 73b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return true; 74b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 75b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 76b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten @Override 77b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onPause() { 78b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super.onPause(); 79b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 80b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSensorManager.unregisterListener(this); 81b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 82b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 83b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten @Override 84b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onResume() { 85b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 86b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten queueEvent(new Runnable() { 87b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void run() { 88b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten }}); 89b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 90b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSensorManager.registerListener(this, mAcceleration, SensorManager.SENSOR_DELAY_GAME); 91b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten super.onResume(); 92b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 93b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 94b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onSensorChanged(SensorEvent event) { 95b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) { 96b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten final float[] accelerationVector = event.values; 97b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten queueEvent(new Runnable(){ 98b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void run() { 99b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRenderer.setAcceleration(accelerationVector); 100b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten }}); 101b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 102b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 103b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 104b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onAccuracyChanged(Sensor sensor, int accuracy) { 105b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignoring sensor accuracy changes. 106b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 107b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 108b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten MyRenderer mRenderer; 109b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 110b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten SensorManager mSensorManager; 111b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Sensor mAcceleration; 112b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 113b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public SurfaceTexture getSurfaceTexture() 114b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten { 115b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return mRenderer.getSurfaceTexture(); 116b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 117b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 118b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten} 119b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 120b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kastenclass MyRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 121b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 122b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public MyRenderer(Context context) { 123b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 124b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mContext = context; 125b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 126b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length 127b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 128b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTriangleVertices.put(mTriangleVerticesData).position(0); 129b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 130b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setIdentityM(mSTMatrix, 0); 131b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setIdentityM(mMMatrix, 0); 132b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 133b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float[] defaultAcceleration = {0.f,0.f,0.f}; 134b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten setAcceleration(defaultAcceleration); 135b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[0] = 0.f; 136b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[1] = 0.f; 137b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[2] = 0.f; 138b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[0] = 0.f; 139b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[1] = 0.f; 140b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[2] = 0.f; 141b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 142b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 143b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 144b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* The following set methods are not synchronized, so should only 145b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * be called within the rendering thread context. Use GLSurfaceView.queueEvent for safe access. 146b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 147b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void setPosition(float x, float y) { 148b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Map from screen (0,0)-(1,1) to scene coordinates */ 149b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[0] = (x*2-1)*mRatio; 150b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[1] = (-y)*2+1; 151b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[2] = 0.f; 152b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[0] = 0; 153b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[1] = 0; 154b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[2] = 0; 155b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 156b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 157b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void setAcceleration(float[] accelerationVector) { 158b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mGForce[0] = accelerationVector[0]; 159b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mGForce[1] = accelerationVector[1]; 160b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mGForce[2] = accelerationVector[2]; 161b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 162b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 163b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onDrawFrame(GL10 glUnused) { 164b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized(this) { 165b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (updateSurface) { 166b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.updateTexImage(); 167b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 168b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.getTransformMatrix(mSTMatrix); 169b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Until timestamp support gets in (very soon) 170b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten //long timestamp = mSurface.getTimestamp(); 171b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten long timestamp = System.nanoTime(); 172b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten doPhysics(timestamp); 173b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 174b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = false; 175b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 176b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 177b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 178b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 179b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 180b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 181b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUseProgram(mProgram); 182b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glUseProgram"); 183b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 184b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 185b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID); 186b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 187b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 188b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 189b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 190b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glVertexAttribPointer maPosition"); 191b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnableVertexAttribArray(maPositionHandle); 192b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glEnableVertexAttribArray maPositionHandle"); 193b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 194b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 195b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glVertexAttribPointer(maTextureHandle, 3, GLES20.GL_FLOAT, false, 196b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 197b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glVertexAttribPointer maTextureHandle"); 198b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnableVertexAttribArray(maTextureHandle); 199b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glEnableVertexAttribArray maTextureHandle"); 200b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 201b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 202b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 203b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 204b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 205b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0); 206b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glUniform1f(muCRatioHandle, mMediaPlayerRatio); 207b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 208b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 209b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glDrawArrays"); 210b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 211b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 212b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onSurfaceChanged(GL10 glUnused, int width, int height) { 213b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 214b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 215b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glViewport(0, 0, width, height); 216b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mRatio = (float) width / height; 217b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.frustumM(mProjMatrix, 0, -mRatio, mRatio, -1, 1, 3, 7); 218b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 219b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 220b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 221b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Ignore the passed-in GL10 interface, and use the GLES20 222b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // class's static methods instead. 223b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 224b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Set up alpha blending and an Android background color */ 225b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glEnable(GLES20.GL_BLEND); 226b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); 227b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glClearColor(0.643f, 0.776f, 0.223f, 1.0f); 228b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 229b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Set up shaders and handles to their variables */ 230b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mProgram = createProgram(mVertexShader, mFragmentShader); 231b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (mProgram == 0) { 232b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return; 233b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 234b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 235b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetAttribLocation aPosition"); 236b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (maPositionHandle == -1) { 237b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for aPosition"); 238b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 239b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 240b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetAttribLocation aTextureCoord"); 241b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (maTextureHandle == -1) { 242b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for aTextureCoord"); 243b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 244b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 245b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 246b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uMVPMatrix"); 247b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 248b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 249b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 250b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 251b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix"); 252b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uSTMatrix"); 253b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 254b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uSTMatrix"); 255b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 256b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 257b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten muCRatioHandle = GLES20.glGetUniformLocation(mProgram, "uCRatio"); 258b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glGetUniformLocation uCRatio"); 259b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (muMVPMatrixHandle == -1) { 260b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException("Could not get attrib location for uCRatio"); 261b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 262b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 263b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* 264b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Create our texture. This has to be done each time the 265b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * surface is created. 266b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 267b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 268b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] textures = new int[1]; 269b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGenTextures(1, textures, 0); 270b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 271b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mTextureID = textures[0]; 272b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID); 273b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glBindTexture mTextureID"); 274b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 275b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Can't do mipmapping with camera source 276b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, 277b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_NEAREST); 278b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameterf(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, 279b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_LINEAR); 280b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Clamp to edge is the only option 281b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, 282b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_CLAMP_TO_EDGE); 283b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, 284b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.GL_CLAMP_TO_EDGE); 285b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glTexParameteri mTextureID"); 286b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 287b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* 288b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Create the SurfaceTexture that will feed this textureID, and pass it to the camera 289b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 290b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 291b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface = new SurfaceTexture(mTextureID); 292b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mSurface.setOnFrameAvailableListener(this); 293b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 294b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setLookAtM(mVMatrix, 0, 0, 0, 5f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 295b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 296b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mLastTime = 0; 297b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 298b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized(this) { 299b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = false; 300b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 301b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 302b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 303b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten synchronized public void onFrameAvailable(SurfaceTexture surface) { 304b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* For simplicity, SurfaceTexture calls here when it has new 305b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * data available. Call may come in from some random thread, 306b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * so let's be safe and use synchronize. No OpenGL calls can be done here. 307b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 308b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten updateSurface = true; 3093bbd3bb7fcb082eba313614f072c11c41b38ebfeGlenn Kasten //Log.v(TAG, "onFrameAvailable " + surface.getTimestamp()); 310b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 311b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 312b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private void doPhysics(long timestamp) { 313b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* 314b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten * Move the camera surface around based on some simple spring physics with drag 315b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten */ 316b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 317b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (mLastTime == 0) 318b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mLastTime = timestamp; 319b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 320b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float deltaT = (timestamp - mLastTime)/1000000000.f; // To seconds 321b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 322b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float springStrength = 20.f; 323b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float frictionCoeff = 10.f; 324b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float mass = 10.f; 325b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float gMultiplier = 4.f; 326b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Only update physics every 30 ms */ 327b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (deltaT > 0.030f) { 328b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mLastTime = timestamp; 329b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 330b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float[] totalForce = new float[3]; 331b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten totalForce[0] = -mPos[0] * springStrength - mVel[0]*frictionCoeff + gMultiplier*mGForce[0]*mass; 332b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten totalForce[1] = -mPos[1] * springStrength - mVel[1]*frictionCoeff + gMultiplier*mGForce[1]*mass; 333b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten totalForce[2] = -mPos[2] * springStrength - mVel[2]*frictionCoeff + gMultiplier*mGForce[2]*mass; 334b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 335b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten float[] accel = new float[3]; 336b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten accel[0] = totalForce[0]/mass; 337b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten accel[1] = totalForce[1]/mass; 338b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten accel[2] = totalForce[2]/mass; 339b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 340b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten /* Not a very accurate integrator */ 341b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[0] = mVel[0] + accel[0]*deltaT; 342b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[1] = mVel[1] + accel[1]*deltaT; 343b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mVel[2] = mVel[2] + accel[2]*deltaT; 344b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 345b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[0] = mPos[0] + mVel[0]*deltaT; 346b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[1] = mPos[1] + mVel[1]*deltaT; 347b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten mPos[2] = mPos[2] + mVel[2]*deltaT; 348b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 349b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.setIdentityM(mMMatrix, 0); 350b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Matrix.translateM(mMMatrix, 0, mPos[0], mPos[1], mPos[2]); 351b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 352b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 353b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 354b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 355b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int loadShader(int shaderType, String source) { 356b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int shader = GLES20.glCreateShader(shaderType); 357b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (shader != 0) { 358b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glShaderSource(shader, source); 359b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glCompileShader(shader); 360b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] compiled = new int[1]; 361b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 362b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (compiled[0] == 0) { 363b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, "Could not compile shader " + shaderType + ":"); 364b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 365b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDeleteShader(shader); 366b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten shader = 0; 367b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 368b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 369b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return shader; 370b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 371b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 372b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int createProgram(String vertexSource, String fragmentSource) { 373b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 374b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (vertexShader == 0) { 375b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return 0; 376b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 377b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 378b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (pixelShader == 0) { 379b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return 0; 380b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 381b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 382b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int program = GLES20.glCreateProgram(); 383b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (program != 0) { 384b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glAttachShader(program, vertexShader); 385b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glAttachShader"); 386b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glAttachShader(program, pixelShader); 387b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten checkGlError("glAttachShader"); 388b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glLinkProgram(program); 389b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int[] linkStatus = new int[1]; 390b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 391b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten if (linkStatus[0] != GLES20.GL_TRUE) { 392b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, "Could not link program: "); 393b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 394b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten GLES20.glDeleteProgram(program); 395b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten program = 0; 396b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 397b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 398b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return program; 399b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 400b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 401b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private void checkGlError(String op) { 402b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten int error; 403b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 404b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten Log.e(TAG, op + ": glError " + error); 405b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten throw new RuntimeException(op + ": glError " + error); 406b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 407b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 408b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 409b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int FLOAT_SIZE_BYTES = 4; 410b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 411b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 412b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 413b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private final float[] mTriangleVerticesData = { 414b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // X, Y, Z, U, V 415b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten -1.0f, -1.0f, 0, 0.f, 0.f, 416b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 1.0f, -1.0f, 0, 1.f, 0.f, 417b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten -1.0f, 1.0f, 0, 0.f, 1.f, 418b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 1.0f, 1.0f, 0, 1.f, 1.f, 419b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten }; 420b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 421b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private FloatBuffer mTriangleVertices; 422b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 423b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private final String mVertexShader = 424b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform mat4 uMVPMatrix;\n" + 425b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform mat4 uSTMatrix;\n" + 426b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform float uCRatio;\n" + 427b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "attribute vec4 aPosition;\n" + 428b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "attribute vec4 aTextureCoord;\n" + 429b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureCoord;\n" + 430b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureNormCoord;\n" + 431b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "void main() {\n" + 432b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " vec4 scaledPos = aPosition;\n" + 433b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " scaledPos.x = scaledPos.x * uCRatio;\n" + 434b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " gl_Position = uMVPMatrix * scaledPos;\n" + 435b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + 436b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " vTextureNormCoord = aTextureCoord.xy;\n" + 437b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "}\n"; 438b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 439b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private final String mFragmentShader = 440b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "#extension GL_OES_EGL_image_external : require\n" + 441b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "precision mediump float;\n" + 442b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureCoord;\n" + 443b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "varying vec2 vTextureNormCoord;\n" + 444b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "uniform samplerExternalOES sTexture;\n" + 445b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "void main() {\n" + 446b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + 447b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten " gl_FragColor.a = 1.0-min(length(vTextureNormCoord-0.5)*2.0,1.0);\n" + 448b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten "}\n"; 449b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 450b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mMVPMatrix = new float[16]; 451b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mProjMatrix = new float[16]; 452b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mMMatrix = new float[16]; 453b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mVMatrix = new float[16]; 454b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mSTMatrix = new float[16]; 455b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 456b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int mProgram; 457b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int mTextureID; 458b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int muMVPMatrixHandle; 459b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int muSTMatrixHandle; 460b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int muCRatioHandle; 461b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int maPositionHandle; 462b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private int maTextureHandle; 463b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 464b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float mRatio = 1.0f; 465b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float mMediaPlayerRatio = 1.0f; 466b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mVel = new float[3]; 467b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mPos = new float[3]; 468b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private float[] mGForce = new float[3]; 469b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 470b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private long mLastTime; 471b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 472b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private SurfaceTexture mSurface; 473b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private boolean updateSurface = false; 474b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 475b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private Context mContext; 476b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final String TAG = "MyRenderer"; 477b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 478b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten // Magic key 479b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten private static final int GL_TEXTURE_EXTERNAL_OES = 0x8D65; 480b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 481b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten public SurfaceTexture getSurfaceTexture() 482b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten { 483b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten return mSurface; 484b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten } 485b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten 486b66b0745d45f4c0c7620749185f7fb3306804ce3Glenn Kasten} 487