From d6e9c61294d19d5dd3d812de6b08127cf7b0ce94 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Tue, 23 Nov 2010 01:05:13 -0800 Subject: [PATCH] Add an API demo showcasing the new rotation vector sensor Change-Id: I3f00560b0340db31779259aa98efc174b0b645cd --- samples/ApiDemos/AndroidManifest.xml | 7 + .../android/apis/os/RotationVectorDemo.java | 216 ++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.java diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index 6e39538fa..e9acbb485 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -671,6 +671,13 @@ + + + + + + + diff --git a/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.java b/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.java new file mode 100644 index 000000000..74178091d --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/os/RotationVectorDemo.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.android.apis.os; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; +import android.app.Activity; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.opengl.GLSurfaceView; +import android.os.Bundle; + +/** + * Wrapper activity demonstrating the use of the new + * {@link SensorEvent#values rotation vector sensor} + * ({@link Sensor#TYPE_ROTATION_VECTOR TYPE_ROTATION_VECTOR}). + * + * @see Sensor + * @see SensorEvent + * @see SensorManager + * + */ +public class RotationVectorDemo extends Activity { + private GLSurfaceView mGLSurfaceView; + private SensorManager mSensorManager; + private MyRenderer mRenderer; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Get an instance of the SensorManager + mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); + + // Create our Preview view and set it as the content of our + // Activity + mRenderer = new MyRenderer(); + mGLSurfaceView = new GLSurfaceView(this); + mGLSurfaceView.setRenderer(mRenderer); + setContentView(mGLSurfaceView); + } + + @Override + protected void onResume() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onResume(); + mRenderer.start(); + mGLSurfaceView.onResume(); + } + + @Override + protected void onPause() { + // Ideally a game should implement onResume() and onPause() + // to take appropriate action when the activity looses focus + super.onPause(); + mRenderer.stop(); + mGLSurfaceView.onPause(); + } + + + class MyRenderer implements GLSurfaceView.Renderer, SensorEventListener { + private Cube mCube; + private Sensor mRotationVectorSensor; + private final float[] mRotationMatrix = new float[16]; + + public MyRenderer() { + // find the rotation-vector sensor + mRotationVectorSensor = mSensorManager.getDefaultSensor( + Sensor.TYPE_ROTATION_VECTOR); + + mCube = new Cube(); + // initialize the rotation matrix to identity + mRotationMatrix[ 0] = 1; + mRotationMatrix[ 4] = 1; + mRotationMatrix[ 8] = 1; + mRotationMatrix[12] = 1; + } + + public void start() { + // enable our sensor when the activity is resumed, ask for + // 10 ms updates. + mSensorManager.registerListener(this, mRotationVectorSensor, 10000); + } + + public void stop() { + // make sure to turn our sensor off when the activity is paused + mSensorManager.unregisterListener(this); + } + + public void onSensorChanged(SensorEvent event) { + // we received a sensor event. it is a good practice to check + // that we received the proper event + if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { + // convert the rotation-vector to a 4x4 matrix. the matrix + // is interpreted by Open GL as the inverse of the + // rotation-vector, which is what we want. + SensorManager.getRotationMatrixFromVector( + mRotationMatrix , event.values); + } + } + + public void onDrawFrame(GL10 gl) { + // clear screen + gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + + // set-up modelview matrix + gl.glMatrixMode(GL10.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glTranslatef(0, 0, -3.0f); + gl.glMultMatrixf(mRotationMatrix, 0); + + // draw our object + gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); + gl.glEnableClientState(GL10.GL_COLOR_ARRAY); + + mCube.draw(gl); + } + + public void onSurfaceChanged(GL10 gl, int width, int height) { + // set view-port + gl.glViewport(0, 0, width, height); + // set projection matrix + float ratio = (float) width / height; + gl.glMatrixMode(GL10.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10); + } + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + // dither is enabled by default, we don't need it + gl.glDisable(GL10.GL_DITHER); + // clear screen in white + gl.glClearColor(1,1,1,1); + } + + class Cube { + // initialize our cube + private FloatBuffer mVertexBuffer; + private FloatBuffer mColorBuffer; + private ByteBuffer mIndexBuffer; + + public Cube() { + final float vertices[] = { + -1, -1, -1, 1, -1, -1, + 1, 1, -1, -1, 1, -1, + -1, -1, 1, 1, -1, 1, + 1, 1, 1, -1, 1, 1, + }; + + final float colors[] = { + 0, 0, 0, 1, 1, 0, 0, 1, + 1, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 0, 1, 1, 1, + }; + + final byte indices[] = { + 0, 4, 5, 0, 5, 1, + 1, 5, 6, 1, 6, 2, + 2, 6, 7, 2, 7, 3, + 3, 7, 4, 3, 4, 0, + 4, 7, 6, 4, 6, 5, + 3, 0, 1, 3, 1, 2 + }; + + ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); + vbb.order(ByteOrder.nativeOrder()); + mVertexBuffer = vbb.asFloatBuffer(); + mVertexBuffer.put(vertices); + mVertexBuffer.position(0); + + ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4); + cbb.order(ByteOrder.nativeOrder()); + mColorBuffer = cbb.asFloatBuffer(); + mColorBuffer.put(colors); + mColorBuffer.position(0); + + mIndexBuffer = ByteBuffer.allocateDirect(indices.length); + mIndexBuffer.put(indices); + mIndexBuffer.position(0); + } + + public void draw(GL10 gl) { + gl.glEnable(GL10.GL_CULL_FACE); + gl.glFrontFace(GL10.GL_CW); + gl.glShadeModel(GL10.GL_SMOOTH); + gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); + gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer); + gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer); + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) { + } + } +}