1 /*
2  * Copyright (C) 2007 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.os;
18 
19 import java.nio.ByteBuffer;
20 import java.nio.ByteOrder;
21 import java.nio.FloatBuffer;
22 import javax.microedition.khronos.egl.EGLConfig;
23 import javax.microedition.khronos.opengles.GL10;
24 import android.app.Activity;
25 import android.hardware.Sensor;
26 import android.hardware.SensorEvent;
27 import android.hardware.SensorEventListener;
28 import android.hardware.SensorManager;
29 import android.opengl.GLSurfaceView;
30 import android.os.Bundle;
31 
32 /**
33  * Wrapper activity demonstrating the use of the new
34  * {@link SensorEvent#values rotation vector sensor}
35  * ({@link Sensor#TYPE_ROTATION_VECTOR TYPE_ROTATION_VECTOR}).
36  *
37  * @see Sensor
38  * @see SensorEvent
39  * @see SensorManager
40  *
41  */
42 public class RotationVectorDemo extends Activity {
43     private GLSurfaceView mGLSurfaceView;
44     private SensorManager mSensorManager;
45     private MyRenderer mRenderer;
46 
47     @Override
onCreate(Bundle savedInstanceState)48     protected void onCreate(Bundle savedInstanceState) {
49         super.onCreate(savedInstanceState);
50 
51         // Get an instance of the SensorManager
52         mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
53 
54         // Create our Preview view and set it as the content of our
55         // Activity
56         mRenderer = new MyRenderer();
57         mGLSurfaceView = new GLSurfaceView(this);
58         mGLSurfaceView.setRenderer(mRenderer);
59         setContentView(mGLSurfaceView);
60     }
61 
62     @Override
onResume()63     protected void onResume() {
64         // Ideally a game should implement onResume() and onPause()
65         // to take appropriate action when the activity looses focus
66         super.onResume();
67         mRenderer.start();
68         mGLSurfaceView.onResume();
69     }
70 
71     @Override
onPause()72     protected void onPause() {
73         // Ideally a game should implement onResume() and onPause()
74         // to take appropriate action when the activity looses focus
75         super.onPause();
76         mRenderer.stop();
77         mGLSurfaceView.onPause();
78     }
79 
80 
81     class MyRenderer implements GLSurfaceView.Renderer, SensorEventListener {
82         private Cube mCube;
83         private Sensor mRotationVectorSensor;
84         private final float[] mRotationMatrix = new float[16];
85 
MyRenderer()86         public MyRenderer() {
87             // find the rotation-vector sensor
88             mRotationVectorSensor = mSensorManager.getDefaultSensor(
89                     Sensor.TYPE_ROTATION_VECTOR);
90 
91             mCube = new Cube();
92             // initialize the rotation matrix to identity
93             mRotationMatrix[ 0] = 1;
94             mRotationMatrix[ 4] = 1;
95             mRotationMatrix[ 8] = 1;
96             mRotationMatrix[12] = 1;
97         }
98 
start()99         public void start() {
100             // enable our sensor when the activity is resumed, ask for
101             // 10 ms updates.
102             mSensorManager.registerListener(this, mRotationVectorSensor, 10000);
103         }
104 
stop()105         public void stop() {
106             // make sure to turn our sensor off when the activity is paused
107             mSensorManager.unregisterListener(this);
108         }
109 
onSensorChanged(SensorEvent event)110         public void onSensorChanged(SensorEvent event) {
111             // we received a sensor event. it is a good practice to check
112             // that we received the proper event
113             if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
114                 // convert the rotation-vector to a 4x4 matrix. the matrix
115                 // is interpreted by Open GL as the inverse of the
116                 // rotation-vector, which is what we want.
117                 SensorManager.getRotationMatrixFromVector(
118                         mRotationMatrix , event.values);
119             }
120         }
121 
onDrawFrame(GL10 gl)122         public void onDrawFrame(GL10 gl) {
123             // clear screen
124             gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
125 
126             // set-up modelview matrix
127             gl.glMatrixMode(GL10.GL_MODELVIEW);
128             gl.glLoadIdentity();
129             gl.glTranslatef(0, 0, -3.0f);
130             gl.glMultMatrixf(mRotationMatrix, 0);
131 
132             // draw our object
133             gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
134             gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
135 
136             mCube.draw(gl);
137         }
138 
onSurfaceChanged(GL10 gl, int width, int height)139         public void onSurfaceChanged(GL10 gl, int width, int height) {
140             // set view-port
141             gl.glViewport(0, 0, width, height);
142             // set projection matrix
143             float ratio = (float) width / height;
144             gl.glMatrixMode(GL10.GL_PROJECTION);
145             gl.glLoadIdentity();
146             gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
147         }
148 
onSurfaceCreated(GL10 gl, EGLConfig config)149         public void onSurfaceCreated(GL10 gl, EGLConfig config) {
150             // dither is enabled by default, we don't need it
151             gl.glDisable(GL10.GL_DITHER);
152             // clear screen in white
153             gl.glClearColor(1,1,1,1);
154         }
155 
156         class Cube {
157             // initialize our cube
158             private FloatBuffer mVertexBuffer;
159             private FloatBuffer mColorBuffer;
160             private ByteBuffer  mIndexBuffer;
161 
Cube()162             public Cube() {
163                 final float vertices[] = {
164                         -1, -1, -1,		 1, -1, -1,
165                          1,  1, -1,	    -1,  1, -1,
166                         -1, -1,  1,      1, -1,  1,
167                          1,  1,  1,     -1,  1,  1,
168                 };
169 
170                 final float colors[] = {
171                         0,  0,  0,  1,  1,  0,  0,  1,
172                         1,  1,  0,  1,  0,  1,  0,  1,
173                         0,  0,  1,  1,  1,  0,  1,  1,
174                         1,  1,  1,  1,  0,  1,  1,  1,
175                 };
176 
177                 final byte indices[] = {
178                         0, 4, 5,    0, 5, 1,
179                         1, 5, 6,    1, 6, 2,
180                         2, 6, 7,    2, 7, 3,
181                         3, 7, 4,    3, 4, 0,
182                         4, 7, 6,    4, 6, 5,
183                         3, 0, 1,    3, 1, 2
184                 };
185 
186                 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
187                 vbb.order(ByteOrder.nativeOrder());
188                 mVertexBuffer = vbb.asFloatBuffer();
189                 mVertexBuffer.put(vertices);
190                 mVertexBuffer.position(0);
191 
192                 ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
193                 cbb.order(ByteOrder.nativeOrder());
194                 mColorBuffer = cbb.asFloatBuffer();
195                 mColorBuffer.put(colors);
196                 mColorBuffer.position(0);
197 
198                 mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
199                 mIndexBuffer.put(indices);
200                 mIndexBuffer.position(0);
201             }
202 
draw(GL10 gl)203             public void draw(GL10 gl) {
204                 gl.glEnable(GL10.GL_CULL_FACE);
205                 gl.glFrontFace(GL10.GL_CW);
206                 gl.glShadeModel(GL10.GL_SMOOTH);
207                 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
208                 gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
209                 gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
210             }
211         }
212 
onAccuracyChanged(Sensor sensor, int accuracy)213         public void onAccuracyChanged(Sensor sensor, int accuracy) {
214         }
215     }
216 }
217