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
17package com.example.android.apis.os;
18
19import java.nio.ByteBuffer;
20import java.nio.ByteOrder;
21import java.nio.FloatBuffer;
22import javax.microedition.khronos.egl.EGLConfig;
23import javax.microedition.khronos.opengles.GL10;
24import android.app.Activity;
25import android.hardware.Sensor;
26import android.hardware.SensorEvent;
27import android.hardware.SensorEventListener;
28import android.hardware.SensorManager;
29import android.opengl.GLSurfaceView;
30import 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 */
42public class RotationVectorDemo extends Activity {
43    private GLSurfaceView mGLSurfaceView;
44    private SensorManager mSensorManager;
45    private MyRenderer mRenderer;
46
47    @Override
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
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
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
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
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
105        public void stop() {
106            // make sure to turn our sensor off when the activity is paused
107            mSensorManager.unregisterListener(this);
108        }
109
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
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
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
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
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
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
213        public void onAccuracyChanged(Sensor sensor, int accuracy) {
214        }
215    }
216}
217