1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.app; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.content.Context; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.hardware.Sensor; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.hardware.SensorEvent; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.hardware.SensorEventListener; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.hardware.SensorManager; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.os.SystemClock; 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.view.Display; 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.view.Surface; 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport android.view.WindowManager; 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 292b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.common.Utils; 302b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Linimport com.android.gallery3d.util.GalleryUtils; 312b3ee0ea07246b859a5b75d8a6102a7cce7ec838Owen Lin 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class EyePosition { 337817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final String TAG = "EyePosition"; 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public interface EyePositionListener { 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onEyePositionChanged(float x, float y, float z); 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final float GYROSCOPE_THRESHOLD = 0.15f; 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final float GYROSCOPE_LIMIT = 10f; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int GYROSCOPE_SETTLE_DOWN = 15; 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final float GYROSCOPE_RESTORE_FACTOR = 0.995f; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 45fd91413ab46e2960803a33652025aebe3e05f2d9Chih-Chung Chang private static final float USER_ANGEL = (float) Math.toRadians(10); 468a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller private static final float USER_ANGEL_COS = (float) Math.cos(USER_ANGEL); 478a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller private static final float USER_ANGEL_SIN = (float) Math.sin(USER_ANGEL); 488a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller private static final float MAX_VIEW_RANGE = 0.5f; 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final int NOT_STARTED = -1; 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static final float USER_DISTANCE_METER = 0.3f; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Context mContext; 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private EyePositionListener mListener; 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Display mDisplay; 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // The eyes' position of the user, the origin is at the center of the 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin // device and the unit is in pixels. 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private float mX; 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private float mY; 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private float mZ; 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final float mUserDistance; // in pixel 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final float mLimit; 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private long mStartTime = NOT_STARTED; 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private Sensor mSensor; 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private PositionListener mPositionListener = new PositionListener(); 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private int mGyroscopeCountdown = 0; 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public EyePosition(Context context, EyePositionListener listener) { 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mContext = context; 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener = listener; 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mLimit = mUserDistance * MAX_VIEW_RANGE; 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin WindowManager wManager = (WindowManager) mContext 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin .getSystemService(Context.WINDOW_SERVICE); 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mDisplay = wManager.getDefaultDisplay(); 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 80fd06154c0d51fd8686ffec3955e54f5c18e87da0Chih-Chung Chang // The 3D effect where the photo albums fan out in 3D based on angle 81fd06154c0d51fd8686ffec3955e54f5c18e87da0Chih-Chung Chang // of device tilt is currently disabled. 82fd06154c0d51fd8686ffec3955e54f5c18e87da0Chih-Chung Chang/* 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin SensorManager sManager = (SensorManager) mContext 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin .getSystemService(Context.SENSOR_SERVICE); 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSensor = sManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSensor == null) { 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "no gyroscope, use accelerometer instead"); 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSensor == null) { 91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Log.w(TAG, "no sensor available"); 92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 93fd06154c0d51fd8686ffec3955e54f5c18e87da0Chih-Chung Chang*/ 94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 95f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 96f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resetPosition() { 97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mStartTime = NOT_STARTED; 98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mX = mY = 0; 99f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mZ = -mUserDistance; 100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener.onEyePositionChanged(mX, mY, mZ); 101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin /* 104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * We assume the user is at the following position 105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * /|\ user's eye 107f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * | / 108f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * -G(gravity) | / 109f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * |_/ 110f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * / |/_____\ -Y (-y direction of device) 111f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * user angel 112f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 113f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void onAccelerometerChanged(float gx, float gy, float gz) { 114f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 115f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float x = gx, y = gy, z = gz; 116f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 117f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (mDisplay.getRotation()) { 118f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_90: x = -gy; y= gx; break; 119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_180: x = -gx; y = -gy; break; 120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_270: x = gy; y = -gx; break; 121f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 122f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 123f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float temp = x * x + y * y + z * z; 124f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float t = -y /temp; 125f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float tx = t * x; 127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float ty = -1 + t * y; 128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float tz = t * z; 129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1308a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller float length = (float) Math.sqrt(tx * tx + ty * ty + tz * tz); 1318a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller float glength = (float) Math.sqrt(temp); 132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mX = Utils.clamp((x * USER_ANGEL_COS / glength 134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin + tx * USER_ANGEL_SIN / length) * mUserDistance, 135f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin -mLimit, mLimit); 136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mY = -Utils.clamp((y * USER_ANGEL_COS / glength 137f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin + ty * USER_ANGEL_SIN / length) * mUserDistance, 138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin -mLimit, mLimit); 1398a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller mZ = (float) -Math.sqrt( 140f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUserDistance * mUserDistance - mX * mX - mY * mY); 141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener.onEyePositionChanged(mX, mY, mZ); 142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void onGyroscopeChanged(float gx, float gy, float gz) { 145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin long now = SystemClock.elapsedRealtime(); 146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float distance = (gx > 0 ? gx : -gx) + (gy > 0 ? gy : - gy); 147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (distance < GYROSCOPE_THRESHOLD 148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin || distance > GYROSCOPE_LIMIT || mGyroscopeCountdown > 0) { 149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin --mGyroscopeCountdown; 150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mStartTime = now; 151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float limit = mUserDistance / 20f; 152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mX > limit || mX < -limit || mY > limit || mY < -limit) { 153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mX *= GYROSCOPE_RESTORE_FACTOR; 154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mY *= GYROSCOPE_RESTORE_FACTOR; 155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mZ = (float) -Math.sqrt( 156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUserDistance * mUserDistance - mX * mX - mY * mY); 157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener.onEyePositionChanged(mX, mY, mZ); 158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return; 160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float t = (now - mStartTime) / 1000f * mUserDistance * (-mZ); 163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mStartTime = now; 164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin float x = -gy, y = -gx; 166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (mDisplay.getRotation()) { 167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_90: x = -gx; y= gy; break; 168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_180: x = gy; y = gx; break; 169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Surface.ROTATION_270: x = gx; y = -gy; break; 170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mX = Utils.clamp((float) (mX + x * t / Math.hypot(mZ, mX)), 173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; 174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mY = Utils.clamp((float) (mY + y * t / Math.hypot(mZ, mY)), 175f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; 176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1778a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller mZ = (float) -Math.sqrt( 178f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mUserDistance * mUserDistance - mX * mX - mY * mY); 179f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener.onEyePositionChanged(mX, mY, mZ); 180f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private class PositionListener implements SensorEventListener { 1837817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onAccuracyChanged(Sensor sensor, int accuracy) { 185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 186f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 1877817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @Override 188f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void onSensorChanged(SensorEvent event) { 189f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin switch (event.sensor.getType()) { 190f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Sensor.TYPE_GYROSCOPE: { 191f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin onGyroscopeChanged( 192f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin event.values[0], event.values[1], event.values[2]); 193f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin break; 194f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 195f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin case Sensor.TYPE_ACCELEROMETER: { 196f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin onAccelerometerChanged( 197f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin event.values[0], event.values[1], event.values[2]); 198f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 199f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 200f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 201f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 202f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 203f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void pause() { 204f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSensor != null) { 205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin SensorManager sManager = (SensorManager) mContext 206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin .getSystemService(Context.SENSOR_SERVICE); 207f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sManager.unregisterListener(mPositionListener); 208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 209f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 210f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 211f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public void resume() { 212f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (mSensor != null) { 213f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin SensorManager sManager = (SensorManager) mContext 214f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin .getSystemService(Context.SENSOR_SERVICE); 215f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin sManager.registerListener(mPositionListener, 216f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mSensor, SensorManager.SENSOR_DELAY_GAME); 217f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 218f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 219f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mStartTime = NOT_STARTED; 220f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mGyroscopeCountdown = GYROSCOPE_SETTLE_DOWN; 221f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mX = mY = 0; 222f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mZ = -mUserDistance; 223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mListener.onEyePositionChanged(mX, mY, mZ); 224f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 225f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 226