1 /* 2 * Copyright (C) 2008 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.example.android.apis.graphics; 18 19 import javax.microedition.khronos.egl.EGLConfig; 20 import javax.microedition.khronos.opengles.GL10; 21 22 import android.app.Activity; 23 import android.content.Context; 24 import android.opengl.GLSurfaceView; 25 import android.os.Bundle; 26 import android.view.MotionEvent; 27 28 /** 29 * Wrapper activity demonstrating the use of {@link GLSurfaceView}, a view 30 * that uses OpenGL drawing into a dedicated surface. 31 * 32 * Shows: 33 * + How to redraw in response to user input. 34 */ 35 public class TouchRotateActivity extends Activity { 36 @Override onCreate(Bundle savedInstanceState)37 protected void onCreate(Bundle savedInstanceState) { 38 super.onCreate(savedInstanceState); 39 40 // Create our Preview view and set it as the content of our 41 // Activity 42 mGLSurfaceView = new TouchSurfaceView(this); 43 setContentView(mGLSurfaceView); 44 mGLSurfaceView.requestFocus(); 45 mGLSurfaceView.setFocusableInTouchMode(true); 46 } 47 48 @Override onResume()49 protected void onResume() { 50 // Ideally a game should implement onResume() and onPause() 51 // to take appropriate action when the activity looses focus 52 super.onResume(); 53 mGLSurfaceView.onResume(); 54 } 55 56 @Override onPause()57 protected void onPause() { 58 // Ideally a game should implement onResume() and onPause() 59 // to take appropriate action when the activity looses focus 60 super.onPause(); 61 mGLSurfaceView.onPause(); 62 } 63 64 private GLSurfaceView mGLSurfaceView; 65 } 66 67 /** 68 * Implement a simple rotation control. 69 * 70 */ 71 class TouchSurfaceView extends GLSurfaceView { 72 TouchSurfaceView(Context context)73 public TouchSurfaceView(Context context) { 74 super(context); 75 mRenderer = new CubeRenderer(); 76 setRenderer(mRenderer); 77 setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); 78 } 79 onTrackballEvent(MotionEvent e)80 @Override public boolean onTrackballEvent(MotionEvent e) { 81 mRenderer.mAngleX += e.getX() * TRACKBALL_SCALE_FACTOR; 82 mRenderer.mAngleY += e.getY() * TRACKBALL_SCALE_FACTOR; 83 requestRender(); 84 return true; 85 } 86 onTouchEvent(MotionEvent e)87 @Override public boolean onTouchEvent(MotionEvent e) { 88 float x = e.getX(); 89 float y = e.getY(); 90 switch (e.getAction()) { 91 case MotionEvent.ACTION_MOVE: 92 float dx = x - mPreviousX; 93 float dy = y - mPreviousY; 94 mRenderer.mAngleX += dx * TOUCH_SCALE_FACTOR; 95 mRenderer.mAngleY += dy * TOUCH_SCALE_FACTOR; 96 requestRender(); 97 } 98 mPreviousX = x; 99 mPreviousY = y; 100 return true; 101 } 102 103 /** 104 * Render a cube. 105 */ 106 private class CubeRenderer implements GLSurfaceView.Renderer { CubeRenderer()107 public CubeRenderer() { 108 mCube = new Cube(); 109 } 110 onDrawFrame(GL10 gl)111 public void onDrawFrame(GL10 gl) { 112 /* 113 * Usually, the first thing one might want to do is to clear 114 * the screen. The most efficient way of doing this is to use 115 * glClear(). 116 */ 117 118 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); 119 120 /* 121 * Now we're ready to draw some 3D objects 122 */ 123 124 gl.glMatrixMode(GL10.GL_MODELVIEW); 125 gl.glLoadIdentity(); 126 gl.glTranslatef(0, 0, -3.0f); 127 gl.glRotatef(mAngleX, 0, 1, 0); 128 gl.glRotatef(mAngleY, 1, 0, 0); 129 130 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 131 gl.glEnableClientState(GL10.GL_COLOR_ARRAY); 132 133 mCube.draw(gl); 134 } 135 onSurfaceChanged(GL10 gl, int width, int height)136 public void onSurfaceChanged(GL10 gl, int width, int height) { 137 gl.glViewport(0, 0, width, height); 138 139 /* 140 * Set our projection matrix. This doesn't have to be done 141 * each time we draw, but usually a new projection needs to 142 * be set when the viewport is resized. 143 */ 144 145 float ratio = (float) width / height; 146 gl.glMatrixMode(GL10.GL_PROJECTION); 147 gl.glLoadIdentity(); 148 gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); 149 } 150 onSurfaceCreated(GL10 gl, EGLConfig config)151 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 152 /* 153 * By default, OpenGL enables features that improve quality 154 * but reduce performance. One might want to tweak that 155 * especially on software renderer. 156 */ 157 gl.glDisable(GL10.GL_DITHER); 158 159 /* 160 * Some one-time OpenGL initialization can be made here 161 * probably based on features of this particular context 162 */ 163 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, 164 GL10.GL_FASTEST); 165 166 167 gl.glClearColor(1,1,1,1); 168 gl.glEnable(GL10.GL_CULL_FACE); 169 gl.glShadeModel(GL10.GL_SMOOTH); 170 gl.glEnable(GL10.GL_DEPTH_TEST); 171 } 172 private Cube mCube; 173 public float mAngleX; 174 public float mAngleY; 175 } 176 177 private final float TOUCH_SCALE_FACTOR = 180.0f / 320; 178 private final float TRACKBALL_SCALE_FACTOR = 36.0f; 179 private CubeRenderer mRenderer; 180 private float mPreviousX; 181 private float mPreviousY; 182 } 183 184 185