From 292b56f26fb713e513245b36e58b0459cd15fa43 Mon Sep 17 00:00:00 2001 From: Boulay Mathias Date: Tue, 28 Feb 2023 22:58:52 +0100 Subject: [PATCH] Feat[Gyro]: Use sensor fusion implementation (#3998) * Feat[Gyro]: Use sensor fusion implementation * Fix: Remove time factor It is pointless when mesuring an absolute rotation, since regardless how big the difference in timing is, we can get the same difference * Handle ORIENTATION_UNKNOWN * Cleanup unused timestamp saving code * Fix[Gyro]: inverted factors on edges I watch out for the screen surface rotation now * Fix[Gyro]: update rotation factors only on non unknown cases * Fix[gyro]: portrait factors on landscape upon start --------- Co-authored-by: artdeell --- .../java/net/kdt/pojavlaunch/GyroControl.java | 61 ++++++++++++------- .../prefs/LauncherPreferences.java | 2 +- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GyroControl.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GyroControl.java index f35f369ef..ce8b41e3e 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GyroControl.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/GyroControl.java @@ -1,31 +1,40 @@ package net.kdt.pojavlaunch; +import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.view.OrientationEventListener; +import android.view.WindowManager; import net.kdt.pojavlaunch.prefs.LauncherPreferences; import org.lwjgl.glfw.CallbackBridge; public class GyroControl implements SensorEventListener, GrabListener{ + private final WindowManager mWindowManager; + private int mSurfaceRotation; private final SensorManager mSensorManager; private final Sensor mSensor; private final OrientationCorrectionListener mCorrectionListener; private boolean mShouldHandleEvents; private boolean mFirstPass; - private long mPreviousTimestamp; private float xFactor; // -1 or 1 depending on device orientation private float yFactor; private boolean mSwapXY; - public GyroControl(Context context) { - mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - mCorrectionListener = new OrientationCorrectionListener(context); + private final float[] mPreviousRotation = new float[16]; + private final float[] mCurrentRotation = new float[16]; + private final float[] mAngleDifference = new float[3]; + + public GyroControl(Activity activity) { + mWindowManager = activity.getWindowManager(); + mSurfaceRotation = -10; + mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE); + mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR); + mCorrectionListener = new OrientationCorrectionListener(activity); } public void enable() { @@ -45,21 +54,20 @@ public class GyroControl implements SensorEventListener, GrabListener{ } @Override public void onSensorChanged(SensorEvent sensorEvent) { - if(mShouldHandleEvents && sensorEvent.sensor == mSensor) { - float factor = LauncherPreferences.PREF_GYRO_SENSITIVITY; - if(!mFirstPass) { - factor *= (sensorEvent.timestamp - mPreviousTimestamp) * 0.000001; - }else mFirstPass = false; - if(mSwapXY) { - float interm = sensorEvent.values[0]; - sensorEvent.values[0] = sensorEvent.values[1]; - sensorEvent.values[1] = interm; - } - CallbackBridge.mouseX += sensorEvent.values[0] * factor * xFactor; - CallbackBridge.mouseY += sensorEvent.values[1] * factor * yFactor; - CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); - mPreviousTimestamp = sensorEvent.timestamp; + if (!mShouldHandleEvents) return; + // Copy the old array content + System.arraycopy(mCurrentRotation, 0, mPreviousRotation, 0, 16); + SensorManager.getRotationMatrixFromVector(mCurrentRotation, sensorEvent.values); + + if(mFirstPass){ // Setup initial position + mFirstPass = false; + return; } + SensorManager.getAngleChange(mAngleDifference, mCurrentRotation, mPreviousRotation); + + CallbackBridge.mouseX -= (mAngleDifference[mSwapXY ? 2 : 1] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * xFactor); + CallbackBridge.mouseY += (mAngleDifference[mSwapXY ? 1 : 2] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * yFactor); + CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY); } @Override @@ -81,10 +89,21 @@ public class GyroControl implements SensorEventListener, GrabListener{ @Override public void onOrientationChanged(int i) { + // Force to wait to be in game before setting factors + // Theoretically, one could use the whole interface in portrait... + if(!mShouldHandleEvents) return; + int surfaceRotation = mWindowManager.getDefaultDisplay().getRotation(); + if(surfaceRotation == mSurfaceRotation) return; + + if(i == OrientationEventListener.ORIENTATION_UNKNOWN) { + return; //change nothing + } + mSurfaceRotation = surfaceRotation; + if((315 < i && i <= 360) || (i < 45) ) { mSwapXY = true; xFactor = 1; - yFactor = -1; + yFactor = 1; }else if(45 < i && i < 135) { mSwapXY = false; xFactor = 1; @@ -92,7 +111,7 @@ public class GyroControl implements SensorEventListener, GrabListener{ }else if(135 < i && i < 225) { mSwapXY = true; xFactor = -1; - yFactor = 1; + yFactor = -1; }else if(225 < i && i < 315) { mSwapXY = false; xFactor = -1; diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java index 58d698c8e..84cab0cef 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/prefs/LauncherPreferences.java @@ -54,7 +54,7 @@ public class LauncherPreferences { public static boolean PREF_JAVA_SANDBOX = true; public static int PREF_SCALE_FACTOR = 100; public static boolean PREF_ENALBE_GYRO = false; - public static float PREF_GYRO_SENSITIVITY = 100; + public static float PREF_GYRO_SENSITIVITY = 1f; public static int PREF_GYRO_SAMPLE_RATE = 16; public static boolean PREF_GYRO_INVERT_X = false;