1 /* 2 * Copyright (C) 2011 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.android.modelviewer; 18 19 import android.renderscript.Matrix4f; 20 import android.renderscript.RSSurfaceView; 21 import android.renderscript.RenderScriptGL; 22 23 import android.content.Context; 24 import android.hardware.Sensor; 25 import android.hardware.SensorEvent; 26 import android.hardware.SensorEventListener; 27 import android.hardware.SensorManager; 28 import android.view.MotionEvent; 29 import android.view.SurfaceHolder; 30 import android.view.ScaleGestureDetector; 31 import android.util.Log; 32 33 public class SimpleModelView extends RSSurfaceView implements SensorEventListener { 34 35 private RenderScriptGL mRS; 36 private SimpleModelRS mRender; 37 38 private ScaleGestureDetector mScaleDetector; 39 40 private SensorManager mSensorManager; 41 private Sensor mRotationVectorSensor; 42 private final float[] mRotationMatrix = new float[16]; 43 44 private static final int INVALID_POINTER_ID = -1; 45 private int mActivePointerId = INVALID_POINTER_ID; 46 private boolean mUseSensor = false; 47 private Matrix4f mIdentityMatrix = new Matrix4f(); 48 49 public SimpleModelView(Context context) { 50 super(context); 51 ensureRenderScript(); 52 mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 53 // Get an instance of the SensorManager 54 mSensorManager = (SensorManager)getContext().getSystemService(Context.SENSOR_SERVICE); 55 // find the rotation-vector sensor 56 mRotationVectorSensor = mSensorManager.getDefaultSensor( 57 Sensor.TYPE_ROTATION_VECTOR); 58 mIdentityMatrix.loadIdentity(); 59 } 60 61 private void ensureRenderScript() { 62 if (mRS == null) { 63 RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); 64 sc.setDepth(16, 24); 65 mRS = createRenderScriptGL(sc); 66 mRender = new SimpleModelRS(); 67 mRender.init(mRS, getResources()); 68 } 69 } 70 71 @Override 72 public void resume() { 73 mSensorManager.registerListener(this, mRotationVectorSensor, 10000); 74 } 75 76 @Override 77 public void pause() { 78 mSensorManager.unregisterListener(this); 79 } 80 81 @Override 82 protected void onAttachedToWindow() { 83 super.onAttachedToWindow(); 84 ensureRenderScript(); 85 } 86 87 @Override 88 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 89 super.surfaceChanged(holder, format, w, h); 90 mRender.surfaceChanged(); 91 } 92 93 @Override 94 protected void onDetachedFromWindow() { 95 mRender = null; 96 if (mRS != null) { 97 mRS = null; 98 destroyRenderScriptGL(); 99 } 100 } 101 102 public void loadA3DFile(String path) { 103 mRender.loadA3DFile(path); 104 } 105 106 @Override 107 public boolean onTouchEvent(MotionEvent ev) { 108 mScaleDetector.onTouchEvent(ev); 109 110 boolean ret = false; 111 float x = ev.getX(); 112 float y = ev.getY(); 113 114 final int action = ev.getAction(); 115 116 switch (action & MotionEvent.ACTION_MASK) { 117 case MotionEvent.ACTION_DOWN: { 118 mRender.onActionDown(x, y); 119 mActivePointerId = ev.getPointerId(0); 120 ret = true; 121 break; 122 } 123 case MotionEvent.ACTION_MOVE: { 124 if (!mScaleDetector.isInProgress()) { 125 mRender.onActionMove(x, y); 126 } 127 mRender.onActionDown(x, y); 128 ret = true; 129 break; 130 } 131 132 case MotionEvent.ACTION_UP: { 133 mActivePointerId = INVALID_POINTER_ID; 134 break; 135 } 136 137 case MotionEvent.ACTION_CANCEL: { 138 mActivePointerId = INVALID_POINTER_ID; 139 break; 140 } 141 142 case MotionEvent.ACTION_POINTER_UP: { 143 final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 144 >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 145 final int pointerId = ev.getPointerId(pointerIndex); 146 if (pointerId == mActivePointerId) { 147 // This was our active pointer going up. Choose a new 148 // active pointer and adjust accordingly. 149 final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 150 x = ev.getX(newPointerIndex); 151 y = ev.getY(newPointerIndex); 152 mRender.onActionDown(x, y); 153 mActivePointerId = ev.getPointerId(newPointerIndex); 154 } 155 break; 156 } 157 } 158 159 return ret; 160 } 161 162 private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 163 @Override 164 public boolean onScale(ScaleGestureDetector detector) { 165 mRender.onActionScale(detector.getScaleFactor()); 166 return true; 167 } 168 } 169 170 public void onSensorChanged(SensorEvent event) { 171 // we received a sensor event. it is a good practice to check 172 // that we received the proper event 173 if (mUseSensor) { 174 if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { 175 // convert the rotation-vector to a 4x4 matrix. the matrix 176 // is interpreted by Open GL as the inverse of the 177 // rotation-vector, which is what we want. 178 SensorManager.getRotationMatrixFromVector( 179 mRotationMatrix , event.values); 180 181 if (mRender != null) { 182 mRender.onPostureChanged(new Matrix4f(mRotationMatrix)); 183 } 184 } 185 } 186 } 187 188 public void onAccuracyChanged(Sensor sensor, int accuracy) { 189 } 190 191 public void toggleSensor() { 192 mUseSensor = !mUseSensor; 193 if (mUseSensor == false) { 194 mRender.onPostureChanged(mIdentityMatrix); 195 } 196 } 197 } 198