OSDN Git Service

original
[gb-231r1-is01/GB_2.3_IS01.git] / cts / apps / CtsVerifier / src / com / android / cts / verifier / sensors / AccelerometerTestRenderer.java
diff --git a/cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestRenderer.java b/cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestRenderer.java
new file mode 100644 (file)
index 0000000..b6c3a6e
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2010 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.android.cts.verifier.sensors;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+
+import com.android.cts.verifier.R;
+
+public class AccelerometerTestRenderer implements GLSurfaceView.Renderer, SensorEventListener {
+
+    /**
+     * A representation of a 3D triangular wedge or arrowhead shape, suitable
+     * for pointing a direction.
+     */
+    private static class Wedge {
+        private final static int VERTS = 6;
+
+        /**
+         * Storage for the vertices.
+         */
+        private FloatBuffer mFVertexBuffer;
+
+        /**
+         * Storage for the drawing sequence of the vertices. This contains
+         * integer indices into the mFVertextBuffer structure.
+         */
+        private ShortBuffer mIndexBuffer;
+
+        /**
+         * Storage for the texture used on the surface of the wedge.
+         */
+        private FloatBuffer mTexBuffer;
+
+        public Wedge() {
+            // Buffers to be passed to gl*Pointer() functions
+            // must be direct & use native ordering
+
+            ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 6 * 4);
+            vbb.order(ByteOrder.nativeOrder());
+            mFVertexBuffer = vbb.asFloatBuffer();
+
+            ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
+            tbb.order(ByteOrder.nativeOrder());
+            mTexBuffer = tbb.asFloatBuffer();
+
+            ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 8 * 2);
+            ibb.order(ByteOrder.nativeOrder());
+            mIndexBuffer = ibb.asShortBuffer();
+
+            /**
+             * Coordinates of the vertices making up a simple wedge. Six total
+             * vertices, representing two isosceles triangles, side by side,
+             * centered on the origin separated by 0.25 units, with elongated
+             * ends pointing down the negative Z axis.
+             */
+            float[] coords = {
+                    // X, Y, Z
+                    -0.125f, -0.25f, -0.25f,
+                    -0.125f,  0.25f, -0.25f,
+                    -0.125f,  0.0f,   0.559016994f,
+                     0.125f, -0.25f, -0.25f,
+                     0.125f,  0.25f, -0.25f,
+                     0.125f,  0.0f,   0.559016994f,
+            };
+
+            for (int i = 0; i < VERTS; i++) {
+                for (int j = 0; j < 3; j++) {
+                    mFVertexBuffer.put(coords[i * 3 + j] * 2.0f);
+                }
+            }
+
+            for (int i = 0; i < VERTS; i++) {
+                for (int j = 0; j < 2; j++) {
+                    mTexBuffer.put(coords[i * 3 + j] * 2.0f + 0.5f);
+                }
+            }
+
+            // left face
+            mIndexBuffer.put((short) 0);
+            mIndexBuffer.put((short) 1);
+            mIndexBuffer.put((short) 2);
+
+            // right face
+            mIndexBuffer.put((short) 5);
+            mIndexBuffer.put((short) 4);
+            mIndexBuffer.put((short) 3);
+
+            // top side, 2 triangles to make rect
+            mIndexBuffer.put((short) 2);
+            mIndexBuffer.put((short) 5);
+            mIndexBuffer.put((short) 3);
+            mIndexBuffer.put((short) 3);
+            mIndexBuffer.put((short) 0);
+            mIndexBuffer.put((short) 2);
+
+            // bottom side, 2 triangles to make rect
+            mIndexBuffer.put((short) 5);
+            mIndexBuffer.put((short) 2);
+            mIndexBuffer.put((short) 1);
+            mIndexBuffer.put((short) 1);
+            mIndexBuffer.put((short) 4);
+            mIndexBuffer.put((short) 5);
+
+            // base, 2 triangles to make rect
+            mIndexBuffer.put((short) 0);
+            mIndexBuffer.put((short) 3);
+            mIndexBuffer.put((short) 4);
+            mIndexBuffer.put((short) 4);
+            mIndexBuffer.put((short) 1);
+            mIndexBuffer.put((short) 0);
+
+            mFVertexBuffer.position(0);
+            mTexBuffer.position(0);
+            mIndexBuffer.position(0);
+        }
+
+        public void draw(GL10 gl) {
+            gl.glFrontFace(GL10.GL_CCW);
+            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
+            gl.glEnable(GL10.GL_TEXTURE_2D);
+            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
+            gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+        }
+    }
+
+    /**
+     * A representation of the Z-axis in vector form.
+     */
+    protected static final float[] Z_AXIS = new float[] {
+            0, 0, 1
+    };
+
+    /**
+     * Computes the cross product of two vectors, storing the resulting
+     * pseudovector in out. All arrays must be length 3 or more, and out is
+     * overwritten.
+     * 
+     * @param left the left operand of the cross product
+     * @param right the right operand of the cross product
+     * @param out the array into which to store the cross-product pseudovector's
+     *            data
+     */
+    public static void crossProduct(float[] left, float[] right, float[] out) {
+        out[0] = left[1] * right[2] - left[2] * right[1];
+        out[1] = left[2] * right[0] - left[0] * right[2];
+        out[2] = left[0] * right[1] - left[1] * right[0];
+    }
+
+    /**
+     * Computes the dot product of two vectors.
+     * 
+     * @param left the first dot product operand
+     * @param right the second dot product operand
+     * @return the dot product of left and right
+     */
+    public static float dotProduct(float[] left, float[] right) {
+        return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
+    }
+
+    /**
+     * Normalizes the input vector into a unit vector.
+     * 
+     * @param vector the vector to normalize. Contents are overwritten.
+     */
+    public static void normalize(float[] vector) {
+        double mag = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2]
+                * vector[2]);
+        vector[0] /= mag;
+        vector[1] /= mag;
+        vector[2] /= mag;
+    }
+
+    /**
+     * The angle around mCrossProd to rotate to align Z-axis with gravity.
+     */
+    protected float mAngle;
+
+    private Context mContext;
+
+    /**
+     * The (pseudo)vector around which to rotate to align Z-axis with gravity.
+     */
+    protected float[] mCrossProd = new float[3];
+
+    private int mTextureID;
+
+    private Wedge mWedge;
+
+    /**
+     * It's a constructor. Can you dig it?
+     * 
+     * @param context the Android Context that owns this renderer
+     */
+    public AccelerometerTestRenderer(Context context) {
+        mContext = context;
+        mWedge = new Wedge();
+    }
+
+    public void onAccuracyChanged(Sensor arg0, int arg1) {
+        // no-op
+    }
+
+    /**
+     * Actually draws the wedge.
+     */
+    public void onDrawFrame(GL10 gl) {
+        // set up the texture for drawing
+        gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+        gl.glActiveTexture(GL10.GL_TEXTURE0);
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
+        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
+
+        // clear the screen and draw
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        gl.glRotatef(-mAngle * 180 / (float) Math.PI, mCrossProd[0], mCrossProd[1], mCrossProd[2]);
+        mWedge.draw(gl);
+    }
+
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+            /*
+             * For this test we want *only* accelerometer data, so we can't use
+             * the convenience methods on SensorManager; so compute manually.
+             */
+            normalize(event.values);
+
+            /*
+             * Because we need to invert gravity (because the accelerometer vector
+             * actually points up), that constitutes a 180-degree rotation around X,
+             * which means we need to invert Y.
+             */
+            event.values[1] *= -1;
+
+            crossProduct(event.values, Z_AXIS, mCrossProd);
+            mAngle = (float) Math.acos(dotProduct(event.values, Z_AXIS));
+        }
+    }
+
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
+        gl.glViewport(0, 0, w, h);
+        float ratio = (float) w / h;
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
+        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+    }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        // set up general OpenGL config
+        gl.glClearColor(0.6f, 0f, 0.4f, 1); // a nice purpley magenta
+        gl.glShadeModel(GL10.GL_SMOOTH);
+        gl.glEnable(GL10.GL_DEPTH_TEST);
+        gl.glEnable(GL10.GL_TEXTURE_2D);
+
+        // create the texture we use on the wedge
+        int[] textures = new int[1];
+        gl.glGenTextures(1, textures, 0);
+        mTextureID = textures[0];
+        
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
+        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
+
+        InputStream is = mContext.getResources().openRawResource(R.raw.sns_texture);
+        Bitmap bitmap;
+        try {
+            bitmap = BitmapFactory.decodeStream(is);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException e) {
+                // Ignore.
+            }
+        }
+
+        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
+        bitmap.recycle();
+    }
+}